]> Kevux Git Server - fll/commitdiff
Update: Add tests to f_iki project, perform cleanups, and fix discovered bugs.
authorKevin Day <thekevinday@gmail.com>
Fri, 4 Mar 2022 03:49:39 +0000 (21:49 -0600)
committerKevin Day <thekevinday@gmail.com>
Fri, 4 Mar 2022 03:49:39 +0000 (21:49 -0600)
19 files changed:
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/private-iki.c
level_0/f_iki/c/private-iki.h
level_0/f_iki/data/build/settings-tests [new file with mode: 0644]
level_0/f_iki/data/build/testfile [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-content_is.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-content_is.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-content_partial_is.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-content_partial_is.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-object_is.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-object_is.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-object_partial_is.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-object_partial_is.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-read.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki-read.h [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki.c [new file with mode: 0644]
level_0/f_iki/tests/unit/c/test-iki.h [new file with mode: 0644]

index 869ee0a649b182fef35fa46fca0d1154d9a60839..49c68b61de1d4d5c497fdbe0b22d1a5076713a2d 100644 (file)
@@ -12,42 +12,64 @@ extern "C" {
       if (quote.string[0] != f_iki_syntax_quote_single_s.string[0] && quote.string[0] != f_iki_syntax_quote_double_s.string[0]) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
-    const f_string_range_t range = macro_f_string_range_t_initialize(content.used);
+    if (!content.used) {
+      return F_data_not;
+    }
 
-    return private_f_iki_content_partial_is(content, range, quote.string[0]);
+    return private_f_iki_content_partial_is(content.string, content.used, quote.string[0]);
   }
 #endif // _di_f_iki_content_is_
 
 #ifndef _di_f_iki_content_partial_is_
   f_status_t f_iki_content_partial_is(const f_string_static_t content, const f_string_range_t range, const f_string_static_t quote) {
     #ifndef _di_level_0_parameter_checking_
-      if (range.start > range.stop) return F_status_set_error(F_parameter);
-      if (range.start >= content.used) return F_status_set_error(F_parameter);
       if (!quote.used) return F_status_set_error(F_parameter);
       if (quote.string[0] != f_iki_syntax_quote_single_s.string[0] && quote.string[0] != f_iki_syntax_quote_double_s.string[0]) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
-    return private_f_iki_content_partial_is(content, range, quote.string[0]);
+    if (!content.used) {
+      return F_data_not;
+    }
+
+    if (range.start > range.stop) {
+      return F_data_not_stop;
+    }
+
+    if (range.start >= content.used) {
+      return F_data_not_eos;
+    }
+
+    return private_f_iki_content_partial_is(content.string + range.start, (range.stop - range.start) + 1, quote.string[0]);
   }
 #endif // _di_f_iki_content_partial_is_
 
 #ifndef _di_f_iki_object_is_
   f_status_t f_iki_object_is(const f_string_static_t object) {
 
-    const f_string_range_t range = macro_f_string_range_t_initialize(object.used);
+    if (!object.used) {
+      return F_data_not;
+    }
 
-    return private_f_iki_object_partial_is(object, range);
+    return private_f_iki_object_partial_is(object.string, object.used);
   }
 #endif // _di_f_iki_object_is_
 
 #ifndef _di_f_iki_object_partial_is_
   f_status_t f_iki_object_partial_is(const f_string_static_t object, const f_string_range_t range) {
-    #ifndef _di_level_0_parameter_checking_
-      if (range.start > range.stop) return F_status_set_error(F_parameter);
-      if (range.start >= object.used) return F_status_set_error(F_parameter);
-    #endif // _di_level_0_parameter_checking_
 
-    return private_f_iki_object_partial_is(object, range);
+    if (!object.used) {
+      return F_data_not;
+    }
+
+    if (range.start > range.stop) {
+      return F_data_not_stop;
+    }
+
+    if (range.start >= object.used) {
+      return F_data_not_eos;
+    }
+
+    return private_f_iki_object_partial_is(object.string + range.start, (range.stop - range.start) + 1);
   }
 #endif // _di_f_iki_object_partial_is_
 
index 9e4ea022521c1301372cea66219195d8a3870b3e..fd79afb43505b21f30034048b317bd0964bf26ed 100644 (file)
@@ -35,6 +35,8 @@ extern "C" {
 /**
  * Determine if an content is a valid IKI content name.
  *
+ * The content does not include the wrapping quotes.
+ *
  * @param content
  *   The string to validate as an content name.
  * @param quote
@@ -44,6 +46,8 @@ extern "C" {
  * @return
  *   F_true on success and string is a valid content name.
  *   F_false on success and string is not a valid content name.
+ *   F_data_not on success, but the content.used is 0.
+ *
  *   F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_f_iki_content_is_
@@ -53,6 +57,8 @@ extern "C" {
 /**
  * Determine if an content, found within the given range, is a valid IKI content name.
  *
+ * The content does not include the wrapping quotes.
+ *
  * @param content
  *   The string to validate as an content name.
  * @param range
@@ -64,6 +70,9 @@ extern "C" {
  * @return
  *   F_true on success and string is a valid content name.
  *   F_false on success and string is not a valid content name.
+ *   F_data_not on success, but the content.used is 0.
+ *   F_data_not_eos on success but the start range exceeds the buffer.used.
+ *   F_data_not_stop on success but the start range exceeds the stop range.
  *
  *   F_parameter (with error bit) if a parameter is invalid.
  */
@@ -80,6 +89,7 @@ extern "C" {
  * @return
  *   F_true on success and string is a valid object name.
  *   F_false on success and string is not a valid object name.
+ *   F_data_not on success, but the object.used is 0.
  *
  *   F_parameter (with error bit) if a parameter is invalid.
  *
@@ -90,7 +100,7 @@ extern "C" {
 #endif // _di_f_iki_object_is_
 
 /**
- * Determine if an object, found within the buffer, is a valid IKI object name.
+ * Determine if an object, found within the given range, is a valid IKI object name.
  *
  * @param object
  *   The string to validate as an object name.
@@ -100,10 +110,13 @@ extern "C" {
  * @return
  *   F_true on success and string is a valid object name.
  *   F_false on success and string is not a valid object name.
+ *   F_data_not on success, but the object.used is 0.
+ *   F_data_not_eos on success but the start range exceeds the object.used.
+ *   F_data_not_stop on success but the start range exceeds the stop range.
  *
  *   F_parameter (with error bit) if a parameter is invalid.
  *
- *   Errors (with error bit) from: f_utf_is_word().
+ *   Errors (with error bit) from: f_utf_is_word_dash_plus().
  */
 #ifndef _di_f_iki_object_partial_is_
   extern f_status_t f_iki_object_partial_is(const f_string_static_t object, const f_string_range_t range);
index fb564ff0e9e9e06659bdd96543675c8ffd0e070d..c0e25aeb1cfc46200bddbd675e9a83b934aeb208 100644 (file)
@@ -93,6 +93,10 @@ extern "C" {
  */
 #ifndef _di_f_iki_delimit_t_
   typedef f_array_length_t f_iki_delimit_t;
+
+  #define f_iki_delimit_t_initialize f_array_length_t_initialize
+
+  #define macro_f_iki_delimits_t_initialize(array, size, used) macro_f_array_lengths_t_initialize(array, size, used)
 #endif // _di_f_iki_delimit_t_
 
 /**
@@ -107,6 +111,9 @@ extern "C" {
 
   #define f_iki_delimits_t_initialize f_array_lengths_t_initialize
 
+  #define macro_f_iki_delimits_t_initialize(array, size, used) macro_f_array_lengths_t_initialize(array, size, used)
+  #define macro_f_iki_delimits_t_initialize2(array, length) macro_f_array_lengths_t_initialize2(array, length)
+
   #define macro_f_iki_delimits_t_clear(delimits) macro_f_array_lengths_t_clear(delimits)
 
   #define macro_f_iki_delimits_t_resize(status, delimits, length) macro_f_array_lengths_t_resize(status, delimits, length)
@@ -133,6 +140,9 @@ extern "C" {
 
   #define f_iki_delimitss_t_initialize f_array_lengthss_t_initialize
 
+  #define macro_f_iki_delimitss_t_initialize(array, size, used) macro_f_array_lengthss_t_initialize(array, size, used)
+  #define macro_f_iki_delimitss_t_initialize2(array, length) macro_f_array_lengthss_t_initialize2(array, length)
+
   #define macro_f_iki_delimitss_t_clear(delimitss) macro_f_array_lengthss_t_clear(delimitss)
 
   #define macro_f_iki_delimitss_t_resize(status, delimitss, length) macro_f_array_lengthss_t_resize(status, delimitss, length)
@@ -147,7 +157,6 @@ extern "C" {
   #define macro_f_iki_delimitss_t_decimate_by(status, delimitss, amount) macro_f_array_lengthss_t_decimate_by(status, delimitss, amount)
 #endif // _di_f_iki_delimitss_t_
 
-
 /**
  * This holds an array of string ranges that represent the entire vocabulary name, content, and syntax.
  *
@@ -160,6 +169,9 @@ extern "C" {
 
   #define f_iki_variable_t_initialize f_string_ranges_t_initialize
 
+  #define macro_f_iki_variable_t_initialize(array, size, used) macro_f_string_ranges_t_initialize(array, size, used)
+  #define macro_f_iki_variable_t_initialize2(array, length) macro_f_string_ranges_t_initialize2(array, length)
+
   #define macro_f_iki_variable_t_clear(variable) macro_f_string_ranges_t_clear(variable)
 
   #define macro_f_iki_variable_t_resize(status, variable, new_length) macro_f_string_ranges_t_resize(status, variable, new_length)
@@ -171,6 +183,31 @@ extern "C" {
 #endif // _di_f_iki_variable_t_
 
 /**
+ * This holds an array of string ranges that represent the entire vocabulary name, content, and syntax.
+ *
+ * array: The array of variable.
+ * size:  Total amount of allocated space.
+ * used:  Total number of allocated spaces used.
+ */
+#ifndef _di_f_iki_variables_t_
+  typedef f_string_rangess_t f_iki_variables_t;
+
+  #define f_iki_variables_t_initialize f_string_rangess_t_initialize
+
+  #define macro_f_iki_variables_t_initialize(array, size, used) macro_f_string_rangess_t_initialize(array, size, used)
+  #define macro_f_iki_variables_t_initialize2(array, length) macro_f_string_rangess_t_initialize2(array, length)
+
+  #define macro_f_iki_variables_t_clear(variable) macro_f_string_rangess_t_clear(variable)
+
+  #define macro_f_iki_variables_t_resize(status, variable, new_length) macro_f_string_rangess_t_resize(status, variable, new_length)
+  #define macro_f_iki_variables_t_adjust(status, variable, new_length) macro_f_string_rangess_t_adjust(status, variable, new_length)
+
+  #define macro_f_iki_variables_t_delete_simple(variable)  macro_f_string_rangess_t_delete_simple(variable)
+  #define macro_f_iki_variables_t_destroy_simple(variable) macro_f_string_rangess_t_destroy_simple(variable)
+
+#endif // _di_f_iki_variables_t_
+
+/**
  * This holds an array of string ranges that represent the vocabulary names.
  *
  * array: The array of vocabulary names.
@@ -182,6 +219,9 @@ extern "C" {
 
   #define f_iki_vocabulary_t_initialize f_string_ranges_t_initialize
 
+  #define macro_f_iki_vocabulary_t_initialize(array, size, used) macro_f_string_ranges_t_initialize(array, size, used)
+  #define macro_f_iki_vocabulary_t_initialize2(array, length) macro_f_string_ranges_t_initialize2(array, length)
+
   #define macro_f_iki_vocabulary_t_clear(vocabulary) macro_f_string_ranges_t_clear(vocabulary)
 
   #define macro_f_iki_vocabulary_t_resize(status, vocabulary, new_length) macro_f_string_ranges_t_resize(status, vocabulary, new_length)
@@ -203,6 +243,9 @@ extern "C" {
 
   #define f_iki_vocabularys_t_initialize f_string_rangess_t_initialize
 
+  #define macro_f_iki_vocabularys_t_initialize(array, size, used) macro_f_string_rangess_t_initialize(array, size, used)
+  #define macro_f_iki_vocabularys_t_initialize2(array, length) macro_f_string_rangess_t_initialize2(array, length)
+
   #define macro_f_iki_vocabularys_t_clear(content) macro_f_string_rangess_t_clear(content)
 
   #define macro_f_iki_vocabularys_t_resize(status, content, new_length) macro_f_string_rangess_t_resize(status, content, new_length)
@@ -226,6 +269,9 @@ extern "C" {
 
   #define f_iki_content_t_initialize f_string_ranges_t_initialize
 
+  #define macro_f_iki_content_t_initialize(array, size, used) macro_f_string_ranges_t_initialize(array, size, used)
+  #define macro_f_iki_content_t_initialize2(array, length) macro_f_string_ranges_t_initialize2(array, length)
+
   #define macro_f_iki_content_t_clear(content) macro_f_string_ranges_t_clear(content)
 
   #define macro_f_iki_content_t_resize(status, content, new_length) macro_f_string_ranges_t_resize(status, content, new_length)
@@ -247,6 +293,9 @@ extern "C" {
 
   #define f_iki_contents_t_initialize f_string_rangess_t_initialize
 
+  #define macro_f_iki_contents_t_initialize(array, size, used) macro_f_string_rangess_t_initialize(array, size, used)
+  #define macro_f_iki_contents_t_initialize2(array, length) macro_f_string_rangess_t_initialize2(array, length)
+
   #define macro_f_iki_contents_t_clear(content) macro_f_string_rangess_t_clear(content)
 
   #define macro_f_iki_contents_t_resize(status, content, new_length) macro_f_string_rangess_t_resize(status, content, new_length)
@@ -279,6 +328,8 @@ extern "C" {
     f_iki_vocabulary_t_initialize, \
   }
 
+  #define macro_f_iki_data_t_initialize(content, delimits, variable, vocabulary) { content, delimits, variable, vocabulary }
+
   #define macro_f_iki_data_t_clear(data) \
     f_iki_content_t_clear(data.content) \
     f_iki_delimits_t_clear(data.delimits) \
@@ -306,6 +357,9 @@ extern "C" {
 
   #define f_fss_iki_datas_t_initialize { 0, 0, 0 }
 
+  #define macro_f_iki_datas_t_initialize(content, size, used) { array, size, used }
+  #define macro_f_iki_datas_t_initialize2(array, length) { array, length, length }
+
   #define macro_f_fss_iki_datas_t_clear(datas) macro_f_memory_structure_clear(datas)
 
   #define macro_f_fss_iki_datas_t_resize(status, datas, length) status = f_iki_datas_resize(length, &datas);
index cc4b5dc9e0eb14fa5e71df88108578ed3564b847..03a9e6c69e15678d0dadb172f4f924bbe7beafbf 100644 (file)
@@ -82,13 +82,13 @@ extern "C" {
 #endif // !defined(_di_f_iki_datas_append_) || !defined(_di_f_iki_datas_decrease_by_) || !defined(_di_f_iki_datas_increase_) || !defined(_di_f_iki_datas_increase_by_) || !defined(_di_f_iki_datas_resize_)
 
 #if !defined(_di_f_iki_content_is_) || !defined(_di_f_iki_content_partial_is_)
-  f_status_t private_f_iki_content_partial_is(const f_string_static_t buffer, const f_string_range_t range, const char quote) {
+  f_status_t private_f_iki_content_partial_is(const f_string_t buffer, const f_array_length_t length, const char quote) {
 
     f_array_length_t delimits = 0;
 
-    for (f_array_length_t i = 0; i < buffer.used; ++i) {
+    for (f_array_length_t i = 0; i < length; i += macro_f_utf_byte_width(buffer[i])) {
 
-      if (buffer.string[i] == quote) {
+      if (buffer[i] == quote) {
         if (delimits && delimits % 2) {
           delimits = 0;
 
@@ -97,7 +97,8 @@ extern "C" {
 
         return F_false;
       }
-      else if (buffer.string[i] == f_iki_syntax_slash_s.string[0]) {
+
+      if (buffer[i] == f_iki_syntax_slash_s.string[0]) {
         ++delimits;
       }
       else {
@@ -110,13 +111,13 @@ extern "C" {
 #endif // !defined(_di_f_iki_content_is_) || !defined(_di_f_iki_content_partial_is_)
 
 #if !defined(_di_f_iki_object_is_) || !defined(_di_f_iki_object_partial_is_)
-  f_status_t private_f_iki_object_partial_is(const f_string_static_t buffer, const f_string_range_t range) {
+  f_status_t private_f_iki_object_partial_is(const f_string_t buffer, const f_array_length_t length) {
 
     f_status_t status = F_none;
 
-    for (f_array_length_t i = 0; i < buffer.used; ++i) {
+    for (f_array_length_t i = 0; i < length; i += macro_f_utf_byte_width(buffer[i])) {
 
-      status = f_utf_is_word(buffer.string + i, buffer.used - i, F_false);
+      status = f_utf_is_word_dash_plus(buffer + i, length - i, F_false);
       if (F_status_is_error(status)) return status;
 
       if (status == F_false) return F_false;
index 658e96356e22cef27e4bfa5e3dca650a5b288506..9632a568208189a7e241fdc599deb20eac7486cd 100644 (file)
@@ -74,6 +74,8 @@ extern "C" {
  *
  * @param buffer
  *   The string to validate as an content name.
+ * @param length
+ *   The length of the string to validate.
  * @param range
  *   The range within the buffer that represents the content name.
  * @param quote
@@ -90,7 +92,7 @@ extern "C" {
  * @see f_iki_content_partial_is()
  */
 #if !defined(_di_f_iki_content_is_) || !defined(_di_f_iki_content_partial_is_)
-  extern f_status_t private_f_iki_content_partial_is(const f_string_static_t buffer, const f_string_range_t range, const char quote) F_attribute_visibility_internal_d;
+  extern f_status_t private_f_iki_content_partial_is(const f_string_t buffer, const f_array_length_t length, const char quote) F_attribute_visibility_internal_d;
 #endif // !defined(_di_f_iki_content_is_) || !defined(_di_f_iki_content_partial_is_)
 
 /**
@@ -100,8 +102,8 @@ extern "C" {
  *
  * @param buffer
  *   The string to validate as an object name.
- * @param range
- *   The range within the buffer that represents the object name.
+ * @param length
+ *   The length of the string to validate.
  *
  * @return
  *   F_true on success and string is a valid object name.
@@ -113,7 +115,7 @@ extern "C" {
  * @see f_iki_object_partial_is()
  */
 #if !defined(_di_f_iki_object_is_) || !defined(_di_f_iki_object_partial_is_)
-  extern f_status_t private_f_iki_object_partial_is(const f_string_static_t buffer, const f_string_range_t range) F_attribute_visibility_internal_d;
+  extern f_status_t private_f_iki_object_partial_is(const f_string_t buffer, const f_array_length_t length) F_attribute_visibility_internal_d;
 #endif // !defined(_di_f_iki_object_is_) || !defined(_di_f_iki_object_partial_is_)
 
 #ifdef __cplusplus
diff --git a/level_0/f_iki/data/build/settings-tests b/level_0/f_iki/data/build/settings-tests
new file mode 100644 (file)
index 0000000..4a1264a
--- /dev/null
@@ -0,0 +1,50 @@
+# fss-0001
+
+build_name test-f_iki
+
+version_major 0
+version_minor 5
+version_micro 9
+version_file major
+version_target major
+
+modes individual level monolithic clang test
+modes_default individual
+
+build_compiler gcc
+build_compiler-clang clang
+build_indexer ar
+build_indexer_arguments rcs
+build_language c
+build_libraries -lc -lcmocka
+build_libraries-individual -lf_memory -lf_string -lf_type_array -lf_utf -lf_iki
+build_libraries-level -lfll_0
+build_libraries-monolithic -lfll
+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 test-iki.c
+build_script no
+build_shared yes
+build_static no
+
+path_headers tests/unit/c
+path_sources tests/unit/c
+
+has_path_standard no
+preserve_path_headers no
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines
+defines -Ibuild/includes
+defines_static -Lbuild/libraries/static
+defines_shared -Lbuild/libraries/shared
+
+flags -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses
+flags-clang -Wno-logical-op-parentheses
+flags-test -fstack-protector
+flags_program -fPIE
+flags_program_shared
+flags_program_static
+flags_shared
+flags_static
diff --git a/level_0/f_iki/data/build/testfile b/level_0/f_iki/data/build/testfile
new file mode 100644 (file)
index 0000000..6e93dcd
--- /dev/null
@@ -0,0 +1,45 @@
+# fss-0005 iki-0002
+
+settings:
+  load_build yes
+  fail exit
+
+  environment LD_LIBRARY_PATH
+
+main:
+  build settings
+  build settings-tests
+
+  operate ld_library_path
+
+  if exists build/programs/shared/test-f_iki
+    shell build/programs/shared/test-f_iki
+
+  if exists build/programs/static/test-f_iki
+    shell build/programs/static/test-f_iki
+
+  if not exists build/programs/shared/test-f_iki
+  and not exists build/programs/static/test-f_iki
+    operate not_created
+
+not_created:
+  print
+  print 'context:"error"Failed to test due to being unable to find either a shared or static test binary to perform tests. context:"reset"'
+
+  exit failure
+
+ld_library_path:
+  if defined environment LD_LIBRARY_PATH
+  and defined parameter work
+    define LD_LIBRARY_PATH 'build/libraries/shared:parameter:"work:value"libraries/shared:define:"LD_LIBRARY_PATH"'
+
+  else
+  if defined environment LD_LIBRARY_PATH
+    define LD_LIBRARY_PATH 'build/libraries/shared:parameter:define:"LD_LIBRARY_PATH"'
+
+  else
+  if defined parameter work
+    define LD_LIBRARY_PATH 'build/libraries/shared:parameter:"work:value"libraries/shared'
+
+  else
+    define LD_LIBRARY_PATH build/libraries/shared
diff --git a/level_0/f_iki/tests/unit/c/test-iki-content_is.c b/level_0/f_iki/tests/unit/c/test-iki-content_is.c
new file mode 100644 (file)
index 0000000..ac93049
--- /dev/null
@@ -0,0 +1,102 @@
+#include "test-iki.h"
+#include "test-iki-content_is.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_content_is__returns_false(void **state) {
+
+  f_string_static_t content = f_string_static_t_initialize;
+
+  const f_string_static_t contents[] = {
+    macro_f_string_static_t_initialize("'false", 0, 6),
+    macro_f_string_static_t_initialize("false'", 0, 6),
+    macro_f_string_static_t_initialize("fa'l'se", 0, 7),
+    macro_f_string_static_t_initialize("f'alse", 0, 6),
+    macro_f_string_static_t_initialize("'false'", 0, 2),
+    macro_f_string_static_t_initialize("\"false", 0, 6),
+    macro_f_string_static_t_initialize("false\"", 0, 6),
+    macro_f_string_static_t_initialize("fa\"l\"se", 0, 7),
+    macro_f_string_static_t_initialize("f\"alse", 0, 6),
+    macro_f_string_static_t_initialize("\"false\"", 0, 2),
+  };
+
+  const f_string_static_t quotes[] = {
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+  };
+
+  for (uint8_t i = 0; i < 10; ++i) {
+
+    const f_status_t status = f_iki_content_is(contents[i], quotes[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_false);
+  } // for
+}
+
+#ifndef _di_level_0_parameter_checking_
+  void test__f_iki_content_is__parameter_checking(void **state) {
+
+    {
+      const f_status_t status = f_iki_content_is(f_string_empty_s, f_string_empty_s);
+
+      assert_int_equal(F_status_set_fine(status), F_parameter);
+    }
+  }
+#endif // _di_level_0_parameter_checking_
+
+void test__f_iki_content_is__returns_data_not(void **state) {
+
+  {
+    const f_status_t status = f_iki_content_is(f_string_empty_s, f_string_ascii_quote_single_s);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not);
+  }
+}
+
+void test__f_iki_content_is__returns_true(void **state) {
+
+  f_string_static_t content = f_string_static_t_initialize;
+
+  const f_string_static_t contents[] = {
+    macro_f_string_static_t_initialize("works", 0, 5),
+    macro_f_string_static_t_initialize("also works", 0, 10),
+    macro_f_string_static_t_initialize("\\'works\\'", 0, 9),
+    macro_f_string_static_t_initialize("\\'wor ks\\'", 0, 10),
+    macro_f_string_static_t_initialize("\\'work\\'s\\'", 0, 11),
+    macro_f_string_static_t_initialize("\\\"works\\\"", 0, 9),
+    macro_f_string_static_t_initialize("\\\"wor ks\\\"", 0, 10),
+    macro_f_string_static_t_initialize("\\\"work\\\"s\\\"", 0, 11),
+  };
+
+  const f_string_static_t quotes[] = {
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+  };
+
+  for (uint8_t i = 0; i < 8; ++i) {
+
+    const f_status_t status = f_iki_content_is(contents[i], quotes[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_true);
+  } // for
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-content_is.h b/level_0/f_iki/tests/unit/c/test-iki-content_is.h
new file mode 100644 (file)
index 0000000..c876cb6
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the iki project.
+ */
+#ifndef _TEST__F_iki_content_is_h
+#define _TEST__F_iki_content_is_h
+
+/**
+ * Test that function returns F_false.
+ *
+ * @see f_iki_content_is()
+ */
+extern void test__f_iki_content_is__returns_false(void **state);
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_iki_content_is()
+ */
+#ifndef _di_level_0_parameter_checking_
+  extern void test__f_iki_content_is__parameter_checking(void **state);
+#endif // _di_level_0_parameter_checking_
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_iki_content_is()
+ */
+extern void test__f_iki_content_is__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_true.
+ *
+ * @see f_iki_content_is()
+ */
+extern void test__f_iki_content_is__returns_true(void **state);
+
+#endif // _TEST__F_iki_content_is_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki-content_partial_is.c b/level_0/f_iki/tests/unit/c/test-iki-content_partial_is.c
new file mode 100644 (file)
index 0000000..96ba579
--- /dev/null
@@ -0,0 +1,155 @@
+#include "test-iki.h"
+#include "test-iki-content_partial_is.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_content_partial_is__returns_false(void **state) {
+
+  f_string_static_t content = f_string_static_t_initialize;
+
+  const f_string_static_t contents[] = {
+    macro_f_string_static_t_initialize("xxxx' falsexxxx", 0, 15),
+    macro_f_string_static_t_initialize("xxxx'falsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfalse'xxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfa'l'sexxxx", 0, 15),
+    macro_f_string_static_t_initialize("xxxxf'alsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxx'false'xxxx", 0, 15),
+    macro_f_string_static_t_initialize("xxxx\"falsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfalse\"xxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfa\"l\"sexxxx", 0, 15),
+    macro_f_string_static_t_initialize("xxxxf\"alsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxx\"false\"xxxx", 0, 15),
+  };
+
+  const f_string_range_t ranges[] = {
+    macro_f_string_range_t_initialize2(4, 10),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 10),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 5),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 10),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 5),
+  };
+
+  const f_string_static_t quotes[] = {
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+  };
+
+  for (uint8_t i = 0; i < 11; ++i) {
+
+    const f_status_t status = f_iki_content_partial_is(contents[i], ranges[i], quotes[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_false);
+  } // for
+}
+
+#ifndef _di_level_0_parameter_checking_
+  void test__f_iki_content_partial_is__parameter_checking(void **state) {
+
+    {
+      const f_string_range_t range = f_string_range_t_initialize;
+
+      const f_status_t status = f_iki_content_partial_is(f_string_empty_s, range, f_string_empty_s);
+
+      assert_int_equal(F_status_set_fine(status), F_parameter);
+    }
+  }
+#endif // _di_level_0_parameter_checking_
+
+void test__f_iki_content_partial_is__returns_data_not(void **state) {
+
+  {
+    const f_string_range_t range = f_string_range_t_initialize;
+
+    const f_status_t status = f_iki_content_partial_is(f_string_empty_s, range, f_string_ascii_quote_single_s);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not);
+  }
+}
+
+void test__f_iki_content_partial_is__returns_data_not_eos(void **state) {
+
+  {
+    const f_string_range_t range = macro_f_string_range_t_initialize2(f_string_ascii_a_s.used, f_string_ascii_a_s.used);
+
+    const f_status_t status = f_iki_content_partial_is(f_string_ascii_a_s, range, f_string_ascii_quote_single_s);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not_eos);
+  }
+}
+
+void test__f_iki_content_partial_is__returns_data_not_stop(void **state) {
+
+  {
+    f_string_range_t range = f_string_range_t_initialize;
+
+    const f_status_t status = f_iki_content_partial_is(f_string_ascii_a_s, range, f_string_ascii_quote_single_s);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not_stop);
+  }
+}
+
+void test__f_iki_content_partial_is__returns_true(void **state) {
+
+  f_string_static_t content = f_string_static_t_initialize;
+
+  const f_string_static_t contents[] = {
+    macro_f_string_static_t_initialize("xxxxworksxxxx", 0, 13),
+    macro_f_string_static_t_initialize("xxxxalso worksxxxx", 0, 18),
+    macro_f_string_static_t_initialize("xxxx\\'works\\'xxxx", 0, 17),
+    macro_f_string_static_t_initialize("xxxx\\'wor ks\\'xxxx", 0, 18),
+    macro_f_string_static_t_initialize("xxxx\\'work\\'s\\'xxxx", 0, 19),
+    macro_f_string_static_t_initialize("xxxx\\\"works\\\"xxxx", 0, 17),
+    macro_f_string_static_t_initialize("xxxx\\\"wor ks\\\"xxxx", 0, 18),
+    macro_f_string_static_t_initialize("xxxx\\\"work\\\"s\\\"xxxx", 0, 19),
+  };
+
+  const f_string_range_t ranges[] = {
+    macro_f_string_range_t_initialize2(4, 8),
+    macro_f_string_range_t_initialize2(4, 13),
+    macro_f_string_range_t_initialize2(4, 12),
+    macro_f_string_range_t_initialize2(4, 13),
+    macro_f_string_range_t_initialize2(4, 14),
+    macro_f_string_range_t_initialize2(4, 12),
+    macro_f_string_range_t_initialize2(4, 13),
+    macro_f_string_range_t_initialize2(4, 14),
+  };
+
+  const f_string_static_t quotes[] = {
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_single_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+    f_string_ascii_quote_double_s,
+  };
+
+  for (uint8_t i = 0; i < 8; ++i) {
+
+    const f_status_t status = f_iki_content_partial_is(contents[i], ranges[i], quotes[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_true);
+  } // for
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-content_partial_is.h b/level_0/f_iki/tests/unit/c/test-iki-content_partial_is.h
new file mode 100644 (file)
index 0000000..b411147
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the iki project.
+ */
+#ifndef _TEST__F_iki_content_partial_is_h
+#define _TEST__F_iki_content_partial_is_h
+
+/**
+ * Test that function returns F_false.
+ *
+ * @see f_iki_content_partial_is()
+ */
+extern void test__f_iki_content_partial_is__returns_false(void **state);
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_iki_content_partial_is()
+ */
+#ifndef _di_level_0_parameter_checking_
+  extern void test__f_iki_content_partial_is__parameter_checking(void **state);
+#endif // _di_level_0_parameter_checking_
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_iki_content_partial_is()
+ */
+extern void test__f_iki_content_partial_is__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_data_not_eos.
+ *
+ * @see f_iki_content_partial_is()
+ */
+extern void test__f_iki_content_partial_is__returns_data_not_eos(void **state);
+
+/**
+ * Test that function returns F_data_not_stop.
+ *
+ * @see f_iki_content_partial_is()
+ */
+extern void test__f_iki_content_partial_is__returns_data_not_stop(void **state);
+
+/**
+ * Test that function returns F_true.
+ *
+ * @see f_iki_content_partial_is()
+ */
+extern void test__f_iki_content_partial_is__returns_true(void **state);
+
+#endif // _TEST__F_iki_content_partial_is_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki-object_is.c b/level_0/f_iki/tests/unit/c/test-iki-object_is.c
new file mode 100644 (file)
index 0000000..0abc946
--- /dev/null
@@ -0,0 +1,68 @@
+#include "test-iki.h"
+#include "test-iki-object_is.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_object_is__returns_false(void **state) {
+
+  f_string_static_t object = f_string_static_t_initialize;
+
+  const f_string_static_t objects[] = {
+    macro_f_string_static_t_initialize("fa lse", 0, 6),
+    macro_f_string_static_t_initialize("filse@", 0, 6),
+    macro_f_string_static_t_initialize("fa;lse", 0, 6),
+    macro_f_string_static_t_initialize("/false", 0, 6),
+    macro_f_string_static_t_initialize("'false", 0, 6),
+    macro_f_string_static_t_initialize("false'", 0, 6),
+    macro_f_string_static_t_initialize("fa'l'se", 0, 7),
+    macro_f_string_static_t_initialize("f'alse", 0, 6),
+    macro_f_string_static_t_initialize("'false'", 0, 7),
+    macro_f_string_static_t_initialize("\"false", 0, 7),
+    macro_f_string_static_t_initialize("false\"", 0, 7),
+    macro_f_string_static_t_initialize("fa\"l\"se", 0, 7),
+    macro_f_string_static_t_initialize("f\"alse", 0, 6),
+    macro_f_string_static_t_initialize("'false'", 0, 7),
+  };
+
+  for (uint8_t i = 0; i < 14; ++i) {
+
+    const f_status_t status = f_iki_object_is(objects[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_false);
+  } // for
+}
+
+void test__f_iki_object_is__returns_data_not(void **state) {
+
+  {
+    const f_status_t status = f_iki_object_is(f_string_empty_s);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not);
+  }
+}
+
+void test__f_iki_object_is__returns_true(void **state) {
+
+  f_string_static_t object = f_string_static_t_initialize;
+
+  const f_string_static_t objects[] = {
+    macro_f_string_static_t_initialize("works", 0, 5),
+    macro_f_string_static_t_initialize("wor_ks", 0, 6),
+    macro_f_string_static_t_initialize("work-s", 0, 6),
+    macro_f_string_static_t_initialize("wor++ks", 0, 7),
+    macro_f_string_static_t_initialize("w_-+s", 0, 5),
+  };
+
+  for (uint8_t i = 0; i < 5; ++i) {
+
+    const f_status_t status = f_iki_object_is(objects[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_true);
+  } // for
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-object_is.h b/level_0/f_iki/tests/unit/c/test-iki-object_is.h
new file mode 100644 (file)
index 0000000..95a075c
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the iki project.
+ */
+#ifndef _TEST__F_iki_object_is_h
+#define _TEST__F_iki_object_is_h
+
+/**
+ * Test that function returns F_false.
+ *
+ * @see f_iki_object_is()
+ */
+extern void test__f_iki_object_is__returns_false(void **state);
+
+// f_iki_object_is() doesn't use parameter checking.
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_iki_object_is()
+ */
+extern void test__f_iki_object_is__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_true.
+ *
+ * @see f_iki_object_is()
+ */
+extern void test__f_iki_object_is__returns_true(void **state);
+
+#endif // _TEST__F_iki_object_is_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki-object_partial_is.c b/level_0/f_iki/tests/unit/c/test-iki-object_partial_is.c
new file mode 100644 (file)
index 0000000..562d548
--- /dev/null
@@ -0,0 +1,117 @@
+#include "test-iki.h"
+#include "test-iki-object_partial_is.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_iki_object_partial_is__returns_false(void **state) {
+
+  f_string_static_t object = f_string_static_t_initialize;
+
+  const f_string_static_t objects[] = {
+    macro_f_string_static_t_initialize("xxxxfa lsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfalse@xxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfal;sexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxx/falsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxx'falsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfalse'xxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfa'l'sexxxx", 0, 15),
+    macro_f_string_static_t_initialize("xxxxf'alsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxx'false'xxxx", 0, 15),
+    macro_f_string_static_t_initialize("xxxx\"falsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfalse\"xxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxfa\"l\"sexxxx", 0, 15),
+    macro_f_string_static_t_initialize("xxxxf\"alsexxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxx'false'xxxx", 0, 15),
+  };
+
+  const f_string_range_t ranges[] = {
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 10),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 10),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 10),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 10),
+  };
+
+  for (uint8_t i = 0; i < 14; ++i) {
+
+    const f_status_t status = f_iki_object_partial_is(objects[i], ranges[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_false);
+  } // for
+}
+
+void test__f_iki_object_partial_is__returns_data_not(void **state) {
+
+  {
+    const f_string_range_t range = f_string_range_t_initialize;
+
+    const f_status_t status = f_iki_object_partial_is(f_string_empty_s, range);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not);
+  }
+}
+
+void test__f_iki_object_partial_is__returns_data_not_eos(void **state) {
+
+  {
+    const f_string_range_t range = macro_f_string_range_t_initialize2(f_string_ascii_a_s.used, f_string_ascii_a_s.used);
+
+    const f_status_t status = f_iki_object_partial_is(f_string_ascii_a_s, range);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not_eos);
+  }
+}
+
+void test__f_iki_object_partial_is__returns_data_not_stop(void **state) {
+
+  {
+    f_string_range_t range = f_string_range_t_initialize;
+
+    const f_status_t status = f_iki_object_partial_is(f_string_ascii_a_s, range);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not_stop);
+  }
+}
+
+void test__f_iki_object_partial_is__returns_true(void **state) {
+
+  f_string_static_t object = f_string_static_t_initialize;
+
+  const f_string_static_t objects[] = {
+    macro_f_string_static_t_initialize("xxxxworksxxxx", 0, 13),
+    macro_f_string_static_t_initialize("xxxxwor_ksxxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxwork-sxxxx", 0, 14),
+    macro_f_string_static_t_initialize("xxxxwor++ksxxxx", 0, 15),
+    macro_f_string_static_t_initialize("xxxxw_-+sxxxx", 0, 13),
+  };
+
+  const f_string_range_t ranges[] = {
+    macro_f_string_range_t_initialize2(4, 8),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 9),
+    macro_f_string_range_t_initialize2(4, 10),
+    macro_f_string_range_t_initialize2(4, 8),
+  };
+
+  for (uint8_t i = 0; i < 5; ++i) {
+
+    const f_status_t status = f_iki_object_partial_is(objects[i], ranges[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_true);
+  } // for
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-object_partial_is.h b/level_0/f_iki/tests/unit/c/test-iki-object_partial_is.h
new file mode 100644 (file)
index 0000000..c51933c
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the iki project.
+ */
+#ifndef _TEST__F_iki_object_partial_is_h
+#define _TEST__F_iki_object_partial_is_h
+
+/**
+ * Test that function returns F_false.
+ *
+ * @see f_iki_object_partial_is()
+ */
+extern void test__f_iki_object_partial_is__returns_false(void **state);
+
+// f_iki_object_partial_is() doesn't use parameter checking.
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_iki_object_partial_is()
+ */
+extern void test__f_iki_object_partial_is__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_data_not_eos.
+ *
+ * @see f_iki_object_partial_is()
+ */
+extern void test__f_iki_object_partial_is__returns_data_not_eos(void **state);
+
+/**
+ * Test that function returns F_data_not_stop.
+ *
+ * @see f_iki_object_partial_is()
+ */
+extern void test__f_iki_object_partial_is__returns_data_not_stop(void **state);
+
+/**
+ * Test that function returns F_true.
+ *
+ * @see f_iki_object_partial_is()
+ */
+extern void test__f_iki_object_partial_is__returns_true(void **state);
+
+#endif // _TEST__F_iki_object_partial_is_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki-read.c b/level_0/f_iki/tests/unit/c/test-iki-read.c
new file mode 100644 (file)
index 0000000..a96c4c2
--- /dev/null
@@ -0,0 +1,292 @@
+#include "test-iki.h"
+#include "test-iki-read.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_level_0_parameter_checking_
+  void test__f_iki_read__parameter_checking(void **state) {
+
+    const f_state_t the_state = f_state_t_initialize;
+    f_string_static_t empty = macro_f_string_static_t_initialize(f_string_empty_s.string, f_string_empty_s.size, f_string_empty_s.used);
+
+    {
+      f_string_range_t range = f_string_range_t_initialize;
+      f_iki_data_t iki = f_iki_data_t_initialize;
+
+      const f_status_t status = f_iki_read(the_state, 0, &range, &iki);
+
+      assert_int_equal(F_status_set_fine(status), F_parameter);
+    }
+
+    {
+      f_iki_data_t iki = f_iki_data_t_initialize;
+
+      const f_status_t status = f_iki_read(the_state, &empty, 0, &iki);
+
+      assert_int_equal(F_status_set_fine(status), F_parameter);
+    }
+
+    {
+      f_string_range_t range = f_string_range_t_initialize;
+
+      const f_status_t status = f_iki_read(the_state, &empty, &range, 0);
+
+      assert_int_equal(F_status_set_fine(status), F_parameter);
+    }
+  }
+#endif // _di_level_0_parameter_checking_
+
+void test__f_iki_read__returns_data_not(void **state) {
+
+  const f_state_t the_state = f_state_t_initialize;
+  f_string_static_t empty = macro_f_string_static_t_initialize(f_string_empty_s.string, f_string_empty_s.size, f_string_empty_s.used);
+
+  {
+    f_string_range_t range = f_string_range_t_initialize;
+    f_iki_data_t iki = f_iki_data_t_initialize;
+
+    const f_status_t status = f_iki_read(the_state, &empty, &range, &iki);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not);
+  }
+}
+
+void test__f_iki_read__returns_data_not_eos(void **state) {
+
+  const f_state_t the_state = f_state_t_initialize;
+  f_string_static_t ascii_a = macro_f_string_static_t_initialize(f_string_ascii_a_s.string, f_string_ascii_a_s.size, f_string_ascii_a_s.used);
+
+  {
+    f_string_range_t range = macro_f_string_range_t_initialize2(f_string_ascii_a_s.used, f_string_ascii_a_s.used);
+    f_iki_data_t iki = f_iki_data_t_initialize;
+
+    const f_status_t status = f_iki_read(the_state, &ascii_a, &range, &iki);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not_eos);
+  }
+}
+
+void test__f_iki_read__returns_data_not_stop(void **state) {
+
+  const f_state_t the_state = f_state_t_initialize;
+  f_string_static_t ascii_a = macro_f_string_static_t_initialize(f_string_ascii_a_s.string, f_string_ascii_a_s.size, f_string_ascii_a_s.used);
+
+  {
+    f_string_range_t range = f_string_range_t_initialize;
+    f_iki_data_t iki = f_iki_data_t_initialize;
+
+    const f_status_t status = f_iki_read(the_state, &ascii_a, &range, &iki);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not_stop);
+  }
+}
+
+void test__f_iki_read__works(void **state) {
+
+  const f_state_t the_state = f_state_t_initialize;
+  f_string_static_t empty = macro_f_string_static_t_initialize(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(f_string_ascii_a_s.string, f_string_ascii_a_s.size, f_string_ascii_a_s.used);
+
+  f_string_static_t buffers[] = {
+    empty,
+    ascii_a,
+    macro_f_string_static_t_initialize("iki:'one'", 0, 9),
+    macro_f_string_static_t_initialize("Has iki:'one' two:'iki and spaces'.", 0, 35),
+    macro_f_string_static_t_initialize("iki:\"one\"", 0, 9),
+    macro_f_string_static_t_initialize("Has iki:\"one\" two:\"iki and spaces\".", 0, 35),
+    macro_f_string_static_t_initialize("export PATH=\"/bin:/sbin:some:'A_PATH'\"", 0, 38),
+    macro_f_string_static_t_initialize("export PATH=\"/bin:/sbin:some:\"A_PATH\"\"", 0, 38),
+    macro_f_string_static_t_initialize("This wor_ks:'hopefully'!", 0, 24),
+    macro_f_string_static_t_initialize("This work-s:'hopefully'!", 0, 24),
+    macro_f_string_static_t_initialize("This wor++ks:'hopefully'!", 0, 25),
+    macro_f_string_static_t_initialize("This w_-+s:'hopefully'!", 0, 23),
+    macro_f_string_static_t_initialize("This wor_ks:\"hopefully\"!", 0, 24),
+    macro_f_string_static_t_initialize("This work-s:\"hopefully\"!", 0, 24),
+    macro_f_string_static_t_initialize("This wor++ks:\"hopefully\"!", 0, 25),
+    macro_f_string_static_t_initialize("This w_-+s:\"hopefully\"!", 0, 23),
+    macro_f_string_static_t_initialize("IKI Content:'May have spaces\\' and quotes.'", 0, 43),
+    macro_f_string_static_t_initialize("IKI Content:\"May have spaces\\\" and quotes.\"", 0, 43),
+    macro_f_string_static_t_initialize("IKI Content:'May have spaces\\' and\" quotes.'", 0, 44),
+    macro_f_string_static_t_initialize("IKI Content:\"May have spaces\\\" and' quotes.\"", 0, 44),
+    macro_f_string_static_t_initialize("url:'https://localhost/fake-0.6.0.tar.gz?query=xx&parameter=yyy%20' end.", 0, 72),
+    macro_f_string_static_t_initialize("url:\"https://localhost/fake-0.6.0.tar.gz?query=xx&parameter=yyy%20\" end.", 0, 72),
+  };
+
+  const f_array_length_t matches[] = {
+    0,
+    0,
+    1,
+    2,
+    1,
+    2,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+  };
+
+  const f_status_t statuss[] = {
+    F_data_not,
+    F_data_not_stop,
+    F_none_stop,
+    F_none,
+    F_none_stop,
+    F_none,
+    F_none,
+    F_none,
+    F_none,
+    F_none,
+    F_none,
+    F_none,
+    F_none,
+    F_none,
+    F_none,
+    F_none,
+    F_none_stop,
+    F_none_stop,
+    F_none_stop,
+    F_none_stop,
+    F_none,
+    F_none,
+  };
+
+  const f_string_range_t variables[][22] = {
+    { f_string_range_t_initialize, f_string_range_t_initialize },
+    { f_string_range_t_initialize, f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(0, 8), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 12), macro_f_string_range_t_initialize2(14, 33) },
+    { macro_f_string_range_t_initialize2(0, 8), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 12), macro_f_string_range_t_initialize2(14, 33) },
+    { macro_f_string_range_t_initialize2(24, 36), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(24, 36), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 22), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 22), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 23), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 21), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 22), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 22), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 23), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 21), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 42), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 42), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 43), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 43), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(0, 66), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(0, 66), f_string_range_t_initialize },
+  };
+
+  const f_string_range_t vocabularys[][22] = {
+    { f_string_range_t_initialize, f_string_range_t_initialize },
+    { f_string_range_t_initialize, f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(0, 2), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 6), macro_f_string_range_t_initialize2(14, 16) },
+    { macro_f_string_range_t_initialize2(0, 2), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 6), macro_f_string_range_t_initialize2(14, 16) },
+    { macro_f_string_range_t_initialize2(24, 27), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(24, 27), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 10), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 10), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 11), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 9), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 10), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 10), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 11), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 9), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 10), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 10), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 10), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(4, 10), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(0, 2), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(0, 2), f_string_range_t_initialize },
+  };
+
+  const f_string_range_t contents[][22] = {
+    { f_string_range_t_initialize, f_string_range_t_initialize },
+    { f_string_range_t_initialize, f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 7), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(9, 11), macro_f_string_range_t_initialize2(19, 32) },
+    { macro_f_string_range_t_initialize2(5, 7), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(9, 11), macro_f_string_range_t_initialize2(19, 32) },
+    { macro_f_string_range_t_initialize2(30, 35), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(30, 35), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(13, 21), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(13, 21), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(14, 22), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(12, 20), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(13, 21), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(13, 21), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(14, 22), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(12, 20), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(13, 41), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(13, 41), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(13, 42), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(13, 42), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 65), f_string_range_t_initialize },
+    { macro_f_string_range_t_initialize2(5, 65), f_string_range_t_initialize },
+  };
+
+  for (uint8_t i = 0; i < 22; ++i) {
+
+    f_string_range_t range = macro_f_string_range_t_initialize(buffers[i].used);
+    f_iki_data_t iki = f_iki_data_t_initialize;
+
+    const f_status_t status = f_iki_read(the_state, &buffers[i], &range, &iki);
+
+    assert_int_equal(F_status_set_fine(status), statuss[i]);
+
+    if (matches[i] == 2) {
+      const f_status_t status = f_iki_read(the_state, &buffers[i], &range, &iki);
+
+      assert_int_equal(F_status_is_error_not(status) ? 0 : 1, 0);
+    }
+
+    assert_int_equal(iki.variable.used, matches[i]);
+
+    if (iki.variable.used) {
+      assert_int_equal(iki.variable.array[0].start, variables[i][0].start);
+      assert_int_equal(iki.variable.array[0].stop, variables[i][0].stop);
+
+      assert_int_equal(iki.vocabulary.array[0].start, vocabularys[i][0].start);
+      assert_int_equal(iki.vocabulary.array[0].stop, vocabularys[i][0].stop);
+
+      assert_int_equal(iki.content.array[0].start, contents[i][0].start);
+      assert_int_equal(iki.content.array[0].stop, contents[i][0].stop);
+
+      if (iki.variable.used == 2) {
+        assert_int_equal(iki.variable.array[1].start, variables[i][1].start);
+        assert_int_equal(iki.variable.array[1].stop, variables[i][1].stop);
+
+        assert_int_equal(iki.vocabulary.array[1].start, vocabularys[i][1].start);
+        assert_int_equal(iki.vocabulary.array[1].stop, vocabularys[i][1].stop);
+
+        assert_int_equal(iki.content.array[1].start, contents[i][1].start);
+        assert_int_equal(iki.content.array[1].stop, contents[i][1].stop);
+      }
+    }
+
+    f_iki_data_delete(&iki);
+
+    iki.variable.used = 0;
+    iki.vocabulary.used = 0;
+    iki.content.used = 0;
+    iki.delimits.used = 0;
+  } // for
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki-read.h b/level_0/f_iki/tests/unit/c/test-iki-read.h
new file mode 100644 (file)
index 0000000..16dba9f
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the iki project.
+ */
+#ifndef _TEST__F_iki_read_h
+#define _TEST__F_iki_read_h
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_iki_read()
+ */
+#ifndef _di_level_0_parameter_checking_
+  extern void test__f_iki_read__parameter_checking(void **state);
+#endif // _di_level_0_parameter_checking_
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_iki_read()
+ */
+extern void test__f_iki_read__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_data_not_eos.
+ *
+ * @see f_iki_read()
+ */
+extern void test__f_iki_read__returns_data_not_eos(void **state);
+
+/**
+ * Test that function returns F_data_not_stop.
+ *
+ * @see f_iki_read()
+ */
+extern void test__f_iki_read__returns_data_not_stop(void **state);
+
+/**
+ * Test that function works.
+ *
+ * @see f_iki_read()
+ */
+extern void test__f_iki_read__works(void **state);
+
+#endif // _TEST__F_iki_read_h
diff --git a/level_0/f_iki/tests/unit/c/test-iki.c b/level_0/f_iki/tests/unit/c/test-iki.c
new file mode 100644 (file)
index 0000000..633c380
--- /dev/null
@@ -0,0 +1,61 @@
+#include "test-iki.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int setup(void **state) {
+
+  return 0;
+}
+
+int setdown(void **state) {
+
+  errno = 0;
+
+  return 0;
+}
+
+int main(void) {
+
+  const struct CMUnitTest tests[] = {
+    cmocka_unit_test(test__f_iki_content_is__returns_false),
+    cmocka_unit_test(test__f_iki_content_is__returns_data_not),
+    cmocka_unit_test(test__f_iki_content_is__returns_true),
+
+    cmocka_unit_test(test__f_iki_content_partial_is__returns_data_not),
+    cmocka_unit_test(test__f_iki_content_partial_is__returns_data_not_eos),
+    cmocka_unit_test(test__f_iki_content_partial_is__returns_data_not_stop),
+    cmocka_unit_test(test__f_iki_content_partial_is__returns_false),
+    cmocka_unit_test(test__f_iki_content_partial_is__returns_true),
+
+    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),
+
+    cmocka_unit_test(test__f_iki_object_partial_is__returns_data_not),
+    cmocka_unit_test(test__f_iki_object_partial_is__returns_data_not_eos),
+    cmocka_unit_test(test__f_iki_object_partial_is__returns_data_not_stop),
+    cmocka_unit_test(test__f_iki_object_partial_is__returns_false),
+    cmocka_unit_test(test__f_iki_object_partial_is__returns_true),
+
+    cmocka_unit_test(test__f_iki_read__returns_data_not),
+    cmocka_unit_test(test__f_iki_read__returns_data_not_eos),
+    cmocka_unit_test(test__f_iki_read__returns_data_not_stop),
+    cmocka_unit_test(test__f_iki_read__works),
+
+    #ifndef _di_level_0_parameter_checking_
+      cmocka_unit_test(test__f_iki_content_is__parameter_checking),
+      cmocka_unit_test(test__f_iki_content_partial_is__parameter_checking),
+      // f_iki_object_is() doesn't use parameter checking.
+      // f_iki_object_partial_is() doesn't use parameter checking.
+      cmocka_unit_test(test__f_iki_read__parameter_checking),
+    #endif // _di_level_0_parameter_checking_
+  };
+
+  return cmocka_run_group_tests(tests, setup, setdown);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_iki/tests/unit/c/test-iki.h b/level_0/f_iki/tests/unit/c/test-iki.h
new file mode 100644 (file)
index 0000000..c1bc15e
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the iki project.
+ */
+#ifndef _TEST__F_iki_h
+#define _TEST__F_iki_h
+
+// Libc includes.
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+// cmocka includes.
+#include <cmocka.h>
+
+// FLL-0 includes.
+#include <fll/level_0/iki.h>
+
+// Mock includes.
+//#include "mock-iki.h"
+
+// Test includes.
+#include "test-iki-content_is.h"
+#include "test-iki-content_partial_is.h"
+#include "test-iki-object_is.h"
+#include "test-iki-object_partial_is.h"
+#include "test-iki-read.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform any setup operations.
+ *
+ * @param state
+ *   The test state.
+ *
+ * @return
+ *   The status of this function, where 0 means success.
+ */
+extern int setup(void **state);
+
+/**
+ * Peform any setdown operations.
+ *
+ * @param state
+ *   The test state.
+ *
+ * @return
+ *   The status of this function, where 0 means success.
+ */
+extern int setdown(void **state);
+
+/**
+ * Run all tests.
+ *
+ * @return
+ *   The final result of the tests.
+ *
+ * @see cmocka_run_group_tests()
+ * @see cmocka_unit_test()
+ */
+extern int main(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _TEST__F_iki_h