--- /dev/null
+#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
#include <level_1/serialized.h>
+#include "private-serialized.h"
#ifdef __cplusplus
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_
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;
// 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);
}
#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"
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.
#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".
*
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"