]> Kevux Git Server - fll/commitdiff
Feature: Implement EKI at level_0.
authorKevin Day <Kevin@kevux.org>
Sun, 17 Nov 2024 23:22:29 +0000 (17:22 -0600)
committerKevin Day <Kevin@kevux.org>
Sun, 17 Nov 2024 23:27:01 +0000 (17:27 -0600)
This provides the initial eki implementation and unit testing.

I had to choose between making an f_eki compliment of f_iki or appending EKI into f_iki.
I ended up choosing the latter because it is simpler and will require fewer cross-dependencies when using higher levels.
There is enough overlap in functionality to justify this.
These are almost completely identical specifications.

Add additional unit tests to catch more problems and implement these same unit tests in f_iki for consistency purposes.

This includes some code clean up.
The `wrapped` is changed to use `0x0` and `0x1` rather than `F_false` and `F_true`.
These are functionally identical but the code is more consistent when having `0x0`, `0x1`, and `0x2` instead of `F_false`, `F_true`, and `0x2`.

37 files changed:
build/level_0/settings
build/monolithic/settings
level_0/f_iki/c/iki.c
level_0/f_iki/c/iki.h
level_0/f_iki/c/iki/common.h
level_0/f_iki/c/iki/data.c
level_0/f_iki/c/iki/data.h
level_0/f_iki/c/iki/eki.c [new file with mode: 0644]
level_0/f_iki/c/iki/eki.h [new file with mode: 0644]
level_0/f_iki/c/iki/private-eki.c [new file with mode: 0644]
level_0/f_iki/c/iki/private-eki.h [new file with mode: 0644]
level_0/f_iki/data/build/settings
level_0/f_iki/data/build/settings-mocks
level_0/f_iki/data/build/settings-tests
level_0/f_iki/tests/unit/c/mock-iki.c
level_0/f_iki/tests/unit/c/mock-iki.h
level_0/f_iki/tests/unit/c/test-iki-eki_read.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-eki_read.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekis_append.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekis_append.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekis_append_all.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekis_append_all.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekis_delete_callback.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekis_delete_callback.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekis_destroy_callback.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekis_destroy_callback.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekiss_append.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekiss_append.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekiss_append_all.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekiss_append_all.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekiss_delete_callback.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekiss_delete_callback.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekiss_destroy_callback.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-ekiss_destroy_callback.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-read.c
level_0/f_iki/tests/unit/c/test-iki.c
level_0/f_iki/tests/unit/c/test-iki.h

index 5dc2c865fb0380a803916f38f117db24f3555317..d68f4893f778f9c8d3992c79b0815b78b32a8261 100644 (file)
@@ -51,7 +51,7 @@ build_sources_library environment.c
 build_sources_library execute.c
 build_sources_library file.c private-file.c file/common.c file/stream.c
 build_sources_library fss.c fss/common.c fss/item.c fss/named.c fss/nest.c fss/payload.c fss/quote.c fss/set.c fss/set_quote.c fss/simple_packet.c
-build_sources_library iki.c iki/common.c iki/data.c private-iki.c iki/private-data.c
+build_sources_library iki.c iki/common.c iki/data.c iki/eki.c private-iki.c iki/private-data.c iki/private-eki.c
 build_sources_library limit.c limit/set.c limit/value.c
 build_sources_library memory.c memory/array.c memory/arrays.c
 build_sources_library private-memory.c memory/private-array.c
@@ -100,7 +100,7 @@ build_sources_headers environment.h environment/common.h
 build_sources_headers execute.h execute/common.h
 build_sources_headers file.h file/common.h file/stream.h
 build_sources_headers fss.h fss/common.h fss/item.h fss/named.h fss/nest.h fss/payload.h fss/quote.h fss/set.h fss/set_quote.h fss/simple_packet.h
-build_sources_headers iki.h iki/common.h iki/data.h
+build_sources_headers iki.h iki/common.h iki/data.h iki/eki.h
 build_sources_headers limit.h limit/set.h limit/value.h
 build_sources_headers memory.h memory/array.h memory/arrays.h memory/common.h
 build_sources_headers network.h network/common.h
index 396ea17153dd4ba873c6d7b733b088d614e01782..50e9763ea053521156078c03f44505d86ade25a3 100644 (file)
@@ -51,7 +51,7 @@ build_sources_library level_0/environment.c
 build_sources_library level_0/execute.c
 build_sources_library level_0/file.c level_0/private-file.c level_0/file/common.c level_0/file/stream.c
 build_sources_library level_0/fss.c level_0/fss/common.c level_0/fss/item.c level_0/fss/named.c level_0/fss/nest.c level_0/fss/payload.c level_0/fss/quote.c level_0/fss/set.c level_0/fss/set_quote.c level_0/fss/simple_packet.c
-build_sources_library level_0/iki.c level_0/iki/common.c level_0/iki/data.c level_0/private-iki.c level_0/iki/private-data.c
+build_sources_library level_0/iki.c level_0/iki/common.c level_0/iki/data.c level_0/iki/eki.c level_0/private-iki.c level_0/iki/private-data.c level_0/iki/private-eki.c
 build_sources_library level_0/limit.c level_0/limit/set.c level_0/limit/value.c
 build_sources_library level_0/memory.c level_0/memory/array.c level_0/memory/arrays.c
 build_sources_library level_0/private-memory.c level_0/memory/private-array.c
@@ -121,7 +121,7 @@ build_sources_headers level_0/environment.h level_0/environment/common.h
 build_sources_headers level_0/execute.h level_0/execute/common.h
 build_sources_headers level_0/file.h level_0/file/common.h level_0/file/stream.h
 build_sources_headers level_0/fss.h level_0/fss/common.h level_0/fss/item.h level_0/fss/named.h level_0/fss/nest.h level_0/fss/payload.h level_0/fss/quote.h level_0/fss/set.h level_0/fss/set_quote.h level_0/fss/simple_packet.h
-build_sources_headers level_0/iki.h level_0/iki/common.h level_0/iki/data.h
+build_sources_headers level_0/iki.h level_0/iki/common.h level_0/iki/data.h level_0/iki/eki.h
 build_sources_headers level_0/limit.h level_0/limit/set.h level_0/limit/value.h
 build_sources_headers level_0/memory.h level_0/memory/array.h level_0/memory/arrays.h level_0/memory/common.h
 build_sources_headers level_0/network.h level_0/network/common.h
index db637ba6ba063c2a633cc099e0c64c05271174ae..54ab886ffd81d53ca7f0a28996e8b1503e9670a2 100644 (file)
@@ -33,6 +33,611 @@ extern "C" {
   }
 #endif // _di_f_iki_content_partial_is_
 
+#ifndef _di_f_iki_eki_read_
+  void f_iki_eki_read(f_string_static_t * const buffer, f_range_t * const range, f_iki_eki_t * const data, f_state_t * const state) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!state) return;
+
+      if (!buffer || !range || !data) {
+        state->status = F_status_set_error(F_parameter);
+
+        return;
+      }
+    #endif // _di_level_0_parameter_checking_
+
+    if (!buffer->used) {
+      state->status = F_data_not;
+
+      return;
+    }
+
+    if (range->start > range->stop) {
+      state->status = F_data_not_stop;
+
+      return;
+    }
+
+    if (range->start >= buffer->used) {
+      state->status = F_data_not_eos;
+
+      return;
+    }
+
+    f_number_unsigned_t width_max = 0;
+
+    if (width_max > buffer->used - range->start) {
+      width_max = buffer->used - range->start;
+    }
+
+    f_range_t content_range = f_range_t_initialize;
+    f_range_t found_vocabulary = f_range_t_initialize;
+    f_number_unsigned_t i = 0;
+    f_number_unsigned_t content_slash_delimits = 0;
+    f_number_unsigned_t content_slash_first = 0;
+    f_number_unsigned_t content_slash_total = 0;
+    f_number_unsigned_t found_content = 0;
+    f_number_unsigned_t vocabulary_count = 0;
+    f_number_unsigned_t vocabulary_slash_first = 0;
+    const f_number_unsigned_t delimits_used = data->delimits.used;
+
+    uint8_t mode = 0x0; // 0x0 = nothing, 0x1 = separator found, 0x2 = possible multiple vocabulary names, 0x4 = completed multiple vocabulary names.
+    uint8_t quote = 0;
+    uint8_t wrapped = 0x0; // 0x0 = not wrapped, 0x1 = wrapped, 0x2 = valid wrapped.
+
+    do {
+
+      // Find the start of the vocabulary name.
+      while (range->start <= range->stop && range->start < buffer->used) {
+
+        if (state->interrupt) {
+          state->interrupt((void * const) state, 0);
+          if (F_status_set_fine(state->status) == F_interrupt) break;
+        }
+
+        width_max = buffer->used - range->start;
+
+        state->status = f_utf_is_word_dash_plus(buffer->string + range->start, width_max, F_false);
+
+        if (F_status_is_error(state->status)) {
+          if (F_status_set_fine(state->status) == F_utf_fragment || F_status_set_fine(state->status) == F_complete_not_utf) {
+            if (state->flag & f_iki_state_flag_utf_fail_on_valid_not_e) break;
+
+            state->status = F_false;
+          }
+          else {
+            break;
+          }
+        }
+
+        if (state->status == F_true) {
+          if (!wrapped) {
+            found_vocabulary.start = range->start;
+            found_vocabulary.stop = range->start;
+          }
+
+          state->status = f_utf_buffer_increment(*buffer, range, 1);
+          if (F_status_is_error(state->status)) break;
+
+          state->status = F_true;
+
+          break;
+        }
+
+        // Wrapped must be followed by a valid vocabulary name.
+        if (buffer->string[range->start] == f_iki_syntax_wrap_open_s.string[0]) {
+          found_vocabulary.start = range->start;
+          found_vocabulary.stop = range->start;
+
+          wrapped = 0x1;
+        }
+        else if (wrapped) {
+          wrapped = 0x0;
+        }
+
+        state->status = f_utf_buffer_increment(*buffer, range, 1);
+        if (F_status_is_error(state->status)) break;
+      } // while
+
+      // Find the end of the vocabulary name.
+      while (F_status_is_error_not(state->status) && range->start <= range->stop && range->start < buffer->used) {
+
+        if (state->interrupt) {
+          state->interrupt((void * const) state, 0);
+          if (F_status_set_fine(state->status) == F_interrupt) break;
+        }
+
+        if (buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0]) {
+          ++range->start;
+
+          continue;
+        }
+
+        if (buffer->string[range->start] == f_iki_syntax_separator_s.string[0]) {
+          do {
+            state->status = f_utf_buffer_increment(*buffer, range, 1);
+          } while (F_status_is_error_not(state->status) && range->start <= range->stop && range->start < buffer->used && buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0]);
+
+          if (F_status_is_error(state->status) || range->start > range->stop || range->start >= buffer->used) break;
+
+          // Found a valid vocabulary name.
+          if (buffer->string[range->start] == f_iki_syntax_quote_single_s.string[0] || buffer->string[range->start] == f_iki_syntax_quote_double_s.string[0] || buffer->string[range->start] == f_iki_syntax_quote_grave_s.string[0]) {
+            state->status = F_true;
+            quote = buffer->string[range->start];
+            vocabulary_count = 1;
+          }
+          else {
+            mode &= ~0x6;
+            vocabulary_count = 0;
+
+            do {
+              if (state->interrupt) {
+                state->interrupt((void * const) state, 0);
+                if (F_status_set_fine(state->status) == F_interrupt) break;
+              }
+
+              if (buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0]) {
+                ++range->start;
+
+                continue;
+              }
+
+              if (buffer->string[range->start] == f_iki_syntax_quote_single_s.string[0] || buffer->string[range->start] == f_iki_syntax_quote_double_s.string[0] || buffer->string[range->start] == f_iki_syntax_quote_grave_s.string[0]) {
+                if ((mode & 0x6) && (!wrapped || wrapped == 0x2)) {
+                  if (mode & 0x4) {
+                    mode &= ~0x2;
+                  }
+                  else {
+                    mode |= 0x4;
+                  }
+
+                  state->status = F_true;
+                  quote = buffer->string[range->start];
+                  ++vocabulary_count;
+                }
+                else {
+                  state->status = F_next;
+                  mode &= ~0x6;
+                }
+
+                break;
+              }
+
+              if (buffer->string[range->start] == f_iki_syntax_slash_s.string[0]) {
+                mode &= ~0x1;
+                vocabulary_slash_first = range->start;
+
+                // The slash only needs to be delimited if it were to otherwise be a valid vocabulary name.
+                while (range->start <= range->stop && range->start < buffer->used) {
+
+                  if (state->interrupt) {
+                    state->interrupt((void * const) state, 0);
+                    if (F_status_set_fine(state->status) == F_interrupt) break;
+                  }
+
+                  if (buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0]) {
+                    ++range->start;
+
+                    continue;
+                  }
+
+                  if (mode & 0x1) {
+
+                    // Save delimit for a would-be valid IKI that is now delimited.
+                    if (buffer->string[range->start] == f_iki_syntax_quote_single_s.string[0] || buffer->string[range->start] == f_iki_syntax_quote_double_s.string[0] || buffer->string[range->start] == f_iki_syntax_quote_grave_s.string[0]) {
+                      state->status = f_memory_array_increase(state->step_small, sizeof(f_number_unsigned_t), (void **) &data->delimits.array, &data->delimits.used, &data->delimits.size);
+                      if (F_status_is_error(state->status)) break;
+
+                      data->delimits.array[data->delimits.used++] = vocabulary_slash_first;
+
+                      ++range->start;
+                    }
+
+                    state->status = F_next;
+
+                    break;
+                  }
+
+                  if (buffer->string[range->start] == f_iki_syntax_separator_s.string[0]) {
+                    mode |= 0x1;
+                  }
+                  else if (buffer->string[range->start] != f_iki_syntax_slash_s.string[0]) {
+                    state->status = F_next;
+
+                    break;
+                  }
+
+                  state->status = f_utf_buffer_increment(*buffer, range, 1);
+                  if (F_status_is_error(state->status)) break;
+                } // while
+
+                if (state->status == F_true) break;
+                if (F_status_is_error(state->status) || range->start > range->stop || range->start >= buffer->used || state->status == F_next) break;
+              }
+              else if (buffer->string[range->start] == f_iki_syntax_separator_s.string[0]) {
+                if (!(mode & 0x2)) {
+                  mode &= ~0x6;
+
+                  break;
+                }
+
+                ++range->start;
+                ++vocabulary_count;
+                mode &= ~0x2;
+                mode |= 0x4;
+
+                continue;
+              }
+              else if (buffer->string[range->start] == f_iki_syntax_wrap_close_s.string[0]) {
+                if (wrapped == 0x1) {
+                  wrapped = 0x2;
+                  found_vocabulary.stop = range->start;
+                }
+                else {
+                  state->status = F_next;
+                  mode &= ~0x6;
+
+                  break;
+                }
+              }
+              else {
+                width_max = buffer->used - range->start;
+
+                state->status = f_utf_is_word_dash_plus(buffer->string + range->start, width_max, F_false);
+
+                if (F_status_is_error_not(state->status)) {
+                  if (state->status != F_true) {
+                    state->status = F_next;
+
+                    break;
+                  }
+                }
+
+                if (state->status == F_true) {
+                  mode |= 0x2;
+                  found_vocabulary.stop = range->start;
+                }
+              }
+
+              state->status = f_utf_buffer_increment(*buffer, range, 1);
+              if (F_status_is_error(state->status)) break;
+
+            } while (F_status_is_error_not(state->status) && range->start <= range->stop && range->start < buffer->used);
+          }
+
+          break;
+        }
+
+        if (buffer->string[range->start] == f_iki_syntax_slash_s.string[0]) {
+          mode &= ~0x1;
+          vocabulary_slash_first = range->start;
+
+          // The slash only needs to be delimited if it were to otherwise be a valid vocabulary name.
+          while (range->start <= range->stop && range->start < buffer->used) {
+
+            if (state->interrupt) {
+              state->interrupt((void * const) state, 0);
+              if (F_status_set_fine(state->status) == F_interrupt) break;
+            }
+
+            if (buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0]) {
+              ++range->start;
+
+              continue;
+            }
+
+            if (mode & 0x1) {
+
+              // Save delimit for a would-be valid IKI that is now delimited.
+              if (buffer->string[range->start] == f_iki_syntax_quote_single_s.string[0] || buffer->string[range->start] == f_iki_syntax_quote_double_s.string[0] || buffer->string[range->start] == f_iki_syntax_quote_grave_s.string[0]) {
+                state->status = f_memory_array_increase(state->step_small, sizeof(f_number_unsigned_t), (void **) &data->delimits.array, &data->delimits.used, &data->delimits.size);
+                if (F_status_is_error(state->status)) break;
+
+                data->delimits.array[data->delimits.used++] = vocabulary_slash_first;
+
+                ++range->start;
+              }
+
+              state->status = F_next;
+
+              break;
+            }
+
+            if (buffer->string[range->start] == f_iki_syntax_separator_s.string[0]) {
+              mode |= 0x1;
+            }
+            else if (buffer->string[range->start] != f_iki_syntax_slash_s.string[0]) {
+              state->status = F_next;
+
+              break;
+            }
+
+            state->status = f_utf_buffer_increment(*buffer, range, 1);
+            if (F_status_is_error(state->status)) break;
+          } // while
+
+          if (state->status == F_true) break;
+          if (F_status_is_error(state->status) || range->start > range->stop || range->start >= buffer->used || state->status == F_next) break;
+        }
+        else if (buffer->string[range->start] == f_iki_syntax_wrap_open_s.string[0]) {
+          state->status = F_next;
+
+          break;
+        }
+        else if (wrapped == 0x1 && buffer->string[range->start] == f_iki_syntax_wrap_close_s.string[0]) {
+          wrapped = 0x2;
+          found_vocabulary.stop = range->start;
+        }
+        else if (wrapped == 0x2) {
+
+          // Wrapped close must be immediately before a separator (ignoring any placeholders in between).
+          state->status = F_next;
+
+          break;
+        }
+        else {
+          width_max = buffer->used - range->start;
+
+          state->status = f_utf_is_word_dash_plus(buffer->string + range->start, width_max, F_false);
+
+          if (F_status_is_error(state->status)) {
+            if (F_status_set_fine(state->status) == F_utf_fragment || F_status_set_fine(state->status) == F_complete_not_utf) {
+              if (state->flag & f_iki_state_flag_utf_fail_on_valid_not_e) break;
+
+              state->status = F_false;
+            }
+            else {
+              break;
+            }
+          }
+
+          if (state->status == F_true) {
+            found_vocabulary.stop = range->start;
+          }
+          else {
+
+            // Not a valid IKI vocabulary name.
+            state->status = f_utf_buffer_increment(*buffer, range, 1);
+            if (F_status_is_error(state->status)) break;
+
+            state->status = F_next;
+
+            break;
+          }
+        }
+
+        state->status = f_utf_buffer_increment(*buffer, range, 1);
+        if (F_status_is_error(state->status)) break;
+      } // while
+
+      if (F_status_is_error(state->status) || range->start > range->stop || range->start >= buffer->used) break;
+
+      if (state->status == F_next) {
+        quote = 0;
+        wrapped = 0x0;
+
+        continue;
+      }
+
+      // Process potentially valid content.
+      if (quote) {
+        found_content = ++range->start;
+
+        while (range->start <= range->stop && range->start < buffer->used) {
+
+          if (state->interrupt) {
+            state->interrupt((void * const) state, 0);
+            if (F_status_set_fine(state->status) == F_interrupt) break;
+          }
+
+          if (buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0]) {
+            ++range->start;
+
+            continue;
+          }
+
+          if (buffer->string[range->start] == quote) {
+            state->status = f_memory_array_increase(state->step_small, sizeof(f_range_t), (void **) &data->variable.array, &data->variable.used, &data->variable.size);
+            if (F_status_is_error(state->status)) break;
+
+            state->status = f_memory_array_increase(state->step_small, sizeof(f_ranges_t), (void **) &data->vocabularys.array, &data->vocabularys.used, &data->vocabularys.size);
+            if (F_status_is_error(state->status)) break;
+
+            state->status = f_memory_array_increase_by(vocabulary_count, sizeof(f_range_t), (void **) &data->vocabularys.array[data->vocabularys.used].array, &data->vocabularys.array[data->vocabularys.used].used, &data->vocabularys.array[data->vocabularys.used].size);
+            if (F_status_is_error(state->status)) break;
+
+            state->status = f_memory_array_increase(state->step_small, sizeof(f_range_t), (void **) &data->content.array, &data->content.used, &data->content.size);
+            if (F_status_is_error(state->status)) break;
+
+            data->variable.array[data->variable.used].start = found_vocabulary.start;
+            data->variable.array[data->variable.used++].stop = range->start;
+
+            i = wrapped ? found_vocabulary.start + f_iki_syntax_wrap_open_s.used : found_vocabulary.start;
+
+            for (data->vocabularys.array[data->vocabularys.used].used = 0; data->vocabularys.array[data->vocabularys.used].used < vocabulary_count; ) {
+
+              if (state->interrupt) {
+                state->interrupt((void * const) state, 0);
+                if (F_status_set_fine(state->status) == F_interrupt) break;
+              }
+
+              data->vocabularys.array[data->vocabularys.used].array[data->vocabularys.array[data->vocabularys.used].used].start = i;
+
+              while (i <= found_vocabulary.stop && buffer->string[i] != f_iki_syntax_separator_s.string[0] && buffer->string[i] != f_iki_syntax_wrap_close_s.string[0]) ++i;
+
+              data->vocabularys.array[data->vocabularys.used].array[data->vocabularys.array[data->vocabularys.used].used++].stop = (buffer->string[i] == f_iki_syntax_separator_s.string[0] || buffer->string[i] == f_iki_syntax_wrap_close_s.string[0]) ? i - 1 : i;
+
+              if (i <= found_vocabulary.stop && buffer->string[i] == f_iki_syntax_separator_s.string[0]) {
+                if (i == found_vocabulary.stop) break;
+
+                ++i;
+              }
+            } // for
+
+            ++data->vocabularys.used;
+
+            data->content.array[data->content.used].start = found_content;
+            data->content.array[data->content.used++].stop = range->start - 1;
+
+            if (++range->start > range->stop) {
+              state->status = F_okay_stop;
+            }
+            else if (range->start >= buffer->used) {
+              state->status = F_okay_eos;
+            }
+            else {
+              state->status = F_okay;
+            }
+
+            return;
+          }
+
+          if (buffer->string[range->start] == f_iki_syntax_slash_s.string[0]) {
+            content_slash_first = range->start;
+            content_slash_total = 0;
+
+            while (range->start <= range->stop && range->start < buffer->used) {
+
+              if (state->interrupt) {
+                state->interrupt((void * const) state, 0);
+                if (F_status_set_fine(state->status) == F_interrupt) break;
+              }
+
+              if (buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0]) {
+                ++range->start;
+
+                continue;
+              }
+
+              if (buffer->string[range->start] == quote) {
+                content_slash_delimits = content_slash_total / 2;
+                content_range.start = 1;
+                content_range.stop = 0;
+
+                if (content_slash_total % 2) {
+                  ++content_slash_delimits;
+                }
+
+                state->status = f_memory_array_increase_by(content_slash_delimits, sizeof(f_number_unsigned_t), (void **) &data->delimits.array, &data->delimits.used, &data->delimits.size);
+                if (F_status_is_error(state->status)) break;
+
+                content_range.start = content_slash_first;
+                content_range.stop = range->stop;
+
+                for (i = 0; i < content_slash_delimits; ) {
+
+                  if (buffer->string[content_range.start] == f_iki_syntax_slash_s.string[0]) {
+                    data->delimits.array[data->delimits.used++] = content_range.start;
+                    ++i;
+                  }
+
+                  state->status = f_utf_buffer_increment(*buffer, (&content_range), 1);
+                  if (F_status_is_error(state->status)) break;
+                } // for
+
+                if (F_status_is_error(state->status)) break;
+
+                // Valid content's ending quote is not delimited, save and return.
+                if (content_slash_total % 2 == 0) {
+                  state->status = f_memory_array_increase(state->step_small, sizeof(f_range_t), (void **) &data->variable.array, &data->variable.used, &data->variable.size);
+                  if (F_status_is_error(state->status)) break;
+
+                  state->status = f_memory_array_increase(state->step_small, sizeof(f_ranges_t), (void **) &data->vocabularys.array, &data->vocabularys.used, &data->vocabularys.size);
+                  if (F_status_is_error(state->status)) break;
+
+                  state->status = f_memory_array_increase(vocabulary_count, sizeof(f_range_t), (void **) &data->vocabularys.array[data->vocabularys.used].array, &data->vocabularys.array[data->vocabularys.used].used, &data->vocabularys.array[data->vocabularys.used].size);
+                  if (F_status_is_error(state->status)) break;
+
+                  state->status = f_memory_array_increase(state->step_small, sizeof(f_range_t), (void **) &data->content.array, &data->content.used, &data->content.size);
+                  if (F_status_is_error(state->status)) break;
+
+                  data->variable.array[data->variable.used].start = found_vocabulary.start;
+                  data->variable.array[data->variable.used++].stop = range->start;
+
+                  i = wrapped ? found_vocabulary.start + f_iki_syntax_wrap_open_s.used : found_vocabulary.start;
+
+                  for (data->vocabularys.array[data->vocabularys.used].used = 0; data->vocabularys.array[data->vocabularys.used].used < vocabulary_count; ) {
+
+                    if (state->interrupt) {
+                      state->interrupt((void * const) state, 0);
+                      if (F_status_set_fine(state->status) == F_interrupt) break;
+                    }
+
+                    data->vocabularys.array[data->vocabularys.used].array[data->vocabularys.array[data->vocabularys.used].used].start = i;
+
+                    while (i <= found_vocabulary.stop && buffer->string[i] != f_iki_syntax_separator_s.string[0] && buffer->string[i] != f_iki_syntax_wrap_close_s.string[0]) ++i;
+
+                    data->vocabularys.array[data->vocabularys.used].array[data->vocabularys.array[data->vocabularys.used].used++].stop = (buffer->string[i] == f_iki_syntax_separator_s.string[0] || buffer->string[i] == f_iki_syntax_wrap_close_s.string[0]) ? i - 1 : i;
+
+                    if (i <= found_vocabulary.stop && buffer->string[i] == f_iki_syntax_separator_s.string[0]) {
+                      if (i == found_vocabulary.stop) break;
+
+                      ++i;
+                    }
+                  } // for
+
+                  ++data->vocabularys.used;
+
+                  data->content.array[data->content.used].start = found_content;
+                  data->content.array[data->content.used++].stop = range->start - 1;
+
+                  if (++range->start > range->stop) {
+                    state->status = F_okay_stop;
+                  }
+                  else if (range->start >= buffer->used) {
+                    state->status = F_okay_eos;
+                  }
+                  else {
+                    state->status = F_okay;
+                  }
+
+                  return;
+                }
+
+                break;
+              }
+
+              if (buffer->string[range->start] != f_iki_syntax_slash_s.string[0]) break;
+
+              ++content_slash_total;
+
+              state->status = f_utf_buffer_increment(*buffer, range, 1);
+              if (F_status_is_error(state->status)) break;
+            } // while
+
+            if (F_status_is_error(state->status)) break;
+          }
+
+          state->status = f_utf_buffer_increment(*buffer, range, 1);
+          if (F_status_is_error(state->status)) break;
+        } // while
+
+        quote = 0;
+        wrapped = 0x0;
+      }
+
+      if (F_status_is_error(state->status) || range->start > range->stop || range->start >= buffer->used) break;
+
+      state->status = f_utf_buffer_increment(*buffer, range, 1);
+      if (F_status_is_error(state->status)) break;
+
+    } while (range->start <= range->stop && range->start < buffer->used);
+
+    if (F_status_set_fine(state->status) == F_complete_not_utf_eos || F_status_set_fine(state->status) == F_complete_not_utf_stop) {
+      if (!(state->flag & f_iki_state_flag_utf_fail_on_valid_not_e)) {
+        state->status = F_status_set_fine(state->status);
+      }
+    }
+
+    if (F_status_is_error(state->status)) {
+      data->delimits.used = delimits_used;
+
+      return;
+    }
+
+    state->status = (range->start > range->stop) ? F_data_not_stop : F_data_not_eos;
+  }
+#endif // _di_f_iki_eki_read_
+
 #ifndef _di_f_iki_object_is_
   f_status_t f_iki_object_is(const f_string_static_t object) {
 
@@ -89,13 +694,20 @@ extern "C" {
       width_max = buffer->used - range->start;
     }
 
+    f_range_t content_range = f_range_t_initialize;
     f_range_t found_vocabulary = f_range_t_initialize;
+    f_number_unsigned_t i = 0;
+    f_number_unsigned_t content_slash_delimits = 0;
+    f_number_unsigned_t content_slash_first = 0;
+    f_number_unsigned_t content_slash_total = 0;
     f_number_unsigned_t found_content = 0;
     f_number_unsigned_t vocabulary_slash_first = 0;
     const f_number_unsigned_t delimits_used = data->delimits.used;
 
+
     uint8_t quote = 0;
-    uint8_t wrapped = F_false; // 0x0 (false) = not wapped, 0x1 (true) = wrapped, 0x2 = valid wrapped.
+    uint8_t separator_found = F_false;
+    uint8_t wrapped = 0x0; // 0x0 (false) = not wrapped, 0x1 (true) = wrapped, 0x2 = valid wrapped.
 
     do {
 
@@ -141,10 +753,10 @@ extern "C" {
           found_vocabulary.start = range->start;
           found_vocabulary.stop = range->start;
 
-          wrapped = F_true;
+          wrapped = 0x1;
         }
         else if (wrapped) {
-          wrapped = F_false;
+          wrapped = 0x0;
         }
 
         state->status = f_utf_buffer_increment(*buffer, range, 1);
@@ -167,8 +779,8 @@ extern "C" {
 
         if (buffer->string[range->start] == f_iki_syntax_separator_s.string[0]) {
 
-          // Wrapped must close in a wrap close before the seperator.
-          if (wrapped == F_true) {
+          // Wrapped must close in a "wrap close" before the separator is matched.
+          if (wrapped == 0x1) {
             state->status = F_next;
 
             break;
@@ -176,7 +788,7 @@ extern "C" {
 
           do {
             state->status = f_utf_buffer_increment(*buffer, range, 1);
-          } while (F_status_is_fine(state->status) && buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0] && range->start <= range->stop && range->start < buffer->used);
+          } while (F_status_is_error_not(state->status) && range->start <= range->stop && range->start < buffer->used && buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0]);
 
           if (F_status_is_error(state->status) || range->start > range->stop || range->start >= buffer->used) break;
 
@@ -193,8 +805,7 @@ extern "C" {
         }
 
         if (buffer->string[range->start] == f_iki_syntax_slash_s.string[0]) {
-          bool separator_found = F_false;
-
+          separator_found = F_false;
           vocabulary_slash_first = range->start;
 
           // The slash only needs to be delimited if it were to otherwise be a valid vocabulary name.
@@ -249,7 +860,7 @@ extern "C" {
 
           break;
         }
-        else if (wrapped == F_true && buffer->string[range->start] == f_iki_syntax_wrap_close_s.string[0]) {
+        else if (wrapped == 0x1 && buffer->string[range->start] == f_iki_syntax_wrap_close_s.string[0]) {
           wrapped = 0x2;
           found_vocabulary.stop = range->start;
         }
@@ -299,7 +910,7 @@ extern "C" {
 
       if (state->status == F_next) {
         quote = 0;
-        wrapped = F_false;
+        wrapped = 0x0;
 
         continue;
       }
@@ -354,11 +965,16 @@ extern "C" {
           }
 
           if (buffer->string[range->start] == f_iki_syntax_slash_s.string[0]) {
-            f_number_unsigned_t content_slash_first = range->start;
-            f_number_unsigned_t content_slash_total = 0;
+            content_slash_first = range->start;
+            content_slash_total = 0;
 
             while (range->start <= range->stop && range->start < buffer->used) {
 
+              if (state->interrupt) {
+                state->interrupt((void * const) state, 0);
+                if (F_status_set_fine(state->status) == F_interrupt) break;
+              }
+
               if (buffer->string[range->start] == f_iki_syntax_placeholder_s.string[0]) {
                 ++range->start;
 
@@ -366,9 +982,9 @@ extern "C" {
               }
 
               if (buffer->string[range->start] == quote) {
-                f_number_unsigned_t content_slash_delimits = content_slash_total / 2;
-                f_range_t content_range = f_range_t_initialize;
-                f_number_unsigned_t i = 0;
+                content_slash_delimits = content_slash_total / 2;
+                content_range.start = 1;
+                content_range.stop = 0;
 
                 if (content_slash_total % 2) {
                   ++content_slash_delimits;
@@ -380,7 +996,7 @@ extern "C" {
                 content_range.start = content_slash_first;
                 content_range.stop = range->stop;
 
-                while (i < content_slash_delimits) {
+                for (i = 0; i < content_slash_delimits; ) {
 
                   if (buffer->string[content_range.start] == f_iki_syntax_slash_s.string[0]) {
                     data->delimits.array[data->delimits.used++] = content_range.start;
@@ -389,7 +1005,7 @@ extern "C" {
 
                   state->status = f_utf_buffer_increment(*buffer, (&content_range), 1);
                   if (F_status_is_error(state->status)) break;
-                } // while
+                } // for
 
                 if (F_status_is_error(state->status)) break;
 
@@ -445,7 +1061,7 @@ extern "C" {
         } // while
 
         quote = 0;
-        wrapped = F_false;
+        wrapped = 0x0;
       }
 
       if (F_status_is_error(state->status) || range->start > range->stop || range->start >= buffer->used) break;
index a109ea2ac1c8cd563e024e20aae59567ceba1560..09c6510419769780cbcd0625077745c7b272cbab 100644 (file)
@@ -7,8 +7,11 @@
  *
  * Provides a Wiki-Like syntax meant to be much simpler.
  *
- * This simpler Wiki-Like syntax, called Iki, focuses just on simply adding context.
+ * This simpler Wiki-Like syntax, called IKI, focuses just on simply adding context.
  * The context itself is not explicitly defined but a few common standards are provided.
+ *
+ * This includes support for EKI format, which is just an extended form of IKI.
+ * Many of the IKI functions can be used for EKI, except for vocabulary related and anything directly operating with f_iki_eki_t related.
  */
 #ifndef _F_iki_h
 #define _F_iki_h
@@ -28,6 +31,7 @@
 // FLL-0 iki includes.
 #include <fll/level_0/iki/common.h>
 #include <fll/level_0/iki/data.h>
+#include <fll/level_0/iki/eki.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -82,6 +86,60 @@ extern "C" {
 #endif // _di_f_iki_content_partial_is_
 
 /**
+ * Read a single EKI Vocabulary and Content.
+ *
+ * This does not verify if the vocabulary name is known.
+ * This only finds a complete vocabulary name and content.
+ *
+ * This will increment the range after the end of any valud vocabulary and content set.
+ *
+ * This will update the buffer at the given range with any placeholders to escaped data.
+ * Calling this more than once on the same buffer range could result in multiple escaping.
+ *
+ * @param buffer
+ *   The string to process.
+ * @param range
+ *   The start/stop location within the buffer to be processed.
+ *   The start location will be updated as the buffer is being processed.
+ *   The start location will represent where the read stopped on return.
+ *   A start location past the stop location or buffer used means that the entire range was processed.
+ * @param data
+ *   The EKI variable data.
+ * @param state
+ *   A state for providing flags and handling interrupts during long running operations.
+ *   There is no state.handle().
+ *   There is no "callbacks" structure.
+ *   There is no data structure passed to these functions.
+ *   This must not be NULL.
+ *
+ *   When state.interrupt() returns, only F_interrupt and F_interrupt_not are processed.
+ *   Error bit designates an error but must be passed along with F_interrupt.
+ *   All other statuses are ignored.
+ *
+ *   This alters state.status:
+ *     F_okay on success and an IKI vocabulary name was found.
+ *     F_okay_eos on success and an IKI vocabulary name was found and end of string was reached.
+ *     F_okay_stop on success and an IKI vocabulary name was found and stop point was reached.
+ *     F_complete_not_utf_eos on success but string ended on incomplete UTF-8 and f_iki_state_flag_utf_fail_on_valid_not_e is not set.
+ *     F_complete_not_utf_stop on success but stop point reached on incomplete UTF-8 and f_iki_state_flag_utf_fail_on_valid_not_e is not set.
+ *     F_data_not on success, but there were no IKI vocabulary names found.
+ *     F_data_not_eos on success and EOS was reached, but there were no IKI vocabulary names found.
+ *     F_data_not_stop on success and stop point was reached, but there were no IKI vocabulary names found.
+ *
+ *     F_complete_not_utf_eos (with error bit) on success but string ended on incomplete UTF-8 and f_iki_state_flag_utf_fail_on_valid_not_e is set.
+ *     F_complete_not_utf_stop (with error bit) on success but stop point reached on incomplete UTF-8 and f_iki_state_flag_utf_fail_on_valid_not_e is set.
+ *     F_interrupt (with error bit) if stopping due to an interrupt.
+ *     F_memory_not (with error bit) on out of memory.
+ *     F_parameter (with error bit) if a parameter is invalid.
+ *     F_string_too_large (with error bit) if a string length is too large to store in the buffer.
+ *
+ * @see f_memory_array_increase_by()
+ */
+#ifndef _di_f_iki_eki_read_
+  extern void f_iki_eki_read(f_string_static_t * const buffer, f_range_t * const range, f_iki_eki_t * const data, f_state_t * const state);
+#endif // _di_f_iki_eki_read_
+
+/**
  * Determine if an object is a valid IKI object name.
  *
  * @param object
@@ -124,7 +182,7 @@ extern "C" {
 #endif // _di_f_iki_object_partial_is_
 
 /**
- * Read a single iki Vocabulary and Content.
+ * Read a single IKI Vocabulary and Content.
  *
  * This does not verify if the vocabulary name is known.
  * This only finds a complete vocabulary name and content.
index eee30762d79835f9a8c7764a84944506b4f59bac..92a2b4c1def7dcffa60c5ffd83de1195a646f7b4 100644 (file)
@@ -192,7 +192,7 @@ extern "C" {
 #endif // _di_f_iki_vocabulary_0002_s_
 
 /**
- * This containg all of the IKI data.
+ * This containing all of the IKI data.
  *
  * Properties:
  *   - content:    A set of ranges representing the content (variable value) list to store the content associated with the found vocabulary name.
@@ -268,6 +268,83 @@ extern "C" {
   #define macro_f_iki_datass_t_initialize_2(array, length) { array, length, length }
 #endif // _di_f_iki_datass_t_
 
+/**
+ * This containing all of the EKI data (extended IKI data).
+ *
+ * Properties:
+ *   - content:     A set of ranges representing the content (variable value) list to store the content associated with the found vocabulary name.
+ *   - delimits:    A delimits array representing where delimits exist within the buffer.
+ *   - variable:    A set of ranges representing the entire vocabulary (variable name), content, and the syntax.
+ *   - vocabularys: A set of ranges representing the vocabularies (variable names) list to store each found vocabulary name.
+ */
+#ifndef _di_f_iki_eki_t_
+  typedef struct {
+    f_ranges_t content;
+    f_number_unsigneds_t delimits;
+    f_ranges_t variable;
+    f_rangess_t vocabularys;
+  } f_iki_eki_t;
+
+  #define f_iki_eki_t_initialize { \
+    f_ranges_t_initialize, \
+    f_number_unsigneds_t_initialize, \
+    f_ranges_t_initialize, \
+    f_rangess_t_initialize, \
+  }
+
+  #define macro_f_iki_eki_t_initialize_1(content, delimits, variable, vocabularys) { content, delimits, variable, vocabularys }
+
+  #define macro_f_iki_eki_t_clear(data) \
+    f_ranges_t_clear(data.content) \
+    f_number_unsigneds_t_clear(data.delimits) \
+    f_ranges_t_clear(data.variable) \
+    f_ranges_t_clear(data.vocabulary)
+#endif // _di_f_iki_eki_t_
+
+/**
+ * An array of f_iki_eki_t.
+ *
+ * Properties:
+ *   - array: The array of IKI EKI.
+ *   - size:  Total amount of allocated space.
+ *   - used:  Total number of allocated spaces used.
+ */
+#ifndef _di_f_iki_ekis_t_
+  typedef struct {
+    f_iki_eki_t *array;
+
+    f_number_unsigned_t size;
+    f_number_unsigned_t used;
+  } f_iki_ekis_t;
+
+  #define f_iki_ekis_t_initialize { 0, 0, 0 }
+
+  #define macro_f_iki_ekis_t_initialize_1(content, size, used) { array, size, used }
+  #define macro_f_iki_ekis_t_initialize_2(array, length) { array, length, length }
+#endif // _di_f_iki_ekis_t_
+
+/**
+ * An array of f_iki_ekis_t.
+ *
+ * Properties:
+ *   - array: The array of IKI EKIs.
+ *   - size:  Total amount of allocated space.
+ *   - used:  Total number of allocated spaces used.
+ */
+#ifndef _di_f_iki_ekiss_t_
+  typedef struct {
+    f_iki_ekis_t *array;
+
+    f_number_unsigned_t size;
+    f_number_unsigned_t used;
+  } f_iki_ekiss_t;
+
+  #define f_iki_ekiss_t_initialize { 0, 0, 0 }
+
+  #define macro_f_iki_ekiss_t_initialize_1(content, size, used) { array, size, used }
+  #define macro_f_iki_ekiss_t_initialize_2(array, length) { array, length, length }
+#endif // _di_f_iki_ekiss_t_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index e5e7d7322a3bbc82ed5328dacd8acdf2253d2a32..95d53225357f181887d3fe16b60f5f0c61397bae 100644 (file)
@@ -1,5 +1,4 @@
 #include "../iki.h"
-#include "data.h"
 #include "private-data.h"
 
 #ifdef __cplusplus
index 3d2e0f6bec5cf154bdc3a1e1ef3126ff0510be78..3c685d9780b9ad9e56852ed3d3ab1cf5eeaf9479 100644 (file)
@@ -130,7 +130,6 @@ extern "C" {
  *   Errors (with error bit) from: f_memory_array_resize().
  *
  * @see f_memory_array_resize()
- * @see f_memory_arrays_resize()
  */
 #ifndef _di_f_iki_datas_delete_callback_
   extern f_status_t f_iki_datas_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
diff --git a/level_0/f_iki/c/iki/eki.c b/level_0/f_iki/c/iki/eki.c
new file mode 100644 (file)
index 0000000..163fefc
--- /dev/null
@@ -0,0 +1,342 @@
+#include "../iki.h"
+#include "private-eki.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_f_iki_eki_delete_
+  f_status_t f_iki_eki_delete(f_iki_eki_t * const data) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!data) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    {
+      f_status_t status = F_okay;
+
+      if (data->content.size && data->content.array) {
+        status = f_memory_array_resize(0, sizeof(f_range_t), (void **) &data->content.array, &data->content.used, &data->content.size);
+        if (F_status_is_error(status)) return status;
+      }
+
+      if (data->delimits.size && data->delimits.array) {
+        status = f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &data->delimits.array, &data->delimits.used, &data->delimits.size);
+        if (F_status_is_error(status)) return status;
+      }
+
+      if (data->variable.size && data->variable.array) {
+        status = f_memory_array_resize(0, sizeof(f_range_t), (void **) &data->variable.array, &data->variable.used, &data->variable.size);
+        if (F_status_is_error(status)) return status;
+      }
+
+      if (data->vocabularys.size && data->vocabularys.array) {
+        status = f_memory_arrays_resize(0, sizeof(f_ranges_t), (void **) &data->vocabularys.array, &data->vocabularys.used, &data->vocabularys.size, &f_rangess_delete_callback);
+        if (F_status_is_error(status)) return status;
+      }
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_iki_eki_delete_
+
+#ifndef _di_f_iki_eki_destroy_
+  f_status_t f_iki_eki_destroy(f_iki_eki_t * const data) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!data) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    {
+      f_status_t status = F_okay;
+
+      if (data->content.size && data->content.array) {
+        status = f_memory_array_adjust(0, sizeof(f_range_t), (void **) &data->content.array, &data->content.used, &data->content.size);
+        if (F_status_is_error(status)) return status;
+      }
+
+      if (data->delimits.size && data->delimits.array) {
+        status = f_memory_array_adjust(0, sizeof(f_number_unsigned_t), (void **) &data->delimits.array, &data->delimits.used, &data->delimits.size);
+        if (F_status_is_error(status)) return status;
+      }
+
+      if (data->variable.size && data->variable.array) {
+        status = f_memory_array_adjust(0, sizeof(f_range_t), (void **) &data->variable.array, &data->variable.used, &data->variable.size);
+        if (F_status_is_error(status)) return status;
+      }
+
+      if (data->vocabularys.size && data->vocabularys.array) {
+        status = f_memory_arrays_adjust(0, sizeof(f_ranges_t), (void **) &data->vocabularys.array, &data->vocabularys.used, &data->vocabularys.size, &f_rangess_destroy_callback);
+        if (F_status_is_error(status)) return status;
+      }
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_iki_eki_destroy_
+
+#ifndef _di_f_iki_ekis_append_
+  f_status_t f_iki_ekis_append(const f_iki_eki_t source, f_iki_ekis_t * const destination) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!destination) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    {
+      f_status_t status = f_memory_array_increase(F_iki_default_allocation_small_d, sizeof(f_iki_eki_t), (void **) &destination->array, &destination->used, &destination->size);
+      if (F_status_is_error(status)) return status;
+
+      destination->array[destination->used].content.used = 0;
+      destination->array[destination->used].delimits.used = 0;
+      destination->array[destination->used].variable.used = 0;
+      destination->array[destination->used].vocabularys.used = 0;
+
+      if (source.content.used) {
+        status = f_ranges_append_all(source.content, &destination->array[destination->used].content);
+        if (F_status_is_error(status)) return status;
+      }
+
+      if (source.delimits.used) {
+        for (f_number_unsigned_t i = 0; i < source.delimits.used; ++i) {
+
+          status = f_memory_array_append(source.delimits.array + i, sizeof(f_number_unsigned_t), (void **) &destination->array[destination->used].delimits.array, &destination->array[destination->used].delimits.used, &destination->array[destination->used].delimits.size);
+          if (F_status_is_error(status)) return status;
+        } // for
+      }
+
+      if (source.variable.used) {
+        status = f_ranges_append_all(source.variable, &destination->array[destination->used].variable);
+        if (F_status_is_error(status)) return status;
+      }
+
+      if (source.vocabularys.used) {
+        status = f_rangess_append_all(source.vocabularys, &destination->array[destination->used].vocabularys);
+        if (F_status_is_error(status)) return status;
+      }
+    }
+
+    ++destination->used;
+
+    return F_okay;
+  }
+#endif // _di_f_iki_ekis_append_
+
+#ifndef _di_f_iki_ekis_append_all_
+  f_status_t f_iki_ekis_append_all(const f_iki_ekis_t source, f_iki_ekis_t * const destination) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!destination) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (!source.used) return F_data_not;
+
+    return private_f_iki_ekis_append_all(source, destination);
+  }
+#endif // _di_f_iki_ekis_append_all_
+
+#ifndef _di_f_iki_ekis_delete_callback_
+  f_status_t f_iki_ekis_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_iki_eki_t * const array = (f_iki_eki_t *) void_array;
+      f_status_t status = F_okay;
+
+      for (f_number_unsigned_t i = start; i < stop; ++i) {
+
+        if (array[i].content.size && array[i].content.array) {
+          status = f_memory_array_resize(0, sizeof(f_range_t), (void **) &array[i].content.array, &array[i].content.used, &array[i].content.size);
+          if (F_status_is_error(status)) return status;
+        }
+
+        if (array[i].delimits.size && array[i].delimits.array) {
+          status = f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &array[i].delimits.array, &array[i].delimits.used, &array[i].delimits.size);
+          if (F_status_is_error(status)) return status;
+        }
+
+        if (array[i].variable.size && array[i].variable.array) {
+          status = f_memory_array_resize(0, sizeof(f_range_t), (void **) &array[i].variable.array, &array[i].variable.used, &array[i].variable.size);
+          if (F_status_is_error(status)) return status;
+        }
+
+        if (array[i].vocabularys.size && array[i].vocabularys.array) {
+          status = f_memory_arrays_resize(0, sizeof(f_ranges_t), (void **) &array[i].vocabularys.array, &array[i].vocabularys.used, &array[i].vocabularys.size, &f_rangess_delete_callback);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_iki_ekis_delete_callback_
+
+#ifndef _di_f_iki_ekis_destroy_callback_
+  f_status_t f_iki_ekis_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_iki_eki_t * const array = (f_iki_eki_t *) void_array;
+      f_status_t status = F_okay;
+
+      for (f_number_unsigned_t i = start; i < stop; ++i) {
+
+        if (array[i].content.size && array[i].content.array) {
+          status = f_memory_array_adjust(0, sizeof(f_range_t), (void **) &array[i].content.array, &array[i].content.used, &array[i].content.size);
+          if (F_status_is_error(status)) return status;
+        }
+
+        if (array[i].delimits.size && array[i].delimits.array) {
+          status = f_memory_array_adjust(0, sizeof(f_number_unsigned_t), (void **) &array[i].delimits.array, &array[i].delimits.used, &array[i].delimits.size);
+          if (F_status_is_error(status)) return status;
+        }
+
+        if (array[i].variable.size && array[i].variable.array) {
+          status = f_memory_array_adjust(0, sizeof(f_range_t), (void **) &array[i].variable.array, &array[i].variable.used, &array[i].variable.size);
+          if (F_status_is_error(status)) return status;
+        }
+
+        if (array[i].vocabularys.size && array[i].vocabularys.array) {
+          status = f_memory_arrays_adjust(0, sizeof(f_ranges_t), (void **) &array[i].vocabularys.array, &array[i].vocabularys.used, &array[i].vocabularys.size, &f_rangess_destroy_callback);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_iki_ekis_destroy_callback_
+
+#ifndef _di_f_iki_ekiss_append_
+  f_status_t f_iki_ekiss_append(const f_iki_ekis_t source, f_iki_ekiss_t * const destination) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!destination) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (!source.used) return F_data_not;
+
+    {
+      f_status_t status = f_memory_array_increase(F_memory_default_allocation_small_d, sizeof(f_iki_ekis_t), (void **) &destination->array, &destination->used, &destination->size);
+      if (F_status_is_error(status)) return status;
+
+      status = private_f_iki_ekis_append_all(source, &destination->array[destination->used]);
+      if (F_status_is_error(status)) return status;
+    }
+
+    ++destination->used;
+
+    return F_okay;
+  }
+#endif // _di_f_iki_ekiss_append_
+
+#ifndef _di_f_iki_ekiss_append_all_
+  f_status_t f_iki_ekiss_append_all(const f_iki_ekiss_t source, f_iki_ekiss_t * const destination) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!destination) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (!source.used) return F_data_not;
+
+    {
+      f_status_t status = f_memory_array_increase_by(source.used, sizeof(f_iki_ekis_t), (void **) &destination->array, &destination->used, &destination->size);
+      if (F_status_is_error(status)) return status;
+
+      for (f_number_unsigned_t i = 0; i < source.used; ++i, ++destination->used) {
+
+        destination->array[destination->used].used = 0;
+
+        if (source.array[i].used) {
+          status = private_f_iki_ekis_append_all(source.array[i], &destination->array[destination->used]);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_iki_ekiss_append_all_
+
+#ifndef _di_f_iki_ekiss_delete_callback_
+  f_status_t f_iki_ekiss_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_iki_ekis_t * const array = (f_iki_ekis_t *) void_array;
+      f_status_t status = F_okay;
+      f_number_unsigned_t j = 0;
+
+      for (f_number_unsigned_t i = start; i < stop; ++i) {
+
+        for (j = 0; j < array[i].size; ++j) {
+
+          if (array[i].array[j].content.size && array[i].array[j].content.array) {
+            status = f_memory_array_resize(0, sizeof(f_range_t), (void **) &array[i].array[j].content.array, &array[i].array[j].content.used, &array[i].array[j].content.size);
+            if (F_status_is_error(status)) return status;
+          }
+
+          if (array[i].array[j].delimits.size && array[i].array[j].delimits.array) {
+            status = f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &array[i].array[j].delimits.array, &array[i].array[j].delimits.used, &array[i].array[j].delimits.size);
+            if (F_status_is_error(status)) return status;
+          }
+
+          if (array[i].array[j].variable.size && array[i].array[j].variable.array) {
+            status = f_memory_array_resize(0, sizeof(f_range_t), (void **) &array[i].array[j].variable.array, &array[i].array[j].variable.used, &array[i].array[j].variable.size);
+            if (F_status_is_error(status)) return status;
+          }
+
+          if (array[i].array[j].vocabularys.size && array[i].array[j].vocabularys.array) {
+            status = f_memory_arrays_resize(0, sizeof(f_ranges_t), (void **) &array[i].array[j].vocabularys.array, &array[i].array[j].vocabularys.used, &array[i].array[j].vocabularys.size, &f_rangess_delete_callback);
+            if (F_status_is_error(status)) return status;
+          }
+        } // for
+
+        if (array[i].size && array[i].array) {
+          status = f_memory_array_resize(0, sizeof(f_iki_eki_t), (void **) &array[i].array, &array[i].used, &array[i].size);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_iki_ekiss_delete_callback_
+
+#ifndef _di_f_iki_ekiss_destroy_callback_
+  f_status_t f_iki_ekiss_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_iki_ekis_t * const array = (f_iki_ekis_t *) void_array;
+      f_status_t status = F_okay;
+      f_number_unsigned_t j = 0;
+
+      for (f_number_unsigned_t i = start; i < stop; ++i) {
+
+        for (j = 0; j < array[i].size; ++j) {
+
+          if (array[i].array[j].content.size && array[i].array[j].content.array) {
+            status = f_memory_array_adjust(0, sizeof(f_range_t), (void **) &array[i].array[j].content.array, &array[i].array[j].content.used, &array[i].array[j].content.size);
+            if (F_status_is_error(status)) return status;
+          }
+
+          if (array[i].array[j].delimits.size && array[i].array[j].delimits.array) {
+            status = f_memory_array_adjust(0, sizeof(f_number_unsigned_t), (void **) &array[i].array[j].delimits.array, &array[i].array[j].delimits.used, &array[i].array[j].delimits.size);
+            if (F_status_is_error(status)) return status;
+          }
+
+          if (array[i].array[j].variable.size && array[i].array[j].variable.array) {
+            status = f_memory_array_adjust(0, sizeof(f_range_t), (void **) &array[i].array[j].variable.array, &array[i].array[j].variable.used, &array[i].array[j].variable.size);
+            if (F_status_is_error(status)) return status;
+          }
+
+          if (array[i].array[j].vocabularys.size && array[i].array[j].vocabularys.array) {
+            status = f_memory_arrays_adjust(0, sizeof(f_ranges_t), (void **) &array[i].array[j].vocabularys.array, &array[i].array[j].vocabularys.used, &array[i].array[j].vocabularys.size, &f_rangess_destroy_callback);
+            if (F_status_is_error(status)) return status;
+          }
+        } // for
+
+        if (array[i].size && array[i].array) {
+          status = f_memory_array_adjust(0, sizeof(f_iki_eki_t), (void **) &array[i].array, &array[i].used, &array[i].size);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_iki_ekiss_destroy_callback_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/c/iki/eki.h b/level_0/f_iki/c/iki/eki.h
new file mode 100644 (file)
index 0000000..5e5196e
--- /dev/null
@@ -0,0 +1,293 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Defines data to be used for/by iki related functionality.
+ *
+ * This is auto-included by iki.h and should not need to be explicitly included.
+ */
+#ifndef _F_iki_eki_h
+#define _F_iki_eki_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Delete the IKI EKI data.
+ *
+ * @param data
+ *   The IKI EKI data to delete.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *   Errors (with error bit) from: f_memory_arrays_resize().
+ *
+ * @see f_memory_array_resize()
+ * @see f_memory_arrays_resize()
+ */
+#ifndef _di_f_iki_eki_delete_
+  extern f_status_t f_iki_eki_delete(f_iki_eki_t * const data);
+#endif // _di_f_iki_eki_delete_
+
+/**
+ * Destroy the IKI EKI data.
+ *
+ * @param data
+ *   The IKI EKI data to destroy.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_adjust().
+ *   Errors (with error bit) from: f_memory_arrays_adjust().
+ *
+ * @see f_memory_array_adjust()
+ * @see f_memory_arrays_adjust()
+ */
+#ifndef _di_f_iki_eki_destroy_
+  extern f_status_t f_iki_eki_destroy(f_iki_eki_t * const data);
+#endif // _di_f_iki_eki_destroy_
+
+/**
+ * Append the single source iki_eki onto the destination.
+ *
+ * @param source
+ *   The source iki_eki to append.
+ * @param destination
+ *   The destination iki_ekis the source is appended onto.
+ *
+ * @return
+ *   F_okay on success.
+ *   F_data_not on success, but there is nothing to append (size == 0).
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_append().
+ *   Errors (with error bit) from: f_memory_array_increase().
+ *   Errors (with error bit) from: f_ranges_append_all().
+ *   Errors (with error bit) from: f_rangess_append_all().
+ *
+ * @see f_memory_array_append()
+ * @see f_memory_array_increase()
+ * @see f_ranges_append_all()
+ * @see f_rangess_append_all()
+ */
+#ifndef _di_f_iki_ekis_append_
+  extern f_status_t f_iki_ekis_append(const f_iki_eki_t source, f_iki_ekis_t * const destination);
+#endif // _di_f_iki_ekis_append_
+
+/**
+ * Append the source iki_ekis onto the destination.
+ *
+ * @param source
+ *   The source iki_ekis to append.
+ * @param destination
+ *   The destination iki_ekis the source is appended onto.
+ *
+ * @return
+ *   F_okay on success.
+ *   F_data_not on success, but there is nothing to append (size == 0).
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_append().
+ *   Errors (with error bit) from: f_memory_array_increase_by().
+ *   Errors (with error bit) from: f_ranges_append_all().
+ *   Errors (with error bit) from: f_rangess_append_all().
+ *
+ * @see f_memory_array_append()
+ * @see f_memory_array_increase_by()
+ * @see f_ranges_append_all()
+ * @see f_rangess_append_all()
+ */
+#ifndef _di_f_iki_ekis_append_all_
+  extern f_status_t f_iki_ekis_append_all(const f_iki_ekis_t source, f_iki_ekis_t * const destination);
+#endif // _di_f_iki_ekis_append_all_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_resize() for an f_iki_ekis_t structure.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *   Errors (with error bit) from: f_memory_arrays_resize().
+ *
+ * @see f_memory_array_resize()
+ * @see f_memory_arrays_resize()
+ */
+#ifndef _di_f_iki_ekis_delete_callback_
+  extern f_status_t f_iki_ekis_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_iki_ekis_delete_callback_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_adjust() for an f_iki_ekis_t structure.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_adjust().
+ *   Errors (with error bit) from: f_memory_arrays_adjust().
+ *
+ * @see f_memory_array_adjust()
+ * @see f_memory_arrays_adjust()
+ */
+#ifndef _di_f_iki_ekis_destroy_callback_
+  extern f_status_t f_iki_ekis_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_iki_ekis_destroy_callback_
+
+/**
+ * Append the single source iki_ekis onto the destination.
+ *
+ * @param source
+ *   The source iki_ekis to append.
+ * @param destination
+ *   The destination ranges the source is appended onto.
+ *
+ * @return
+ *   F_okay on success.
+ *   F_data_not on success, but there is nothing to append (size == 0).
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_increase().
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *
+ * @see f_memory_array_increase()
+ * @see f_memory_array_resize()
+ */
+#ifndef _di_f_iki_ekiss_append_
+  extern f_status_t f_iki_ekiss_append(const f_iki_ekis_t source, f_iki_ekiss_t * const destination);
+#endif // _di_f_iki_ekiss_append_
+
+/**
+ * Append the source iki_ekiss onto the destination.
+ *
+ * @param source
+ *   The source iki_ekiss to append.
+ * @param destination
+ *   The destination ranges the source is appended onto.
+ *
+ * @return
+ *   F_okay on success.
+ *   F_data_not on success, but there is nothing to append (size == 0).
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_increase_by().
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *
+ * @see f_memory_array_increase_by()
+ * @see f_memory_array_resize()
+ */
+#ifndef _di_f_iki_ekiss_append_all_
+  extern f_status_t f_iki_ekiss_append_all(const f_iki_ekiss_t source, f_iki_ekiss_t * const destination);
+#endif // _di_f_iki_ekiss_append_all_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_resize() for an f_iki_ekiss_t structure.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *   Errors (with error bit) from: f_memory_arrays_resize().
+ *
+ * @see f_memory_array_resize()
+ * @see f_memory_arrays_resize()
+ */
+#ifndef _di_f_iki_ekiss_delete_callback_
+  extern f_status_t f_iki_ekiss_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_iki_ekiss_delete_callback_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_adjust() for an f_iki_ekiss_t structure.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_memory_array_adjust().
+ *   Errors (with error bit) from: f_memory_arrays_adjust().
+ *
+ * @see f_memory_array_adjust()
+ * @see f_memory_arrays_adjust()
+ */
+#ifndef _di_f_iki_ekiss_destroy_callback_
+  extern f_status_t f_iki_ekiss_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_iki_ekiss_destroy_callback_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_iki_eki_h
diff --git a/level_0/f_iki/c/iki/private-eki.c b/level_0/f_iki/c/iki/private-eki.c
new file mode 100644 (file)
index 0000000..fd200c9
--- /dev/null
@@ -0,0 +1,53 @@
+#include "../iki.h"
+#include "private-eki.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_f_iki_ekis_append_) || !defined(_di_f_iki_ekis_append_all_) || !defined(_di_f_iki_ekiss_append_all_)
+  extern f_status_t private_f_iki_ekis_append_all(const f_iki_ekis_t source, f_iki_ekis_t * const destination) {
+
+    f_status_t status = f_memory_array_increase_by(source.used, sizeof(f_iki_eki_t), (void **) &destination->array, &destination->used, &destination->size);
+    if (F_status_is_error(status)) return status;
+
+    {
+      f_number_unsigned_t j = 0;
+
+      for (f_number_unsigned_t i = 0; i < source.used; ++i, ++destination->used) {
+
+        destination->array[destination->used].content.used = 0;
+        destination->array[destination->used].delimits.used = 0;
+        destination->array[destination->used].variable.used = 0;
+        destination->array[destination->used].vocabularys.used = 0;
+
+        if (source.array[i].content.used) {
+          status = f_ranges_append_all(source.array[i].content, &destination->array[destination->used].content);
+          if (F_status_is_error(status)) return status;
+        }
+
+        for (j = 0; j < source.array[i].delimits.used; ++j) {
+
+          status = f_memory_array_append(source.array[i].delimits.array + j, sizeof(f_number_unsigned_t), (void **) &destination->array[destination->used].delimits.array, &destination->array[destination->used].delimits.used, &destination->array[destination->used].delimits.size);
+          if (F_status_is_error(status)) return status;
+        } // for
+
+        if (source.array[i].variable.used) {
+          status = f_ranges_append_all(source.array[i].variable, &destination->array[destination->used].variable);
+          if (F_status_is_error(status)) return status;
+        }
+
+        if (source.array[i].vocabularys.used) {
+          status = f_rangess_append_all(source.array[i].vocabularys, &destination->array[destination->used].vocabularys);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // !defined(_di_f_iki_ekis_append_) || !defined(_di_f_iki_ekis_append_all_) || !defined(_di_f_iki_ekiss_append_all_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/c/iki/private-eki.h b/level_0/f_iki/c/iki/private-eki.h
new file mode 100644 (file)
index 0000000..e6ee0ff
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * These are provided for internal reduction in redundant code.
+ * These should not be exposed/used outside of this project.
+ */
+#ifndef _PRIVATE_F_iki_eki_h
+#define _PRIVATE_F_iki_eki_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Private implementation for appending the iki_eki array.
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param source
+ *   The source iki_ekis to append.
+ * @param destination
+ *   The iki_ekis array the source is appended onto.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   Errors (with error bit) from: f_memory_array_append().
+ *   Errors (with error bit) from: f_memory_array_increase_by().
+ *   Errors (with error bit) from: f_ranges_append_all().
+ *   Errors (with error bit) from: f_rangess_append_all().
+ *
+ * @see f_memory_array_append()
+ * @see f_memory_array_increase_by()
+ * @see f_ranges_append_all()
+ * @see f_rangess_append_all()
+ *
+ * @see f_iki_ekiss_append()
+ * @see f_iki_ekiss_append_all()
+ */
+#if !defined(_di_f_iki_ekis_append_) || !defined(_di_f_iki_ekis_append_all_) || !defined(_di_f_iki_ekiss_append_all_)
+  extern f_status_t private_f_iki_ekis_append_all(const f_iki_ekis_t source, f_iki_ekis_t * const destination) F_attribute_visibility_internal_d;
+#endif // !defined(_di_f_iki_ekis_append_) || !defined(_di_f_iki_ekis_append_all_) || !defined(_di_f_iki_ekiss_append_all_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_F_iki_eki_h
index 3ccad0794a2eaaf73c108e6754650fda4ef4621a..05102e6aa5e794520c52397b7f4dc681adc55af9 100644 (file)
@@ -36,9 +36,9 @@ build_language c
 build_libraries -lc
 build_libraries-individual -lf_memory -lf_string -lf_type_array -lf_utf
 
-build_sources_library iki.c private-iki.c iki/common.c iki/private-data.c iki/data.c
+build_sources_library iki.c private-iki.c iki/common.c iki/private-data.c iki/private-eki.c iki/data.c iki/eki.c
 
-build_sources_headers iki.h iki/common.h iki/data.h
+build_sources_headers iki.h iki/common.h iki/data.h iki/eki.h
 
 build_script yes
 build_shared yes
index 8dc12b68cba9858a7e932f1fa3e1f7a20d4624b3..5b680636186bedcae96036561759284ec819605c 100644 (file)
@@ -30,10 +30,10 @@ build_language c
 build_libraries -lc
 build_libraries-individual -lf_memory -lf_string -lf_type_array -lf_utf
 
-build_sources_library iki.c private-iki.c iki/common.c iki/private-data.c iki/data.c
+build_sources_library iki.c private-iki.c iki/common.c iki/private-data.c iki/private-eki.c iki/data.c iki/eki.c
 build_sources_library ../../tests/unit/c/mock-iki.c
 
-build_sources_headers iki.h iki/common.h iki/data.h
+build_sources_headers iki.h iki/common.h iki/data.h iki/eki.h
 
 build_script yes
 build_shared yes
@@ -70,3 +70,5 @@ flags_library -fPIC
 # Inject mocks.
 flags -Wl,--wrap=f_memory_array_adjust
 flags -Wl,--wrap=f_memory_array_resize
+flags -Wl,--wrap=f_memory_arrays_adjust
+flags -Wl,--wrap=f_memory_arrays_resize
index 14311d2fea07b3bbe8d193067ffcf5d1c3cdda13..294b99562a4db2df6656aa1c66c0be8874c0f835 100644 (file)
@@ -25,9 +25,11 @@ build_language c
 build_libraries -lc -lcmocka
 build_libraries-individual -lf_memory -lf_string -lf_type_array -lf_utf -lf_iki
 
-build_sources_program test-iki-content_is.c test-iki-content_partial_is.c test-iki-object_is.c test-iki-object_partial_is.c test-iki-read.c
+build_sources_program test-iki-content_is.c test-iki-content_partial_is.c test-iki-eki_read.c test-iki-object_is.c test-iki-object_partial_is.c test-iki-read.c
 build_sources_program test-iki-datas_append.c test-iki-datas_append_all.c test-iki-datass_append.c test-iki-datass_append_all.c
 build_sources_program test-iki-datas_delete_callback.c test-iki-datas_destroy_callback.c test-iki-datass_delete_callback.c test-iki-datass_destroy_callback.c
+build_sources_program test-iki-ekis_append.c test-iki-ekis_append_all.c test-iki-ekiss_append.c test-iki-ekiss_append_all.c
+build_sources_program test-iki-ekis_delete_callback.c test-iki-ekis_destroy_callback.c test-iki-ekiss_delete_callback.c test-iki-ekiss_destroy_callback.c
 build_sources_program test-iki.c
 
 build_script no
index f52433354e78171e55ab8d97e9e749475bea46f9..7032378ed476662296f47972ccc610c89d9be96e 100644 (file)
@@ -24,6 +24,23 @@ f_status_t __wrap_f_memory_array_adjust(const f_number_unsigned_t length, const
   return mock_type(f_status_t);
 }
 
+f_status_t __wrap_f_memory_arrays_adjust(const f_number_unsigned_t length, const size_t width, void ** const array, f_number_unsigned_t * const used, f_number_unsigned_t * const size) {
+
+  if (mock_unwrap_f_memory) {
+    return __real_f_memory_arrays_adjust(length, width, array, used, size);
+  }
+
+  if (!array || !used || !size) return F_status_set_error(F_parameter_not);
+
+  const bool failure = mock_type(bool);
+
+  if (failure) return mock_type(f_status_t);
+
+  *size = length;
+
+  return mock_type(f_status_t);
+}
+
 f_status_t __wrap_f_memory_array_resize(const f_number_unsigned_t length, const size_t width, void ** const array, f_number_unsigned_t * const used, f_number_unsigned_t * const size) {
 
   if (mock_unwrap_f_memory) {
@@ -41,6 +58,23 @@ f_status_t __wrap_f_memory_array_resize(const f_number_unsigned_t length, const
   return mock_type(f_status_t);
 }
 
+f_status_t __wrap_f_memory_arrays_resize(const f_number_unsigned_t length, const size_t width, void ** const array, f_number_unsigned_t * const used, f_number_unsigned_t * const size) {
+
+  if (mock_unwrap_f_memory) {
+    return __real_f_memory_arrays_resize(length, width, array, used, size);
+  }
+
+  if (!array || !used || !size) return F_status_set_error(F_parameter_not);
+
+  const bool failure = mock_type(bool);
+
+  if (failure) return mock_type(f_status_t);
+
+  *size = length;
+
+  return mock_type(f_status_t);
+}
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 9946ea25319bf3cfebcc3606ee5605d81dba4dfa..1f035d327214b2c459ecb011b094b5c175edfc97 100644 (file)
@@ -35,9 +35,15 @@ extern int mock_unwrap_f_memory;
 extern f_status_t __real_f_memory_array_adjust(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
 extern f_status_t __real_f_memory_array_resize(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
 
+extern f_status_t __real_f_memory_arrays_adjust(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
+extern f_status_t __real_f_memory_arrays_resize(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
+
 extern f_status_t __wrap_f_memory_array_adjust(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
 extern f_status_t __wrap_f_memory_array_resize(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
 
+extern f_status_t __wrap_f_memory_arrays_adjust(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
+extern f_status_t __wrap_f_memory_arrays_resize(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-eki_read.c b/level_0/f_iki/tests/unit/c/test-iki-eki_read.c
new file mode 100644 (file)
index 0000000..bde259b
--- /dev/null
@@ -0,0 +1,465 @@
+#include "test-iki.h"
+#include "test-iki-eki_read.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_eki_read__parameter_checking(void **state) {
+
+  f_state_t state_data = f_state_t_initialize;
+  f_string_static_t empty = macro_f_string_static_t_initialize_1(f_string_empty_s.string, f_string_empty_s.size, f_string_empty_s.used);
+
+  {
+    f_range_t range = f_range_t_initialize;
+    f_iki_eki_t eki = f_iki_eki_t_initialize;
+
+    f_iki_eki_read(0, &range, &eki, &state_data);
+
+    assert_int_equal(state_data.status, F_status_set_error(F_parameter));
+  }
+
+  {
+    f_iki_eki_t eki = f_iki_eki_t_initialize;
+
+    f_iki_eki_read(&empty, 0, &eki, &state_data);
+
+    assert_int_equal(state_data.status, F_status_set_error(F_parameter));
+  }
+
+  {
+    f_range_t range = f_range_t_initialize;
+
+    f_iki_eki_read(&empty, &range, 0, &state_data);
+
+    assert_int_equal(state_data.status, F_status_set_error(F_parameter));
+  }
+}
+
+void test__f_iki_eki_read__returns_data_not(void **state) {
+
+  f_state_t state_data = f_state_t_initialize;
+  f_string_static_t empty = macro_f_string_static_t_initialize_1(f_string_empty_s.string, f_string_empty_s.size, f_string_empty_s.used);
+
+  {
+    f_range_t range = f_range_t_initialize;
+    f_iki_eki_t eki = f_iki_eki_t_initialize;
+
+    f_iki_eki_read(&empty, &range, &eki, &state_data);
+
+    assert_int_equal(F_status_set_fine(state_data.status), F_data_not);
+  }
+}
+
+void test__f_iki_eki_read__returns_data_not_eos(void **state) {
+
+  f_state_t state_data = f_state_t_initialize;
+  f_string_static_t ascii_a = macro_f_string_static_t_initialize_1(f_string_ascii_a_s.string, f_string_ascii_a_s.size, f_string_ascii_a_s.used);
+
+  {
+    f_range_t range = macro_f_range_t_initialize_1(f_string_ascii_a_s.used, f_string_ascii_a_s.used);
+    f_iki_eki_t eki = f_iki_eki_t_initialize;
+
+    f_iki_eki_read(&ascii_a, &range, &eki, &state_data);
+
+    assert_int_equal(F_status_set_fine(state_data.status), F_data_not_eos);
+  }
+}
+
+void test__f_iki_eki_read__returns_data_not_stop(void **state) {
+
+  f_state_t state_data = f_state_t_initialize;
+  f_string_static_t ascii_a = macro_f_string_static_t_initialize_1(f_string_ascii_a_s.string, f_string_ascii_a_s.size, f_string_ascii_a_s.used);
+
+  {
+    f_range_t range = f_range_t_initialize;
+    f_iki_eki_t eki = f_iki_eki_t_initialize;
+
+    f_iki_eki_read(&ascii_a, &range, &eki, &state_data);
+
+    assert_int_equal(F_status_set_fine(state_data.status), F_data_not_stop);
+  }
+}
+
+void test__f_iki_eki_read__works(void **state) {
+
+  mock_unwrap = 1;
+
+  f_state_t state_data = f_state_t_initialize;
+  f_string_static_t empty = macro_f_string_static_t_initialize_1(f_string_empty_s.string, f_string_empty_s.size, f_string_empty_s.used);
+  f_string_static_t ascii_a = macro_f_string_static_t_initialize_1(f_string_ascii_a_s.string, f_string_ascii_a_s.size, f_string_ascii_a_s.used);
+
+  #define _inline_macro_total_rows 34
+
+  f_string_static_t buffers[] = {
+    empty,
+    ascii_a,
+    macro_f_string_static_t_initialize_1("iki:'one'", 0, 9),
+    macro_f_string_static_t_initialize_1("Has iki:'one' two:'iki and spaces'.", 0, 35),
+    macro_f_string_static_t_initialize_1("iki:\"one\"", 0, 9),
+    macro_f_string_static_t_initialize_1("Has iki:\"one\" two:\"iki and spaces\".", 0, 35),
+    macro_f_string_static_t_initialize_1("export PATH=\"/bin:/sbin:some:'A_PATH'\"", 0, 38),
+    macro_f_string_static_t_initialize_1("export PATH=\"/bin:/sbin:some:\"A_PATH\"\"", 0, 38),
+    macro_f_string_static_t_initialize_1("This wor_ks:'hopefully'!", 0, 24),
+    macro_f_string_static_t_initialize_1("This work-s:'hopefully'!", 0, 24),
+    macro_f_string_static_t_initialize_1("This wor++ks:'hopefully'!", 0, 25),
+    macro_f_string_static_t_initialize_1("This w_-+s:'hopefully'!", 0, 23),
+    macro_f_string_static_t_initialize_1("This wor_ks:\"hopefully\"!", 0, 24),
+    macro_f_string_static_t_initialize_1("This work-s:\"hopefully\"!", 0, 24),
+    macro_f_string_static_t_initialize_1("This wor++ks:\"hopefully\"!", 0, 25),
+    macro_f_string_static_t_initialize_1("This w_-+s:\"hopefully\"!", 0, 23),
+    macro_f_string_static_t_initialize_1("IKI Content:'May have spaces\\' and quotes.'", 0, 43),
+    macro_f_string_static_t_initialize_1("IKI Content:\"May have spaces\\\" and quotes.\"", 0, 43),
+    macro_f_string_static_t_initialize_1("IKI Content:'May have spaces\\' and\" quotes.'", 0, 44),
+    macro_f_string_static_t_initialize_1("IKI Content:\"May have spaces\\\" and' quotes.\"", 0, 44),
+    macro_f_string_static_t_initialize_1("url:'https://localhost/fake-0.7.0.tar.gz?query=xx&parameter=yyy%20' end.", 0, 72),
+    macro_f_string_static_t_initialize_1("url:\"https://localhost/fake-0.7.0.tar.gz?query=xx&parameter=yyy%20\" end.", 0, 72),
+    macro_f_string_static_t_initialize_1("url:`https://localhost/fake-0.7.0.tar.gz?query=xx&parameter=yyy%20` end.", 0, 72),
+    macro_f_string_static_t_initialize_1("iki:'\"`' iki:'`\"'", 0, 17),
+    macro_f_string_static_t_initialize_1("[iki]:\"one\"", 0, 11),
+    macro_f_string_static_t_initialize_1("[iki]\\:\"none\"", 0, 13),
+    macro_f_string_static_t_initialize_1("[eki:iki]:\"one\"", 0, 15),
+    macro_f_string_static_t_initialize_1("[[iki]]:\"none\"", 0, 14),
+    macro_f_string_static_t_initialize_1("[[iki]]:`none`", 0, 14),
+    macro_f_string_static_t_initialize_1("[iki]:`one`", 0, 11),
+    macro_f_string_static_t_initialize_1("[iki]\\:'not'", 0, 12),
+    macro_f_string_static_t_initialize_1("iki\\:'not'", 0, 10),
+    macro_f_string_static_t_initialize_1("an:iki\\:'not'", 0, 13),
+    macro_f_string_static_t_initialize_1("an:iki:'is!'", 0, 12),
+  };
+
+  const f_number_unsigned_t matches_total[] = {
+    0,
+    0,
+    1,
+    2,
+    1,
+    2,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    2,
+    1,
+    0,
+    1,
+    0,
+    0,
+    1,
+    0,
+    0,
+    0,
+    1,
+  };
+
+  const f_number_unsigned_t matches_set[] = {
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    2,
+    2,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    2,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    2,
+  };
+
+  const f_number_unsigned_t matches_each[][_inline_macro_total_rows] = {
+    { 0, 0 },
+    { 0, 0 },
+    { 1, 0 },
+    { 2, 0 },
+    { 1, 0 },
+    { 2, 0 },
+    { 1, 1 },
+    { 1, 1 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 1, 0 },
+    { 2, 0 },
+    { 1, 0 },
+    { 0, 0 },
+    { 1, 0 },
+    { 0, 0 },
+    { 0, 0 },
+    { 1, 0 },
+    { 0, 0 },
+    { 0, 0 },
+    { 0, 0 },
+    { 1, 1 },
+  };
+
+  const f_status_t statuss[] = {
+    F_data_not,
+    F_data_not_stop,
+    F_okay_stop,
+    F_okay,
+    F_okay_stop,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay_stop,
+    F_okay_stop,
+    F_okay_stop,
+    F_okay_stop,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay,
+    F_okay_stop,
+    F_data_not_stop,
+    F_okay_stop,
+    F_data_not_stop,
+    F_data_not_stop,
+    F_okay_stop,
+    F_data_not_stop,
+    F_data_not_stop,
+    F_data_not_stop,
+    F_okay_stop,
+  };
+
+  const f_range_t variables[][_inline_macro_total_rows] = {
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 8), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 12), macro_f_range_t_initialize_1(14, 33) },
+    { macro_f_range_t_initialize_1(0, 8), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 12), macro_f_range_t_initialize_1(14, 33) },
+    { macro_f_range_t_initialize_1(19, 36), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(19, 36), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 22), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 22), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 23), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 21), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 22), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 22), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 23), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 21), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 42), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 42), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 43), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 43), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 66), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 66), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 66), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 7), macro_f_range_t_initialize_1(9, 16) },
+    { macro_f_range_t_initialize_1(0, 10), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 14), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 10), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 11), f_range_t_initialize },
+  };
+
+  const f_range_t vocabularys[][_inline_macro_total_rows] = {
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 2), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 6), macro_f_range_t_initialize_1(14, 16) },
+    { macro_f_range_t_initialize_1(0, 2), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 6), macro_f_range_t_initialize_1(14, 16) },
+    { macro_f_range_t_initialize_1(19, 22),  macro_f_range_t_initialize_1(24, 27) },
+    { macro_f_range_t_initialize_1(19, 22),  macro_f_range_t_initialize_1(24, 27) },
+    { macro_f_range_t_initialize_1(5, 10), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 10), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 11), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 9), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 10), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 10), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 11), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 9), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 10), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 10), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 10), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(4, 10), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 2), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 2), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 2), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 2), macro_f_range_t_initialize_1(9, 11) },
+    { macro_f_range_t_initialize_1(1, 3), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(1, 3), macro_f_range_t_initialize_1(5, 7) },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(1, 3), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 1), macro_f_range_t_initialize_1(3, 5) },
+  };
+
+  const f_range_t contents[][_inline_macro_total_rows] = {
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 7), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(9, 11), macro_f_range_t_initialize_1(19, 32) },
+    { macro_f_range_t_initialize_1(5, 7), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(9, 11), macro_f_range_t_initialize_1(19, 32) },
+    { macro_f_range_t_initialize_1(30, 35), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(30, 35), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(13, 21), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(13, 21), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(14, 22), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(12, 20), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(13, 21), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(13, 21), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(14, 22), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(12, 20), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(13, 41), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(13, 41), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(13, 42), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(13, 42), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 65), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 65), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 65), f_range_t_initialize },
+    { macro_f_range_t_initialize_1(5, 6), macro_f_range_t_initialize_1(14, 15) },
+    { macro_f_range_t_initialize_1(7, 9), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(11, 13), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(7, 9), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(8, 10), f_range_t_initialize },
+  };
+
+  for (uint8_t i = 0; i < _inline_macro_total_rows; ++i) {
+
+    f_range_t range = macro_f_range_t_initialize_2(buffers[i].used);
+    f_iki_eki_t eki = f_iki_eki_t_initialize;
+    f_number_unsigned_t j = 0;
+
+    f_iki_eki_read(&buffers[i], &range, &eki, &state_data);
+
+    assert_int_equal(state_data.status, statuss[i]);
+
+    if (matches_set[i]) {
+      if (matches_each[i][0] == 2) {
+        f_iki_eki_read(&buffers[i], &range, &eki, &state_data);
+
+        assert_int_equal(F_status_is_error_not(state_data.status) ? 0 : 1, 0);
+      }
+
+      if (matches_set[i] > 1) {
+        if (matches_each[i][1] == 2) {
+          f_iki_eki_read(&buffers[i], &range, &eki, &state_data);
+
+          assert_int_equal(F_status_is_error_not(state_data.status) ? 0 : 1, 0);
+        }
+      }
+    }
+
+    if (matches_set[i]) {
+      assert_int_equal(eki.variable.used, matches_total[i]);
+      assert_int_equal(eki.vocabularys.used, matches_total[i]);
+      assert_int_equal(eki.content.used, matches_total[i]);
+
+      if (matches_each[i][0]) {
+        assert_int_equal(eki.variable.array[0].start, variables[i][0].start);
+        assert_int_equal(eki.variable.array[0].stop, variables[i][0].stop);
+
+        assert_int_equal(eki.vocabularys.array[0].array[0].start, vocabularys[i][j].start);
+        assert_int_equal(eki.vocabularys.array[0].array[0].stop, vocabularys[i][j].stop);
+        ++j;
+
+        if (matches_each[i][0] > 1) {
+          assert_int_equal(eki.vocabularys.array[1].array[0].start, vocabularys[i][j].start);
+          assert_int_equal(eki.vocabularys.array[1].array[0].stop, vocabularys[i][j].stop);
+          ++j;
+        }
+
+        if (matches_set[i] > 1 && matches_each[i][1]) {
+          assert_int_equal(eki.vocabularys.array[0].array[1].start, vocabularys[i][j].start);
+          assert_int_equal(eki.vocabularys.array[0].array[1].stop, vocabularys[i][j].stop);
+          ++j;
+
+          if (matches_each[i][1] > 1) {
+            assert_int_equal(eki.vocabularys.array[1].array[1].start, vocabularys[i][j].start);
+            assert_int_equal(eki.vocabularys.array[1].array[1].stop, vocabularys[i][j].stop);
+            ++j;
+          }
+        }
+
+        assert_int_equal(eki.content.array[0].start, contents[i][0].start);
+        assert_int_equal(eki.content.array[0].stop, contents[i][0].stop);
+      }
+    }
+
+    f_iki_eki_delete(&eki);
+
+    eki.variable.used = 0;
+    eki.vocabularys.used = 0;
+    eki.content.used = 0;
+    eki.delimits.used = 0;
+  } // for
+
+  #undef _inline_macro_total_rows
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-eki_read.h b/level_0/f_iki/tests/unit/c/test-iki-eki_read.h
new file mode 100644 (file)
index 0000000..cc53cca
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the iki project.
+ */
+#ifndef _TEST__F_iki_eki_read_h
+#define _TEST__F_iki_eki_read_h
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_iki_eki_read()
+ */
+extern void test__f_iki_eki_read__parameter_checking(void **state);
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_iki_eki_read()
+ */
+extern void test__f_iki_eki_read__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_data_not_eos.
+ *
+ * @see f_iki_eki_read()
+ */
+extern void test__f_iki_eki_read__returns_data_not_eos(void **state);
+
+/**
+ * Test that function returns F_data_not_stop.
+ *
+ * @see f_iki_eki_read()
+ */
+extern void test__f_iki_eki_read__returns_data_not_stop(void **state);
+
+/**
+ * Test that function works.
+ *
+ * @see f_iki_eki_read()
+ */
+extern void test__f_iki_eki_read__works(void **state);
+
+#endif // _TEST__F_iki_eki_read_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekis_append.c b/level_0/f_iki/tests/unit/c/test-iki-ekis_append.c
new file mode 100644 (file)
index 0000000..f8155af
--- /dev/null
@@ -0,0 +1,130 @@
+#include "test-iki.h"
+#include "test-iki-ekis_append.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_ekis_append__works(void **state) {
+
+  const f_number_unsigned_t length = 5;
+  f_iki_eki_t source = f_iki_eki_t_initialize;
+  f_iki_ekis_t destination = f_iki_ekis_t_initialize;
+
+  {
+    f_number_unsigned_t i = 1;
+
+    f_status_t status = f_memory_array_resize(length, sizeof(f_range_t), (void **) &source.content.array, &source.content.used, &source.content.size);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.content.size, length);
+
+    status = f_memory_array_resize(length, sizeof(f_number_unsigned_t), (void **) &source.delimits.array, &source.delimits.used, &source.delimits.size);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.delimits.size, length);
+
+    status = f_memory_array_resize(length, sizeof(f_range_t), (void **) &source.variable.array, &source.variable.used, &source.variable.size);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.variable.size, length);
+
+    status = f_memory_arrays_resize(length, sizeof(f_ranges_t), (void **) &source.vocabularys.array, &source.vocabularys.used, &source.vocabularys.size, &f_rangess_delete_callback);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.vocabularys.size, length);
+
+    for (; source.content.used < length; ++i) {
+
+      source.content.array[source.content.used].start = i - 1;
+      source.content.array[source.content.used++].stop = i;
+    } // for
+
+    for (; source.delimits.used < length; ++i) {
+      source.delimits.array[source.delimits.used++] = i;
+    } // for
+
+    for (; source.variable.used < length; ++i) {
+
+      source.variable.array[source.variable.used].start = i - 1;
+      source.variable.array[source.variable.used++].stop = i;
+    } // for
+
+    for (; source.vocabularys.used < length; ++i) {
+
+      status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &source.vocabularys.array[source.vocabularys.used].array, &source.vocabularys.array[source.vocabularys.used].used, &source.vocabularys.array[source.vocabularys.used].size);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.vocabularys.array[source.vocabularys.used].size, 1);
+
+      // The used property must be set to ensure append works for child elements to be appended.
+      source.vocabularys.array[source.vocabularys.used].used = 1;
+      source.vocabularys.array[source.vocabularys.used].array[0].start = i - 1;
+      source.vocabularys.array[source.vocabularys.used++].array[0].stop = i;
+    } // for
+  }
+
+  {
+    const f_status_t status = f_iki_ekis_append(source, &destination);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(destination.used, 1);
+    assert_int_equal(destination.array[0].content.used, source.content.used);
+    assert_int_equal(destination.array[0].delimits.used, source.delimits.used);
+    assert_int_equal(destination.array[0].variable.used, source.variable.used);
+    assert_int_equal(destination.array[0].vocabularys.used, source.vocabularys.used);
+
+    for (f_number_unsigned_t i = 0; i < length; ++i) {
+
+      assert_int_equal(destination.array[0].content.array[i].start, source.content.array[i].start);
+      assert_int_equal(destination.array[0].content.array[i].stop, source.content.array[i].stop);
+
+      assert_int_equal(destination.array[0].delimits.array[i], source.delimits.array[i]);
+
+      assert_int_equal(destination.array[0].variable.array[i].start, source.variable.array[i].start);
+      assert_int_equal(destination.array[0].variable.array[i].stop, source.variable.array[i].stop);
+
+      assert_int_equal(destination.array[0].vocabularys.array[i].used, 1);
+
+      assert_int_equal(destination.array[0].vocabularys.array[i].array[0].start, source.vocabularys.array[i].array[0].start);
+      assert_int_equal(destination.array[0].vocabularys.array[i].array[0].stop, source.vocabularys.array[i].array[0].stop);
+    } // for
+  }
+
+  free((void *) source.content.array);
+  free((void *) source.delimits.array);
+  free((void *) source.variable.array);
+
+  for (f_number_unsigned_t i = 0; i < source.vocabularys.used; ++i) {
+    free((void *) source.vocabularys.array[i].array);
+  } // for
+
+  free((void *) source.vocabularys.array);
+
+  free((void *) destination.array[0].content.array);
+  free((void *) destination.array[0].delimits.array);
+  free((void *) destination.array[0].variable.array);
+
+  for (f_number_unsigned_t i = 0; i < destination.array[0].vocabularys.used; ++i) {
+    free((void *) destination.array[0].vocabularys.array[i].array);
+  } // for
+
+  free((void *) destination.array[0].vocabularys.array);
+
+  free((void *) destination.array);
+}
+
+void test__f_iki_ekis_append__parameter_checking(void **state) {
+
+  const f_iki_eki_t data = f_iki_eki_t_initialize;
+
+  {
+    const f_status_t status = f_iki_ekis_append(data, 0);
+
+    assert_int_equal(status, F_status_set_error(F_parameter));
+  }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekis_append.h b/level_0/f_iki/tests/unit/c/test-iki-ekis_append.h
new file mode 100644 (file)
index 0000000..01a8243
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_iki_ekis_append_h
+#define _TEST__F_iki_ekis_append_h
+
+/**
+ * Test that the function works.
+ *
+ * @see f_iki_ekis_append()
+ */
+extern void test__f_iki_ekis_append__works(void **state);
+
+/**
+ * Test that the function correctly fails on invalid parameter.
+ *
+ * @see f_iki_ekis_append()
+ */
+extern void test__f_iki_ekis_append__parameter_checking(void **state);
+
+#endif // _TEST__F_iki_ekis_append_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekis_append_all.c b/level_0/f_iki/tests/unit/c/test-iki-ekis_append_all.c
new file mode 100644 (file)
index 0000000..2459a2d
--- /dev/null
@@ -0,0 +1,180 @@
+#include "test-iki.h"
+#include "test-iki-ekis_append_all.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_ekis_append_all__returns_data_not(void **state) {
+
+  const int length = 5;
+  f_iki_ekis_t source = f_iki_ekis_t_initialize;
+  f_iki_ekis_t destination = f_iki_ekis_t_initialize;
+
+  {
+    const f_status_t status = f_memory_array_resize(length, sizeof(f_iki_eki_t), (void **) &source.array, &source.used, &source.size);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.used, 0);
+    assert_int_equal(source.size, length);
+  }
+
+  {
+    const f_status_t status = f_iki_ekis_append_all(source, &destination);
+
+    assert_int_equal(status, F_data_not);
+    assert_int_equal(destination.used, 0);
+    assert_int_equal(destination.size, 0);
+    assert_null(destination.array);
+  }
+
+  free((void *) source.array);
+}
+
+void test__f_iki_ekis_append_all__parameter_checking(void **state) {
+
+  const f_iki_ekis_t data = f_iki_ekis_t_initialize;
+
+  {
+    const f_status_t status = f_iki_ekis_append_all(data, 0);
+
+    assert_int_equal(status, F_status_set_error(F_parameter));
+  }
+}
+
+void test__f_iki_ekis_append_all__works(void **state) {
+
+  const int length = 5;
+  f_iki_ekis_t source = f_iki_ekis_t_initialize;
+  f_iki_ekis_t destination = f_iki_ekis_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(2, sizeof(f_iki_eki_t), (void **) &source.array, &source.used, &source.size);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.size, 2);
+
+    f_number_unsigned_t i = 1;
+    f_number_unsigned_t j = 0;
+
+    for (; j < 2; ++j) {
+
+      status = f_memory_array_resize(length, sizeof(f_range_t), (void **) &source.array[j].content.array, &source.array[j].content.used, &source.array[j].content.size);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.array[j].content.size, length);
+
+      status = f_memory_array_resize(length, sizeof(f_number_unsigned_t), (void **) &source.array[j].delimits.array, &source.array[j].delimits.used, &source.array[j].delimits.size);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.array[j].delimits.size, length);
+
+      status = f_memory_array_resize(length, sizeof(f_range_t), (void **) &source.array[j].variable.array, &source.array[j].variable.used, &source.array[j].variable.size);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.array[j].variable.size, length);
+
+      status = f_memory_arrays_resize(length, sizeof(f_ranges_t), (void **) &source.array[j].vocabularys.array, &source.array[j].vocabularys.used, &source.array[j].vocabularys.size, &f_rangess_delete_callback);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.array[j].vocabularys.size, length);
+
+      for (; source.array[j].content.used < length; ++i) {
+
+        source.array[j].content.array[source.array[j].content.used].start = i - 1;
+        source.array[j].content.array[source.array[j].content.used++].stop = i;
+      } // for
+
+      for (; source.array[j].delimits.used < length; ++i) {
+
+        source.array[j].delimits.array[source.array[j].delimits.used++] = i;
+      } // for
+
+      for (; source.array[j].variable.used < length; ++i) {
+
+        source.array[j].variable.array[source.array[j].variable.used].start = i - 1;
+        source.array[j].variable.array[source.array[j].variable.used++].stop = i;
+      } // for
+
+      for (; source.array[j].vocabularys.used < length; ++i) {
+
+        status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &source.array[j].vocabularys.array[source.array[j].vocabularys.used].array, &source.array[j].vocabularys.array[source.array[j].vocabularys.used].used, &source.array[j].vocabularys.array[source.array[j].vocabularys.used].size);
+
+        assert_int_equal(status, F_okay);
+        assert_int_equal(source.array[j].vocabularys.array[source.array[j].vocabularys.used].size, 1);
+
+        // The used property must be set to ensure append works for child elements to be appended.
+        source.array[j].vocabularys.array[source.array[j].vocabularys.used].used = 1;
+        source.array[j].vocabularys.array[source.array[j].vocabularys.used].array[0].start = i - 1;
+        source.array[j].vocabularys.array[source.array[j].vocabularys.used++].array[0].stop = i;
+      } // for
+    } // for
+
+    source.used = 2;
+  }
+
+  {
+    const f_status_t status = f_iki_ekis_append_all(source, &destination);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(destination.used, source.used);
+    assert_int_equal(destination.size, source.used);
+
+    for (f_number_unsigned_t j = 0; j < 2; ++j) {
+
+      assert_int_equal(destination.array[j].content.used, source.array[j].content.used);
+      assert_int_equal(destination.array[j].delimits.used, source.array[j].delimits.used);
+      assert_int_equal(destination.array[j].variable.used, source.array[j].variable.used);
+      assert_int_equal(destination.array[j].vocabularys.used, source.array[j].vocabularys.used);
+
+      for (f_number_unsigned_t i = 0; i < length; ++i) {
+
+        assert_int_equal(destination.array[j].content.array[i].start, source.array[j].content.array[i].start);
+        assert_int_equal(destination.array[j].content.array[i].stop, source.array[j].content.array[i].stop);
+
+        assert_int_equal(destination.array[j].delimits.array[i], source.array[j].delimits.array[i]);
+
+        assert_int_equal(destination.array[j].variable.array[i].start, source.array[j].variable.array[i].start);
+        assert_int_equal(destination.array[j].variable.array[i].stop, source.array[j].variable.array[i].stop);
+
+        assert_int_equal(destination.array[j].vocabularys.array[i].used, 1);
+
+        assert_int_equal(destination.array[j].vocabularys.array[i].array[0].start, source.array[j].vocabularys.array[i].array[0].start);
+        assert_int_equal(destination.array[j].vocabularys.array[i].array[0].stop, source.array[j].vocabularys.array[i].array[0].stop);
+      } // for
+    } // for
+  }
+
+  for (f_number_unsigned_t i = 0; i < source.used; ++i) {
+
+    free((void *) source.array[i].content.array);
+    free((void *) source.array[i].delimits.array);
+    free((void *) source.array[i].variable.array);
+
+    for (f_number_unsigned_t j = 0; j < source.array[i].vocabularys.used; ++j) {
+      free((void *) source.array[i].vocabularys.array[j].array);
+    } // for
+
+    free((void *) source.array[i].vocabularys.array);
+  } // for
+
+  for (f_number_unsigned_t i = 0; i < destination.used; ++i) {
+
+    free((void *) destination.array[i].content.array);
+    free((void *) destination.array[i].delimits.array);
+    free((void *) destination.array[i].variable.array);
+
+    for (f_number_unsigned_t j = 0; j < destination.array[i].vocabularys.used; ++j) {
+      free((void *) destination.array[i].vocabularys.array[j].array);
+    } // for
+
+    free((void *) destination.array[i].vocabularys.array);
+  } // for
+
+  free((void *) source.array);
+  free((void *) destination.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekis_append_all.h b/level_0/f_iki/tests/unit/c/test-iki-ekis_append_all.h
new file mode 100644 (file)
index 0000000..4c75778
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_iki_ekis_append_all_h
+#define _TEST__F_iki_ekis_append_all_h
+
+/**
+ * Test that the function returns F_data_not when asked to copy an empty structure.
+ *
+ * @see f_iki_ekis_append_all()
+ */
+extern void test__f_iki_ekis_append_all__returns_data_not(void **state);
+
+/**
+ * Test that the function correctly fails on invalid parameter.
+ *
+ * @see f_iki_ekis_append_all()
+ */
+extern void test__f_iki_ekis_append_all__parameter_checking(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_iki_ekis_append_all()
+ */
+extern void test__f_iki_ekis_append_all__works(void **state);
+
+#endif // _TEST__F_iki_ekis_append_all_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekis_delete_callback.c b/level_0/f_iki/tests/unit/c/test-iki-ekis_delete_callback.c
new file mode 100644 (file)
index 0000000..c509dab
--- /dev/null
@@ -0,0 +1,141 @@
+#include "test-iki.h"
+#include "test-iki-ekis_delete_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_ekis_delete_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_range_t base = macro_f_range_t_initialize_1(1, 0);
+  f_range_t base_array[] = { base };
+  f_ranges_t bases = { .array = base_array, .used = 0, .size = 1 };
+
+  f_ranges_t content = bases;
+  f_number_unsigned_t delimit_array[] = { 0 };
+  f_number_unsigneds_t delimits = { .array = delimit_array, .used = 0, .size = 1 };
+  f_ranges_t variable = bases;
+  f_ranges_t vocabulary_array[] = { bases };
+  f_rangess_t vocabularys = { .array = vocabulary_array, .used = 0, .size = 1 };
+
+  f_iki_eki_t data = { .content = content, .delimits = delimits, .variable = variable, .vocabularys = vocabularys };
+  f_iki_eki_t data_array[] = { data };
+
+  {
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekis_delete_callback(0, 1, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  data_array[0].content = content;
+  data_array[0].delimits = delimits;
+  data_array[0].variable = variable;
+  data_array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekis_delete_callback(0, 1, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  data_array[0].content = content;
+  data_array[0].delimits = delimits;
+  data_array[0].variable = variable;
+  data_array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekis_delete_callback(0, 1, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  data_array[0].content = content;
+  data_array[0].delimits = delimits;
+  data_array[0].variable = variable;
+  data_array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_arrays_resize, true);
+    will_return(__wrap_f_memory_arrays_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekis_delete_callback(0, 1, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+}
+
+void test__f_iki_ekis_delete_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  const f_number_unsigned_t length = 1;
+
+  f_iki_ekis_t datas = f_iki_ekis_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(1, sizeof(f_iki_eki_t), (void **) &datas.array, &datas.used, &datas.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datas.array[0].content.array, &datas.array[0].content.used, &datas.array[0].content.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_number_unsigned_t), (void **) &datas.array[0].delimits.array, &datas.array[0].delimits.used, &datas.array[0].delimits.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datas.array[0].variable.array, &datas.array[0].variable.used, &datas.array[0].variable.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_arrays_resize(1, sizeof(f_ranges_t), (void **) &datas.array[0].vocabularys.array, &datas.array[0].vocabularys.used, &datas.array[0].vocabularys.size, &f_rangess_delete_callback);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datas.array[0].vocabularys.array[0].array, &datas.array[0].vocabularys.array[0].used, &datas.array[0].vocabularys.array[0].size);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    const f_status_t status = f_iki_ekis_delete_callback(0, length, (void *) datas.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datas.array[0].content.size, 0);
+    assert_int_equal(datas.array[0].delimits.size, 0);
+    assert_int_equal(datas.array[0].variable.size, 0);
+    assert_int_equal(datas.array[0].vocabularys.size, 0);
+  }
+
+  free((void *) datas.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekis_delete_callback.h b/level_0/f_iki/tests/unit/c/test-iki-ekis_delete_callback.h
new file mode 100644 (file)
index 0000000..9ad9a5f
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_iki__ekis_delete_callback
+#define _TEST__F_iki__ekis_delete_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_iki_ekis_delete_callback()
+ */
+extern void test__f_iki_ekis_delete_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_iki_ekis_delete_callback()
+ */
+extern void test__f_iki_ekis_delete_callback__works(void **state);
+
+#endif // _TEST__F_iki__ekis_delete_callback
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekis_destroy_callback.c b/level_0/f_iki/tests/unit/c/test-iki-ekis_destroy_callback.c
new file mode 100644 (file)
index 0000000..28a2b8a
--- /dev/null
@@ -0,0 +1,141 @@
+#include "test-iki.h"
+#include "test-iki-ekis_destroy_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_ekis_destroy_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_range_t base = macro_f_range_t_initialize_1(1, 0);
+  f_range_t base_array[] = { base };
+  f_ranges_t bases = { .array = base_array, .used = 0, .size = 1 };
+
+  f_ranges_t content = bases;
+  f_number_unsigned_t delimit_array[] = { 0 };
+  f_number_unsigneds_t delimits = { .array = delimit_array, .used = 0, .size = 1 };
+  f_ranges_t variable = bases;
+  f_ranges_t vocabulary_array[] = { bases };
+  f_rangess_t vocabularys = { .array = vocabulary_array, .used = 0, .size = 1 };
+
+  f_iki_eki_t data = { .content = content, .delimits = delimits, .variable = variable, .vocabularys = vocabularys };
+  f_iki_eki_t data_array[] = { data };
+
+  {
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekis_destroy_callback(0, 1, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  data_array[0].content = content;
+  data_array[0].delimits = delimits;
+  data_array[0].variable = variable;
+  data_array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekis_destroy_callback(0, 1, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  data_array[0].content = content;
+  data_array[0].delimits = delimits;
+  data_array[0].variable = variable;
+  data_array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekis_destroy_callback(0, 1, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  data_array[0].content = content;
+  data_array[0].delimits = delimits;
+  data_array[0].variable = variable;
+  data_array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_arrays_adjust, true);
+    will_return(__wrap_f_memory_arrays_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekis_destroy_callback(0, 1, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+}
+
+void test__f_iki_ekis_destroy_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  const f_number_unsigned_t length = 1;
+
+  f_iki_ekis_t datas = f_iki_ekis_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(1, sizeof(f_iki_eki_t), (void **) &datas.array, &datas.used, &datas.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datas.array[0].content.array, &datas.array[0].content.used, &datas.array[0].content.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_number_unsigned_t), (void **) &datas.array[0].delimits.array, &datas.array[0].delimits.used, &datas.array[0].delimits.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datas.array[0].variable.array, &datas.array[0].variable.used, &datas.array[0].variable.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_arrays_resize(1, sizeof(f_ranges_t), (void **) &datas.array[0].vocabularys.array, &datas.array[0].vocabularys.used, &datas.array[0].vocabularys.size, &f_rangess_delete_callback);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datas.array[0].vocabularys.array[0].array, &datas.array[0].vocabularys.array[0].used, &datas.array[0].vocabularys.array[0].size);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    const f_status_t status = f_iki_ekis_destroy_callback(0, length, (void *) datas.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datas.array[0].content.size, 0);
+    assert_int_equal(datas.array[0].delimits.size, 0);
+    assert_int_equal(datas.array[0].variable.size, 0);
+    assert_int_equal(datas.array[0].vocabularys.size, 0);
+  }
+
+  free((void *) datas.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekis_destroy_callback.h b/level_0/f_iki/tests/unit/c/test-iki-ekis_destroy_callback.h
new file mode 100644 (file)
index 0000000..7ac49d1
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_iki__ekis_destroy_callback
+#define _TEST__F_iki__ekis_destroy_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_iki_ekis_destroy_callback()
+ */
+extern void test__f_iki_ekis_destroy_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_iki_ekis_destroy_callback()
+ */
+extern void test__f_iki_ekis_destroy_callback__works(void **state);
+
+#endif // _TEST__F_iki__ekis_destroy_callback
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekiss_append.c b/level_0/f_iki/tests/unit/c/test-iki-ekiss_append.c
new file mode 100644 (file)
index 0000000..a275d13
--- /dev/null
@@ -0,0 +1,185 @@
+#include "test-iki.h"
+#include "test-iki-ekiss_append.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_ekiss_append__works(void **state) {
+
+  const int length = 5;
+  const int length_outer = 2;
+  f_iki_ekis_t source = f_iki_ekis_t_initialize;
+  f_iki_ekiss_t destination = f_iki_ekiss_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(length_outer, sizeof(f_iki_eki_t), (void **) &source.array, &source.used, &source.size);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.size, length_outer);
+
+    f_number_unsigned_t i = 1;
+
+    for (f_number_unsigned_t j = 0; j < length_outer; ++j) {
+
+      status = f_memory_array_resize(length, sizeof(f_range_t), (void **) &source.array[j].content.array, &source.array[j].content.used, &source.array[j].content.size);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.array[j].content.size, length);
+
+      status = f_memory_array_resize(length, sizeof(f_number_unsigned_t), (void **) &source.array[j].delimits.array, &source.array[j].delimits.used, &source.array[j].delimits.size);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.array[j].delimits.size, length);
+
+      status = f_memory_array_resize(length, sizeof(f_range_t), (void **) &source.array[j].variable.array, &source.array[j].variable.used, &source.array[j].variable.size);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.array[j].variable.size, length);
+
+      status = f_memory_arrays_resize(length, sizeof(f_ranges_t), (void **) &source.array[j].vocabularys.array, &source.array[j].vocabularys.used, &source.array[j].vocabularys.size, &f_rangess_delete_callback);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.array[j].vocabularys.size, length);
+
+      for (; source.array[j].content.used < length; ++i) {
+
+        source.array[j].content.array[source.array[j].content.used].start = i - 1;
+        source.array[j].content.array[source.array[j].content.used++].stop = i;
+      } // for
+
+      for (; source.array[j].delimits.used < length; ++i) {
+
+        source.array[j].delimits.array[source.array[j].delimits.used++] = i;
+      } // for
+
+      for (; source.array[j].variable.used < length; ++i) {
+
+        source.array[j].variable.array[source.array[j].variable.used].start = i - 1;
+        source.array[j].variable.array[source.array[j].variable.used++].stop = i;
+      } // for
+
+      for (; source.array[j].vocabularys.used < length; ++i) {
+
+        status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &source.array[j].vocabularys.array[source.array[j].vocabularys.used].array, &source.array[j].vocabularys.array[source.array[j].vocabularys.used].used, &source.array[j].vocabularys.array[source.array[j].vocabularys.used].size);
+
+        assert_int_equal(status, F_okay);
+        assert_int_equal(source.array[j].vocabularys.array[source.array[j].vocabularys.used].size, 1);
+
+        // The used property must be set to ensure append works for child elements to be appended.
+        source.array[j].vocabularys.array[source.array[j].vocabularys.used].used = 1;
+        source.array[j].vocabularys.array[source.array[j].vocabularys.used].array[0].start = i - 1;
+        source.array[j].vocabularys.array[source.array[j].vocabularys.used++].array[0].stop = i;
+      } // for
+    } // for
+
+    source.used = length_outer;
+  }
+
+  {
+    const f_status_t status = f_iki_ekiss_append(source, &destination);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(destination.used, 1);
+    assert_int_equal(destination.array[0].used, source.used);
+
+    for (f_number_unsigned_t j = 0; j < destination.used; ++j) {
+
+      assert_int_equal(destination.array[0].array[j].content.used, source.array[j].content.used);
+      assert_int_equal(destination.array[0].array[j].delimits.used, source.array[j].delimits.used);
+      assert_int_equal(destination.array[0].array[j].variable.used, source.array[j].variable.used);
+      assert_int_equal(destination.array[0].array[j].vocabularys.used, source.array[j].vocabularys.used);
+
+      for (f_number_unsigned_t i = 0; i < length; ++i) {
+
+        assert_int_equal(destination.array[0].array[j].content.array[i].start, source.array[j].content.array[i].start);
+        assert_int_equal(destination.array[0].array[j].content.array[i].stop, source.array[j].content.array[i].stop);
+
+        assert_int_equal(destination.array[0].array[j].delimits.array[i], source.array[j].delimits.array[i]);
+
+        assert_int_equal(destination.array[0].array[j].variable.array[i].start, source.array[j].variable.array[i].start);
+        assert_int_equal(destination.array[0].array[j].variable.array[i].stop, source.array[j].variable.array[i].stop);
+
+        assert_int_equal(destination.array[0].array[j].vocabularys.array[i].used, 1);
+
+        assert_int_equal(destination.array[0].array[j].vocabularys.array[i].array[0].start, source.array[j].vocabularys.array[i].array[0].start);
+        assert_int_equal(destination.array[0].array[j].vocabularys.array[i].array[0].stop, source.array[j].vocabularys.array[i].array[0].stop);
+      } // for
+    } // for
+  }
+
+  for (f_number_unsigned_t i = 0; i < source.used; ++i) {
+
+    free((void *) source.array[i].content.array);
+    free((void *) source.array[i].delimits.array);
+    free((void *) source.array[i].variable.array);
+
+    for (f_number_unsigned_t j = 0; j < source.array[i].vocabularys.used; ++j) {
+      free((void *) source.array[i].vocabularys.array[j].array);
+    } // for
+
+    free((void *) source.array[i].vocabularys.array);
+  } // for
+
+  for (f_number_unsigned_t j = 0; j < destination.used; ++j) {
+
+    for (f_number_unsigned_t i = 0; i < destination.array[j].used; ++i) {
+
+      free((void *) destination.array[j].array[i].content.array);
+      free((void *) destination.array[j].array[i].delimits.array);
+      free((void *) destination.array[j].array[i].variable.array);
+
+      for (f_number_unsigned_t k = 0; k < destination.array[j].array[i].vocabularys.used; ++k) {
+        free((void *) destination.array[j].array[i].vocabularys.array[k].array);
+      } // for
+
+      free((void *) destination.array[j].array[i].vocabularys.array);
+    } // for
+
+    free((void *) destination.array[j].array);
+  } // for
+
+  free((void *) source.array);
+  free((void *) destination.array);
+}
+
+void test__f_iki_ekiss_append__returns_data_not(void **state) {
+
+  const int length = 5;
+  f_iki_ekis_t source = f_iki_ekiss_t_initialize;
+  f_iki_ekiss_t destination = f_iki_ekiss_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(length, sizeof(f_iki_eki_t), (void **) &source.array, &source.used, &source.size);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.used, 0);
+    assert_int_equal(source.size, length);
+  }
+
+  {
+    const f_status_t status = f_iki_ekiss_append(source, &destination);
+
+    assert_int_equal(status, F_data_not);
+    assert_int_equal(destination.used, 0);
+    assert_int_equal(destination.size, 0);
+    assert_null(destination.array);
+  }
+
+  free((void *) source.array);
+}
+
+void test__f_iki_ekiss_append__parameter_checking(void **state) {
+
+  f_iki_ekis_t data = f_iki_ekis_t_initialize;
+
+  {
+    const f_status_t status = f_iki_ekiss_append(data, 0);
+
+    assert_int_equal(status, F_status_set_error(F_parameter));
+  }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekiss_append.h b/level_0/f_iki/tests/unit/c/test-iki-ekiss_append.h
new file mode 100644 (file)
index 0000000..20716de
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_iki_ekiss_append_h
+#define _TEST__F_iki_ekiss_append_h
+
+/**
+ * Test that the function works.
+ *
+ * @see f_iki_ekiss_append()
+ */
+extern void test__f_iki_ekiss_append__works(void **state);
+
+/**
+ * Test that the function returns F_data_not when asked to copy an empty structure.
+ *
+ * @see f_iki_ekiss_append()
+ */
+extern void test__f_iki_ekiss_append__returns_data_not(void **state);
+
+/**
+ * Test that the function correctly fails on invalid parameter.
+ *
+ * @see f_iki_ekiss_append()
+ */
+extern void test__f_iki_ekiss_append__parameter_checking(void **state);
+
+#endif // _TEST__F_iki_ekiss_append_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekiss_append_all.c b/level_0/f_iki/tests/unit/c/test-iki-ekiss_append_all.c
new file mode 100644 (file)
index 0000000..1cc8c8f
--- /dev/null
@@ -0,0 +1,201 @@
+#include "test-iki.h"
+#include "test-iki-ekiss_append_all.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_ekiss_append_all__returns_data_not(void **state) {
+
+  const int length = 5;
+  f_iki_ekiss_t source = f_iki_ekiss_t_initialize;
+  f_iki_ekiss_t destination = f_iki_ekiss_t_initialize;
+
+  {
+    const f_status_t status = f_memory_arrays_resize(length, sizeof(f_iki_eki_t), (void **) &source.array, &source.used, &source.size, &f_iki_ekis_delete_callback);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.used, 0);
+    assert_int_equal(source.size, length);
+  }
+
+  {
+    const f_status_t status = f_iki_ekiss_append_all(source, &destination);
+
+    assert_int_equal(status, F_data_not);
+    assert_int_equal(destination.used, 0);
+    assert_int_equal(destination.size, 0);
+    assert_null(destination.array);
+  }
+
+  free((void *) source.array);
+}
+
+void test__f_iki_ekiss_append_all__parameter_checking(void **state) {
+
+  const f_iki_ekiss_t data = f_iki_ekiss_t_initialize;
+
+  {
+    const f_status_t status = f_iki_ekiss_append_all(data, 0);
+
+    assert_int_equal(status, F_status_set_error(F_parameter));
+  }
+}
+
+void test__f_iki_ekiss_append_all__works(void **state) {
+
+  const int length = 5;
+  const int length_inner = 2;
+  const int length_outer = 2;
+  f_iki_ekiss_t source = f_iki_ekiss_t_initialize;
+  f_iki_ekiss_t destination = f_iki_ekiss_t_initialize;
+
+  {
+    f_status_t status = f_memory_arrays_resize(length_outer, sizeof(f_iki_eki_t), (void **) &source.array, &source.used, &source.size, &f_iki_ekis_delete_callback);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(source.size, length_outer);
+
+    f_number_unsigned_t i = 1;
+    f_number_unsigned_t j = 0;
+
+    for (; source.used < length_outer; ++source.used) {
+
+      status = f_memory_array_resize(length_inner, sizeof(f_iki_eki_t), (void **) &source.array[source.used].array, &source.array[source.used].used, &source.array[source.used].size);
+
+      assert_int_equal(status, F_okay);
+      assert_int_equal(source.array[source.used].size, length_inner);
+
+      for (j = 0; j < length_inner; ++j) {
+
+        status = f_memory_array_resize(length, sizeof(f_range_t), (void **) &source.array[source.used].array[j].content.array, &source.array[source.used].array[j].content.used, &source.array[source.used].array[j].content.size);
+
+        assert_int_equal(status, F_okay);
+        assert_int_equal(source.array[source.used].array[j].content.size, length);
+
+        status = f_memory_array_resize(length, sizeof(f_number_unsigned_t), (void **) &source.array[source.used].array[j].delimits.array, &source.array[source.used].array[j].delimits.used, &source.array[source.used].array[j].delimits.size);
+
+        assert_int_equal(status, F_okay);
+        assert_int_equal(source.array[source.used].array[j].delimits.size, length);
+
+        status = f_memory_array_resize(length, sizeof(f_range_t), (void **) &source.array[source.used].array[j].variable.array, &source.array[source.used].array[j].variable.used, &source.array[source.used].array[j].variable.size);
+
+        assert_int_equal(status, F_okay);
+        assert_int_equal(source.array[source.used].array[j].variable.size, length);
+
+        status = f_memory_arrays_resize(length, sizeof(f_ranges_t), (void **) &source.array[source.used].array[j].vocabularys.array, &source.array[source.used].array[j].vocabularys.used, &source.array[source.used].array[j].vocabularys.size, &f_rangess_delete_callback);
+
+        assert_int_equal(status, F_okay);
+        assert_int_equal(source.array[source.used].array[j].vocabularys.size, length);
+
+        for (; source.array[source.used].array[j].content.used < length; ++i) {
+
+          source.array[source.used].array[j].content.array[source.array[source.used].array[j].content.used].start = i - 1;
+          source.array[source.used].array[j].content.array[source.array[source.used].array[j].content.used++].stop = i;
+        } // for
+
+        for (; source.array[source.used].array[j].delimits.used < length; ++i) {
+          source.array[source.used].array[j].delimits.array[source.array[source.used].array[j].delimits.used++] = i;
+        } // for
+
+        for (; source.array[source.used].array[j].variable.used < length; ++i) {
+
+          source.array[source.used].array[j].variable.array[source.array[source.used].array[j].variable.used].start = i - 1;
+          source.array[source.used].array[j].variable.array[source.array[source.used].array[j].variable.used++].stop = i;
+        } // for
+
+        for (; source.array[source.used].array[j].vocabularys.used < length; ++i) {
+
+          status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &source.array[source.used].array[j].vocabularys.array[source.array[source.used].array[j].vocabularys.used].array, &source.array[source.used].array[j].vocabularys.array[source.array[source.used].array[j].vocabularys.used].used, &source.array[source.used].array[j].vocabularys.array[source.array[source.used].array[j].vocabularys.used].size);
+
+          assert_int_equal(status, F_okay);
+          assert_int_equal(source.array[source.used].array[j].vocabularys.array[source.array[source.used].array[j].vocabularys.used].size, 1);
+
+          // The used property must be set to ensure append works for child elements to be appended.
+          source.array[source.used].array[j].vocabularys.array[source.array[source.used].array[j].vocabularys.used].used = 1;
+          source.array[source.used].array[j].vocabularys.array[source.array[source.used].array[j].vocabularys.used].array[0].start = i - 1;
+          source.array[source.used].array[j].vocabularys.array[source.array[source.used].array[j].vocabularys.used++].array[0].stop = i;
+        } // for
+      } // for
+
+      source.array[source.used].used = length_inner;
+    } // for
+  }
+
+  {
+    const f_status_t status = f_iki_ekiss_append_all(source, &destination);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(destination.used, source.used);
+
+    for (f_number_unsigned_t k = 0; k < length_outer; ++k) {
+
+      for (f_number_unsigned_t j = 0; j < length_inner; ++j) {
+
+        assert_int_equal(destination.array[k].array[j].content.used, source.array[k].array[j].content.used);
+        assert_int_equal(destination.array[k].array[j].delimits.used, source.array[k].array[j].delimits.used);
+        assert_int_equal(destination.array[k].array[j].variable.used, source.array[k].array[j].variable.used);
+        assert_int_equal(destination.array[k].array[j].vocabularys.used, source.array[k].array[j].vocabularys.used);
+
+        for (f_number_unsigned_t i = 0; i < length; ++i) {
+
+          assert_int_equal(destination.array[k].array[j].content.array[i].start, source.array[k].array[j].content.array[i].start);
+          assert_int_equal(destination.array[k].array[j].content.array[i].stop, source.array[k].array[j].content.array[i].stop);
+
+          assert_int_equal(destination.array[k].array[j].delimits.array[i], source.array[k].array[j].delimits.array[i]);
+
+          assert_int_equal(destination.array[k].array[j].variable.array[i].start, source.array[k].array[j].variable.array[i].start);
+          assert_int_equal(destination.array[k].array[j].variable.array[i].stop, source.array[k].array[j].variable.array[i].stop);
+
+          assert_int_equal(destination.array[k].array[j].vocabularys.array[i].used, 1);
+
+          assert_int_equal(destination.array[k].array[j].vocabularys.array[i].array[0].start, source.array[k].array[j].vocabularys.array[i].array[0].start);
+          assert_int_equal(destination.array[k].array[j].vocabularys.array[i].array[0].stop, source.array[k].array[j].vocabularys.array[i].array[0].stop);
+        } // for
+      } // for
+    } // for
+  }
+
+  for (f_number_unsigned_t j = 0; j < source.used; ++j) {
+
+    for (f_number_unsigned_t i = 0; i < source.array[j].used; ++i) {
+
+      free((void *) source.array[j].array[i].content.array);
+      free((void *) source.array[j].array[i].delimits.array);
+      free((void *) source.array[j].array[i].variable.array);
+
+      for (f_number_unsigned_t k = 0; k < source.array[j].array[i].vocabularys.used; ++k) {
+        free((void *) source.array[j].array[i].vocabularys.array[k].array);
+      } // for
+
+      free((void *) source.array[j].array[i].vocabularys.array);
+    } // for
+
+    free((void *) source.array[j].array);
+  } // for
+
+  for (f_number_unsigned_t j = 0; j < destination.used; ++j) {
+
+    for (f_number_unsigned_t i = 0; i < destination.array[j].used; ++i) {
+
+      free((void *) destination.array[j].array[i].content.array);
+      free((void *) destination.array[j].array[i].delimits.array);
+      free((void *) destination.array[j].array[i].variable.array);
+
+      for (f_number_unsigned_t k = 0; k < destination.array[j].array[i].vocabularys.used; ++k) {
+        free((void *) destination.array[j].array[i].vocabularys.array[k].array);
+      } // for
+
+      free((void *) destination.array[j].array[i].vocabularys.array);
+    } // for
+
+    free((void *) destination.array[j].array);
+  } // for
+
+  free((void *) source.array);
+  free((void *) destination.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekiss_append_all.h b/level_0/f_iki/tests/unit/c/test-iki-ekiss_append_all.h
new file mode 100644 (file)
index 0000000..c3a16d3
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_iki_ekiss_append_all_h
+#define _TEST__F_iki_ekiss_append_all_h
+
+/**
+ * Test that the function returns F_data_not when asked to copy an empty structure.
+ *
+ * @see f_iki_ekiss_append_all()
+ */
+extern void test__f_iki_ekiss_append_all__returns_data_not(void **state);
+
+/**
+ * Test that the function correctly fails on invalid parameter.
+ *
+ * @see f_iki_ekiss_append_all()
+ */
+extern void test__f_iki_ekiss_append_all__parameter_checking(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_iki_ekiss_append_all()
+ */
+extern void test__f_iki_ekiss_append_all__works(void **state);
+
+#endif // _TEST__F_iki_ekiss_append_all_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekiss_delete_callback.c b/level_0/f_iki/tests/unit/c/test-iki-ekiss_delete_callback.c
new file mode 100644 (file)
index 0000000..c305149
--- /dev/null
@@ -0,0 +1,173 @@
+#include "test-iki.h"
+#include "test-iki-ekiss_delete_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_ekiss_delete_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_range_t base = macro_f_range_t_initialize_1(1, 0);
+  f_range_t base_array[] = { base };
+  f_ranges_t bases = { .array = base_array, .used = 0, .size = 1 };
+
+  f_ranges_t content = bases;
+  f_number_unsigned_t delimit_array[] = { 0 };
+  f_number_unsigneds_t delimits = { .array = delimit_array, .used = 0, .size = 1 };
+  f_ranges_t variable = bases;
+  f_ranges_t vocabulary_array[] = { bases };
+  f_rangess_t vocabularys = { .array = vocabulary_array, .used = 0, .size = 1 };
+
+  f_iki_eki_t data = { .content = content, .delimits = delimits, .variable = variable, .vocabularys = vocabularys };
+  f_iki_eki_t data_array[] = { data };
+  f_iki_ekis_t datas = { .array = data_array, .used = 1, .size = 1 };
+  f_iki_ekis_t datas_array[] = { datas };
+
+  {
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_delete_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  datas_array[0].size = 1;
+  datas_array[0].array[0].content = content;
+  datas_array[0].array[0].delimits = delimits;
+  datas_array[0].array[0].variable = variable;
+  datas_array[0].array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_delete_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  datas_array[0].size = 1;
+  datas_array[0].array[0].content = content;
+  datas_array[0].array[0].delimits = delimits;
+  datas_array[0].array[0].variable = variable;
+  datas_array[0].array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_delete_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  datas_array[0].size = 1;
+  datas_array[0].array[0].content = content;
+  datas_array[0].array[0].delimits = delimits;
+  datas_array[0].array[0].variable = variable;
+  datas_array[0].array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_arrays_resize, true);
+    will_return(__wrap_f_memory_arrays_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_delete_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  datas_array[0].size = 1;
+  datas_array[0].array[0].content = content;
+  datas_array[0].array[0].delimits = delimits;
+  datas_array[0].array[0].variable = variable;
+  datas_array[0].array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, false);
+    will_return(__wrap_f_memory_array_resize, F_okay);
+
+    will_return(__wrap_f_memory_arrays_resize, false);
+    will_return(__wrap_f_memory_arrays_resize, F_okay);
+
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_delete_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+}
+
+void test__f_iki_ekiss_delete_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  const f_number_unsigned_t length = 1;
+
+  f_iki_ekiss_t datass = f_iki_ekiss_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(length, sizeof(f_iki_ekis_t), (void **) &datass.array, &datass.used, &datass.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_iki_eki_t), (void **) &datass.array[0].array, &datass.array[0].used, &datass.array[0].size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datass.array[0].array[0].content.array, &datass.array[0].array[0].content.used, &datass.array[0].array[0].content.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_number_unsigned_t), (void **) &datass.array[0].array[0].delimits.array, &datass.array[0].array[0].delimits.used, &datass.array[0].array[0].delimits.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datass.array[0].array[0].variable.array, &datass.array[0].array[0].variable.used, &datass.array[0].array[0].variable.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_arrays_resize(1, sizeof(f_ranges_t), (void **) &datass.array[0].array[0].vocabularys.array, &datass.array[0].array[0].vocabularys.used, &datass.array[0].array[0].vocabularys.size, &f_rangess_delete_callback);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datass.array[0].array[0].vocabularys.array[0].array, &datass.array[0].array[0].vocabularys.array[0].used, &datass.array[0].array[0].vocabularys.array[0].size);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    const f_status_t status = f_iki_ekiss_delete_callback(0, length, (void *) datass.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datass.array[0].size, 0);
+  }
+
+  free((void *) datass.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekiss_delete_callback.h b/level_0/f_iki/tests/unit/c/test-iki-ekiss_delete_callback.h
new file mode 100644 (file)
index 0000000..cc51088
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_iki__ekiss_delete_callback
+#define _TEST__F_iki__ekiss_delete_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_iki_ekiss_delete_callback()
+ */
+extern void test__f_iki_ekiss_delete_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_iki_ekiss_delete_callback()
+ */
+extern void test__f_iki_ekiss_delete_callback__works(void **state);
+
+#endif // _TEST__F_iki__ekiss_delete_callback
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekiss_destroy_callback.c b/level_0/f_iki/tests/unit/c/test-iki-ekiss_destroy_callback.c
new file mode 100644 (file)
index 0000000..9ae2110
--- /dev/null
@@ -0,0 +1,173 @@
+#include "test-iki.h"
+#include "test-iki-ekiss_destroy_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_ekiss_destroy_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_range_t base = macro_f_range_t_initialize_1(1, 0);
+  f_range_t base_array[] = { base };
+  f_ranges_t bases = { .array = base_array, .used = 0, .size = 1 };
+
+  f_ranges_t content = bases;
+  f_number_unsigned_t delimit_array[] = { 0 };
+  f_number_unsigneds_t delimits = { .array = delimit_array, .used = 0, .size = 1 };
+  f_ranges_t variable = bases;
+  f_ranges_t vocabulary_array[] = { bases };
+  f_rangess_t vocabularys = { .array = vocabulary_array, .used = 0, .size = 1 };
+
+  f_iki_eki_t data = { .content = content, .delimits = delimits, .variable = variable, .vocabularys = vocabularys };
+  f_iki_eki_t data_array[] = { data };
+  f_iki_ekis_t datas = { .array = data_array, .used = 1, .size = 1 };
+  f_iki_ekis_t datas_array[] = { datas };
+
+  {
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_destroy_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  datas_array[0].size = 1;
+  datas_array[0].array[0].content = content;
+  datas_array[0].array[0].delimits = delimits;
+  datas_array[0].array[0].variable = variable;
+  datas_array[0].array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_destroy_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  datas_array[0].size = 1;
+  datas_array[0].array[0].content = content;
+  datas_array[0].array[0].delimits = delimits;
+  datas_array[0].array[0].variable = variable;
+  datas_array[0].array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_destroy_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  datas_array[0].size = 1;
+  datas_array[0].array[0].content = content;
+  datas_array[0].array[0].delimits = delimits;
+  datas_array[0].array[0].variable = variable;
+  datas_array[0].array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_arrays_adjust, true);
+    will_return(__wrap_f_memory_arrays_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_destroy_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  datas_array[0].size = 1;
+  datas_array[0].array[0].content = content;
+  datas_array[0].array[0].delimits = delimits;
+  datas_array[0].array[0].variable = variable;
+  datas_array[0].array[0].vocabularys = vocabularys;
+
+  {
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, false);
+    will_return(__wrap_f_memory_array_adjust, F_okay);
+
+    will_return(__wrap_f_memory_arrays_adjust, false);
+    will_return(__wrap_f_memory_arrays_adjust, F_okay);
+
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_iki_ekiss_destroy_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+}
+
+void test__f_iki_ekiss_destroy_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  const f_number_unsigned_t length = 1;
+
+  f_iki_ekiss_t datass = f_iki_ekiss_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(length, sizeof(f_iki_ekis_t), (void **) &datass.array, &datass.used, &datass.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_iki_eki_t), (void **) &datass.array[0].array, &datass.array[0].used, &datass.array[0].size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datass.array[0].array[0].content.array, &datass.array[0].array[0].content.used, &datass.array[0].array[0].content.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_number_unsigned_t), (void **) &datass.array[0].array[0].delimits.array, &datass.array[0].array[0].delimits.used, &datass.array[0].array[0].delimits.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datass.array[0].array[0].variable.array, &datass.array[0].array[0].variable.used, &datass.array[0].array[0].variable.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_arrays_resize(1, sizeof(f_ranges_t), (void **) &datass.array[0].array[0].vocabularys.array, &datass.array[0].array[0].vocabularys.used, &datass.array[0].array[0].vocabularys.size, &f_rangess_delete_callback);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_range_t), (void **) &datass.array[0].array[0].vocabularys.array[0].array, &datass.array[0].array[0].vocabularys.array[0].used, &datass.array[0].array[0].vocabularys.array[0].size);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    const f_status_t status = f_iki_ekiss_destroy_callback(0, length, (void *) datass.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datass.array[0].size, 0);
+  }
+
+  free((void *) datass.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-ekiss_destroy_callback.h b/level_0/f_iki/tests/unit/c/test-iki-ekiss_destroy_callback.h
new file mode 100644 (file)
index 0000000..4d1d3df
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_iki__ekiss_destroy_callback
+#define _TEST__F_iki__ekiss_destroy_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_iki_ekiss_destroy_callback()
+ */
+extern void test__f_iki_ekiss_destroy_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_iki_ekiss_destroy_callback()
+ */
+extern void test__f_iki_ekiss_destroy_callback__works(void **state);
+
+#endif // _TEST__F_iki__ekiss_destroy_callback
index 393d49740dfda5c479fa3722db7aed9720ac280c..3d288f5a1f6cf761508018e47bf0b991b8226f26 100644 (file)
@@ -89,6 +89,8 @@ void test__f_iki_read__works(void **state) {
   f_string_static_t empty = macro_f_string_static_t_initialize_1(f_string_empty_s.string, f_string_empty_s.size, f_string_empty_s.used);
   f_string_static_t ascii_a = macro_f_string_static_t_initialize_1(f_string_ascii_a_s.string, f_string_ascii_a_s.size, f_string_ascii_a_s.used);
 
+  #define _inline_macro_total_rows 34
+
   f_string_static_t buffers[] = {
     empty,
     ascii_a,
@@ -114,6 +116,16 @@ void test__f_iki_read__works(void **state) {
     macro_f_string_static_t_initialize_1("url:\"https://localhost/fake-0.7.0.tar.gz?query=xx&parameter=yyy%20\" end.", 0, 72),
     macro_f_string_static_t_initialize_1("url:`https://localhost/fake-0.7.0.tar.gz?query=xx&parameter=yyy%20` end.", 0, 72),
     macro_f_string_static_t_initialize_1("iki:'\"`' iki:'`\"'", 0, 17),
+    macro_f_string_static_t_initialize_1("[iki]:\"one\"", 0, 11),
+    macro_f_string_static_t_initialize_1("[iki]\\:\"none\"", 0, 13),
+    macro_f_string_static_t_initialize_1("[eki:iki]:\"one\"", 0, 15),
+    macro_f_string_static_t_initialize_1("[[iki]]:\"none\"", 0, 14),
+    macro_f_string_static_t_initialize_1("[[iki]]:`none`", 0, 14),
+    macro_f_string_static_t_initialize_1("[iki]:`one`", 0, 11),
+    macro_f_string_static_t_initialize_1("[iki]\\:'not'", 0, 12),
+    macro_f_string_static_t_initialize_1("iki\\:'not'", 0, 10),
+    macro_f_string_static_t_initialize_1("an:iki\\:'not'", 0, 13),
+    macro_f_string_static_t_initialize_1("an:iki:'is!'", 0, 12),
   };
 
   const f_number_unsigned_t matches[] = {
@@ -141,6 +153,16 @@ void test__f_iki_read__works(void **state) {
     1,
     1,
     2,
+    1,
+    0,
+    0,
+    0,
+    0,
+    1,
+    0,
+    0,
+    0,
+    1,
   };
 
   const f_status_t statuss[] = {
@@ -168,9 +190,19 @@ void test__f_iki_read__works(void **state) {
     F_okay,
     F_okay,
     F_okay,
+    F_okay_stop,
+    F_data_not_stop,
+    F_data_not_stop,
+    F_data_not_stop,
+    F_data_not_stop,
+    F_okay_stop,
+    F_data_not_stop,
+    F_data_not_stop,
+    F_data_not_stop,
+    F_okay_stop,
   };
 
-  const f_range_t variables[][24] = {
+  const f_range_t variables[][_inline_macro_total_rows] = {
     { f_range_t_initialize, f_range_t_initialize },
     { f_range_t_initialize, f_range_t_initialize },
     { macro_f_range_t_initialize_1(0, 8), f_range_t_initialize },
@@ -195,9 +227,19 @@ void test__f_iki_read__works(void **state) {
     { macro_f_range_t_initialize_1(0, 66), f_range_t_initialize },
     { macro_f_range_t_initialize_1(0, 66), f_range_t_initialize },
     { macro_f_range_t_initialize_1(0, 7), macro_f_range_t_initialize_1(9, 16) },
+    { macro_f_range_t_initialize_1(0, 10), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(0, 10), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(3, 11), f_range_t_initialize },
   };
 
-  const f_range_t vocabularys[][24] = {
+  const f_range_t vocabularys[][_inline_macro_total_rows] = {
     { f_range_t_initialize, f_range_t_initialize },
     { f_range_t_initialize, f_range_t_initialize },
     { macro_f_range_t_initialize_1(0, 2), f_range_t_initialize },
@@ -222,9 +264,19 @@ void test__f_iki_read__works(void **state) {
     { macro_f_range_t_initialize_1(0, 2), f_range_t_initialize },
     { macro_f_range_t_initialize_1(0, 2), f_range_t_initialize },
     { macro_f_range_t_initialize_1(0, 2), macro_f_range_t_initialize_1(9, 11) },
+    { macro_f_range_t_initialize_1(1, 3), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(1, 3), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(3, 5), f_range_t_initialize },
   };
 
-  const f_range_t contents[][24] = {
+  const f_range_t contents[][_inline_macro_total_rows] = {
     { f_range_t_initialize, f_range_t_initialize },
     { f_range_t_initialize, f_range_t_initialize },
     { macro_f_range_t_initialize_1(5, 7), f_range_t_initialize },
@@ -249,9 +301,19 @@ void test__f_iki_read__works(void **state) {
     { macro_f_range_t_initialize_1(5, 65), f_range_t_initialize },
     { macro_f_range_t_initialize_1(5, 65), f_range_t_initialize },
     { macro_f_range_t_initialize_1(5, 6), macro_f_range_t_initialize_1(14, 15) },
+    { macro_f_range_t_initialize_1(7, 9), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(7, 9), f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { f_range_t_initialize, f_range_t_initialize },
+    { macro_f_range_t_initialize_1(8, 10), f_range_t_initialize },
   };
 
-  for (uint8_t i = 0; i < 24; ++i) {
+  for (uint8_t i = 0; i < _inline_macro_total_rows; ++i) {
 
     f_range_t range = macro_f_range_t_initialize_2(buffers[i].used);
     f_iki_data_t iki = f_iki_data_t_initialize;
@@ -297,6 +359,8 @@ void test__f_iki_read__works(void **state) {
     iki.content.used = 0;
     iki.delimits.used = 0;
   } // for
+
+  #undef _inline_macro_total_rows
 }
 
 #ifdef __cplusplus
index f03237228a313dc32b7304a0e28de93320d3517f..fefd70e24e3e1262a699b1278916f5d5a1a72745 100644 (file)
@@ -48,6 +48,30 @@ int main(void) {
     cmocka_unit_test(test__f_iki_datass_append_all__works),
     cmocka_unit_test(test__f_iki_datass_append_all__returns_data_not),
 
+    cmocka_unit_test(test__f_iki_eki_read__returns_data_not),
+    cmocka_unit_test(test__f_iki_eki_read__returns_data_not_eos),
+    cmocka_unit_test(test__f_iki_eki_read__returns_data_not_stop),
+    cmocka_unit_test(test__f_iki_eki_read__works),
+
+    cmocka_unit_test(test__f_iki_ekis_delete_callback__fails),
+    cmocka_unit_test(test__f_iki_ekis_destroy_callback__fails),
+    cmocka_unit_test(test__f_iki_ekiss_destroy_callback__fails),
+    cmocka_unit_test(test__f_iki_ekiss_delete_callback__fails),
+
+    cmocka_unit_test(test__f_iki_ekis_delete_callback__works),
+    cmocka_unit_test(test__f_iki_ekis_destroy_callback__works),
+    cmocka_unit_test(test__f_iki_ekiss_delete_callback__works),
+    cmocka_unit_test(test__f_iki_ekiss_destroy_callback__works),
+
+    cmocka_unit_test(test__f_iki_ekis_append__works),
+    cmocka_unit_test(test__f_iki_ekis_append_all__works),
+    cmocka_unit_test(test__f_iki_ekis_append_all__returns_data_not),
+
+    cmocka_unit_test(test__f_iki_ekiss_append__works),
+    cmocka_unit_test(test__f_iki_ekiss_append__returns_data_not),
+    cmocka_unit_test(test__f_iki_ekiss_append_all__works),
+    cmocka_unit_test(test__f_iki_ekiss_append_all__returns_data_not),
+
     cmocka_unit_test(test__f_iki_object_is__returns_data_not),
     cmocka_unit_test(test__f_iki_object_is__returns_false),
     cmocka_unit_test(test__f_iki_object_is__returns_true),
@@ -78,6 +102,19 @@ int main(void) {
       cmocka_unit_test(test__f_iki_datass_append__parameter_checking),
       cmocka_unit_test(test__f_iki_datass_append_all__parameter_checking),
 
+      // f_iki_ekis_destroy_callback() doesn't use parameter checking.
+      // f_iki_ekis_delete_callback() doesn't use parameter checking.
+      // f_iki_ekiss_destroy_callback() doesn't use parameter checking.
+      // f_iki_ekiss_delete_callback() doesn't use parameter checking.
+
+      cmocka_unit_test(test__f_iki_eki_read__parameter_checking),
+
+      cmocka_unit_test(test__f_iki_ekis_append__parameter_checking),
+      cmocka_unit_test(test__f_iki_ekis_append_all__parameter_checking),
+
+      cmocka_unit_test(test__f_iki_ekiss_append__parameter_checking),
+      cmocka_unit_test(test__f_iki_ekiss_append_all__parameter_checking),
+
       // f_iki_object_is() doesn't use parameter checking.
       // f_iki_object_partial_is() doesn't use parameter checking.
 
index 24c1e1b44cb7f2ed9945a33bcadbd9cafe56fdad..d60a5271cc4a06e366c249a01ced36a79be16788 100644 (file)
 #include "test-iki-datass_append_all.h"
 #include "test-iki-datass_delete_callback.h"
 #include "test-iki-datass_destroy_callback.h"
+#include "test-iki-eki_read.h"
+#include "test-iki-ekis_append.h"
+#include "test-iki-ekis_append_all.h"
+#include "test-iki-ekis_delete_callback.h"
+#include "test-iki-ekis_destroy_callback.h"
+#include "test-iki-ekiss_append.h"
+#include "test-iki-ekiss_append_all.h"
+#include "test-iki-ekiss_delete_callback.h"
+#include "test-iki-ekiss_destroy_callback.h"
 #include "test-iki-object_is.h"
 #include "test-iki-object_partial_is.h"
 #include "test-iki-read.h"