]> Kevux Git Server - fll/commitdiff
Update: implement missing serialized functions and fix bugs
authorKevin Day <thekevinday@gmail.com>
Fri, 1 May 2020 03:36:45 +0000 (22:36 -0500)
committerKevin Day <thekevinday@gmail.com>
Fri, 1 May 2020 03:36:45 +0000 (22:36 -0500)
Implement fl_unserialize_simple() and fl_unserialize_simple_get().

The last character in the last string in the unserialized array gets cut off.
- This happened because the stopping point was incorrectly compensating for the splitter character for the last character in the string.

The width (UTF-8 character width) is not part of the locations size.

build/level_1/settings
build/monolithic/settings
level_1/fl_serialized/c/private-serialized.c [new file with mode: 0644]
level_1/fl_serialized/c/private-serialized.h [new file with mode: 0644]
level_1/fl_serialized/c/serialized.c
level_1/fl_serialized/c/serialized.h
level_1/fl_serialized/data/build/settings

index 9b7c26da5e367cb14335257bb7eae893ae3a8475..8ab7eb5db4349052ae60049d190fec367f1ca999 100644 (file)
@@ -12,7 +12,7 @@ build_linker ar
 build_libraries -lc
 build_libraries_fll -lfll_0
 build_libraries_fll-level -lfll_0
-build_sources_library color.c console.c directory.c file.c fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c print.c serialized.c socket.c status.c string.c utf.c private-string.c private-utf.c
+build_sources_library color.c console.c directory.c file.c fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c print.c serialized.c private-serialized.c socket.c status.c string.c utf.c private-string.c private-utf.c
 build_sources_program 
 build_sources_headers color.h console.h directory.h file.h fss.h fss_basic.h fss_basic_list.h fss_status.h fss_extended.h fss_extended_list.h fss_macro.h print.h serialized.h socket.h status.h string.h utf.h
 build_shared yes
index 68d14a6a9d5a3b5a2fcf1b04b0bd27b3c6a694eb..dec2e3cf319be5e3f0fe6544b47fdedf34fa0c8e 100644 (file)
@@ -11,7 +11,7 @@ build_compiler gcc
 build_linker ar
 build_libraries -lc
 build_libraries_fll
-build_sources_library level_0/console.c level_0/conversion.c level_0/file.c level_0/memory.c level_0/pipe.c level_0/print.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/directory.c level_1/file.c level_1/fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/serialized.c level_1/socket.c level_1/status.c level_1/string.c level_1/utf.c level_1/print.c level_1/private-string.c level_1/private-utf.c level_2/execute.c level_2/file.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/program.c level_2/status.c
+build_sources_library level_0/console.c level_0/conversion.c level_0/file.c level_0/memory.c level_0/pipe.c level_0/print.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/directory.c level_1/file.c level_1/fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/serialized.c level_1/private-serialized.c level_1/socket.c level_1/status.c level_1/string.c level_1/utf.c level_1/print.c level_1/private-string.c level_1/private-utf.c level_2/execute.c level_2/file.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/program.c level_2/status.c
 build_sources_program
 build_sources_headers level_0/color.h level_0/console.h level_0/conversion.h level_0/file.h level_0/fss.h level_0/memory.h level_0/path_fll.h level_0/path_filesystem.h level_0/pipe.h level_0/print.h level_0/serialized.h level_0/socket.h level_0/status.h level_0/string.h level_0/type.h level_0/type_array.h level_0/utf.h level_1/color.h level_1/console.h level_1/directory.h level_1/file.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_status.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/serialized.h level_1/socket.h level_1/status.h level_1/string.h level_1/utf.h level_1/print.h level_2/execute.h level_2/file.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/program.h level_2/status.h
 build_sources_bash
diff --git a/level_1/fl_serialized/c/private-serialized.c b/level_1/fl_serialized/c/private-serialized.c
new file mode 100644 (file)
index 0000000..46982b4
--- /dev/null
@@ -0,0 +1,61 @@
+#include <level_1/serialized.h>
+#include "private-serialized.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_fl_unserialize_simple_find_) || !defined(_di_fl_unserialize_simple_get_)
+  f_return_status private_fl_unserialize_simple_find(const f_string_dynamic serialized, const f_array_length index, f_string_location *location) {
+    f_status status = f_none;
+
+    f_array_length i = 0;
+    f_array_length start = 0;
+    f_array_length current = 0;
+
+    unsigned short width = 0;
+
+    while (i < serialized.used) {
+      width = f_macro_utf_byte_width(serialized.string[i]);
+
+      if (serialized.string[i] == f_serialized_simple_splitter) {
+        if (current == index) {
+          if (start == i) {
+            // provide an invalid start to stop range to communicate that there is no data.
+            location->start = 1;
+            location->stop = 0;
+          }
+          else {
+            location->start = start;
+            location->stop = i - 1;
+          }
+
+          return f_none;
+        }
+
+        start = i + width;
+        current++;
+      }
+      else if (i == serialized.used) {
+        if (current == index) {
+          location->start = start;
+          location->stop = i - 1;
+        }
+
+        return f_none_on_eos;
+      }
+
+      if (i + width > serialized.used) {
+        return f_status_set_error(f_incomplete_utf_on_eos);
+      }
+
+      i += width;
+    } // while
+
+    return f_no_data_on_eos;
+  }
+#endif // !defined(_di_fl_unserialize_simple_find_) || !defined(_di_fl_unserialize_simple_get_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_1/fl_serialized/c/private-serialized.h b/level_1/fl_serialized/c/private-serialized.h
new file mode 100644 (file)
index 0000000..cd61998
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * FLL - Level 1
+ *
+ * Project: Serialized
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * These are provided for internal reduction in redundant code.
+ * These should not be exposed/used outside of this project.
+ */
+#ifndef _PRIVATE_FL_serialized_h
+#define _PRIVATE_FL_serialized_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Private implementation of fl_unserialize_simple_get().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param serialized
+ *   A serialized string to de-serialize.
+ * @param index
+ *   An index position within the serialized string to get the deserialized positions of.
+ * @param location
+ *   A location within the serialized string representing the string at the given index.
+ *
+ * @return
+ *   f_none on success.
+ *   f_none_on_eos on success at end of string.
+ *   f_no_data_on_eos if end of string reached before index was reached.
+ *   f_incomplete_utf_on_eos (with error bit) if end of string is reached before a complete UTF-8 character can be processed.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ */
+#if !defined(_di_fl_unserialize_simple_find_) || !defined(_di_fl_unserialize_simple_get_)
+  extern f_return_status private_fl_unserialize_simple_find(const f_string_dynamic serialized, const f_array_length index, f_string_location *location) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_unserialize_simple_find_) || !defined(_di_fl_unserialize_simple_get_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_FL_serialized_h
index 1a5a79f1bfa50a1494252329b033d68869aa540f..10aae56f8d1828698a21c96ce3e43f528a0c909e 100644 (file)
@@ -1,4 +1,5 @@
 #include <level_1/serialized.h>
+#include "private-serialized.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -32,9 +33,80 @@ extern "C" {
   }
 #endif // _di_fl_serialize_simple_
 
+#ifndef _di_fl_unserialize_simple_
+  f_return_status fl_unserialize_simple(const f_string_dynamic serialized, f_string_dynamics *strings) {
+    #ifndef _di_level_0_parameter_checking_
+      if (serialized.used == 0) return f_status_set_error(f_invalid_parameter);
+      if (strings == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    f_status status = f_none;
+
+    f_array_length i = 0;
+    f_array_length start = 0;
+
+    uint8_t width = 0;
+
+    while (i < serialized.used) {
+      width = f_macro_utf_byte_width(serialized.string[i]);
+
+      if (serialized.string[i] == f_serialized_simple_splitter || i + 1 >= serialized.used) {
+        if (strings->used >= strings->size) {
+          f_macro_string_dynamics_resize(status, (*strings), strings->size + f_serialized_default_allocation_step);
+
+          if (f_status_is_error(status)) return status;
+        }
+
+        if (start == i) {
+          strings->array[strings->used].used = 0;
+          strings->used++;
+        }
+        else {
+          f_string_length total;
+
+          if (i + 1 >= serialized.used) {
+            total = (i - start) + 1;
+          }
+          else {
+            // subtract one from stop point to disclused the f_serialized_simple_splitter character.
+            total = ((i - 1) - start) + 1;
+          }
+
+          if (total > strings->array[strings->used].size) {
+            f_macro_string_dynamic_new(status, strings->array[strings->used], total);
+
+            if (f_status_is_error(status)) return status;
+
+            strings->array[strings->used].size = total;
+          }
+
+          memcpy(strings->array[strings->used].string, serialized.string + start, total);
+
+          strings->array[strings->used].used = total;
+          strings->used++;
+        }
+
+        if (i + width > serialized.used) {
+          return f_status_set_error(f_incomplete_utf_on_eos);
+        }
+
+        start = i + width;
+      }
+      else if (i + width > serialized.used) {
+        return f_status_set_error(f_incomplete_utf_on_eos);
+      }
+
+      i += width;
+    } // while
+
+    return f_none;
+  }
+#endif // _di_fl_unserialize_simple_
+
 #ifndef _di_fl_unserialize_simple_map_
   f_return_status fl_unserialize_simple_map(const f_string_dynamic serialized, f_string_locations *locations) {
     #ifndef _di_level_0_parameter_checking_
+      if (serialized.used == 0) return f_status_set_error(f_invalid_parameter);
       if (locations == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_0_parameter_checking_
 
@@ -43,13 +115,13 @@ extern "C" {
     f_array_length i = 0;
     f_array_length start = 0;
 
-    unsigned short width = 0;
+    uint8_t width = 0;
 
     while (i < serialized.used) {
       width = f_macro_utf_byte_width(serialized.string[i]);
 
-      if (serialized.string[i] == f_serialized_simple_splitter || i == serialized.used) {
-        if (locations->used + width >= locations->size) {
+      if (serialized.string[i] == f_serialized_simple_splitter || i + 1 >= serialized.used) {
+        if (locations->used >= locations->size) {
           f_macro_string_locations_resize(status, (*locations), locations->size + f_serialized_default_allocation_step);
 
           if (f_status_is_error(status)) return status;
@@ -59,14 +131,19 @@ extern "C" {
           // provide an invalid start to stop range to communicate that there is no data.
           locations->array[locations->used].start = 1;
           locations->array[locations->used].stop = 0;
-          locations->used++;
+        }
+        else if (i + 1 >= serialized.used) {
+          locations->array[locations->used].start = start;
+          locations->array[locations->used].stop = i;
         }
         else {
+          // subtract one from stop point to disclused the f_serialized_simple_splitter character.
           locations->array[locations->used].start = start;
           locations->array[locations->used].stop = i - 1;
-          locations->used++;
         }
 
+        locations->used++;
+
         if (i + width > serialized.used) {
           return f_status_set_error(f_incomplete_utf_on_eos);
         }
@@ -87,57 +164,48 @@ extern "C" {
 #ifndef _di_fl_unserialize_simple_find_
   f_return_status fl_unserialize_simple_find(const f_string_dynamic serialized, const f_array_length index, f_string_location *location) {
     #ifndef _di_level_0_parameter_checking_
+      if (serialized.used == 0) return f_status_set_error(f_invalid_parameter);
       if (location == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_0_parameter_checking_
 
-    f_status status = f_none;
+    return private_fl_unserialize_simple_find(serialized, index, location);
+  }
+#endif // _di_fl_unserialize_simple_find_
 
-    f_array_length i = 0;
-    f_array_length start = 0;
-    f_array_length current = 0;
+#ifndef _di_fl_unserialize_simple_get_
+  f_return_status fl_unserialize_simple_get(const f_string_dynamic serialized, const f_array_length index, f_string_dynamic *dynamic) {
+    #ifndef _di_level_0_parameter_checking_
+      if (serialized.used == 0) return f_status_set_error(f_invalid_parameter);
+      if (dynamic == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_0_parameter_checking_
 
-    unsigned short width = 0;
+    f_string_location location = f_string_location_initialize;
 
-    while (i < serialized.used) {
-      width = f_macro_utf_byte_width(serialized.string[i]);
+    f_status status = private_fl_unserialize_simple_find(serialized, index, &location);
 
-      if (serialized.string[i] == f_serialized_simple_splitter) {
-        if (current == index) {
-          if (start == i) {
-            // provide an invalid start to stop range to communicate that there is no data.
-            location->start = 1;
-            location->stop = 0;
-          }
-          else {
-            location->start = start;
-            location->stop = i - 1;
-          }
+    if (f_status_is_error(status)) return status;
 
-          return f_none;
-        }
+    if (status == f_no_data_on_eos) {
+      dynamic->used = 0;
+      return status;
+    }
 
-        start = i + width;
-        current++;
-      }
-      else if (i == serialized.used) {
-        if (current == index) {
-          location->start = start;
-          location->stop = i - 1;
-        }
+    f_string_length total = (location.stop - location.start) + 1;
 
-        return f_none_on_eos;
-      }
+    if (total >= dynamic->size) {
+      f_status status_allocation = f_none;
 
-      if (i + width > serialized.used) {
-        return f_status_set_error(f_incomplete_utf_on_eos);
-      }
+      f_macro_string_dynamic_resize(status_allocation, (*dynamic), total);
 
-      i += width;
-    } // while
+      if (f_status_is_error(status_allocation)) return status_allocation;
+    }
 
-    return f_no_data_on_eos;
+    memcpy(dynamic->string, serialized.string + location.start, total);
+    dynamic->used = total;
+
+    return status;
   }
-#endif // _di_fl_unserialize_simple_find_
+#endif // _di_fl_unserialize_simple_get_
 
 #ifdef __cplusplus
 } // extern "C"
index d5d92b146767fa28f538180ae2cf2807f6888c0b..f2e41855eae826c42001d3bde8d7e1bba246618c 100644 (file)
@@ -50,7 +50,30 @@ extern "C" {
   extern f_return_status fl_serialize_simple(const f_string_dynamic value, f_string_dynamic *serialized);
 #endif // _di_fl_serialize_simple_
 
-// @todo: implement fl_unserialize_simple() such that a new array of strings is allocated.
+/**
+ * De-serialized the entire serialized string into multiple separate strings using the Simple serialize algorithm.
+ *
+ * The simple Serialize algorithm is akin to the PATH environment variable, example: PATH="/bin:/sbin:/usr/bin".
+ *
+ * After processing the above example, there would be the following positions:
+ *   1) start = 0, stop = 3.
+ *   2) start = 5, stop = 9.
+ *   3) start = 11, stop = 18.
+ *
+ * @param serialized
+ *   A serialized string to de-serialize.
+ * @param strings
+ *   An array of strings de-serialized from serialized.
+ *
+ * @return
+ *   f_none on success.
+ *   f_incomplete_utf_on_eos if end of sting is reached before a complete UTF-8 character can be processed.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ */
+#ifndef _di_fl_unserialize_simple_
+  extern f_return_status fl_unserialize_simple(const f_string_dynamic serialized, f_string_dynamics *strings);
+#endif // _di_fl_unserialize_simple_
 
 /**
  * Identify string positions within a serialized string using the Simple serialize algorithm.
@@ -78,7 +101,7 @@ extern "C" {
 #endif // _di_fl_unserialize_simple_map_
 
 /**
- * Unserialize a specific string using the Simple serialize algorithm.
+ * Unserialize and find the address for a specific string using the Simple serialize algorithm.
  *
  * The simple Serialize algorithm is akin to the PATH environment variable, example: PATH="/bin:/sbin:/usr/bin".
  *
@@ -105,7 +128,34 @@ extern "C" {
   extern f_return_status fl_unserialize_simple_find(const f_string_dynamic serialized, const f_array_length index, f_string_location *location);
 #endif // _di_fl_unserialize_simple_find_
 
-// @todo: implement fl_unserialize_simple_get() such that a new string is allocated, if found.
+/**
+ * Unserialize and get a copy of a specific string using the Simple serialize algorithm.
+ *
+ * The simple Serialize algorithm is akin to the PATH environment variable, example: PATH="/bin:/sbin:/usr/bin".
+ *
+ * After processing the above example, there would be the following positions, for the given index:
+ *   1) with index = 0, start = 0, stop = 3.
+ *   2) with index = 1, start = 5, stop = 9.
+ *   3) with index = 2, start = 11, stop = 18.
+ *
+ * @param serialized
+ *   A serialized string to de-serialize.
+ * @param index
+ *   An index position within the serialized string to get the deserialized positions of.
+ * @param dynamic
+ *   The unserialized string from the specified index.
+ *
+ * @return
+ *   f_none on success.
+ *   f_none_on_eos on success at end of string.
+ *   f_no_data_on_eos if end of string reached before index was reached (dynamic->used is set to 0).
+ *   f_incomplete_utf_on_eos (with error bit) if end of string is reached before a complete UTF-8 character can be processed.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ */
+#ifndef _di_fl_unserialize_simple_get_
+  extern f_return_status fl_unserialize_simple_get(const f_string_dynamic serialized, const f_array_length index, f_string_dynamic *dynamic);
+#endif // _di_fl_unserialize_simple_get_
 
 #ifdef __cplusplus
 } // extern "C"
index d29f63f4c904352d486afa68190acf599be1a766..bac7c1c18cf27f27d3423692097fdce593a1dfdb 100644 (file)
@@ -11,7 +11,7 @@ build_compiler gcc
 build_linker ar
 build_libraries -lc
 build_libraries_fll -lf_utf -lf_memory
-build_sources_library serialized.c
+build_sources_library serialized.c private-serialized.c
 build_sources_program
 build_sources_headers serialized.h
 build_sources_bash