The FSS-0008 Embedded List is just copied from FSS-0003 Extended List.
Fix some minor problems observed during this transition.
I will need to follow up with rewriting the FSS-0003 Extended List code.
I will probably just use FSS-0002 Basic List as a fresh starting point given that list is not recursive.
build_language c
build_libraries -lc
build_libraries-level -lfll_0
-build_sources_library color.c console.c conversion.c directory.c private-directory.c environment.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c iki.c print.c private-print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c
+build_sources_library color.c console.c conversion.c directory.c private-directory.c environment.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c iki.c print.c private-print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c
build_sources_program
-build_sources_headers color.h console.h conversion.h directory.h environment.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h iki.h print.h status.h string.h utf.h utf_file.h
+build_sources_headers color.h console.h conversion.h directory.h environment.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h iki.h print.h status.h string.h utf.h utf_file.h
build_sources_script
build_sources_setting
build_script yes
build_language c
build_libraries -lc
build_libraries-level -lfll_1 -lfll_0
-build_sources_library error.c private-error.c execute.c private-execute.c file.c private-file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c iki.c private-iki.c path.c program.c status.c
+build_sources_library error.c private-error.c execute.c private-execute.c file.c private-file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c fss_status.c iki.c private-iki.c path.c program.c status.c
build_sources_program
-build_sources_headers error.h error-common.h execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h path.h program.h status.h
+build_sources_headers error.h error-common.h execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h path.h program.h status.h
build_sources_script
build_sources_setting
build_script yes
build_language c
build_libraries -lc
build_libraries-monolithic
-build_sources_library level_0/account.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-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/iki.c level_1/print.c level_1/private-print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.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/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c
+build_sources_library level_0/account.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_embedded_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_embedded_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c
build_sources_program
-build_sources_headers level_0/account.h level_0/account-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.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/iki.h level_2/path.h level_2/program.h level_2/status.h
+build_sources_headers level_0/account.h level_0/account-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_embedded_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_embedded_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h
build_sources_script
build_sources_setting
build_script yes
#define f_fss_extended_list_open_end f_string_eol[0]
#define f_fss_extended_list_close '}'
#define f_fss_extended_list_close_end f_string_eol[0]
+ #define f_fss_embedded_list_open '{'
+ #define f_fss_embedded_list_open_end f_string_eol[0]
+ #define f_fss_embedded_list_close '}'
+ #define f_fss_embedded_list_close_end f_string_eol[0]
#define f_fss_type_header_open '#'
#define f_fss_type_header_part1 ' '
#define f_fss_type_header_part2 'f'
f_fss_embeded_list,
f_fss_reverse_mapping,
f_fss_extended_reverse_mapping,
- f_fss_simple_json,
f_fss_simple_list,
+ f_fss_iki_text,
+ f_fss_basic_rule,
};
#endif // _di_f_fss_codes_
* 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 found
- * A set of all locations where a valid object was found.
+ * A location where a valid object was found.
* @param quote
* This will store whether or not this object is quote and what quote is in use.
* Set pointer address to 0 to not use.
* 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 found
- * A set of all locations where a valid object was found.
+ * A location where a valid object was found.
* @param delimits
* A delimits array representing where delimits exist within the buffer.
*
--- /dev/null
+#include "fss_embedded_list.h"
+#include "private-fss.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fl_fss_embedded_list_object_read_
+ f_return_status fl_fss_embedded_list_object_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_object_t *found, f_fss_delimits_t *delimits) {
+ #ifndef _di_level_1_parameter_checking_
+ if (!buffer) return F_status_set_error(F_parameter);
+ if (!range) return F_status_set_error(F_parameter);
+ if (!found) return F_status_set_error(F_parameter);
+ if (!delimits) return F_status_set_error(F_parameter);
+ #endif // _di_level_1_parameter_checking_
+
+ const f_array_length_t delimits_used = delimits->used;
+
+ f_status_t status = f_fss_skip_past_space(*buffer, range);
+ if (F_status_is_error(status)) return status;
+
+ if (status == F_none_eol) {
+
+ // move the start position to after the EOL.
+ range->start++;
+
+ return FL_fss_found_object_not;
+ }
+
+ if (status == F_none_eos) {
+ return F_data_not_eos;
+ }
+
+ if (status == F_none_stop) {
+ return F_data_not_stop;
+ }
+
+ // return found nothing if this line only contains whitespace and delimit placeholders.
+ if (buffer->string[range->start] == f_fss_eol) {
+
+ // move the start position to after the EOL.
+ range->start++;
+
+ return FL_fss_found_object_not;
+ }
+
+ // begin the search.
+ found->start = range->start;
+
+ // ignore all comment lines.
+ if (buffer->string[range->start] == f_fss_comment) {
+ status = f_fss_seek_to_eol(*buffer, range);
+
+ if (F_status_is_error(status)) {
+ delimits->used = delimits_used;
+ return status;
+ }
+
+ if (status == F_none_eos) {
+ return F_data_not_eos;
+ }
+
+ if (status == F_none_stop) {
+ return F_data_not_stop;
+ }
+
+ // move the start position to after the EOL.
+ range->start++;
+
+ return FL_fss_found_object_not;
+ }
+
+ f_string_length_t start = 0;
+ f_string_length_t stop = 0;
+ f_string_length_t slash_first = 0;
+ f_string_length_t slash_count = 0;
+
+ bool graph_first = F_true;
+
+ // identify where the object ends.
+ while (range->start <= range->stop && range->start < buffer->used && buffer->string[range->start] != f_fss_eol) {
+
+ if (buffer->string[range->start] == f_fss_delimit_slash) {
+ slash_first = range->start;
+ slash_count = 1;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+
+ while (range->start <= range->stop && range->start < buffer->used && (buffer->string[range->start] == f_fss_delimit_placeholder || buffer->string[range->start] == f_fss_delimit_slash)) {
+
+ if (buffer->string[range->start] == f_fss_delimit_slash) slash_count++;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ fl_macro_fss_object_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, F_data_not_eos, F_data_not_stop);
+
+ if (buffer->string[range->start] == f_fss_embedded_list_open) {
+ graph_first = F_false;
+ stop = range->start - 1;
+ range->start++;
+
+ while (range->start <= range->stop && range->start < buffer->used) {
+
+ if (buffer->string[range->start] == f_fss_eol) break;
+
+ status = f_fss_is_graph(*buffer, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_true) break;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ fl_macro_fss_object_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, F_data_not_eos, F_data_not_stop);
+
+ if (buffer->string[range->start] == f_fss_eol) {
+ start = range->start;
+
+ range->start = slash_first;
+
+ status = private_fl_fss_delimits_increase_by((slash_count / 2) + 1, delimits);
+ if (F_status_is_error(status)) break;
+
+ if (slash_count % 2 == 0) {
+ while (slash_count > 0) {
+
+ if (buffer->string[range->start] == f_fss_delimit_slash) {
+ if (slash_count % 2 == 1) {
+ delimits->array[delimits->used] = range->start;
+ delimits->used++;
+ }
+
+ slash_count--;
+ }
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ found->stop = stop;
+ range->start = start + 1;
+
+ return FL_fss_found_object;
+ }
+
+ range->start = start + 1;
+ return FL_fss_found_object_not;
+ }
+ }
+ else if (graph_first && buffer->string[range->start] == f_fss_comment) {
+ graph_first = F_false;
+
+ // comments may only have whitespace before the '#', therefore only the first slash needs to be delimited.
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = slash_first;
+ range->start++;
+ }
+ else {
+ graph_first = F_false;
+ }
+
+ continue;
+ }
+ else if (buffer->string[range->start] == f_fss_embedded_list_open) {
+ graph_first = F_false;
+ stop = range->start - 1;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+
+ while (range->start <= range->stop && range->start < buffer->used) {
+
+ if (buffer->string[range->start] == f_fss_eol) break;
+
+ status = f_fss_is_space(*buffer, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) break;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ fl_macro_fss_object_return_on_overflow_delimited((*buffer), (*range), (*found), F_none_eos, F_none_stop);
+
+ if (buffer->string[range->start] == f_fss_eol) {
+ found->stop = stop;
+
+ // move the start position to after the EOL.
+ range->start++;
+
+ return FL_fss_found_object;
+ }
+
+ continue;
+ }
+ else if (graph_first) {
+ status = f_fss_is_space(*buffer, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ graph_first = F_false;
+ }
+ }
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) {
+ delimits->used = delimits_used;
+ return status;
+ }
+
+ // seek to the end of the line when no valid object is found.
+ while (range->start <= range->stop && range->start < buffer->used && buffer->string[range->start] != f_fss_eol) {
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+
+ if (F_status_is_error(status)) {
+ delimits->used = delimits_used;
+ return status;
+ }
+ } // while
+
+ fl_macro_fss_object_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, F_data_not_eos, F_data_not_stop);
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+
+ if (F_status_is_error(status)) {
+ delimits->used = delimits_used;
+ return status;
+ }
+
+ return FL_fss_found_object_not;
+ }
+#endif // _di_fl_fss_embedded_list_object_read_
+
+#ifndef _di_fl_fss_embedded_list_content_read_
+ f_return_status fl_fss_embedded_list_content_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_nest_t *found, f_fss_delimits_t *delimits, f_fss_comments_t *comments) {
+ #ifndef _di_level_1_parameter_checking_
+ if (!buffer) return F_status_set_error(F_parameter);
+ if (!range) return F_status_set_error(F_parameter);
+ if (!found) return F_status_set_error(F_parameter);
+ if (!delimits) return F_status_set_error(F_parameter);
+ if (!comments) return F_status_set_error(F_parameter);
+ #endif // _di_level_1_parameter_checking_
+
+ const f_array_length_t found_used = found->used;
+
+ f_status_t status = f_fss_skip_past_delimit(*buffer, range);
+ if (F_status_is_error(status)) return status;
+
+ if (status == F_none_eos || status == F_none_stop) {
+ return status;
+ }
+
+ status = private_fl_fss_nest_increase(found);
+ if (F_status_is_error(status)) return status;
+
+ f_string_lengths_t positions_start = f_string_lengths_t_initialize;
+
+ f_macro_string_lengths_t_new(status, positions_start, f_fss_default_allocation_step);
+ if (F_status_is_error(status)) return status;
+
+ f_fss_objects_t objects = f_fss_objects_t_initialize;
+
+ f_macro_fss_objects_t_new(status, objects, f_fss_default_allocation_step);
+
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_t_delete_simple(positions_start);
+
+ return status;
+ }
+
+ const f_array_length_t delimits_used = delimits->used;
+ const f_array_length_t comments_used = comments->used;
+
+ f_array_length_t depth = 0;
+ f_array_length_t position = 0;
+
+ f_string_length_t position_previous = range->start;
+ f_string_length_t line_start = range->start;
+ f_string_length_t newline_last = range->start;
+ f_string_length_t comment_delimit = 0;
+
+ f_string_length_t slash_first = 0;
+ f_string_length_t slash_last = 0;
+ f_string_length_t slash_count = 0;
+
+ f_string_length_t before_list_open = position_previous;
+
+ bool is_open = F_false;
+
+ uint8_t graph_first = 0x0; // 0x0 = false, 0x1 = true, 0x2 = false, but there is a delimited comment, comment_delimit is set.
+
+ // initialize depth 1 start position.
+ // positions_start.used is used as a max depth (such that positions_start.used == max depth + 1).
+ positions_start.array[0] = range->start;
+ positions_start.used = 1;
+
+ while (range->start <= range->stop && range->start < buffer->used) {
+
+ if (buffer->string[range->start] == f_fss_eol) {
+ if (graph_first == 0x2) {
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = comment_delimit;
+ }
+
+ newline_last = range->start;
+ position_previous = range->start++;
+ graph_first = 0x1;
+
+ if (depth > 0) {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+ }
+ else {
+ fl_macro_fss_nest_return_on_overflow_delimited((*buffer), (*range), (*found), positions_start, objects, F_none_eos, F_none_stop);
+ }
+
+ line_start = range->start;
+ continue;
+ }
+
+ if (buffer->string[range->start] == f_fss_delimit_slash) {
+ slash_first = range->start;
+ slash_last = range->start;
+ slash_count = 1;
+
+ position_previous = range->start;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+
+ while (range->start <= range->stop && range->start < buffer->used && (buffer->string[range->start] == f_fss_delimit_placeholder || buffer->string[range->start] == f_fss_delimit_slash)) {
+ position_previous = range->start;
+
+ if (buffer->string[range->start] == f_fss_delimit_slash) {
+ slash_last = range->start++;
+ }
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ if (depth > 0) {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+ }
+ else {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+ }
+
+ // All slashes for an open are delimited (because it could represent a slash in the object name).
+ // for example 'object {' = valid open, name 'object', 'object \{' represents 'object {', 'object \\{' = valid open, name 'object \', 'object \\\{' represents 'object \{', etc..
+ // Only the first slash before a close is delimited, all others are maintained.
+ // for example '}' = valid close, '\}' represents '}', '\\}' represents '\}', '\\\}' represents '\\}', '\\\\}' represents '\\\}', and so on..
+ // When slash is odd and a (delimited) valid open/close is found, then save delimited positions and continue.
+ if (buffer->string[range->start] == f_fss_eol) {
+ if (graph_first == 0x2) {
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = comment_delimit;
+ }
+
+ newline_last = range->start;
+ position_previous = range->start++;
+ line_start = range->start;
+ graph_first = 0x1;
+ }
+ else if (buffer->string[range->start] == f_fss_embedded_list_open || buffer->string[range->start] == f_fss_embedded_list_close) {
+ before_list_open = position_previous;
+ is_open = F_false;
+ graph_first = 0x0;
+
+ if (buffer->string[range->start] == f_fss_embedded_list_open) {
+ is_open = F_true;
+ }
+
+ position_previous = range->start++;
+
+ while (range->start <= range->stop && range->start < buffer->used) {
+
+ if (buffer->string[range->start] == f_fss_eol) {
+ if (graph_first == 0x2) {
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = comment_delimit;
+ }
+
+ newline_last = range->start;
+ line_start = range->start + 1;
+ graph_first = 0x1;
+ break;
+ }
+
+ if (buffer->string[range->start] != f_fss_delimit_placeholder) {
+ status = f_fss_is_space(*buffer, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) break;
+ }
+
+ position_previous = range->start;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ if (depth > 0) {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+ }
+ else {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+ }
+
+ // this is a valid object open/close that has been delimited, save the slash delimit positions.
+ if (buffer->string[range->start] == f_fss_eol) {
+ newline_last = range->start;
+ line_start = range->start + 1;
+ graph_first = 0x1;
+
+ if (is_open) {
+ bool is_object = F_false;
+
+ if (slash_count % 2 == 0) {
+ is_object = F_true;
+ }
+
+ range->start = slash_first;
+
+ status = private_fl_fss_delimits_increase_by((slash_count / 2) + 1, delimits);
+ if (F_status_is_error(status)) break;
+
+ // apply slash delimits, only slashes and placeholders should be present.
+ while (slash_count > 0) {
+
+ if (buffer->string[range->start] == f_fss_delimit_slash) {
+ if (slash_count % 2 == 1) {
+ delimits->array[delimits->used++] = range->start;
+ }
+
+ slash_count--;
+ }
+
+ // Delimit slashes and placeholders are required to be in the ASCII range.
+ position_previous = range->start++;
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ // when slashes are even, the object is valid and needs to be processed.
+ if (is_object) {
+ depth++;
+
+ if (depth > positions_start.size) {
+ f_macro_string_lengths_t_resize(status, positions_start, positions_start.size + f_fss_default_allocation_step);
+ if (F_status_is_error(status)) break;
+ }
+
+ if (positions_start.used < depth) {
+ positions_start.used = depth;
+ }
+
+ positions_start.array[depth] = newline_last + 1;
+
+ objects.array[depth].start = line_start;
+ objects.array[depth].stop = before_list_open;
+ }
+ }
+ else {
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = slash_last;
+ }
+
+ range->start = newline_last;
+ }
+ }
+ else if (graph_first == 0x1 && buffer->string[range->start] == f_fss_comment) {
+ graph_first = 0x2;
+ comment_delimit = slash_first;
+ }
+ else {
+ graph_first = 0x0;
+ }
+ }
+ else if (buffer->string[range->start] == f_fss_embedded_list_open) {
+ graph_first = 0x0;
+ before_list_open = position_previous;
+ position_previous = range->start;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+
+ while (range->start <= range->stop && range->start < buffer->used) {
+
+ if (buffer->string[range->start] == f_fss_eol) break;
+
+ if (buffer->string[range->start] != f_fss_delimit_placeholder) {
+ status = f_fss_is_space(*buffer, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) break;
+ }
+
+ position_previous = range->start;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ if (depth > 0) {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+ }
+ else {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+ }
+
+ if (buffer->string[range->start] == f_fss_eol) {
+ depth++;
+
+ if (depth >= positions_start.size) {
+ f_macro_string_lengths_t_resize(status, positions_start, positions_start.size + f_fss_default_allocation_step);
+ if (F_status_is_error(status)) break;
+
+ f_macro_fss_objects_t_resize(status, objects, objects.size + f_fss_default_allocation_step);
+ if (F_status_is_error(status)) break;
+ }
+
+ if (positions_start.used <= depth) {
+ positions_start.used = depth + 1;
+ }
+
+ positions_start.array[depth] = range->start + 1;
+
+ objects.array[depth].start = line_start;
+ objects.array[depth].stop = before_list_open;
+
+ if (graph_first == 0x2) {
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = comment_delimit;
+ }
+
+ newline_last = range->start;
+ line_start = range->start + 1;
+ graph_first = 0x1;
+ }
+ else {
+
+ // No valid object close found, seek until EOL.
+ status = f_fss_seek_to_eol(*buffer, range);
+ if (F_status_is_error(status)) break;
+
+ if (graph_first == 0x2) {
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = comment_delimit;
+ }
+
+ newline_last = range->start;
+ line_start = range->start + 1;
+ graph_first = 0x1;
+
+ while (range->start <= range->stop && range->start < buffer->used) {
+
+ if (buffer->string[range->start] == f_fss_eol) {
+ newline_last = range->start;
+ line_start = range->start + 1;
+ break;
+ }
+
+ position_previous = range->start;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ if (depth > 0) {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+ }
+ else {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+ }
+ }
+ }
+ else if (buffer->string[range->start] == f_fss_embedded_list_close) {
+ graph_first = 0x0;
+
+ while (range->start <= range->stop && range->start < buffer->used) {
+
+ position_previous = range->start;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+
+ if (buffer->string[range->start] == f_fss_eol) {
+ break;
+ }
+
+ if (buffer->string[range->start] != f_fss_delimit_placeholder) {
+ status = f_fss_is_space(*buffer, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ break;
+ }
+ }
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ if (depth > 0) {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+ }
+ else {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+ }
+
+ if (buffer->string[range->start] == f_fss_eol) {
+ status = private_fl_fss_nest_increase(found);
+ if (F_status_is_error(status)) break;
+
+ if (found->depth[depth].used == found->depth[depth].size) {
+ f_macro_fss_items_t_resize(status, found->depth[depth], found->depth[depth].size + f_fss_default_allocation_step);
+ if (F_status_is_error(status)) break;
+ }
+
+ position = found->depth[depth].used;
+
+ if (found->depth[depth].array[position].content.size != 1) {
+ f_macro_fss_content_t_resize(status, found->depth[depth].array[position].content, 1);
+ if (F_status_is_error(status)) break;
+ }
+
+ if (depth) {
+ found->depth[depth].array[position].parent = found->depth[depth - 1].used;
+
+ // only assign object positions for nested objects.
+ found->depth[depth].array[position].object.start = objects.array[depth].start;
+ found->depth[depth].array[position].object.stop = objects.array[depth].stop;
+ }
+
+ found->depth[depth].array[position].content.array[0].start = positions_start.array[depth];
+ found->depth[depth].array[position].content.array[0].stop = newline_last;
+ found->depth[depth].array[position].content.used = 1;
+
+ if (position >= found->depth[depth].used) {
+ found->depth[depth].used++;
+ }
+
+ if (found->used < depth + 1) {
+ found->used = depth + 1;
+ }
+
+ if (graph_first == 0x2) {
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = comment_delimit;
+ }
+
+ newline_last = range->start;
+ line_start = range->start + 1;
+ graph_first = 0x1;
+
+ if (!depth) {
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+
+ fl_macro_fss_nest_return_on_overflow_delimited((*buffer), (*range), (*found), positions_start, objects, F_none_eos, F_none_stop)
+
+ f_macro_string_lengths_t_delete_simple(positions_start);
+ f_macro_fss_objects_t_delete_simple(objects);
+
+ return FL_fss_found_content;
+ }
+
+ depth--;
+ }
+ else {
+
+ // No valid object close found, seek until EOL.
+ while (range->start <= range->stop && range->start < buffer->used) {
+
+ if (buffer->string[range->start] == f_fss_eol) {
+ if (graph_first == 0x2) {
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = comment_delimit;
+ }
+
+ newline_last = range->start;
+ line_start = range->start + 1;
+ graph_first = 0x1;
+ break;
+ }
+
+ position_previous = range->start;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) break;
+
+ if (depth > 0) {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop)
+ }
+ else {
+ fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop)
+ }
+ }
+ }
+ else if (graph_first == 0x1 && buffer->string[range->start] == f_fss_comment) {
+ position = range->start;
+
+ status = f_fss_seek_to_eol(*buffer, range);
+ if (F_status_is_error(status)) break;
+
+ status = private_fl_fss_ranges_increase(comments);
+ if (F_status_is_error(status)) break;
+
+ if (range->start > range->stop || range->start >= buffer->used) {
+ range->start--;
+ }
+ else {
+ if (graph_first == 0x2) {
+ status = private_fl_fss_delimits_increase(delimits);
+ if (F_status_is_error(status)) break;
+
+ delimits->array[delimits->used++] = comment_delimit;
+ }
+
+ newline_last = range->start;
+ graph_first = 0x1;
+ }
+
+ comments->array[comments->used].start = position;
+ comments->array[comments->used++].stop = range->start++;
+ continue;
+ }
+ else if (buffer->string[range->start] != f_fss_eol) {
+ position_previous = range->start;
+
+ if (graph_first == 0x1) {
+ status = f_fss_is_space(*buffer, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ graph_first = 0x0;
+ }
+ }
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+
+ if (range->start >= buffer->used || range->start > range->stop) {
+ break;
+ }
+
+ continue;
+ }
+
+ position_previous = range->start;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ f_macro_string_lengths_t_delete_simple(positions_start);
+ f_macro_fss_objects_t_delete_simple(objects);
+
+ delimits->used = delimits_used;
+ comments->used = comments_used;
+
+ if (F_status_is_error(status)) {
+ return status;
+ }
+
+ if (range->start > range->stop) {
+ if (!depth) {
+ return F_status_set_error(F_unterminated_stop);
+ }
+
+ return F_status_set_error(F_unterminated_nest_stop);
+ }
+
+ if (!depth) {
+ return F_status_set_error(F_unterminated_eos);
+ }
+
+ return F_status_set_error(F_unterminated_nest_eos);
+ }
+#endif // _di_fl_fss_embedded_list_content_read_
+
+#ifndef _di_fl_fss_embedded_list_object_write_string_
+ f_return_status fl_fss_embedded_list_object_write_string(const f_string_static_t object, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination) {
+ #ifndef _di_level_1_parameter_checking_
+ if (!destination) return F_status_set_error(F_parameter);
+ #endif // _di_level_1_parameter_checking_
+
+ f_status_t status = f_fss_skip_past_delimit(object, range);
+ if (F_status_is_error(status)) return status;
+
+ if (status == F_none_eos) {
+ status = F_data_not_eos;
+ }
+ else if (status == F_none_stop) {
+ status = F_data_not_stop;
+ }
+
+ if (status == F_data_not_stop || status == F_data_not_eos) {
+ if (complete == f_fss_complete_partial || complete == f_fss_complete_partial_trim || complete == f_fss_complete_full || complete == f_fss_complete_full_trim) {
+ const f_status_t status_allocation = private_fl_fss_destination_increase_by(2, destination);
+ if (F_status_is_error(status_allocation)) return status_allocation;
+
+ destination->string[destination->used++] = f_fss_embedded_list_open;
+
+ if (complete == f_fss_complete_full || complete == f_fss_complete_full_trim) {
+ destination->string[destination->used++] = f_fss_embedded_list_open_end;
+ }
+ }
+
+ return status;
+ }
+
+ // ensure that there is room for a slash delimit, the object open character, and the end of line character.
+ status = private_fl_fss_destination_increase_by(destination->used + (range->stop - range->start) + 3, destination);
+ if (F_status_is_error(status)) return status;
+
+ const f_string_length_t input_start = range->start;
+ const f_string_length_t used_start = destination->used;
+
+ f_string_length_t i = 0;
+ f_string_length_t slash_count = 0;
+
+ f_string_range_t range_next = f_string_range_t_initialize;
+
+ bool ends_on_space = F_false;
+
+ uint8_t width = 0;
+
+ // find the first graph character.
+ while (range->start <= range->stop && range->start < object.used) {
+
+ if (object.string[range->start] == f_fss_comment) {
+
+ // when a comment is found, escape it.
+ status = private_fl_fss_destination_increase(destination);
+ if (F_status_is_error(status)) break;
+
+ destination->string[destination->used++] = f_fss_delimit_slash;
+ break;
+ }
+
+ status = f_fss_is_graph(object, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_true) break;
+
+ // objects will not have leading whitespaces, but having this does not result in an invalid object, so just write the provided spaces.
+ if (object.string[range->start] != f_fss_delimit_placeholder) {
+ if (object.string[range->start] == f_fss_eol) {
+ status = F_status_set_error(F_none_eol);
+ break;
+ }
+
+ status = f_fss_is_space(object, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_true) {
+ width = f_macro_utf_byte_width(object.string[range->start]);
+
+ status = private_fl_fss_destination_increase_by(width, destination);
+ if (F_status_is_error(status)) break;
+
+ for (i = 0; i < width; i++) {
+ destination->string[destination->used++] = object.string[range->start + i];
+ } // for
+ }
+ }
+
+ status = f_utf_buffer_increment(object, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
+
+ while (range->start <= range->stop && range->start < object.used) {
+
+ if (object.string[range->start] == f_fss_delimit_slash) {
+ slash_count = 1;
+
+ for (range->start++; range->start <= range->stop && range->start < object.used; range->start++) {
+
+ if (object.string[range->start] == f_fss_delimit_placeholder) {
+ continue;
+ } else if (object.string[range->start] != f_fss_delimit_slash) {
+ break;
+ }
+
+ slash_count++;
+ } // for
+
+ if (F_status_is_error(status)) break;
+
+ if (range->start > range->stop || range->start >= object.used) {
+
+ // slashes at the end of the object must be delimited to avoid delimiting the object close character.
+ slash_count *= 2;
+ }
+
+ status = private_fl_fss_destination_increase_by(slash_count, destination);
+ if (F_status_is_error(status)) break;
+
+ while (slash_count--) {
+ destination->string[destination->used++] = f_fss_delimit_slash;
+ } // while
+
+ if (range->start > range->stop || range->start >= object.used) {
+ ends_on_space = F_false;
+ break;
+ }
+ }
+
+ if (object.string[range->start] != f_fss_delimit_placeholder) {
+ if (object.string[range->start] == f_fss_eol) {
+ status = F_status_set_error(F_none_eol);
+ break;
+ }
+
+ status = f_fss_is_space(object, *range);
+ if (F_status_is_error(status)) break;
+
+ ends_on_space = status == F_true;
+
+ width = f_macro_utf_byte_width(object.string[range->start]);
+
+ status = private_fl_fss_destination_increase_by(width, destination);
+ if (F_status_is_error(status)) break;
+
+ for (i = 0; i < width; i++) {
+ destination->string[destination->used++] = object.string[range->start + i];
+ } // for
+ }
+
+ status = f_utf_buffer_increment(object, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
+
+ if (complete == f_fss_complete_partial || complete == f_fss_complete_partial_trim || complete == f_fss_complete_full || complete == f_fss_complete_full_trim) {
+ if (complete == f_fss_complete_full_trim) {
+ status = private_fl_fss_basic_list_write_object_trim(used_start, destination);
+
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
+
+ // prevent a space from being added post-trimming.
+ ends_on_space = F_true;
+ }
+
+ status = private_fl_fss_destination_increase_by(3, destination);
+
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
+
+ if (!ends_on_space) {
+ destination->string[destination->used++] = f_fss_space;
+ }
+
+ destination->string[destination->used++] = f_fss_embedded_list_open;
+
+ if (complete == f_fss_complete_full || complete == f_fss_complete_full_trim) {
+ destination->string[destination->used++] = f_fss_embedded_list_open_end;
+ }
+ }
+
+ if (range->start > range->stop) {
+ return F_none_stop;
+ }
+
+ if (range->start >= object.used) {
+ return F_none_eos;
+ }
+
+ return F_none;
+ }
+#endif // _di_fl_fss_embedded_list_object_write_string_
+
+#ifndef _di_fl_fss_embedded_list_content_write_string_
+ f_return_status fl_fss_embedded_list_content_write_string(const f_string_static_t content, const uint8_t complete, const f_string_static_t *prepend, const f_string_ranges_t *ignore, f_string_range_t *range, f_string_dynamic_t *destination) {
+ #ifndef _di_level_1_parameter_checking_
+ if (!range) return F_status_set_error(F_parameter);
+ if (!destination) return F_status_set_error(F_parameter);
+ #endif // _di_level_1_parameter_checking_
+
+ f_status_t status = f_fss_skip_past_delimit(content, range);
+ if (F_status_is_error(status)) return status;
+
+ if (status == F_none_eos) {
+ status = F_data_not_eos;
+ }
+ else if (status == F_none_stop) {
+ status = F_data_not_stop;
+ }
+
+ if (range->start > range->stop || range->start >= content.used) {
+ if (complete == f_fss_complete_full || complete == f_fss_complete_full_trim || complete == f_fss_complete_end) {
+ const f_status_t status_allocation = private_fl_fss_destination_increase_by(2, destination);
+ if (F_status_is_error(status_allocation)) return status_allocation;
+
+ destination->string[destination->used++] = f_fss_embedded_list_close;
+ destination->string[destination->used++] = f_fss_embedded_list_close_end;
+ }
+
+ return status;
+ }
+
+ // ensure that there is room for a slash delimit and possibly the end of content characters.
+ status = private_fl_fss_destination_increase_by(destination->used + (range->stop - range->start) + 3, destination);
+ if (F_status_is_error(status)) return status;
+
+ const f_string_length_t input_start = range->start;
+ const f_string_length_t used_start = destination->used;
+
+ bool is_comment = F_false;
+ bool ends_on_eol = F_false;
+ bool has_graph = F_false;
+ bool do_prepend = F_true;
+
+ f_string_length_t i = 0;
+ f_string_length_t slash_count = 0;
+ f_string_length_t start = 0;
+
+ f_array_length_t r = 0;
+
+ uint8_t width = 0;
+
+ while (range->start <= range->stop && range->start < content.used) {
+
+ if (content.string[range->start] == f_fss_delimit_slash && !is_comment) {
+ slash_count = 1;
+
+ if (do_prepend) {
+ status = private_fl_fss_destination_prepend(prepend, destination);
+ if (F_status_is_error(status)) break;
+
+ do_prepend = F_false;
+ }
+
+ destination->string[destination->used++] = content.string[range->start];
+
+ for (range->start++; range->start <= range->stop && range->start < content.used; range->start++) {
+
+ if (content.string[range->start] == f_fss_delimit_placeholder) continue;
+ if (content.string[range->start] != f_fss_delimit_slash) break;
+
+ destination->string[destination->used++] = f_fss_delimit_slash;
+ slash_count++;
+ } // for
+
+ if (content.string[range->start] == f_fss_embedded_list_open || content.string[range->start] == f_fss_embedded_list_close) {
+ start = range->start++;
+
+ status = f_fss_skip_past_space(content, range);
+ if (F_status_is_error(status)) break;
+
+ if (has_graph && content.string[range->start] == f_fss_embedded_list_close) {
+ // do nothing.
+ }
+ else if (content.string[range->start] == f_fss_eol || range->start >= content.used || range->start > range->stop) {
+
+ if (content.string[range->start] == f_fss_eol) {
+ ends_on_eol = F_true;
+ }
+ else {
+ ends_on_eol = F_false;
+ }
+
+ // increase by total slashes + 1, along with the extended list open and possible newline.
+ status = private_fl_fss_destination_increase_by(slash_count + 3, destination);
+ if (F_status_is_error(status)) break;
+
+ while (slash_count--) {
+ destination->string[destination->used++] = f_fss_delimit_slash;
+ } // while
+
+ destination->string[destination->used++] = f_fss_delimit_slash;
+ destination->string[destination->used++] = content.string[start];
+
+ range->start = start + 1;
+
+ status = private_fl_fss_basic_list_write_add_until_end(content, range, destination);
+ if (F_status_is_error(status)) break;
+
+ if (content.string[range->start] != f_fss_eol) {
+ has_graph = F_true;
+ }
+
+ continue;
+ }
+
+ // increase by character at "start" and possible newline.
+ status = private_fl_fss_destination_increase_by(2, destination);
+ if (F_status_is_error(status)) break;
+
+ destination->string[destination->used++] = content.string[start];
+
+ if (content.string[range->start] == f_fss_eol) {
+ destination->string[destination->used++] = f_fss_eol;
+ ends_on_eol = F_true;
+ }
+ else {
+ ends_on_eol = F_false;
+ }
+
+ range->start = start + 1;
+ continue;
+ }
+ }
+ else if ((content.string[range->start] == f_fss_embedded_list_open || (!has_graph && content.string[range->start] == f_fss_embedded_list_close)) && !is_comment) {
+ start = range->start++;
+
+ if (do_prepend) {
+ status = private_fl_fss_destination_prepend(prepend, destination);
+ if (F_status_is_error(status)) break;
+
+ do_prepend = F_false;
+ }
+
+ has_graph = F_true;
+
+ status = f_fss_skip_past_space(content, range);
+ if (F_status_is_error(status)) break;
+
+ if (content.string[range->start] == f_fss_eol || range->start >= content.used || range->start > range->stop) {
+
+ if (content.string[range->start] == f_fss_eol) {
+ do_prepend = F_true;
+ ends_on_eol = F_true;
+ }
+ else {
+ ends_on_eol = F_false;
+ }
+
+ if (ignore && ignore->used) {
+
+ for (r = 0; r < ignore->used; r++) {
+ if (start >= ignore->array[r].start && start <= ignore->array[r].stop) break;
+ } // for
+
+ if (r < ignore->used) {
+ status = private_fl_fss_destination_increase(destination);
+ if (F_status_is_error(status)) break;
+
+ destination->string[destination->used++] = content.string[start];
+ range->start = start + 1;
+ continue;
+ }
+ }
+
+ // increase by slash and extended list open and possible newline.
+ status = private_fl_fss_destination_increase_by(3, destination);
+ if (F_status_is_error(status)) break;
+
+ destination->string[destination->used++] = f_fss_delimit_slash;
+ destination->string[destination->used++] = content.string[start];
+
+ range->start = start + 1;
+
+ status = private_fl_fss_basic_list_write_add_until_end(content, range, destination);
+ if (F_status_is_error(status)) break;
+
+ continue;
+ }
+
+ status = private_fl_fss_destination_increase(destination);
+ if (F_status_is_error(status)) break;
+
+ destination->string[destination->used++] = content.string[start];
+ range->start = start + 1;
+ continue;
+ }
+ else if (content.string[range->start] == f_fss_comment && !has_graph) {
+ is_comment = F_true;
+ }
+ else if (content.string[range->start] == f_fss_eol) {
+ has_graph = F_false;
+ is_comment = F_false;
+ }
+ else if ((status = f_fss_is_graph(content, *range)) == F_true) {
+ has_graph = F_true;
+ }
+ else if (F_status_is_error(status)) {
+ break;
+ }
+
+ if (content.string[range->start] != f_fss_delimit_placeholder) {
+ if (do_prepend) {
+ status = private_fl_fss_destination_prepend(prepend, destination);
+ if (F_status_is_error(status)) break;
+
+ do_prepend = F_false;
+ }
+
+ if (content.string[range->start] == f_fss_eol) {
+ do_prepend = F_true;
+ ends_on_eol = F_true;
+ }
+ else {
+ ends_on_eol = F_false;
+ }
+
+ width = f_macro_utf_byte_width(content.string[range->start]);
+
+ status = private_fl_fss_destination_increase_by(width, destination);
+ if (F_status_is_error(status)) break;
+
+ for (i = 0; i < width; i++) {
+ destination->string[destination->used++] = content.string[range->start + i];
+ } // for
+ }
+
+ status = f_utf_buffer_increment(content, range, 1);
+ if (F_status_is_error(status)) break;
+ } // while
+
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
+
+ if (complete == f_fss_complete_full || complete == f_fss_complete_full_trim || complete == f_fss_complete_end) {
+ status = private_fl_fss_destination_increase_by(3, destination);
+ if (F_status_is_error(status)) return status;
+
+ if (!ends_on_eol) {
+ destination->string[destination->used++] = f_fss_eol;
+ }
+
+ destination->string[destination->used++] = f_fss_embedded_list_close;
+ destination->string[destination->used++] = f_fss_embedded_list_close_end;
+ }
+
+ if (range->start > range->stop) {
+ return F_none_stop;
+ }
+
+ if (range->start >= content.used) {
+ return F_none_eos;
+ }
+
+ return F_none;
+ }
+#endif // _di_fl_fss_embedded_list_content_write_string_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 1
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This is the fss-0008 implementation.
+ */
+#ifndef _FL_fss_embedded_list_h
+#define _FL_fss_embedded_list_h
+
+// libc includes
+#include <ctype.h>
+#include <string.h>
+
+// fll-0 includes
+#include <level_0/status.h>
+#include <level_0/fss.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/type.h>
+#include <level_0/utf.h>
+
+// fll-1 includes
+#include <level_1/fss.h>
+#include <level_1/fss_basic.h>
+#include <level_1/fss_status.h>
+#include <level_1/fss_macro.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Read an fss-0008 object.
+ *
+ * This will record where delimit placeholders exist but will not apply the delimits.
+ *
+ * @param buffer
+ * The buffer to read from.
+ * This will be updated with delimit placeholders as it is being processed.
+ * @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 found
+ * A location where a valid object was found.
+ * @param delimits
+ * A delimits array representing where delimits exist within the buffer.
+ *
+ * @return
+ * FL_fss_found_object on success and object was found (start location is at end of object).
+ * FL_fss_found_object_not on success and no object was found (start location is after character designating this is not an object).
+ * F_none_eos on success after reaching the end of the buffer (a valid object is not yet confirmed).
+ * F_none_stop on success after reaching stopping point (a valid object is not yet confirmed).
+ * F_data_not_eos no objects found after reaching the end of the buffer (essentially only comments are found).
+ * F_data_not_stop no data found after reaching stopping point (essentially only comments are found).
+ * F_unterminated_group_eos if EOS was reached before the a group termination was reached.
+ * F_unterminated_group_stop if stop point was reached before the a group termination was reached.
+ * F_array_too_large (with error bit) if a buffer is too large.
+ * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ * F_incomplete_utf_eos (with error bit) if the end of buffer is reached before the complete UTF-8 character can be processed.
+ * F_incomplete_utf_stop (with error bit) if the stop location is reached before the complete UTF-8 character can be processed.
+ * F_memory_reallocation (with error bit) on reallocation error.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ * Errors (with error bit) from: f_utf_buffer_increment().
+ * Errors (with error bit) from: f_fss_is_graph().
+ * Errors (with error bit) from: f_fss_is_space().
+ * Errors (with error bit) from: f_fss_seek_to_eol().
+ * Errors (with error bit) from: f_fss_skip_past_space().
+ */
+#ifndef _di_fl_fss_embedded_list_object_read_
+ extern f_return_status fl_fss_embedded_list_object_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_object_t *found, f_fss_delimits_t *delimits);
+#endif // _di_fl_fss_embedded_list_object_read_
+
+/**
+ * Read an fss-0008 content.
+ *
+ * @fixme the recursive part of this is actually fss-0008 (Embedded) content, fss-0008 is not recursive, oops!
+ *
+ * This will record where delimit placeholders exist but will not apply the delimits.
+ *
+ * This operates on the assumption that found.array[0].array[found.array[0].used].content is the current content being processed.
+ * Therefore the object for this content will also need to be found.array[0].array[found.array[0].used].object.
+ * The object at depth 0 will not be populated, but all nested objects will be populated at their respective depth along with the content.
+ *
+ * @param buffer
+ * The buffer to read from.
+ * This will be updated with delimit placeholders as it is being processed.
+ * @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 found
+ * A set of all locations where a valid content was found.
+ * @param delimits
+ * A delimits array representing where delimits exist within the buffer.
+ * @param comments
+ * An array of ranges representing where comments are found within any valid content.
+ * This only stores comments found within valid content only.
+ * The comment range will include the trailing newline.
+ *
+ * @return
+ * FL_fss_found_content on success and content was found (start location is at end of content).
+ * FL_fss_found_content_not on success and no content was found (start location is after character designating this is not a content).
+ * F_none_eos on success after reaching the end of the buffer (a valid object is not yet confirmed).
+ * F_none_stop on success after reaching stopping point (a valid object is not yet confirmed).
+ * F_data_not_eos no objects found after reaching the end of the buffer (essentially only comments are found).
+ * F_data_not_stop no data found after reaching stopping point (essentially only comments are found).
+ * F_unterminated_group_eos if EOS was reached before the a group termination was reached.
+ * F_unterminated_group_stop if stop point was reached before the a group termination was reached.
+ * F_array_too_large (with error bit) if a buffer is too large.
+ * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ * F_incomplete_utf_eos (with error bit) if the end of buffer is reached before the complete UTF-8 character can be processed.
+ * F_incomplete_utf_stop (with error bit) if the stop location is reached before the complete UTF-8 character can be processed.
+ * F_memory_reallocation (with error bit) on reallocation error.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ * Errors (with error bit) from: f_utf_buffer_increment().
+ * Errors (with error bit) from: f_fss_is_graph().
+ * Errors (with error bit) from: f_fss_is_space().
+ * Errors (with error bit) from: f_fss_skip_past_space().
+ */
+#ifndef _di_fl_fss_embedded_list_content_read_
+ extern f_return_status fl_fss_embedded_list_content_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_nest_t *found, f_fss_delimits_t *delimits, f_fss_comments_t *comments);
+#endif // _di_fl_fss_embedded_list_content_read_
+
+/**
+ * Write an fss-0008 object from a given string.
+ *
+ * This will write the given string range as a valid object.
+ * Anything within this range will be escaped as necessary.
+ * This will stop if EOL is reached.
+ *
+ * The destination string may have NULLs.
+ *
+ * @param object
+ * The string to write as (does not stop at NULLS, they are ignored and not written).
+ * @param complete
+ * If f_fss_complete_none, then only the object name is written.
+ * If f_fss_complete_full, this will write any appropriate open and close aspects of this object.
+ * If f_fss_complete_full_trim, this will write any appropriate open and close aspects of this object, but will omit whitespace before and after the object.
+ * If f_fss_complete_partial, this will write any appropriate open and close aspects of this object.
+ * If f_fss_complete_partial_tim, this will write any appropriate open and close aspects of this object, but will omit whitespace before and after the object.
+ * @param range
+ * The start/stop location within the object string to write as an object.
+ * @param destination
+ * The buffer where the object is written to.
+ *
+ * @return
+ * F_none on success.
+ * F_none_eos on success after reaching the end of the buffer.
+ * F_data_not_stop no data to write due start location being greater than stop location.
+ * F_data_not_eos no data to write due start location being greater than or equal to buffer size.
+ * F_none_stop on success after reaching stopping point .
+ * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ * F_memory_reallocation (with error bit) on reallocation error.
+ * F_none_eol (with error bit) after reaching an EOL, which is not supported by the standard.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ * Errors (with error bit) from: f_utf_buffer_increment().
+ */
+#ifndef _di_fl_fss_embedded_list_object_write_string_
+ extern f_return_status fl_fss_embedded_list_object_write_string(const f_string_static_t object, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination);
+#endif // _di_fl_fss_embedded_list_object_write_string_
+
+/**
+ * Write an fss-0008 content from a given string.
+ *
+ * This will write the given string range as a valid content.
+ * Anything within this range will be escaped as necessary.
+ *
+ * The destination string may have NULLs.
+ *
+ * @param content
+ * The string to write as (does not stop at NULLS, they are ignored and not written).
+ * @param complete
+ * If f_fss_complete_none, then only the content is written.
+ * If f_fss_complete_next, then the content followed by any appropriate "next" character separating one content from the next, if applicable.
+ * If f_fss_complete_end, then the content followed by any appropriate "end" character designating the last content for some object, printing final newline, if applicable.
+ * If f_fss_complete_partial, this will write any appropriate open and close aspects of this content, except for the final newline.
+ * If f_fss_complete_full, this will write any appropriate open and close aspects of this content, including the final newline.
+ * @param prepend
+ * A string of whitespace to prepend at the start of each line.
+ * This should only be whitespace, anything else could product invalid content.
+ * Set the pointer address to 0 to disable.
+ * @param ignore
+ * An optional list of ranges within the string to ignore.
+ * These ranges are only checked/ignored if there is a valid nested object open or a valid nested object close.
+ * Any valid nested object open or valid nested object close inside an ingore range will not be escaped.
+ * Set the pointer address to 0 to disable.
+ * @param range
+ * The start/stop location within the content string to write as an content.
+ * @param destination
+ * The buffer where the content is written to.
+ *
+ * @return
+ * F_none on success.
+ * F_none_eos on success after reaching the end of the buffer.
+ * F_data_not_stop no data to write due start location being greater than stop location.
+ * F_data_not_eos no data to write due start location being greater than or equal to buffer size.
+ * F_none_stop on success after reaching stopping point .
+ * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ * F_memory_reallocation (with error bit) on reallocation error.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ * Errors (with error bit) from: f_utf_buffer_increment().
+ */
+#ifndef _di_fl_fss_embedded_list_content_write_string_
+ extern f_return_status fl_fss_embedded_list_content_write_string(const f_string_static_t content, const uint8_t complete, const f_string_static_t *prepend, const f_string_ranges_t *ignore, f_string_range_t *range, f_string_dynamic_t *destination);
+#endif // _di_fl_fss_embedded_list_content_write_string_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _FL_fss_embedded_list_h
* 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 found
- * A set of all locations where a valid object was found.
+ * A location where a valid object was found.
* @param quoted
* This will store whether or not this object is quoted and what quote is in use.
* Set pointer address to 0 to not use.
* 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 found
- * A set of all locations where a valid object was found.
+ * A location where a valid object was found.
* @param delimits
* A delimits array representing where delimits exist within the buffer.
*
/**
* Read an fss-0003 content.
*
+ * @fixme the recursive part of this is actually fss-0008 (Embedded) content, fss-0003 is not recursive, oops!
+ *
* This will record where delimit placeholders exist but will not apply the delimits.
*
* This operates on the assumption that found.array[0].array[found.array[0].used].content is the current content being processed.
build_language c
build_libraries -lc
build_libraries-individual -lf_file -lf_fss -lf_memory -lf_utf
-build_sources_library private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c
+build_sources_library private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c
build_sources_program
-build_sources_headers fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h
+build_sources_headers fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h
build_sources_script
build_sources_setting
build_script yes
--- /dev/null
+#include "fss_embedded_list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fll_fss_embedded_list_read_
+ f_return_status fll_fss_embedded_list_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_nest_t *nest, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) {
+ #ifndef _di_level_3_parameter_checking_
+ if (!buffer) return F_status_set_error(F_parameter);
+ if (!range) return F_status_set_error(F_parameter);
+ if (!nest) return F_status_set_error(F_parameter);
+ if (!objects_delimits) return F_status_set_error(F_parameter);
+ if (!comments) return F_status_set_error(F_parameter);
+ #endif // _di_level_3_parameter_checking_
+
+ f_status_t status = F_none;
+ f_status_t status2 = F_none;
+ f_string_length_t initial_used = 0;
+
+ bool found_data = F_false;
+
+ if (!nest->used) {
+ f_macro_fss_nest_t_resize(status2, (*nest), f_fss_default_allocation_step);
+ if (F_status_is_error(status2)) return status2;
+ }
+ else {
+ initial_used = nest->depth[0].used;
+ }
+
+ do {
+ do {
+ if (nest->depth[0].used == nest->depth[0].size) {
+ f_macro_fss_items_t_resize(status2, nest->depth[0], nest->depth[0].used + f_fss_default_allocation_step);
+ if (F_status_is_error(status)) return status;
+ }
+
+ status = fl_fss_embedded_list_object_read(buffer, range, &nest->depth[0].array[nest->depth[0].used].object, objects_delimits);
+ if (F_status_is_error(status)) return status;
+
+ if (range->start >= range->stop || range->start >= buffer->used) {
+ if (status == FL_fss_found_object || status == FL_fss_found_object_content_not) {
+
+ // extended list requires content closure, so this could be an error.
+ return FL_fss_found_object_content_not;
+ }
+
+ if (found_data) {
+ if (range->start >= buffer->used) {
+ return F_none_eos;
+ }
+
+ return F_none_stop;
+ }
+ else {
+ if (range->start >= buffer->used) {
+ return F_data_not_eos;
+ }
+
+ return F_data_not_stop;
+ }
+ }
+
+ if (status == FL_fss_found_object) {
+ found_data = F_true;
+
+ status = fl_fss_embedded_list_content_read(buffer, range, nest, contents_delimits ? contents_delimits : objects_delimits, comments);
+
+ break;
+ }
+ else if (status == FL_fss_found_object_content_not) {
+ found_data = F_true;
+ break;
+ }
+ } while (status == FL_fss_found_object_not);
+
+ if (status == F_none_eos || status == F_none_stop) {
+ return status;
+ }
+ else if (status == F_data_not_eos || status == F_data_not_stop) {
+
+ // If at least some valid object was found, then return F_none equivalents.
+ if (nest->depth[0].used > initial_used) {
+ if (status == F_data_not_eos) return F_none_eos;
+ if (status == F_data_not_stop) return F_none_stop;
+ }
+
+ return status;
+ }
+ else if (status == F_unterminated_eos || status == F_unterminated_stop || status == F_unterminated_nest_eos || status == F_unterminated_nest_stop) {
+
+ // If at least some valid object was found, then return F_none equivalents.
+ if (nest->depth[0].used > initial_used) {
+ if (status == F_data_not_eos) return F_none_eos;
+ if (status == F_data_not_stop) return F_none_stop;
+ }
+
+ return status;
+ }
+ else if (status != FL_fss_found_object && status != FL_fss_found_content && status != FL_fss_found_content_not && status != FL_fss_found_object_content_not) {
+ return status;
+ }
+ // When content is found, the range->start is incremented, if content is found at range->stop, then range->start will be > range.stop.
+ else if (range->start >= range->stop || range->start >= buffer->used) {
+ if (range->start >= buffer->used) {
+ return F_none_eos;
+ }
+
+ return F_none_stop;
+ }
+ } while (range->start < f_string_length_t_size);
+
+ return F_status_is_error(F_number_overflow);
+ }
+#endif // _di_fll_fss_embedded_list_read_
+
+#ifndef _di_fll_fss_embedded_list_write_string_
+ f_return_status fll_fss_embedded_list_write_string(const f_string_static_t object, const f_string_static_t content, const f_string_static_t *content_prepend, const f_string_ranges_t *ignore, f_string_dynamic_t *destination) {
+ #ifndef _di_level_2_parameter_checking_
+ if (!destination) return F_status_set_error(F_parameter);
+ #endif // _di_level_2_parameter_checking_
+
+ f_status_t status = 0;
+ f_string_range_t range = f_macro_string_range_t_initialize(object.used);
+
+ status = fl_fss_embedded_list_object_write_string(object, f_fss_complete_full, &range, destination);
+
+ if (F_status_is_error(status) || status == F_data_not_stop || status == F_data_not_eos) {
+ return status;
+ }
+
+ if (status == F_none || status == F_none_stop || status == F_none_eos || status == F_none_eol) {
+ if (content.used) {
+ range.start = 0;
+ range.stop = content.used - 1;
+ }
+ else {
+ range.start = 1;
+ range.stop = 0;
+ }
+
+ status = fl_fss_embedded_list_content_write_string(content, f_fss_complete_full, content_prepend, ignore, &range, destination);
+ }
+
+ return status;
+ }
+#endif // _di_fll_fss_embedded_list_write_string_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 2
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This is the fss-0008 implementation.
+ */
+#ifndef _FLL_fss_embedded_list_h
+#define _FLL_fss_embedded_list_h
+
+// fll-0 includes
+#include <level_0/status.h>
+#include <level_0/fss.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/type.h>
+
+// fll-1 includes
+#include <level_1/fss.h>
+#include <level_1/fss_embedded_list.h>
+#include <level_1/fss_status.h>
+#include <level_1/fss_macro.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Read a buffer expected to be in fss-0008 format, getting all objects and their respective content.
+ *
+ * @param buffer
+ * The buffer to read from.
+ * @param range
+ * The range within the buffer that is currently being read.
+ * @param nest
+ * An nested set of all objects and content.
+ * @param objects_delimits
+ * An array of delimits for objects detected during processing.
+ * The caller is expected to decide if and when to process them.
+ * @param contents_delimits
+ * (optional) An array of delimits for contents detected during processing.
+ * The caller is expected to decide if and when to process them.
+ * Set pointer address to 0 and all delimits will instead utilize objects_delimits.
+ * @param comments
+ * An array of ranges representing where comments are found within any valid content.
+ * This only stores comments found within valid content only.
+ *
+ * @return
+ * F_none on success (both valid object and valid content found with start location is at end of content).
+ * F_none_eos on success after reaching the end of the buffer (both valid object and valid content found with start location is at end of buffer).
+ * F_none_stop on success after reaching stopping point (both valid object and valid content found with start location is at stop point).
+ * F_data_not_eol if there is no data to write and EOL was reached (@todo: review related code and detemine what this is doing).
+ * F_data_not_eos no data to write due start location being greater than or equal to buffer size.
+ * F_data_not_stop no data to write due start location being greater than stop location.
+ * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ * F_incomplete_utf_eos (with error bit) if the end of buffer is reached before the complete UTF-8 character can be processed.
+ * F_incomplete_utf_stop (with error bit) if the stop location is reached before the complete UTF-8 character can be processed.
+ * F_memory_reallocation (with error bit) on reallocation error.
+ * F_number_overflow (with error bit) if the maximimum buffer size is reached.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_unterminated_eos (with error bit) if end of buffer is reached before a closing bracket is found (object was found).
+ * F_unterminated_nest_eos (with error bit) if end of buffer is reached while inside a nested list before a closing bracket is found (object was found).
+ * F_unterminated_nest_stop (with error bit) if stop location is reached while inside a nested list before a closing bracket is found (object was found).
+ * F_unterminated_stop (with error bit) if stop location is reached before a closing bracket is found (object was found).
+ * F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ * FL_fss_found_object_content_not on success and object was found but no content was found (start location is at end of object).
+ *
+ * Errors (with error bit) from: fl_fss_embedded_list_content_read().
+ * Errors (with error bit) from: fl_fss_embedded_list_object_read().
+ */
+#ifndef _di_fll_fss_embedded_list_read_
+ extern f_return_status fll_fss_embedded_list_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_nest_t *nest, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments);
+#endif // _di_fll_fss_embedded_list_read_
+
+/**
+ * Write a single object string and content string to a buffer, using fss-0008 format.
+ *
+ * @param object
+ * A string representing the object.
+ * @param content
+ * A string representing the content.
+ * @param content_prepend
+ * A string to prepend at the start of each line in content, such as spaces.
+ * Set the pointer address to 0 to disable.
+ * @param ignore
+ * An optional list of ranges within the string to ignore.
+ * These ranges are only checked/ignored if there is a valid nested object open or a valid nested object close.
+ * Any valid nested object open or valid nested object close inside an ingore range will not be escaped.
+ * Set the pointer address to 0 to disable.
+ * @param destination
+ * The buffer where the content is written to.
+ *
+ * @return
+ * F_none on success.
+ * F_none_eos on success after reaching the end of the buffer.
+ * F_none_stop on success after reaching stopping point.
+ * F_data_not_eos no data to write due start location being greater than or equal to buffer size.
+ * F_data_not_stop no data to write due start location being greater than stop location.
+ * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ * F_memory_reallocation (with error bit) on reallocation error.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ * Errors (with error bit) from: fl_fss_embedded_list_content_write_string().
+ * Errors (with error bit) from: fl_fss_embedded_list_object_write_string().
+ * Errors (with error bit) from: fl_string_dynamic_increase_by().
+ */
+#ifndef _di_fll_fss_embedded_list_write_string_
+ extern f_return_status fll_fss_embedded_list_write_string(const f_string_static_t object, const f_string_static_t content, const f_string_static_t *content_prepend, const f_string_ranges_t *ignore, f_string_dynamic_t *destination);
+#endif // _di_fll_fss_embedded_list_write_string_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _FLL_fss_embedded_list_h
build_language c
build_libraries -lc
build_libraries-individual -lfl_conversion -lfl_fss -lfl_status -lfl_string -lf_conversion -lf_file -lf_fss -lf_memory -lf_utf
-build_sources_library fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c
+build_sources_library fss.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c fss_status.c
build_sources_program
-build_sources_headers fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h
+build_sources_headers fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h
build_sources_script
build_sources_setting
build_script yes
--- /dev/null
+#include "fss_embedded_list_read.h"
+#include "private-fss_embedded_list_read.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_read_print_help_
+ f_return_status fss_embedded_list_read_print_help(const f_file_t output, const f_color_context_t context) {
+
+ fll_program_print_help_header(output, context, fss_embedded_list_read_name_long, fss_embedded_list_read_version);
+
+ fll_program_print_help_option(output, context, f_console_standard_short_help, f_console_standard_long_help, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print this help message.");
+ fll_program_print_help_option(output, context, f_console_standard_short_dark, f_console_standard_long_dark, f_console_symbol_short_disable, f_console_symbol_long_disable, " Output using colors that show up better on dark backgrounds.");
+ fll_program_print_help_option(output, context, f_console_standard_short_light, f_console_standard_long_light, f_console_symbol_short_disable, f_console_symbol_long_disable, " Output using colors that show up better on light backgrounds.");
+ fll_program_print_help_option(output, context, f_console_standard_short_no_color, f_console_standard_long_no_color, f_console_symbol_short_disable, f_console_symbol_long_disable, "Do not output in color.");
+ fll_program_print_help_option(output, context, f_console_standard_short_quiet, f_console_standard_long_quiet, f_console_symbol_short_disable, f_console_symbol_long_disable, " Decrease verbosity beyond normal output.");
+ fll_program_print_help_option(output, context, f_console_standard_short_normal, f_console_standard_long_normal, f_console_symbol_short_disable, f_console_symbol_long_disable, " Set verbosity to normal output.");
+ fll_program_print_help_option(output, context, f_console_standard_short_verbose, f_console_standard_long_verbose, f_console_symbol_short_disable, f_console_symbol_long_disable, " Increase verbosity beyond normal output.");
+ fll_program_print_help_option(output, context, f_console_standard_short_debug, f_console_standard_long_debug, f_console_symbol_short_disable, f_console_symbol_long_disable, " Enable debugging, inceasing verbosity beyond normal output.");
+ fll_program_print_help_option(output, context, f_console_standard_short_version, f_console_standard_long_version, f_console_symbol_short_disable, f_console_symbol_long_disable, " Print only the version number.");
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_at, fss_embedded_list_read_long_at, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric index.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_content, fss_embedded_list_read_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the content (default).");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_delimit, fss_embedded_list_read_long_delimit, f_console_symbol_short_enable, f_console_symbol_long_enable, " Designate how to handle applying delimits.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_depth, fss_embedded_list_read_long_depth, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric depth.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_empty, fss_embedded_list_read_long_empty, f_console_symbol_short_enable, f_console_symbol_long_enable, " Include empty content when processing.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_line, fss_embedded_list_read_long_line, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print only the content at the given line.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_name, fss_embedded_list_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object with this name.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_object, fss_embedded_list_read_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the object.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_pipe, fss_embedded_list_read_long_pipe, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print using the special pipe format.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_select, fss_embedded_list_read_long_select, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select sub-content at this index.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_total, fss_embedded_list_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the total number of lines.");
+ fll_program_print_help_option(output, context, fss_embedded_list_read_short_trim, fss_embedded_list_read_long_trim, f_console_symbol_short_enable, f_console_symbol_long_enable, " Trim object names on select or print.");
+
+ fll_program_print_help_usage(output, context, fss_embedded_list_read_name, "filename(s)");
+
+ fl_color_print(output.stream, context.set.important, " Notes:");
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " This program will print the content associated with the given object and content data based on the FSS-0002 Basic List standard.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " When using the ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+ fprintf(output.stream, " option, an order of operations is enforced on the parameters.%c", f_string_eol[0]);
+
+ fprintf(output.stream, " When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%c", f_string_eol[0]);
+
+ fprintf(output.stream, " ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_at);
+ fprintf(output.stream, ": An object index at the specified depth.%c", f_string_eol[0]);
+
+ fprintf(output.stream, " ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+ fprintf(output.stream, ": A new depth within the specified depth, indexed from the root.%c", f_string_eol[0]);
+
+ fprintf(output.stream, " ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_name);
+ fprintf(output.stream, ": An object name at the specified depth.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " The parameter ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+ fprintf(output.stream, " must be in numeric order, but values in between may be skipped.%c", f_string_eol[0]);
+ fprintf(output.stream, " ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%c", f_string_eol[0]);
+ fprintf(output.stream, " ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " The parameter ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+ fprintf(output.stream, " selects a content index at a given depth.%c", f_string_eol[0]);
+ fprintf(output.stream, " (This parameter is not synonymous with the depth parameter and does not relate to nested content).%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " Specify both ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+ fprintf(output.stream, " and the ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_total);
+ fprintf(output.stream, " parameters to get the total objects.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " When both ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_at);
+ fprintf(output.stream, " and ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_name);
+ fprintf(output.stream, " parameters are specified (at the same depth), the ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_at);
+ fprintf(output.stream, " parameter value will be treated as a position relative to the specified ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_name);
+ fprintf(output.stream, " parameter value.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " This program may support parameters, such as ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+ fprintf(output.stream, " or ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+ fprintf(output.stream, ", even if not supported by the standard.%c", f_string_eol[0]);
+ fprintf(output.stream, " This is done to help ensure consistency for scripting.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " For parameters like ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+ fprintf(output.stream, ", if the standard doesn't support nested content, then only a depth of 0 would be valid.%c", f_string_eol[0]);
+
+ fprintf(output.stream, " For parameters like ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+ fprintf(output.stream, ", if the standard doesn't support multiple content groups, then only a select of 0 would be valid.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " The parameter ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_trim);
+ fprintf(output.stream, " will remove leading and trailing whitespaces when selecting objects or when printing objects.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " When specifying both the ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+ fprintf(output.stream, " parameter and the ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_content);
+ fprintf(output.stream, " parameter, the entire object and content are printed, including the formatting.%c", f_string_eol[0]);
+ fprintf(output.stream, " Both the object and content printed are already escaped.%c", f_string_eol[0]);
+ fprintf(output.stream, " Both the object and content are separated by an EOL.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " The parameter ");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_delimit);
+ fprintf(output.stream, " accepts the following:%c", f_string_eol[0]);
+ fprintf(output.stream, " - ");
+ fl_color_print(output.stream, context.set.notable, "%s", fss_embedded_list_read_delimit_mode_name_none);
+ fprintf(output.stream, ": Do not apply delimits.%c", f_string_eol[0]);
+ fprintf(output.stream, " - ");
+ fl_color_print(output.stream, context.set.notable, "%s", fss_embedded_list_read_delimit_mode_name_all);
+ fprintf(output.stream, ": (default) apply all delimits.%c", f_string_eol[0]);
+ fprintf(output.stream, " - a number, 0 or greater: apply delimits for the specified depth.%c", f_string_eol[0]);
+ fprintf(output.stream, " - a number, 0 or greater, followed by a ");
+ fl_color_print(output.stream, context.set.notable, "%s", fss_embedded_list_read_delimit_mode_name_greater);
+ fprintf(output.stream, ": (such as '1+') apply delimits for the specified depth and any greater depth (numerically).%c", f_string_eol[0]);
+ fprintf(output.stream, " - a number, 0 or greater, followed by a ");
+ fl_color_print(output.stream, context.set.notable, "%s", fss_embedded_list_read_delimit_mode_name_lesser);
+ fprintf(output.stream, ": (such as '1-') apply delimits for the specified depth and any lesser depth (numerically).%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ return F_none;
+ }
+#endif // _di_fss_embedded_list_read_print_help_
+
+#ifndef _di_fss_embedded_list_read_main_
+ f_return_status fss_embedded_list_read_main(const f_console_arguments_t arguments, fss_embedded_list_read_data_t *data) {
+ f_status_t status = F_none;
+
+ {
+ const f_console_parameters_t parameters = f_macro_console_parameters_t_initialize(data->parameters, fss_embedded_list_read_total_parameters);
+
+ {
+ f_console_parameter_id_t ids[3] = { fss_embedded_list_read_parameter_no_color, fss_embedded_list_read_parameter_light, fss_embedded_list_read_parameter_dark };
+ const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 3);
+
+ status = fll_program_parameter_process(arguments, parameters, choices, F_true, &data->remaining, &data->context);
+
+ data->error.context = data->context.set.error;
+ data->error.notable = data->context.set.notable;
+
+ if (F_status_is_error(status)) {
+ fss_embedded_list_read_delete_data(data);
+ return F_status_set_error(status);
+ }
+ }
+
+ // Identify priority of verbosity related parameters.
+ {
+ f_console_parameter_id_t ids[4] = { fss_embedded_list_read_parameter_verbosity_quiet, fss_embedded_list_read_parameter_verbosity_normal, fss_embedded_list_read_parameter_verbosity_verbose, fss_embedded_list_read_parameter_verbosity_debug };
+ f_console_parameter_id_t choice = 0;
+ const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 4);
+
+ status = f_console_parameter_prioritize_right(parameters, choices, &choice);
+
+ if (F_status_is_error(status)) {
+ fss_embedded_list_read_delete_data(data);
+ return status;
+ }
+
+ if (choice == fss_embedded_list_read_parameter_verbosity_quiet) {
+ data->error.verbosity = f_console_verbosity_quiet;
+ }
+ else if (choice == fss_embedded_list_read_parameter_verbosity_normal) {
+ data->error.verbosity = f_console_verbosity_normal;
+ }
+ else if (choice == fss_embedded_list_read_parameter_verbosity_verbose) {
+ data->error.verbosity = f_console_verbosity_verbose;
+ }
+ else if (choice == fss_embedded_list_read_parameter_verbosity_debug) {
+ data->error.verbosity = f_console_verbosity_debug;
+ }
+ }
+
+ status = F_none;
+ }
+
+ if (data->parameters[fss_embedded_list_read_parameter_help].result == f_console_result_found) {
+ fss_embedded_list_read_print_help(data->output, data->context);
+
+ fss_embedded_list_read_delete_data(data);
+ return F_none;
+ }
+
+ if (data->parameters[fss_embedded_list_read_parameter_version].result == f_console_result_found) {
+ fll_program_print_version(data->output, fss_embedded_list_read_version);
+
+ fss_embedded_list_read_delete_data(data);
+ return F_none;
+ }
+
+ if (data->remaining.used > 0 || data->process_pipe) {
+ if (data->parameters[fss_embedded_list_read_parameter_at].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_at);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' requires a positive number.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_depth].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' requires a positive number.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_line);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' requires a positive number.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_name].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_name);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' requires a string.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_select].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' requires a positive number.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (data->parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found) {
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_additional) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify the '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_line);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_select].result == f_console_result_additional) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify the '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (data->parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify both the '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' and the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_content);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_total);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+
+ if (data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_additional) {
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify the '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_line);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_total);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+
+ if (data->parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify the '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_pipe);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_total);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_embedded_list_read_parameter_delimit].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_delimit);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' requires a value.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_embedded_list_read_parameter_delimit].result == f_console_result_additional) {
+ const f_string_length_t location = data->parameters[fss_embedded_list_read_parameter_delimit].values.array[0];
+ f_string_length_t length = strnlen(arguments.argv[location], f_console_length_size);
+
+ if (length == 0) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_delimit);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must not be empty.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+ else if (fl_string_compare(arguments.argv[location], fss_embedded_list_read_delimit_mode_name_none, length, fss_embedded_list_read_delimit_mode_name_none_length) == F_equal_to) {
+ data->delimit_mode = fss_embedded_list_read_delimit_mode_none;
+ }
+ else if (fl_string_compare(arguments.argv[location], fss_embedded_list_read_delimit_mode_name_all, length, fss_embedded_list_read_delimit_mode_name_all_length) == F_equal_to) {
+ data->delimit_mode = fss_embedded_list_read_delimit_mode_all;
+ }
+ else {
+ data->delimit_mode = fss_embedded_list_read_delimit_mode_depth;
+
+ if (arguments.argv[location][length - 1] == fss_embedded_list_read_delimit_mode_name_greater[0]) {
+ data->delimit_mode = fss_embedded_list_read_delimit_mode_depth_greater;
+
+ // shorten the length to better convert the remainder to a number.
+ length--;
+ }
+ else if (arguments.argv[location][length - 1] == fss_embedded_list_read_delimit_mode_name_lesser[0]) {
+ data->delimit_mode = fss_embedded_list_read_delimit_mode_depth_lesser;
+
+ // shorten the length to better convert the remainder to a number.
+ length--;
+ }
+
+ f_string_range_t range = f_macro_string_range_t_initialize(length);
+
+ // ignore leading plus sign.
+ if (arguments.argv[location][0] == '+') {
+ range.start++;
+ }
+
+ status = fl_conversion_string_to_number_unsigned(arguments.argv[location], &data->delimit_depth, range);
+
+ if (F_status_is_error(status)) {
+ fll_error_parameter_integer_print(data->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_delimit, arguments.argv[location]);
+ }
+ }
+ }
+ }
+
+ fss_embedded_list_read_depths_t depths = fss_embedded_list_read_depths_t_initialize;
+
+ f_fss_delimits_t objects_delimits = f_fss_delimits_t_initialize;
+ f_fss_delimits_t contents_delimits = f_fss_delimits_t_initialize;
+ f_fss_comments_t comments = f_fss_comments_t_initialize;
+
+ f_string_length_t original_size = data->quantity.total;
+
+ if (F_status_is_error_not(status)) {
+ status = fss_embedded_list_read_main_preprocess_depth(arguments, *data, &depths);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data->error, F_status_set_fine(status), "fss_embedded_list_read_main_preprocess_depth", F_true);
+ }
+ }
+
+ if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_select].result == f_console_result_found) {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter requires a positive number.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (F_status_is_error_not(status) && data->process_pipe) {
+ f_file_t file = f_file_t_initialize;
+
+ file.id = f_type_descriptor_input;
+
+ status = f_file_read(file, &data->buffer);
+
+ if (F_status_is_error(status)) {
+ fll_error_file_print(data->error, F_status_set_fine(status), "f_file_read", F_true, "-", "read", fll_error_file_type_pipe);
+ }
+ else {
+ status = fss_embedded_list_read_main_process_file(arguments, data, "-", depths, &objects_delimits, &contents_delimits, &comments);
+
+ if (F_status_is_error(status)) {
+ fll_error_file_print(data->error, F_status_set_fine(status), "fss_embedded_list_read_main_process_file", F_true, "-", "read", fll_error_file_type_pipe);
+ }
+ }
+
+ // Clear buffers before continuing.
+ f_macro_fss_nest_t_delete_simple(data->nest);
+ f_macro_string_dynamic_t_delete_simple(data->buffer);
+ }
+
+ if (F_status_is_error_not(status) && data->remaining.used > 0) {
+ for (f_array_length_t i = 0; i < data->remaining.used; i++) {
+ f_file_t file = f_file_t_initialize;
+
+ status = f_file_open(arguments.argv[data->remaining.array[i]], 0, &file);
+
+ data->quantity.total = original_size;
+
+ if (F_status_is_error(status)) {
+ fll_error_file_print(data->error, F_status_set_fine(status), "f_file_open", F_true, arguments.argv[data->remaining.array[i]], "open", fll_error_file_type_file);
+ break;
+ }
+
+ if (!data->quantity.total) {
+ status = f_file_size_by_id(file.id, &data->quantity.total);
+ if (F_status_is_error(status)) {
+ fll_error_file_print(data->error, F_status_set_fine(status), "f_file_size_by_id", F_true, arguments.argv[data->remaining.array[i]], "read", fll_error_file_type_file);
+
+ f_file_stream_close(F_true, &file);
+ break;
+ }
+
+ // Skip past empty files.
+ if (!data->quantity.total) {
+ if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+ fprintf(data->output.stream, "0%c", f_string_eol[0]);
+ }
+
+ f_file_stream_close(F_true, &file);
+ continue;
+ }
+ }
+
+ status = f_file_read_until(file, data->quantity.total, &data->buffer);
+
+ f_file_stream_close(F_true, &file);
+
+ if (F_status_is_error(status)) {
+ fll_error_file_print(data->error, F_status_set_fine(status), "f_file_read_until", F_true, arguments.argv[data->remaining.array[i]], "read", fll_error_file_type_file);
+ break;
+ }
+
+ status = fss_embedded_list_read_main_process_file(arguments, data, arguments.argv[data->remaining.array[i]], depths, &objects_delimits, &contents_delimits, &comments);
+
+ if (F_status_is_error(status)) {
+ fll_error_file_print(data->error, F_status_set_fine(status), "fss_embedded_list_read_main_process_file", F_true, arguments.argv[data->remaining.array[i]], "read", fll_error_file_type_file);
+ break;
+ }
+
+ // Clear buffers before repeating the loop.
+ f_macro_fss_nest_t_delete_simple(data->nest);
+ f_macro_string_dynamic_t_delete_simple(data->buffer);
+ } // for
+
+ if (F_status_is_error(status)) {
+ f_macro_fss_nest_t_delete_simple(data->nest);
+ f_macro_string_dynamic_t_delete_simple(data->buffer);
+ }
+ }
+
+ macro_fss_embedded_list_read_depths_t_delete_simple(depths);
+ f_macro_fss_delimits_t_delete_simple(objects_delimits);
+ f_macro_fss_delimits_t_delete_simple(contents_delimits);
+ f_macro_fss_comments_t_delete_simple(comments);
+ }
+ else {
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sYou failed to specify one or more files.%c", fll_error_print_error, f_string_eol[0]);
+ status = F_status_set_error(F_parameter);
+ }
+
+ fss_embedded_list_read_delete_data(data);
+ return status;
+ }
+#endif // _di_fss_embedded_list_read_main_
+
+#ifndef _di_fss_embedded_list_read_delete_data_
+ f_return_status fss_embedded_list_read_delete_data(fss_embedded_list_read_data_t *data) {
+
+ for (f_string_length_t i = 0; i < fss_embedded_list_read_total_parameters; i++) {
+ f_macro_string_lengths_t_delete_simple(data->parameters[i].locations);
+ f_macro_string_lengths_t_delete_simple(data->parameters[i].locations_sub);
+ f_macro_string_lengths_t_delete_simple(data->parameters[i].values);
+ } // for
+
+ f_macro_fss_nest_t_delete_simple(data->nest);
+
+ f_macro_string_dynamic_t_delete_simple(data->buffer);
+ f_macro_string_lengths_t_delete_simple(data->remaining);
+
+ f_macro_color_context_t_delete_simple(data->context);
+
+ return F_none;
+ }
+#endif // _di_fss_embedded_list_read_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This is the FSS Basic List Read program
+ * This program utilizes the Featureless Linux Library.
+ * This program processes files or other input in fss format and stores the results in the fss_embedded_list_read_data_t.
+ *
+ * This processes in accordance to the FSS-0008 Embedded List specification.
+ */
+#ifndef _fss_embedded_list_read_h
+
+// libc includes
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/utf.h>
+#include <level_0/console.h>
+#include <level_0/directory.h>
+#include <level_0/file.h>
+#include <level_0/pipe.h>
+#include <level_0/print.h>
+
+// fll-1 includes
+#include <level_1/color.h>
+#include <level_1/console.h>
+#include <level_1/conversion.h>
+#include <level_1/print.h>
+#include <level_1/string.h>
+
+// fll-2 includes
+#include <level_2/error.h>
+#include <level_2/execute.h>
+#include <level_2/file.h>
+#include <level_2/fss_embedded_list.h>
+#include <level_2/program.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_read_version_
+ #define fss_embedded_list_read_major_version "0"
+ #define fss_embedded_list_read_minor_version "5"
+ #define fss_embedded_list_read_micro_version "2"
+ #define fss_embedded_list_read_version fss_embedded_list_read_major_version "." fss_embedded_list_read_minor_version "." fss_embedded_list_read_micro_version
+#endif // _di_fss_embedded_list_read_version_
+
+#ifndef _di_fss_embedded_list_read_name_
+ #define fss_embedded_list_read_name "fss_embedded_list_read"
+ #define fss_embedded_list_read_name_long "FSS Embedded List Read"
+#endif // _di_fss_embedded_list_read_name_
+
+#ifndef _di_fss_embedded_list_read_defines_
+ #define fss_embedded_list_read_pipe_content_end '\f'
+ #define fss_embedded_list_read_pipe_content_ignore '\v'
+ #define fss_embedded_list_read_pipe_content_start '\b'
+
+ #define fss_embedded_list_read_short_at "a"
+ #define fss_embedded_list_read_short_content "c"
+ #define fss_embedded_list_read_short_delimit "D"
+ #define fss_embedded_list_read_short_depth "d"
+ #define fss_embedded_list_read_short_empty "e"
+ #define fss_embedded_list_read_short_line "l"
+ #define fss_embedded_list_read_short_name "n"
+ #define fss_embedded_list_read_short_object "o"
+ #define fss_embedded_list_read_short_pipe "p"
+ #define fss_embedded_list_read_short_select "s"
+ #define fss_embedded_list_read_short_total "t"
+ #define fss_embedded_list_read_short_trim "T"
+
+ #define fss_embedded_list_read_long_at "at"
+ #define fss_embedded_list_read_long_content "content"
+ #define fss_embedded_list_read_long_delimit "delimit"
+ #define fss_embedded_list_read_long_depth "depth"
+ #define fss_embedded_list_read_long_empty "empty"
+ #define fss_embedded_list_read_long_line "line"
+ #define fss_embedded_list_read_long_name "name"
+ #define fss_embedded_list_read_long_object "object"
+ #define fss_embedded_list_read_long_pipe "pipe"
+ #define fss_embedded_list_read_long_select "select"
+ #define fss_embedded_list_read_long_total "total"
+ #define fss_embedded_list_read_long_trim "trim"
+
+ enum {
+ fss_embedded_list_read_parameter_help,
+ fss_embedded_list_read_parameter_light,
+ fss_embedded_list_read_parameter_dark,
+ fss_embedded_list_read_parameter_no_color,
+ fss_embedded_list_read_parameter_verbosity_quiet,
+ fss_embedded_list_read_parameter_verbosity_normal,
+ fss_embedded_list_read_parameter_verbosity_verbose,
+ fss_embedded_list_read_parameter_verbosity_debug,
+ fss_embedded_list_read_parameter_version,
+
+ fss_embedded_list_read_parameter_at,
+ fss_embedded_list_read_parameter_content,
+ fss_embedded_list_read_parameter_delimit,
+ fss_embedded_list_read_parameter_depth,
+ fss_embedded_list_read_parameter_empty,
+ fss_embedded_list_read_parameter_line,
+ fss_embedded_list_read_parameter_name,
+ fss_embedded_list_read_parameter_object,
+ fss_embedded_list_read_parameter_pipe,
+ fss_embedded_list_read_parameter_select,
+ fss_embedded_list_read_parameter_total,
+ fss_embedded_list_read_parameter_trim,
+ };
+
+ #define fss_embedded_list_read_console_parameter_t_initialize \
+ { \
+ f_console_parameter_t_initialize(f_console_standard_short_help, f_console_standard_long_help, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(f_console_standard_short_light, f_console_standard_long_light, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_quiet, f_console_standard_long_quiet, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_normal, f_console_standard_long_normal, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_verbose, f_console_standard_long_verbose, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_debug, f_console_standard_long_debug, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_at, fss_embedded_list_read_long_at, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_content, fss_embedded_list_read_long_content, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_delimit, fss_embedded_list_read_long_delimit, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_depth, fss_embedded_list_read_long_depth, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_empty, fss_embedded_list_read_long_empty, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_line, fss_embedded_list_read_long_line, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_name, fss_embedded_list_read_long_name, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_object, fss_embedded_list_read_long_object, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_pipe, fss_embedded_list_read_long_pipe, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_select, fss_embedded_list_read_long_select, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_total, fss_embedded_list_read_long_total, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_read_short_trim, fss_embedded_list_read_long_trim, 0, 0, f_console_type_normal), \
+ }
+
+ #define fss_embedded_list_read_total_parameters 21
+#endif // _di_fss_embedded_list_read_defines_
+
+#ifndef _di_fss_embedded_list_read_delimit_mode_
+ #define fss_embedded_list_read_delimit_mode_name_none "none"
+ #define fss_embedded_list_read_delimit_mode_name_all "all"
+ #define fss_embedded_list_read_delimit_mode_name_greater "+"
+ #define fss_embedded_list_read_delimit_mode_name_lesser "-"
+
+ #define fss_embedded_list_read_delimit_mode_name_none_length 4
+ #define fss_embedded_list_read_delimit_mode_name_all_length 3
+ #define fss_embedded_list_read_delimit_mode_name_greater_length 1
+ #define fss_embedded_list_read_delimit_mode_name_lesser_length 1
+
+ enum {
+ fss_embedded_list_read_delimit_mode_none = 1,
+ fss_embedded_list_read_delimit_mode_all,
+ fss_embedded_list_read_delimit_mode_depth,
+ fss_embedded_list_read_delimit_mode_depth_greater,
+ fss_embedded_list_read_delimit_mode_depth_lesser,
+ };
+#endif // _di_fss_embedded_list_read_delimit_modes_
+
+#ifndef _di_fss_embedded_list_read_data_t_
+ typedef struct {
+ f_console_parameter_t parameters[fss_embedded_list_read_total_parameters];
+
+ f_string_lengths_t remaining;
+ bool process_pipe;
+
+ f_file_t output;
+ fll_error_print_t error;
+
+ f_string_dynamic_t buffer;
+ f_fss_nest_t nest;
+ f_string_quantity_t quantity;
+
+ uint8_t delimit_mode;
+ f_string_length_t delimit_depth;
+
+ f_color_context_t context;
+ } fss_embedded_list_read_data_t;
+
+ #define fss_embedded_list_read_data_t_initialize \
+ { \
+ fss_embedded_list_read_console_parameter_t_initialize, \
+ f_string_lengths_t_initialize, \
+ F_false, \
+ f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+ fll_error_print_t_initialize, \
+ f_string_dynamic_t_initialize, \
+ f_fss_nest_t_initialize, \
+ f_string_quantity_t_initialize, \
+ fss_embedded_list_read_delimit_mode_all, \
+ 0, \
+ f_color_context_t_initialize, \
+ }
+#endif // _di_fss_embedded_list_read_data_t_
+
+/**
+ * Print help.
+ *
+ * @param output
+ * The file to print to.
+ * @param context
+ * The color context settings.
+ *
+ * @return
+ * F_none on success.
+ */
+#ifndef _di_fss_embedded_list_read_print_help_
+ extern f_return_status fss_embedded_list_read_print_help(const f_file_t output, const f_color_context_t context);
+#endif // _di_fss_embedded_list_read_print_help_
+
+/**
+ * Execute main program.
+ *
+ * Be sure to call fss_embedded_list_read_delete_data() after executing this.
+ *
+ * @param arguments
+ * The parameters passed to the process.
+ * @param data
+ * The program data.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_read_delete_data()
+ */
+#ifndef _di_fss_embedded_list_read_main_
+ extern f_return_status fss_embedded_list_read_main(const f_console_arguments_t arguments, fss_embedded_list_read_data_t *data);
+#endif // _di_fss_embedded_list_read_main_
+
+/**
+ * Deallocate data.
+ *
+ * Be sure to call this after executing fss_embedded_list_read_main().
+ *
+ * @param data
+ * The program data.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_read_main()
+ */
+#ifndef _di_fss_embedded_list_read_delete_data_
+ extern f_return_status fss_embedded_list_read_delete_data(fss_embedded_list_read_data_t *data);
+#endif // _di_fss_embedded_list_read_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _fss_embedded_list_read_h
--- /dev/null
+#include "fss_embedded_list_read.h"
+
+int main(const unsigned long argc, const f_string_t *argv) {
+ const f_console_arguments_t arguments = { argc, argv };
+ fss_embedded_list_read_data_t data = fss_embedded_list_read_data_t_initialize;
+
+ if (f_pipe_input_exists()) {
+ data.process_pipe = F_true;
+ }
+
+ if (F_status_is_error(fss_embedded_list_read_main(arguments, &data))) {
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+#include "fss_embedded_list_read.h"
+#include "private-fss_embedded_list_read.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_read_main_preprocess_depth_
+ f_return_status fss_embedded_list_read_main_preprocess_depth(const f_console_arguments_t arguments, const fss_embedded_list_read_data_t data, fss_embedded_list_read_depths_t *depths) {
+ f_status_t status = F_none;
+
+ const f_array_length_t values_total = data.parameters[fss_embedded_list_read_parameter_depth].values.used + data.parameters[fss_embedded_list_read_parameter_at].values.used + data.parameters[fss_embedded_list_read_parameter_name].values.used;
+
+ f_array_length_t values_order[values_total];
+ f_array_length_t values_type[values_total];
+
+ f_array_length_t i = 0;
+ f_array_length_t j = 0;
+
+ // determine the linear order in which all of the three parameter values are to be applied.
+ if (values_total) {
+ memset(values_order, 0, values_total);
+
+ f_array_length_t k = 0;
+ f_array_length_t l = 0;
+
+ for (; j < data.parameters[fss_embedded_list_read_parameter_depth].values.used; ++j) {
+
+ values_order[i] = data.parameters[fss_embedded_list_read_parameter_depth].values.array[j];
+ values_type[i++] = fss_embedded_list_read_parameter_depth;
+ } // for
+
+ if (i) {
+ for (j = 0; j < data.parameters[fss_embedded_list_read_parameter_at].values.used; ++j) {
+
+ for (k = 0; k < i; ++k) {
+
+ if (values_order[k] > data.parameters[fss_embedded_list_read_parameter_at].values.array[j]) {
+ for (l = i; l > k; --l) {
+ values_order[l] = values_order[l - 1];
+ values_type[l] = values_type[l - 1];
+ } // for
+
+ values_order[k] = data.parameters[fss_embedded_list_read_parameter_at].values.array[j];
+ values_type[k] = fss_embedded_list_read_parameter_at;
+ i++;
+ break;
+ }
+ } // for
+
+ if (k == i) {
+ values_order[i] = data.parameters[fss_embedded_list_read_parameter_at].values.array[j];
+ values_type[i++] = fss_embedded_list_read_parameter_at;
+ }
+ } // for
+ }
+ else {
+ for (; j < data.parameters[fss_embedded_list_read_parameter_at].values.used; ++j) {
+
+ values_order[i] = data.parameters[fss_embedded_list_read_parameter_at].values.array[j];
+ values_type[i++] = fss_embedded_list_read_parameter_at;
+ } // for
+ }
+
+ if (i) {
+ for (j = 0; j < data.parameters[fss_embedded_list_read_parameter_name].values.used; ++j) {
+
+ for (k = 0; k < i; ++k) {
+
+ if (values_order[k] > data.parameters[fss_embedded_list_read_parameter_name].values.array[j]) {
+ for (l = i; l > k; --l) {
+ values_order[l] = values_order[l - 1];
+ values_type[l] = values_type[l - 1];
+ } // for
+
+ values_order[k] = data.parameters[fss_embedded_list_read_parameter_name].values.array[j];
+ values_type[k] = fss_embedded_list_read_parameter_name;
+ i++;
+ break;
+ }
+ } // for
+
+ if (k == i) {
+ values_order[i] = data.parameters[fss_embedded_list_read_parameter_name].values.array[j];
+ values_type[i++] = fss_embedded_list_read_parameter_name;
+ }
+ } // for
+ }
+ else {
+ for (; j < data.parameters[fss_embedded_list_read_parameter_name].values.used; ++j) {
+
+ values_order[i] = data.parameters[fss_embedded_list_read_parameter_name].values.array[j];
+ values_type[i++] = fss_embedded_list_read_parameter_name;
+ } // for
+ }
+ }
+
+ {
+ i = 1;
+
+ if (data.parameters[fss_embedded_list_read_parameter_depth].result == f_console_result_additional) {
+ i = data.parameters[fss_embedded_list_read_parameter_depth].values.used + 1;
+ }
+
+ macro_fss_embedded_list_read_depths_t_new(status, (*depths), i);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fss_embedded_list_read_main_preprocess_depth", F_true);
+ return status;
+ }
+ }
+
+ // provide default level-0 depth values.
+ depths->array[0].depth = 0;
+ depths->array[0].index_at = 0;
+ depths->array[0].index_name = 0;
+ depths->array[0].value_at = 0;
+
+ {
+ f_number_unsigned_t number = 0;
+ bool first_depth = F_true;
+
+ for (i = 0; i < values_total; ++i) {
+
+ if (values_type[i] == fss_embedded_list_read_parameter_depth || values_type[i] == fss_embedded_list_read_parameter_at) {
+ const f_string_range_t range = f_macro_string_range_t_initialize(strlen(arguments.argv[values_order[i]]));
+
+ status = fl_conversion_string_to_number_unsigned(arguments.argv[values_order[i]], &number, range);
+
+ if (F_status_is_error(status)) {
+ fll_error_parameter_integer_print(data.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_depth, arguments.argv[values_order[i]]);
+ return status;
+ }
+ }
+
+ if (values_type[i] == fss_embedded_list_read_parameter_depth) {
+
+ if (first_depth) {
+ if (i && number) {
+ depths->array[++depths->used].index_at = 0;
+ depths->array[depths->used].index_name = 0;
+ depths->array[depths->used].value_at = 0;
+ }
+
+ first_depth = F_false;
+ depths->array[depths->used].depth = number;
+ }
+ else {
+ depths->array[++depths->used].depth = number;
+ depths->array[depths->used].index_at = 0;
+ depths->array[depths->used].index_name = 0;
+ depths->array[depths->used].value_at = 0;
+ }
+ }
+ else if (values_type[i] == fss_embedded_list_read_parameter_at) {
+ depths->array[depths->used].index_at = values_order[i];
+ depths->array[depths->used].value_at = number;
+ }
+ else if (values_type[i] == fss_embedded_list_read_parameter_name) {
+ depths->array[depths->used].index_name = values_order[i];
+ depths->array[depths->used].value_name.used = 0;
+
+ if (data.parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) {
+ status = fl_string_rip(arguments.argv[values_order[i]], strnlen(arguments.argv[values_order[i]], f_console_length_size), &depths->array[depths->used].value_name);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_rip", F_true);
+ return status;
+ }
+ }
+ else {
+ status = fl_string_append(arguments.argv[values_order[i]], strnlen(arguments.argv[values_order[i]], f_console_length_size), &depths->array[depths->used].value_name);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true);
+ return status;
+ }
+ }
+ }
+ } // for
+
+ depths->used++;
+ }
+
+ for (i = 0; i < depths->used; i++) {
+
+ for (j = i + 1; j < depths->used; j++) {
+
+ if (depths->array[i].depth == depths->array[j].depth) {
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sThe value '", fll_error_print_error);
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%llu", depths->array[i].depth);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' may only be specified once for the parameter '");
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+ fl_color_print(data.error.to.stream, data.context.set.error, "'.%c", f_string_eol[0]);
+
+ return F_status_set_error(F_parameter);
+ }
+ else if (depths->array[i].depth > depths->array[j].depth) {
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' may not have the value '");
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%llu", depths->array[i].depth);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' before the value '");
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%llu", depths->array[j].depth);
+ fl_color_print(data.error.to.stream, data.context.set.error, "'.%c", f_string_eol[0]);
+
+ return F_status_set_error(F_parameter);
+ }
+ } // for
+ } // for
+
+ return F_none;
+ }
+#endif // _di_fss_embedded_list_read_main_preprocess_depth_
+
+#ifndef _di_fss_embedded_list_read_main_process_file_
+ f_return_status fss_embedded_list_read_main_process_file(const f_console_arguments_t arguments, fss_embedded_list_read_data_t *data, const f_string_t filename, const fss_embedded_list_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) {
+ f_status_t status = F_none;
+
+ {
+ f_string_range_t input = f_macro_string_range_t_initialize(data->buffer.used);
+
+ objects_delimits->used = 0;
+ contents_delimits->used = 0;
+ comments->used = 0;
+
+ status = fll_fss_embedded_list_read(&data->buffer, &input, &data->nest, objects_delimits, contents_delimits, comments);
+
+ if (F_status_is_error(status)) {
+ // @todo: detect and replace fll_error_file_type_file with fll_error_file_type_pipe as appropriate.
+ fll_error_file_print(data->error, F_status_set_fine(status), "fll_fss_embedded_list_read", F_true, filename, "process", fll_error_file_type_file);
+ }
+ else if (status == F_data_not_stop || status == F_data_not_eos) {
+ f_macro_fss_nest_t_delete_simple(data->nest);
+ f_macro_string_dynamic_t_delete_simple(data->buffer);
+
+ if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+ fprintf(data->output.stream, "0%c", f_string_eol[0]);
+ return F_none;
+ }
+
+ return F_status_set_warning(status);
+ }
+
+ if (F_status_is_error(status)) {
+ f_macro_fss_nest_t_delete_simple(data->nest);
+ f_macro_string_dynamic_t_delete_simple(data->buffer);
+
+ return status;
+ }
+
+ f_array_length_t i = 0;
+ f_array_length_t j = 0;
+
+ // comments are not to be part of the file, so remove them.
+ for (; i < comments->used; ++i) {
+ for (j = comments->array[i].start; j <= comments->array[i].stop; ++j) {
+ data->buffer.string[j] = f_fss_delimit_placeholder;
+ } // for
+ } // for
+ }
+
+ // Requested depths cannot be greater than contents depth.
+ if (depths.used > data->nest.used) {
+ if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+ fprintf(data->output.stream, "0%c", f_string_eol[0]);
+ return F_none;
+ }
+
+ return F_none;
+ }
+
+ {
+ f_number_unsigned_t select = 0;
+
+ if (data->parameters[fss_embedded_list_read_parameter_select].result == f_console_result_additional) {
+ const f_string_length_t index = data->parameters[fss_embedded_list_read_parameter_select].values.array[data->parameters[fss_embedded_list_read_parameter_select].values.used - 1];
+ const f_string_range_t range = f_macro_string_range_t_initialize(strlen(arguments.argv[index]));
+
+ status = fl_conversion_string_to_number_unsigned(arguments.argv[index], &select, range);
+
+ if (F_status_is_error(status)) {
+ fll_error_parameter_integer_print(data->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_select, arguments.argv[index]);
+ return status;
+ }
+
+ // This standard does not support multiple content groups.
+ if (select > 0) {
+ return F_none;
+ }
+ }
+ }
+
+ f_array_length_t line = 0;
+
+ if (data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_additional) {
+ const f_array_length_t index = data->parameters[fss_embedded_list_read_parameter_line].values.array[data->parameters[fss_embedded_list_read_parameter_line].values.used - 1];
+ const f_string_range_t range = f_macro_string_range_t_initialize(strlen(arguments.argv[index]));
+
+ status = fl_conversion_string_to_number_unsigned(arguments.argv[index], &line, range);
+
+ if (F_status_is_error(status)) {
+ fll_error_parameter_integer_print(data->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_line, arguments.argv[index]);
+ return status;
+ }
+ }
+
+ fss_embedded_list_read_process_delimits(*data, objects_delimits, contents_delimits);
+
+ const fss_embedded_list_read_skip_t parents = fss_embedded_list_read_skip_t_initialize;
+
+ return fss_embedded_list_read_main_process_for_depth(arguments, filename, depths, 0, line, parents, data, objects_delimits, contents_delimits);
+ }
+#endif // _di_fss_embedded_list_read_main_process_file_
+
+#ifndef _di_fss_embedded_list_read_main_process_for_depth_
+ f_return_status fss_embedded_list_read_main_process_for_depth(const f_console_arguments_t arguments, const f_string_t filename, const fss_embedded_list_read_depths_t depths, const f_array_length_t depths_index, const f_array_length_t line, const fss_embedded_list_read_skip_t parents, fss_embedded_list_read_data_t *data, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) {
+
+ f_fss_items_t *items = &data->nest.depth[depths.array[depths_index].depth];
+
+ bool skip[items->used];
+
+ // setup defaults to be not skipped unless any given parent is skipped.
+ memset(skip, F_false, sizeof(skip) * items->used);
+
+ if (parents.used) {
+ for (f_array_length_t i = 0; i < items->used; ++i) {
+
+ if (items->array[i].parent >= parents.used || parents.skip[items->array[i].parent]) {
+ skip[i] = F_true;
+ }
+ } // for
+ }
+
+ if (depths.array[depths_index].index_name || depths.array[depths_index].index_at) {
+ const f_string_lengths_t except_none = f_string_lengths_t_initialize;
+
+ f_array_length_t i = 0;
+ f_array_length_t j = 0;
+
+ if (!depths.array[depths_index].index_name || (depths.array[depths_index].index_at && depths.array[depths_index].index_at < depths.array[depths_index].index_name)) {
+
+ // all other non-"at" parameters must be FALSE.
+ for (; i < items->used; ++i) {
+
+ if (skip[i]) continue;
+
+ if (j != depths.array[depths_index].value_at) {
+ skip[i] = F_true;
+ }
+
+ ++j;
+ } // for
+
+ if (depths.array[depths_index].value_at < items->used && !skip[depths.array[depths_index].value_at]) {
+ if (depths.array[depths_index].index_name) {
+
+ if (data->parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) {
+
+ if (fl_string_dynamic_partial_compare_except_trim_dynamic(depths.array[depths_index].value_name, data->buffer, items->array[depths.array[depths_index].value_at].object, except_none, *objects_delimits) != F_equal_to) {
+ skip[depths.array[depths_index].value_at] = F_true;
+ }
+ }
+ else {
+ if (fl_string_dynamic_partial_compare_except_dynamic(depths.array[depths_index].value_name, data->buffer, items->array[depths.array[depths_index].value_at].object, except_none, *objects_delimits) != F_equal_to) {
+ skip[depths.array[depths_index].value_at] = F_true;
+ }
+ }
+ }
+ }
+ }
+ else {
+
+ if (data->parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) {
+
+ for (i = 0; i < items->used; ++i) {
+
+ if (skip[i]) continue;
+
+ if (fl_string_dynamic_partial_compare_except_trim_dynamic(depths.array[depths_index].value_name, data->buffer, items->array[i].object, except_none, *objects_delimits) != F_equal_to) {
+ skip[i] = F_true;
+ }
+ } // for
+ }
+ else {
+
+ for (i = 0; i < items->used; ++i) {
+
+ if (skip[i]) continue;
+
+ if (fl_string_dynamic_partial_compare_except_dynamic(depths.array[depths_index].value_name, data->buffer, items->array[i].object, except_none, *objects_delimits) != F_equal_to) {
+ skip[i] = F_true;
+ }
+ } // for
+ }
+
+ if (depths.array[depths_index].index_at) {
+
+ // all other non-"at" parameters must be FALSE.
+ for (i = 0, j = 0; i < items->used; ++i) {
+
+ if (skip[i]) continue;
+
+ if (j != depths.array[depths_index].value_at) {
+ skip[i] = F_true;
+ }
+
+ ++j;
+ } // for
+ }
+ }
+ }
+
+ // if the current depth is not the final depth, then recurse into the next depth.
+ if (depths_index + 1 < depths.used) {
+ bool skip_next[data->nest.depth[depths.array[depths_index + 1].depth - 1].used];
+
+ fss_embedded_list_read_skip_t parents_next = fss_embedded_list_read_skip_t_initialize;
+
+ if (depths.array[depths_index].depth + 1 == depths.array[depths_index + 1].depth) {
+ parents_next.skip = skip;
+ parents_next.used = items->used;
+ }
+ else {
+ const f_array_length_t parents_depth = depths.array[depths_index + 1].depth - 1;
+ const f_array_length_t depth_next = depths.array[depths_index + 1].depth;
+
+ parents_next.skip = skip_next;
+ parents_next.used = data->nest.depth[parents_depth].used;
+
+ memset(skip_next, F_true, sizeof(skip_next) * parents_next.used);
+
+ f_fss_items_t *items_next = &data->nest.depth[depth_next];
+ f_fss_items_t *items_previous = 0;
+ f_fss_item_t *item_previous = 0;
+
+ f_array_length_t i = 0;
+ f_array_length_t j = 0;
+
+ for (; i < items_next->used; ++i) {
+
+ j = depth_next;
+
+ item_previous = &items_next->array[i];
+ items_previous = &data->nest.depth[--j];
+
+ while (j > depths.array[depths_index].depth) {
+
+ item_previous = &items_previous->array[item_previous->parent];
+ items_previous = &data->nest.depth[--j];
+ } // while
+
+ if (skip[item_previous->parent]) {
+ skip_next[items_next->array[i].parent] = F_true;
+ }
+ else {
+ skip_next[items_next->array[i].parent] = F_false;
+ }
+ } // for
+ }
+
+ return fss_embedded_list_read_main_process_for_depth(arguments, filename, depths, depths_index + 1, line, parents_next, data, objects_delimits, contents_delimits);
+ }
+
+ // process objects.
+ f_array_length_t i = 0;
+ f_array_length_t j = 0;
+
+ if (data->parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found) {
+ if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+ f_array_length_t total = 0;
+
+ for (i = 0; i < items->used; i++) {
+ if (skip[i]) continue;
+
+ total++;
+ } // for
+
+ fprintf(data->output.stream, "%llu%c", total, f_string_eol[0]);
+
+ return F_none;
+ }
+
+ f_return_status (*print_object)(FILE *, const f_string_static_t, const f_string_range_t, const f_string_lengths_t) = &f_print_except_dynamic_partial;
+
+ if (data->parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) {
+ print_object = &fl_print_trim_except_dynamic_partial;
+ }
+
+ for (i = 0; i < items->used; i++) {
+
+ if (skip[i]) continue;
+
+ print_object(data->output.stream, data->buffer, items->array[i].object, *objects_delimits);
+
+ if (data->parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+ fss_embedded_list_read_print_object_end(*data);
+
+ if (items->array[i].content.used) {
+ f_print_except_dynamic_partial(data->output.stream, data->buffer, items->array[i].content.array[0], *contents_delimits);
+ }
+ }
+
+ fss_embedded_list_read_print_set_end(*data);
+ } // for
+
+ return F_none;
+ }
+
+ // process contents.
+ bool include_empty = 0;
+
+ if (data->parameters[fss_embedded_list_read_parameter_empty].result == f_console_result_found) {
+ include_empty = 1;
+ }
+
+ if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+ f_array_length_t total = 0;
+
+ for (i = 0; i < items->used; ++i) {
+
+ if (skip[i]) continue;
+
+ if (!items->array[i].content.used) {
+ if (include_empty) {
+ total++;
+ }
+
+ continue;
+ }
+
+ for (j = items->array[i].content.array[0].start; j <= items->array[i].content.array[0].stop; ++j) {
+
+ if (!data->buffer.string[j]) continue;
+
+ if (data->buffer.string[j] == f_string_eol[0]) {
+ total++;
+ }
+ } // for
+ } // for
+
+ fprintf(data->output.stream, "%llu%c", total, f_string_eol[0]);
+ return F_none;
+ }
+
+ if (data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_additional) {
+ f_array_length_t line_current = 0;
+
+ for (; i < items->used; ++i) {
+
+ if (skip[i]) continue;
+
+ if (!items->array[i].content.used) {
+ if (include_empty) {
+ if (line_current == line) {
+ fss_embedded_list_read_print_set_end(*data);
+ break;
+ }
+
+ line_current++;
+ }
+
+ continue;
+ }
+
+ j = items->array[i].content.array[0].start;
+
+ if (line_current != line) {
+ for (; j <= items->array[i].content.array[0].stop; ++j) {
+
+ if (data->buffer.string[j] == f_string_eol[0]) {
+ line_current++;
+
+ if (line_current == line) {
+ ++j;
+ break;
+ }
+ }
+ } // for
+ }
+
+ if (line_current == line) {
+ if (j > items->array[i].content.array[0].stop) continue;
+
+ for (; j <= items->array[i].content.array[0].stop; ++j) {
+
+ if (!data->buffer.string[j]) continue;
+
+ if (data->buffer.string[j] == f_string_eol[0]) {
+ fprintf(data->output.stream, "%c", f_string_eol[0]);
+ break;
+ }
+
+ fprintf(data->output.stream, "%c", data->buffer.string[j]);
+ } // for
+
+ break;
+ }
+ } // for
+
+ return F_none;
+ }
+
+ for (i = 0; i < items->used; i++) {
+
+ if (skip[i]) continue;
+
+ if (!items->array[i].content.used) {
+ if (include_empty) {
+ fss_embedded_list_read_print_set_end(*data);
+ }
+
+ continue;
+ }
+
+ f_print_except_dynamic_partial(data->output.stream, data->buffer, items->array[i].content.array[0], *contents_delimits);
+
+ if (data->parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+ fprintf(data->output.stream, "%c", fss_embedded_list_read_pipe_content_end);
+ }
+ } // for
+
+ return F_none;
+ }
+#endif // _di_fss_embedded_list_read_main_process_for_depth_
+
+#ifndef _di_fss_embedded_list_read_print_object_end_
+ void fss_embedded_list_read_print_object_end(const fss_embedded_list_read_data_t data) {
+
+ if (data.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+ fprintf(data.output.stream, "%c", fss_embedded_list_read_pipe_content_start);
+ }
+ else {
+ if (data.parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && data.parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+ fprintf(data.output.stream, "%c%c", f_fss_embedded_list_open, f_fss_embedded_list_open_end);
+ }
+ else {
+ fprintf(data.output.stream, "%c", f_fss_eol);
+ }
+ }
+ }
+#endif // _di_fss_embedded_list_read_print_object_end_
+
+#ifndef _di_fss_embedded_list_read_print_content_end_
+ void fss_embedded_list_read_print_content_end(const fss_embedded_list_read_data_t data) {
+
+ if (data.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+ fprintf(data.output.stream, "%c", fss_embedded_list_read_pipe_content_start);
+ }
+ else {
+ if (data.parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && data.parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+ fprintf(data.output.stream, "%c%c", f_fss_embedded_list_close, f_fss_embedded_list_close_end);
+ }
+ else {
+ fprintf(data.output.stream, "%c", f_fss_eol);
+ }
+ }
+ }
+#endif // _di_fss_embedded_list_read_print_content_end_
+
+#ifndef _di_fss_embedded_list_read_print_content_ignore_
+ void fss_embedded_list_read_print_content_ignore(const fss_embedded_list_read_data_t data) {
+
+ if (data.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+ fprintf(data.output.stream, "%c", fss_embedded_list_read_pipe_content_ignore);
+ }
+ }
+#endif // _di_fss_embedded_list_read_print_content_ignore_
+
+#ifndef _di_fss_embedded_list_read_print_set_end_
+ void fss_embedded_list_read_print_set_end(const fss_embedded_list_read_data_t data) {
+
+ if (data.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+ fprintf(data.output.stream, "%c", fss_embedded_list_read_pipe_content_end);
+ }
+ else {
+ if (data.parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && data.parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+ fprintf(data.output.stream, "%c%c", f_fss_embedded_list_close, f_fss_embedded_list_close_end);
+ }
+ else {
+ fprintf(data.output.stream, "%c", f_fss_eol);
+ }
+ }
+ }
+#endif // _di_fss_embedded_list_read_print_set_end_
+
+#ifndef _di_fss_embedded_list_read_process_delimits_
+ void fss_embedded_list_read_process_delimits(const fss_embedded_list_read_data_t data, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) {
+
+ if (!data.nest.used) return;
+
+ if ((!objects_delimits->used && !contents_delimits->used) || data.delimit_mode == fss_embedded_list_read_delimit_mode_all) return;
+
+ if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_lesser && data.nest.used < data.delimit_depth) return;
+ if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater && data.delimit_depth == 0) return;
+
+ if (data.delimit_mode == fss_embedded_list_read_delimit_mode_none) {
+ objects_delimits->used = 0;
+ contents_delimits->used = 0;
+ return;
+ }
+
+ if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth || data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater) {
+ if (data.delimit_depth >= data.nest.used) {
+ objects_delimits->used = 0;
+ contents_delimits->used = 0;
+ return;
+ }
+ }
+
+ const f_string_length_t original_objects_used = objects_delimits->used;
+ const f_string_length_t original_contents_used = contents_delimits->used;
+
+ f_string_length_t original_objects_delimits[original_objects_used];
+ f_string_length_t original_contents_delimits[original_contents_used];
+
+ memcpy(&original_objects_delimits, objects_delimits->array, original_objects_used * sizeof(f_string_length_t));
+ memcpy(&original_contents_delimits, contents_delimits->array, original_contents_used * sizeof(f_string_length_t));
+
+ objects_delimits->used = 0;
+ contents_delimits->used = 0;
+
+ if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth) {
+
+ // only depth 0 objects are stored in objects_delimits.
+ if (data.delimit_depth) {
+ fss_embedded_list_read_process_delimits_objects(data, data.delimit_depth, original_contents_delimits, original_contents_used, contents_delimits);
+ }
+ else {
+ fss_embedded_list_read_process_delimits_objects(data, data.delimit_depth, original_objects_delimits, original_objects_used, objects_delimits);
+ }
+
+ fss_embedded_list_read_process_delimits_contents(data, data.delimit_depth, original_contents_delimits, original_contents_used, contents_delimits);
+ }
+ else {
+
+ if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_lesser) {
+
+ // only depth 0 objects are stored in objects_delimits.
+ fss_embedded_list_read_process_delimits_objects(data, 0, original_objects_delimits, original_objects_used, objects_delimits);
+ fss_embedded_list_read_process_delimits_contents(data, 0, original_contents_delimits, original_contents_used, contents_delimits);
+
+ for (f_array_length_t i = 1; i <= data.delimit_depth && i < data.nest.used; ++i) {
+
+ fss_embedded_list_read_process_delimits_objects(data, i, original_contents_delimits, original_contents_used, contents_delimits);
+ fss_embedded_list_read_process_delimits_contents(data, i, original_contents_delimits, original_contents_used, contents_delimits);
+ } // for
+ }
+ else if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater) {
+ for (f_array_length_t i = data.delimit_depth; i < data.nest.used; ++i) {
+
+ fss_embedded_list_read_process_delimits_objects(data, i, original_contents_delimits, original_contents_used, contents_delimits);
+ fss_embedded_list_read_process_delimits_contents(data, i, original_contents_delimits, original_contents_used, contents_delimits);
+ } // for
+ }
+ }
+ }
+#endif // _di_fss_embedded_list_read_process_delimits_
+
+#ifndef _di_fss_embedded_list_read_process_delimits_contents_
+ void fss_embedded_list_read_process_delimits_contents(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t original_delimits[], const f_string_length_t original_used, f_fss_delimits_t *delimits) {
+
+ if (!original_used) return;
+
+ f_fss_items_t *items = &data.nest.depth[depth];
+
+ if (!items->used) return;
+
+ f_array_length_t i = 0;
+ f_array_length_t j = 0;
+ f_array_length_t k = 0;
+ f_array_length_t l = 0;
+ f_array_length_t m = 0;
+
+ for (i = 0; i < items->used; ++i) {
+
+ for (j = 0; j < original_used; ++j) {
+
+ for (k = 0; k < items->array[i].content.used; ++k) {
+
+ if (original_delimits[j] >= items->array[i].content.array[k].start && original_delimits[j] <= items->array[i].content.array[k].stop) {
+
+ // preserve linear order when adding back delimits.
+ if (delimits->used) {
+ for (l = 0; l < delimits->used; ++l) {
+
+ if (original_delimits[j] > delimits->array[l]) continue;
+ if (original_delimits[j] == delimits->array[l]) break;
+
+ for (m = delimits->used; m > l; --m) {
+ delimits->array[m] = delimits->array[m - 1];
+ } // for
+
+ if (fss_embedded_list_read_process_delimits_within_greater(data, depth, original_delimits[j]) == F_false) {
+ delimits->array[l] = original_delimits[j];
+ delimits->used++;
+ }
+
+ break;
+ } // for
+ }
+ else if (fss_embedded_list_read_process_delimits_within_greater(data, depth, original_delimits[j]) == F_false) {
+ delimits->array[0] = original_delimits[j];
+ delimits->used = 1;
+ }
+ }
+ }
+ } // for
+ } // for
+ }
+#endif // _di_fss_embedded_list_read_process_delimits_contents_
+
+#ifndef _di_fss_embedded_list_read_process_delimits_objects_
+ void fss_embedded_list_read_process_delimits_objects(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t original_delimits[], const f_string_length_t original_used, f_fss_delimits_t *delimits) {
+
+ if (!original_used) return;
+
+ f_fss_items_t *items = &data.nest.depth[depth];
+
+ if (!items->used) return;
+
+ f_array_length_t i = 0;
+ f_array_length_t j = 0;
+ f_array_length_t k = 0;
+ f_array_length_t l = 0;
+
+ for (i = 0; i < items->used; ++i) {
+
+ for (j = 0; j < original_used; ++j) {
+
+ if (original_delimits[j] >= items->array[i].object.start && original_delimits[j] <= items->array[i].object.stop) {
+
+ // preserve linear order when adding back delimits.
+ if (delimits->used) {
+ for (k = 0; k < delimits->used; ++k) {
+
+ if (original_delimits[j] > delimits->array[k]) continue;
+ if (original_delimits[j] == delimits->array[k]) break;
+
+ for (l = delimits->used; l > k; --l) {
+ delimits->array[l] = delimits->array[l - 1];
+ } // for
+
+ if (fss_embedded_list_read_process_delimits_within_greater(data, depth, original_delimits[j]) == F_false) {
+ delimits->array[k] = original_delimits[j];
+ delimits->used++;
+ }
+
+ break;
+ } // for
+ }
+ else if (fss_embedded_list_read_process_delimits_within_greater(data, depth, original_delimits[j]) == F_false) {
+ delimits->array[0] = original_delimits[j];
+ delimits->used = 1;
+ }
+ }
+ } // for
+ } // for
+ }
+#endif // _di_fss_embedded_list_read_process_delimits_objects_
+
+#ifndef _di_fss_embedded_list_read_process_delimits_within_greater_
+ f_return_status fss_embedded_list_read_process_delimits_within_greater(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t location) {
+
+ if (depth + 1 >= data.nest.used) return F_false;
+
+ f_fss_items_t *items = 0;
+
+ f_string_length_t i = 0;
+ f_string_length_t j = 0;
+
+ for (f_string_length_t d = depth + 1; d < data.nest.used; ++d) {
+ items = &data.nest.depth[d];
+
+ for (i = 0; i < items->used; ++i) {
+
+ for (j = 0; j < items->array[i].content.used; ++j) {
+
+ if (location >= items->array[i].content.array[j].start && location <= items->array[i].content.array[j].stop) {
+ return F_true;
+ }
+ } // for
+ } // for
+ } // for
+
+ return F_false;
+ }
+#endif // _di_fss_embedded_list_read_process_delimits_within_greater_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ */
+#ifndef _PRIVATE_fss_embedded_list_read_h
+#define _PRIVATE_fss_embedded_list_read_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A structure of parameters applied at some depth.
+ *
+ * depth: the depth number in which this is to be processed at.
+ *
+ * index_at: position of the "--at" parameter value in the argv list, when 0 there is no parameter.
+ * index_name: position of the "--name" parameter value in the argv list, when 0 there is no parameter.
+ *
+ * value_at: the value of the "--at" parameter, already processed and ready to use, only when index_at > 0.
+ * value_name: the value of the "--name" parameter, already processed and ready to use, only when index_name > 0.
+ */
+#ifndef _di_fss_embedded_list_read_depth_t_
+ typedef struct {
+ f_string_length_t depth;
+
+ f_array_length_t index_at;
+ f_array_length_t index_name;
+
+ f_number_unsigned_t value_at;
+ f_string_dynamic_t value_name;
+ } fss_embedded_list_read_depth_t;
+
+ #define fss_embedded_list_read_depth_t_initialize \
+ { \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ f_string_dynamic_t_initialize, \
+ }
+
+ #define macro_fss_embedded_list_read_depth_t_clear(structure) \
+ structure.depth = 0; \
+ structure.index_at = 0; \
+ structure.index_name = 0; \
+ structure.value_at = 0; \
+ f_macro_string_dynamic_t_clear(structure.value_name)
+
+ #define macro_fss_embedded_list_read_depth_t_delete(status, structure) f_macro_string_dynamic_t_delete(status, structure.value_name)
+ #define macro_fss_embedded_list_read_depth_t_destroy(status, structure) f_macro_string_dynamic_t_destroy(status, structure.value_name)
+
+ #define macro_fss_embedded_list_read_depth_t_delete_simple(structure) f_macro_string_dynamic_t_delete_simple(structure.value_name)
+ #define macro_fss_embedded_list_read_depth_t_destroy_simple(structure) f_macro_string_dynamic_t_destroy_simple(structure.value_name)
+#endif // _di_fss_embedded_list_read_depth_t_
+
+/**
+ * A structure containing a statically allocated array of booleans and the array length.
+ *
+ * skip: a statically allocated array representing list items that are to be skipped.
+ * used: the length of the statically allocated skip array.
+ */
+#ifndef _di_fss_embedded_list_read_skip_t_
+ typedef struct {
+ bool *skip;
+ f_array_length_t used;
+ } fss_embedded_list_read_skip_t;
+
+ #define fss_embedded_list_read_skip_t_initialize \
+ { \
+ 0, \
+ 0, \
+ }
+
+ #define macro_fss_embedded_list_read_skip_t_initialize(skip, used) \
+ { \
+ skip, \
+ used, \
+ }
+#endif // _di_fss_embedded_list_read_skip_t_
+
+/**
+ * An array of depth parameters.
+ *
+ * array: the array of depths.
+ * size: total amount of allocated space.
+ * used: total number of allocated spaces used.
+ */
+#ifndef _di_fss_embedded_list_read_depths_t_
+ typedef struct {
+ fss_embedded_list_read_depth_t *array;
+
+ f_array_length_t size;
+ f_array_length_t used;
+ } fss_embedded_list_read_depths_t;
+
+ #define fss_embedded_list_read_depths_t_initialize { 0, 0, 0 }
+
+ #define macro_fss_embedded_list_read_depths_t_clear(depths) f_macro_memory_structure_t_clear(depths)
+
+ #define macro_fss_embedded_list_read_depths_t_new(status, depths, length) f_macro_memory_structure_t_new(status, depths, fss_embedded_list_read_depth_t, length)
+
+ #define macro_fss_embedded_list_read_depths_t_delete(status, depths) \
+ status = F_none; \
+ depths.used = depths.size; \
+ while (depths.used > 0) { \
+ depths.used--; \
+ macro_fss_embedded_list_read_depth_t_delete(status, depths.array[depths.used]); \
+ if (status != F_none) break; \
+ } \
+ if (status == F_none) f_macro_memory_structure_t_delete(depths, fss_embedded_list_read_depth_t)
+
+ #define macro_fss_embedded_list_read_depths_t_destroy(status, depths) \
+ status = F_none; \
+ depths.used = depths.size; \
+ while (depths.used > 0) { \
+ depths.used--; \
+ macro_fss_embedded_list_read_depth_t_destroy(status, depths.array[depths.used]); \
+ if (status != F_none) break; \
+ } \
+ if (status == F_none) f_macro_memory_structure_t_destroy(depths, fss_embedded_list_read_depth_t)
+
+ #define macro_fss_embedded_list_read_depths_t_delete_simple(depths) \
+ depths.used = depths.size; \
+ while (depths.used > 0) { \
+ depths.used--; \
+ macro_fss_embedded_list_read_depth_t_delete_simple(depths.array[depths.used]); \
+ } \
+ if (!depths.used) f_macro_memory_structure_t_delete_simple(depths, fss_embedded_list_read_depth_t)
+
+ #define macro_fss_embedded_list_read_depths_t_destroy_simple(depths) \
+ depths.used = depths.size; \
+ while (depths.used > 0) { \
+ depths.used--; \
+ macro_fss_embedded_list_read_depth_t_destroy_simple(depths.array[depths.used]); \
+ } \
+ if (!depths.used) f_macro_memory_structure_t_destroy_simple(depths, fss_embedded_list_read_depth_t)
+
+ #define macro_fss_embedded_list_read_t_depths_resize(status, depths, new_length) \
+ status = F_none; \
+ if (new_length < depths.size) { \
+ f_array_length_t i = depths.size - new_length; \
+ for (; i < depths.size; i++) { \
+ macro_fss_embedded_list_read_depth_t_delete(status, depths.array[i]); \
+ if (status != F_none) break; \
+ } \
+ } \
+ if (status == F_none) status = f_memory_resize((void **) & depths.array, sizeof(fss_embedded_list_read_depth_t), depths.size, new_length); \
+ if (status == F_none) { \
+ if (new_length > depths.size) { \
+ f_array_length_t i = depths.size; \
+ for (; i < new_length; i++) { \
+ memset(&depths.array[i], 0, sizeof(fss_embedded_list_read_depth_t)); \
+ } \
+ } \
+ depths.size = new_length; \
+ if (depths.used > depths.size) depths.used = new_length; \
+ }
+
+ #define macro_fss_embedded_list_read_depths_t_adjust(status, depths, new_length) \
+ status = F_none; \
+ if (new_length < depths.size) { \
+ f_array_length_t i = depths.size - new_length; \
+ for (; i < depths.size; i++) { \
+ macro_fss_embedded_list_read_depth_t_delete(status, depths.array[i]); \
+ if (status != F_none) break; \
+ } \
+ } \
+ if (status == F_none) status = f_memory_adjust((void **) & depths.array, sizeof(fss_embedded_list_read_depth_t), depths.size, new_length); \
+ if (status == F_none) { \
+ if (new_length > depths.size) { \
+ f_array_length_t i = depths.size; \
+ for (; i < new_length; i++) { \
+ memset(&depths.array[i], 0, sizeof(fss_embedded_list_read_depth_t)); \
+ } \
+ } \
+ depths.size = new_length; \
+ if (depths.used > depths.size) depths.used = new_length; \
+ }
+#endif // _di_fss_embedded_list_read_depths_t_
+
+/**
+ * Pre-process the parameters, parsing out and handling the depth and depth related parameters.
+ *
+ * Will handle depth-sensitive parameter conflicts, such as --name being used with --at (which is not allowed).
+ *
+ * @param arguments
+ * The console arguments to pre-process.
+ * @param data
+ * The program specific data.
+ * @param depths
+ * This stores the pre-processed depth parameters.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fss_embedded_list_read_main_preprocess_depth_
+ extern f_return_status fss_embedded_list_read_main_preprocess_depth(const f_console_arguments_t arguments, const fss_embedded_list_read_data_t data, fss_embedded_list_read_depths_t *depths) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_main_preprocess_depth_
+
+/**
+ * Process a given file.
+ *
+ * @param arguments
+ * The console arguments passed to the program.
+ * @param data
+ * The program specific data.
+ * @param file_name
+ * The name of the file being processed.
+ * @param depths
+ * The processed depth parameters.
+ * @param objects_delimits
+ * An array of delimits detected during processing, for top-level objects.
+ * @param contents_delimits
+ * An array of delimits detected during processing, for contents.
+ * @param comments
+ * An array of ranges representing where comments are found within any valid content.
+ * This only stores comments found within valid content only.
+ *
+ * @see fss_embedded_list_read_main_preprocess_depth()
+ * @see fss_embedded_list_read_main_process_for_depth()
+ *
+ * @return
+ * F_none on success.
+ *
+ * Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fss_embedded_list_read_main_process_file_
+ extern f_return_status fss_embedded_list_read_main_process_file(const f_console_arguments_t arguments, fss_embedded_list_read_data_t *data, const f_string_t file_name, const fss_embedded_list_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_main_process_file_
+
+/**
+ * Process the items for a given depth.
+ *
+ * This will recursively continue down the depth chain until the final depth is reached.
+ *
+ * @param arguments
+ * The console arguments passed to the program.
+ * @param file_name
+ * The name of the file being processed.
+ * @param depths
+ * The array of all depth related parameter settings.
+ * @param depths_index
+ * The array location within depth being worked on.
+ * @param line
+ * The line number parameter value, used for printing a specific line number for content.
+ * @param parents
+ * The skip status of any parent lists.
+ * Set parents.length to 0 for depth 0.
+ * @param data
+ * The program specific data.
+ * @param objects_delimits
+ * An array of delimits detected during processing, for top-level objects.
+ * @param contents_delimits
+ * An array of delimits detected during processing, for contents.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_read_main_process_file()
+ */
+#ifndef _di_fss_embedded_list_read_main_process_for_depth_
+ extern f_return_status fss_embedded_list_read_main_process_for_depth(const f_console_arguments_t arguments, const f_string_t filename, const fss_embedded_list_read_depths_t depths, const f_array_length_t depths_index, const f_array_length_t line, const fss_embedded_list_read_skip_t parents, fss_embedded_list_read_data_t *data, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_main_process_for_depth_
+
+/**
+ * Print the end of an content.
+ *
+ * @param data
+ * The program specific data.
+ */
+#ifndef _di_fss_embedded_list_read_print_content_end_
+ extern void fss_embedded_list_read_print_content_end(const fss_embedded_list_read_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_print_content_end_
+
+/**
+ * Print the ignore character for content.
+ *
+ * This is only used in pipe output mode.
+ *
+ * @param data
+ * The program specific data.
+ */
+#ifndef _di_fss_embedded_list_read_print_content_ignore_
+ extern void fss_embedded_list_read_print_content_ignore(const fss_embedded_list_read_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_print_content_ignore_
+
+/**
+ * Print the end of an object (which is essentially the start of a content).
+ *
+ * @param data
+ * The program specific data.
+ */
+#ifndef _di_fss_embedded_list_read_print_object_end_
+ extern void fss_embedded_list_read_print_object_end(const fss_embedded_list_read_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_print_object_end_
+
+/**
+ * Print the end of an object/content set.
+ *
+ * @param data
+ * The program specific data.
+ */
+#ifndef _di_fss_embedded_list_read_print_set_end_
+ extern void fss_embedded_list_read_print_set_end(const fss_embedded_list_read_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_print_set_end_
+
+/**
+ * Rewrite the object and content delimit ranges to be within the given depth range.
+ *
+ * @param data
+ * The program specific data.
+ * @param objects_delimits
+ * An array of delimits detected during processing, for top-level objects.
+ * @param contents_delimits
+ * An array of delimits detected during processing, for contents.
+ *
+ * @see fss_embedded_list_read_main_process_file()
+ */
+#ifndef _di_fss_embedded_list_read_process_delimits_
+ extern void fss_embedded_list_read_process_delimits(const fss_embedded_list_read_data_t data, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_process_delimits_
+
+/**
+ * Write the given delimits at the given depth back into the new delimits array, specifically for contents.
+ *
+ * @param data
+ * The program specific data.
+ * @param depth
+ * The depth in which to process.
+ * @param original_delimits
+ * The original delimits structure.
+ * @param original_used
+ * The size of the original delimits structure.
+ * @param delimits
+ * The delimits array in which the delimits are written to.
+ *
+ * @see fss_embedded_list_read_process_delimits()
+ */
+#ifndef _di_fss_embedded_list_read_process_delimits_contents_
+ extern void fss_embedded_list_read_process_delimits_contents(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t original_delimits[], const f_string_length_t original_used, f_fss_delimits_t *delimits) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_process_delimits_contents_
+
+/**
+ * Write the given delimits at the given depth back into the new delimits array, specifically for objects.
+ *
+ * @param data
+ * The program specific data.
+ * @param depth
+ * The depth in which to process.
+ * @param original_delimits
+ * The original delimits structure.
+ * @param original_used
+ * The size of the original delimits structure.
+ * @param delimits
+ * The delimits array in which the delimits are written to.
+ *
+ * @see fss_embedded_list_read_process_delimits()
+ */
+#ifndef _di_fss_embedded_list_read_process_delimits_objects_
+ extern void fss_embedded_list_read_process_delimits_objects(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t original_delimits[], const f_string_length_t original_used, f_fss_delimits_t *delimits) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_process_delimits_objects_
+
+/**
+ * Determine if the given location is actually within another depth.
+ *
+ * @param data
+ * The program specific data.
+ * @param depth
+ * The depth in which to process.
+ * @param location
+ * The location to investigate.
+ *
+ * @return
+ * TRUE if location is within a greater depth.
+ * FALSE if location is not within a greater depth.
+ *
+ * @see fss_embedded_list_read_process_delimits_objects()
+ * @see fss_embedded_list_read_process_delimits_contents()
+ */
+#ifndef _di_fss_embedded_list_read_process_delimits_within_greater_
+ extern f_return_status fss_embedded_list_read_process_delimits_within_greater(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t location) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_process_delimits_within_greater_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_fss_embedded_list_read_h
--- /dev/null
+# fss-0000
+
--- /dev/null
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
+f_utf
+f_color
+f_console
+f_directory
+f_environment
+f_file
+f_fss
+f_pipe
+f_print
+fl_color
+fl_console
+fl_conversion
+fl_fss
+fl_print
+fl_status
+fl_string
+fll_error
+fll_execute
+fll_file
+fll_fss
+fll_program
--- /dev/null
+# fss-0001
+
+project_name fss_embedded_list_read
+
+version_major 0
+version_minor 5
+version_micro 2
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual level monolithic
+modes_default monolithic
+
+build_compiler gcc
+build_indexer ar
+build_language c
+build_libraries -lc
+build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-level -lfll_2 -lfll_1 -lfll_0
+build_libraries-monolithic -lfll
+build_sources_library fss_embedded_list_read.c private-fss_embedded_list_read.c
+build_sources_program main.c
+build_sources_headers fss_embedded_list_read.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_3
+path_headers_preserve no
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+path_sources
+path_standard yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+defines_static
+defines_shared
+
+flags_all -z now -g -fdiagnostics-color=always
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE
--- /dev/null
+#include "fss_embedded_list_write.h"
+#include "private-fss_embedded_list_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_write_print_help_
+ f_return_status fss_embedded_list_write_print_help(const f_file_t output, const f_color_context_t context) {
+
+ fll_program_print_help_header(output, context, fss_embedded_list_write_name_long, fss_embedded_list_write_version);
+
+ fll_program_print_help_option(output, context, f_console_standard_short_help, f_console_standard_long_help, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print this help message.");
+ fll_program_print_help_option(output, context, f_console_standard_short_dark, f_console_standard_long_dark, f_console_symbol_short_disable, f_console_symbol_long_disable, " Output using colors that show up better on dark backgrounds.");
+ fll_program_print_help_option(output, context, f_console_standard_short_light, f_console_standard_long_light, f_console_symbol_short_disable, f_console_symbol_long_disable, " Output using colors that show up better on light backgrounds.");
+ fll_program_print_help_option(output, context, f_console_standard_short_no_color, f_console_standard_long_no_color, f_console_symbol_short_disable, f_console_symbol_long_disable, "Do not output in color.");
+ fll_program_print_help_option(output, context, f_console_standard_short_quiet, f_console_standard_long_quiet, f_console_symbol_short_disable, f_console_symbol_long_disable, " Decrease verbosity beyond normal output.");
+ fll_program_print_help_option(output, context, f_console_standard_short_normal, f_console_standard_long_normal, f_console_symbol_short_disable, f_console_symbol_long_disable, " Set verbosity to normal output.");
+ fll_program_print_help_option(output, context, f_console_standard_short_verbose, f_console_standard_long_verbose, f_console_symbol_short_disable, f_console_symbol_long_disable, " Increase verbosity beyond normal output.");
+ fll_program_print_help_option(output, context, f_console_standard_short_debug, f_console_standard_long_debug, f_console_symbol_short_disable, f_console_symbol_long_disable, " Enable debugging, inceasing verbosity beyond normal output.");
+ fll_program_print_help_option(output, context, f_console_standard_short_version, f_console_standard_long_version, f_console_symbol_short_disable, f_console_symbol_long_disable, " Print only the version number.");
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fll_program_print_help_option(output, context, fss_embedded_list_write_short_file, fss_embedded_list_write_long_file, f_console_symbol_short_enable, f_console_symbol_long_enable, " Specify a file to send output to.");
+ fll_program_print_help_option(output, context, fss_embedded_list_write_short_content, fss_embedded_list_write_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, "The Content to output.");
+ fll_program_print_help_option(output, context, fss_embedded_list_write_short_double, fss_embedded_list_write_long_double, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use double quotes (default).");
+ fll_program_print_help_option(output, context, fss_embedded_list_write_short_ignore, fss_embedded_list_write_long_ignore, f_console_symbol_short_enable, f_console_symbol_long_enable, " Ignore a given range within a content.");
+ fll_program_print_help_option(output, context, fss_embedded_list_write_short_object, fss_embedded_list_write_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " The Object to output.");
+ fll_program_print_help_option(output, context, fss_embedded_list_write_short_partial, fss_embedded_list_write_long_partial, f_console_symbol_short_enable, f_console_symbol_long_enable, "Do not output end of Object/Content character.");
+ fll_program_print_help_option(output, context, fss_embedded_list_write_short_prepend, fss_embedded_list_write_long_prepend, f_console_symbol_short_enable, f_console_symbol_long_enable, "Prepend the given whitespace characters to the start of each multi-line Content.");
+ fll_program_print_help_option(output, context, fss_embedded_list_write_short_single, fss_embedded_list_write_long_single, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use single quotes.");
+ fll_program_print_help_option(output, context, fss_embedded_list_write_short_trim, fss_embedded_list_write_long_trim, f_console_symbol_short_enable, f_console_symbol_long_enable, " Trim object names.");
+
+ fll_program_print_help_usage(output, context, fss_embedded_list_write_name, "");
+
+ fprintf(output.stream, " The pipe uses the Backspace character '");
+ fl_color_print(output.stream, context.set.notable, "\\b");
+ fprintf(output.stream, "' (");
+ fl_color_print(output.stream, context.set.notable, "U+0008");
+ fprintf(output.stream, ") to designate the start of a Content.%c", f_string_eol[0]);
+
+ fprintf(output.stream, " The pipe uses the Form Feed character '");
+ fl_color_print(output.stream, context.set.notable, "\\f");
+ fprintf(output.stream, "' (");
+ fl_color_print(output.stream, context.set.notable, "U+000C");
+ fprintf(output.stream, ") to designate the end of the last Content.%c", f_string_eol[0]);
+
+ fprintf(output.stream, " The pipe uses the Vertical Line character '");
+ fl_color_print(output.stream, context.set.notable, "\\v");
+ fprintf(output.stream, "' (");
+ fl_color_print(output.stream, context.set.notable, "U+000B");
+ fprintf(output.stream, ") is used to ignore a content range (use this both before and after the range).%c", f_string_eol[0]);
+
+ fprintf(output.stream, " For the pipe, an Object is terminated by either a Backspace character '");
+ fl_color_print(output.stream, context.set.notable, "\\b");
+ fprintf(output.stream, "' (");
+ fl_color_print(output.stream, context.set.notable, "U+0008");
+ fprintf(output.stream, ") or a Form Feed character '");
+ fl_color_print(output.stream, context.set.notable, "\\f");
+ fprintf(output.stream, "' (");
+ fl_color_print(output.stream, context.set.notable, "U+000C");
+ fprintf(output.stream, ").%c", f_string_eol[0]);
+
+ fprintf(output.stream, " The end of the pipe represents the end of any Object or Content.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " The FSS-0008 (Embedded List) specification does not support quoted names, therefore the parameters '");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_single);
+ fprintf(output.stream, "' and '");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_double);
+ fprintf(output.stream, "' do nothing.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ fprintf(output.stream, " The parameter '");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_ignore);
+ fprintf(output.stream, "' designates to not escape any valid nested Object or Content within some Content.%c", f_string_eol[0]);
+ fprintf(output.stream, " This parameter requires two values.%c", f_string_eol[0]);
+ fprintf(output.stream, " This parameter is not used for ignoring anything from the input pipe.%c", f_string_eol[0]);
+ fprintf(output.stream, " This parameter must be specified after a '");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+ fprintf(output.stream, "' parameter and this applies only to the Content represented by that specific '");
+ fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+ fprintf(output.stream, "' parameter.%c", f_string_eol[0]);
+
+ fprintf(output.stream, "%c", f_string_eol[0]);
+
+ return F_none;
+ }
+#endif // _di_fss_embedded_list_write_print_help_
+
+#ifndef _di_fss_embedded_list_write_main_
+ f_return_status fss_embedded_list_write_main(const f_console_arguments_t arguments, fss_embedded_list_write_data_t *data) {
+ f_status_t status = F_none;
+
+ {
+ const f_console_parameters_t parameters = f_macro_console_parameters_t_initialize(data->parameters, fss_embedded_list_write_total_parameters);
+
+ {
+ f_console_parameter_id_t ids[3] = { fss_embedded_list_write_parameter_no_color, fss_embedded_list_write_parameter_light, fss_embedded_list_write_parameter_dark };
+ const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 3);
+
+ status = fll_program_parameter_process(arguments, parameters, choices, F_true, &data->remaining, &data->context);
+
+ data->error.context = data->context.set.error;
+ data->error.notable = data->context.set.notable;
+
+ if (F_status_is_error(status)) {
+ fss_embedded_list_write_delete_data(data);
+ return F_status_set_error(status);
+ }
+ }
+
+ // Identify priority of verbosity related parameters.
+ {
+ f_console_parameter_id_t ids[4] = { fss_embedded_list_write_parameter_verbosity_quiet, fss_embedded_list_write_parameter_verbosity_normal, fss_embedded_list_write_parameter_verbosity_verbose, fss_embedded_list_write_parameter_verbosity_debug };
+ f_console_parameter_id_t choice = 0;
+ const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 4);
+
+ status = f_console_parameter_prioritize_right(parameters, choices, &choice);
+
+ if (F_status_is_error(status)) {
+ fss_embedded_list_write_delete_data(data);
+ return status;
+ }
+
+ if (choice == fss_embedded_list_write_parameter_verbosity_quiet) {
+ data->error.verbosity = f_console_verbosity_quiet;
+ }
+ else if (choice == fss_embedded_list_write_parameter_verbosity_normal) {
+ data->error.verbosity = f_console_verbosity_normal;
+ }
+ else if (choice == fss_embedded_list_write_parameter_verbosity_verbose) {
+ data->error.verbosity = f_console_verbosity_verbose;
+ }
+ else if (choice == fss_embedded_list_write_parameter_verbosity_debug) {
+ data->error.verbosity = f_console_verbosity_debug;
+ }
+ }
+
+ status = F_none;
+ }
+
+ if (data->parameters[fss_embedded_list_write_parameter_help].result == f_console_result_found) {
+ fss_embedded_list_write_print_help(data->output, data->context);
+
+ fss_embedded_list_write_delete_data(data);
+ return status;
+ }
+
+ if (data->parameters[fss_embedded_list_write_parameter_version].result == f_console_result_found) {
+ fll_program_print_version(data->output, fss_embedded_list_write_version);
+
+ fss_embedded_list_write_delete_data(data);
+ return status;
+ }
+
+ f_file_t output = f_file_t_initialize;
+
+ output.id = f_type_descriptor_output;
+ output.stream = f_type_output;
+ output.flag = f_file_flag_create | f_file_flag_write_only | f_file_flag_append;
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_embedded_list_write_parameter_file].result == f_console_result_additional) {
+ if (data->parameters[fss_embedded_list_write_parameter_file].values.used > 1) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_file);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' may only be specified once.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ else {
+ const f_string_length_t location = data->parameters[fss_embedded_list_write_parameter_file].values.array[0];
+
+ output.id = -1;
+ output.stream = 0;
+ status = f_file_stream_open(arguments.argv[location], 0, &output);
+
+ if (F_status_is_error(status)) {
+ fll_error_file_print(data->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[location], "open", fll_error_file_type_file);
+ }
+ }
+ }
+ else if (data->parameters[fss_embedded_list_write_parameter_file].result == f_console_result_found) {
+ fss_embedded_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_embedded_list_write_long_file);
+ status = F_status_set_error(F_parameter);
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_embedded_list_write_parameter_object].locations.used || data->parameters[fss_embedded_list_write_parameter_content].locations.used) {
+ if (data->parameters[fss_embedded_list_write_parameter_object].locations.used) {
+ if (data->parameters[fss_embedded_list_write_parameter_object].locations.used != data->parameters[fss_embedded_list_write_parameter_object].values.used) {
+ fss_embedded_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_embedded_list_write_parameter_content].locations.used != data->parameters[fss_embedded_list_write_parameter_content].values.used) {
+ fss_embedded_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_embedded_list_write_parameter_object].locations.used != data->parameters[fss_embedded_list_write_parameter_content].locations.used && data->parameters[fss_embedded_list_write_parameter_partial].result == f_console_result_none) {
+ fss_embedded_list_write_error_parameter_same_times_print(*data);
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_embedded_list_write_parameter_content].locations.used && data->parameters[fss_embedded_list_write_parameter_partial].locations.used) {
+ if (data->parameters[fss_embedded_list_write_parameter_content].result == f_console_result_additional) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_partial);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter only allows either the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter or the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter, but not both.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_embedded_list_write_parameter_content].result == f_console_result_additional) {
+ f_array_length_t location_object = 0;
+ f_array_length_t location_content = 0;
+ f_array_length_t location_sub_object = 0;
+ f_array_length_t location_sub_content = 0;
+
+ for (f_array_length_t i = 0; i < data->parameters[fss_embedded_list_write_parameter_object].locations.used; i++) {
+ location_object = data->parameters[fss_embedded_list_write_parameter_object].locations.array[i];
+ location_content = data->parameters[fss_embedded_list_write_parameter_content].locations.array[i];
+ location_sub_object = data->parameters[fss_embedded_list_write_parameter_object].locations_sub.array[i];
+ location_sub_content = data->parameters[fss_embedded_list_write_parameter_content].locations_sub.array[i];
+
+ if (location_object > location_content || location_object == location_content && location_sub_object > location_sub_content) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must be specified before a '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ break;
+ }
+ } // for
+ }
+ }
+ }
+ else if (data->parameters[fss_embedded_list_write_parameter_content].locations.used) {
+ if (data->parameters[fss_embedded_list_write_parameter_content].locations.used != data->parameters[fss_embedded_list_write_parameter_content].values.used) {
+ fss_embedded_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+ status = F_status_set_error(F_parameter);
+ }
+ else if (!data->parameters[fss_embedded_list_write_parameter_partial].locations.used) {
+ fss_embedded_list_write_error_parameter_same_times_print(*data);
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+ else if (!data->process_pipe) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThis requires either piped data or the use of the '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (F_status_is_error_not(status) && data->process_pipe) {
+ if (data->parameters[fss_embedded_list_write_parameter_partial].result == f_console_result_found) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_partial);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter cannot be used when processing a pipe.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_embedded_list_write_parameter_prepend].result == f_console_result_found) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_embedded_list_write_parameter_prepend].result == f_console_result_additional) {
+ const f_string_length_t index = data->parameters[fss_embedded_list_write_parameter_prepend].values.array[data->parameters[fss_embedded_list_write_parameter_prepend].values.used - 1];
+ const f_string_length_t length = strnlen(arguments.argv[index], f_console_length_size);
+
+ if (length) {
+ f_string_range_t range = f_macro_string_range_t_initialize(length);
+
+ data->prepend.string = arguments.argv[index];
+ data->prepend.used = length;
+ data->prepend.size = length;
+
+ for (; range.start < length; range.start++) {
+
+ status = f_fss_is_space(data->prepend, range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must only contain whitespace.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ break;
+ }
+ } // for
+ }
+ else {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must not be an empty string.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_embedded_list_write_parameter_ignore].result == f_console_result_found) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_ignore);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' was specified, but no values were given.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_embedded_list_write_parameter_ignore].result == f_console_result_additional) {
+ const f_array_length_t total_locations = data->parameters[fss_embedded_list_write_parameter_ignore].locations.used;
+ const f_array_length_t total_arguments = data->parameters[fss_embedded_list_write_parameter_ignore].values.used;
+
+ if (total_locations * 2 > total_arguments) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_ignore);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' requires two values.%c", f_string_eol[0]);
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+
+ f_fss_quote_t quote = f_fss_delimit_quote_double;
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_embedded_list_write_parameter_double].result == f_console_result_found) {
+ if (data->parameters[fss_embedded_list_write_parameter_single].result == f_console_result_found) {
+ if (data->parameters[fss_embedded_list_write_parameter_double].location < data->parameters[fss_embedded_list_write_parameter_single].location) {
+ quote = f_fss_delimit_quote_single;
+ }
+ }
+ }
+ else if (data->parameters[fss_embedded_list_write_parameter_single].result == f_console_result_found) {
+ quote = f_fss_delimit_quote_single;
+ }
+ }
+
+ f_string_dynamic_t buffer = f_string_dynamic_t_initialize;
+ f_string_dynamic_t object = f_string_dynamic_t_initialize;
+ f_string_dynamic_t content = f_string_dynamic_t_initialize;
+
+ if (F_status_is_error_not(status)) {
+ f_string_dynamic_t escaped = f_string_dynamic_t_initialize;
+ f_string_ranges_t ignore = f_string_ranges_t_initialize;
+
+ if (data->process_pipe) {
+ status = fss_embedded_list_write_process_pipe(*data, output, quote, &buffer, &ignore);
+
+ if (F_status_is_error(status)) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "input pipe");
+ fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]);
+ }
+ }
+
+ ignore.used = 0;
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_embedded_list_write_parameter_partial].result == f_console_result_found) {
+
+ if (data->parameters[fss_embedded_list_write_parameter_object].result == f_console_result_additional) {
+ for (f_array_length_t i = 0; i < data->parameters[fss_embedded_list_write_parameter_object].values.used; i++) {
+
+ object.string = arguments.argv[data->parameters[fss_embedded_list_write_parameter_object].values.array[i]];
+ object.used = strnlen(object.string, f_console_length_size);
+ object.size = object.used;
+
+ status = fss_embedded_list_write_process(*data, output, quote, &object, 0, 0, &buffer);
+ if (F_status_is_error(status)) break;
+ } // for
+ }
+ else {
+ for (f_array_length_t i = 0; i < data->parameters[fss_embedded_list_write_parameter_content].values.used; i++) {
+
+ status = fss_embedded_list_write_process_parameter_ignore(arguments, *data, data->parameters[fss_embedded_list_write_parameter_content].locations, i, &ignore);
+ if (F_status_is_error(status)) break;
+
+ content.string = arguments.argv[data->parameters[fss_embedded_list_write_parameter_content].values.array[i]];
+ content.used = strnlen(content.string, f_console_length_size);
+ content.size = content.used;
+
+ status = fss_embedded_list_write_process(*data, output, quote, 0, &content, &ignore, &buffer);
+ if (F_status_is_error(status)) break;
+ } // for
+ }
+ }
+ else {
+ for (f_array_length_t i = 0; i < data->parameters[fss_embedded_list_write_parameter_object].values.used; i++) {
+
+ status = fss_embedded_list_write_process_parameter_ignore(arguments, *data, data->parameters[fss_embedded_list_write_parameter_content].locations, i, &ignore);
+ if (F_status_is_error(status)) break;
+
+ object.string = arguments.argv[data->parameters[fss_embedded_list_write_parameter_object].values.array[i]];
+ object.used = strnlen(object.string, f_console_length_size);
+ object.size = object.used;
+
+ content.string = arguments.argv[data->parameters[fss_embedded_list_write_parameter_content].values.array[i]];
+ content.used = strnlen(content.string, f_console_length_size);
+ content.size = content.used;
+
+ status = fss_embedded_list_write_process(*data, output, quote, &object, &content, &ignore, &buffer);
+ if (F_status_is_error(status)) break;
+ } // for
+ }
+
+ if (F_status_is_error(status)) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "input arguments");
+ fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]);
+ }
+ }
+ else if (data->error.verbosity != f_console_verbosity_quiet && data->parameters[fss_embedded_list_write_parameter_file].result == f_console_result_none) {
+
+ // ensure there is always a newline at the end, unless in quiet mode.
+ fprintf(data->output.stream, "%c", f_string_eol[0]);
+ }
+ }
+
+ f_macro_string_dynamic_t_delete_simple(escaped);
+ f_macro_string_ranges_t_delete_simple(ignore);
+
+ // object and content, though being a "dynamic" type, is being used statically, so clear them up to avoid invalid free().
+ object.string = 0;
+ object.used = 0;
+ object.size = 0;
+
+ content.string = 0;
+ content.used = 0;
+ content.size = 0;
+ }
+
+ if (data->parameters[fss_embedded_list_write_parameter_file].result == f_console_result_additional) {
+ if (output.id != -1) {
+ f_file_stream_close(F_true, &output);
+ }
+ }
+
+ // ensure a newline is always put at the end of the program execution, unless in quiet mode.
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ if (F_status_is_error(status)) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ }
+ }
+
+ f_macro_string_dynamic_t_delete_simple(buffer);
+ f_macro_string_dynamic_t_delete_simple(object);
+ f_macro_string_dynamic_t_delete_simple(content);
+ fss_embedded_list_write_delete_data(data);
+ return status;
+ }
+#endif // _di_fss_embedded_list_write_main_
+
+#ifndef _di_fss_embedded_list_write_delete_data_
+ f_return_status fss_embedded_list_write_delete_data(fss_embedded_list_write_data_t *data) {
+
+ for (f_string_length_t i = 0; i < fss_embedded_list_write_total_parameters; i++) {
+ f_macro_string_lengths_t_delete_simple(data->parameters[i].locations);
+ f_macro_string_lengths_t_delete_simple(data->parameters[i].locations_sub);
+ f_macro_string_lengths_t_delete_simple(data->parameters[i].values);
+ } // for
+
+ f_macro_string_lengths_t_delete_simple(data->remaining);
+
+ f_macro_color_context_t_delete_simple(data->context);
+
+ return F_none;
+ }
+#endif // _di_fss_embedded_list_write_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This program provides FSS-0008 Embedded List write functionality.
+ */
+#ifndef _fss_embedded_list_write_h
+
+// libc includes
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/utf.h>
+#include <level_0/console.h>
+#include <level_0/file.h>
+#include <level_0/pipe.h>
+#include <level_0/print.h>
+
+// fll-1 includes
+#include <level_1/color.h>
+#include <level_1/console.h>
+#include <level_1/conversion.h>
+#include <level_1/fss_embedded_list.h>
+#include <level_1/status.h>
+#include <level_1/string.h>
+
+// fll-2 includes
+#include <level_2/error.h>
+#include <level_2/fss_status.h>
+#include <level_2/program.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_write_version_
+ #define fss_embedded_list_write_major_version "0"
+ #define fss_embedded_list_write_minor_version "5"
+ #define fss_embedded_list_write_micro_version "2"
+ #define fss_embedded_list_write_version fss_embedded_list_write_major_version "." fss_embedded_list_write_minor_version "." fss_embedded_list_write_micro_version
+#endif // _di_fss_embedded_list_write_version_
+
+#ifndef _di_fss_embedded_list_write_name_
+ #define fss_embedded_list_write_name "fss_embedded_list_write"
+ #define fss_embedded_list_write_name_long "FSS Embedded List Write"
+#endif // _di_fss_embedded_list_write_name_
+
+#ifndef _di_fss_embedded_list_write_defines_
+ #define fss_embedded_list_write_pipe_content_end '\f'
+ #define fss_embedded_list_write_pipe_content_ignore '\v'
+ #define fss_embedded_list_write_pipe_content_start '\b'
+
+ #define fss_embedded_list_write_short_file "f"
+ #define fss_embedded_list_write_short_content "c"
+ #define fss_embedded_list_write_short_double "d"
+ #define fss_embedded_list_write_short_ignore "I"
+ #define fss_embedded_list_write_short_object "o"
+ #define fss_embedded_list_write_short_partial "p"
+ #define fss_embedded_list_write_short_prepend "P"
+ #define fss_embedded_list_write_short_single "s"
+ #define fss_embedded_list_write_short_trim "T"
+
+ #define fss_embedded_list_write_long_file "file"
+ #define fss_embedded_list_write_long_content "content"
+ #define fss_embedded_list_write_long_double "double"
+ #define fss_embedded_list_write_long_ignore "ignore"
+ #define fss_embedded_list_write_long_object "object"
+ #define fss_embedded_list_write_long_partial "partial"
+ #define fss_embedded_list_write_long_prepend "prepend"
+ #define fss_embedded_list_write_long_single "single"
+ #define fss_embedded_list_write_long_trim "trim"
+
+ enum {
+ fss_embedded_list_write_parameter_help,
+ fss_embedded_list_write_parameter_light,
+ fss_embedded_list_write_parameter_dark,
+ fss_embedded_list_write_parameter_no_color,
+ fss_embedded_list_write_parameter_verbosity_quiet,
+ fss_embedded_list_write_parameter_verbosity_normal,
+ fss_embedded_list_write_parameter_verbosity_verbose,
+ fss_embedded_list_write_parameter_verbosity_debug,
+ fss_embedded_list_write_parameter_version,
+
+ fss_embedded_list_write_parameter_file,
+ fss_embedded_list_write_parameter_content,
+ fss_embedded_list_write_parameter_double,
+ fss_embedded_list_write_parameter_ignore,
+ fss_embedded_list_write_parameter_object,
+ fss_embedded_list_write_parameter_partial,
+ fss_embedded_list_write_parameter_prepend,
+ fss_embedded_list_write_parameter_single,
+ fss_embedded_list_write_parameter_trim,
+ };
+
+ #define fss_embedded_list_write_console_parameter_t_initialize \
+ { \
+ f_console_parameter_t_initialize(f_console_standard_short_help, f_console_standard_long_help, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(f_console_standard_short_light, f_console_standard_long_light, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, F_false, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_quiet, f_console_standard_long_quiet, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_normal, f_console_standard_long_normal, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_verbose, f_console_standard_long_verbose, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_debug, f_console_standard_long_debug, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(fss_embedded_list_write_short_file, fss_embedded_list_write_long_file, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_write_short_content, fss_embedded_list_write_long_content, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_write_short_double, fss_embedded_list_write_long_double, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_write_short_ignore, fss_embedded_list_write_long_ignore, 0, 2, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_write_short_object, fss_embedded_list_write_long_object, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_write_short_partial, fss_embedded_list_write_long_partial, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_write_short_prepend, fss_embedded_list_write_long_prepend, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_write_short_single, fss_embedded_list_write_long_single, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_embedded_list_write_short_trim, fss_embedded_list_write_long_trim, 0, 0, f_console_type_normal), \
+ }
+
+ #define fss_embedded_list_write_total_parameters 18
+#endif // _di_fss_embedded_list_write_defines_
+
+#ifndef _di_fss_embedded_list_write_data_t_
+ typedef struct {
+ f_console_parameter_t parameters[fss_embedded_list_write_total_parameters];
+
+ f_string_lengths_t remaining;
+ bool process_pipe;
+
+ f_file_t output;
+ fll_error_print_t error;
+ f_string_static_t prepend;
+
+ f_color_context_t context;
+ } fss_embedded_list_write_data_t;
+
+ #define fss_embedded_list_write_data_t_initialize \
+ { \
+ fss_embedded_list_write_console_parameter_t_initialize, \
+ f_string_lengths_t_initialize, \
+ F_false, \
+ f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+ fll_error_print_t_initialize, \
+ f_string_static_t_initialize, \
+ f_color_context_t_initialize, \
+ }
+#endif // _di_fss_embedded_list_write_data_t_
+
+/**
+ * Print help.
+ *
+ * @param output
+ * The file to print to.
+ * @param context
+ * The color context settings.
+ *
+ * @return
+ * F_none on success.
+ */
+#ifndef _di_fss_embedded_list_write_print_help_
+ extern f_return_status fss_embedded_list_write_print_help(const f_file_t output, const f_color_context_t context);
+#endif // _di_fss_embedded_list_write_print_help_
+
+/**
+ * Execute main program.
+ *
+ * Be sure to call fss_embedded_list_write_delete_data() after executing this.
+ *
+ * @param arguments
+ * The parameters passed to the process.
+ * @param data
+ * The program data.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_write_delete_data()
+ */
+#ifndef _di_fss_embedded_list_write_main_
+ extern f_return_status fss_embedded_list_write_main(const f_console_arguments_t arguments, fss_embedded_list_write_data_t *data);
+#endif // _di_fss_embedded_list_write_main_
+
+/**
+ * Deallocate data.
+ *
+ * Be sure to call this after executing fss_embedded_list_write_main().
+ *
+ * @param data
+ * The program data.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_write_main()
+ */
+#ifndef _di_fss_embedded_list_write_delete_data_
+ extern f_return_status fss_embedded_list_write_delete_data(fss_embedded_list_write_data_t *data);
+#endif // _di_fss_embedded_list_write_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _fss_embedded_list_write_h
--- /dev/null
+#include "fss_embedded_list_write.h"
+
+int main(const unsigned long argc, const f_string_t *argv) {
+ const f_console_arguments_t arguments = { argc, argv };
+ fss_embedded_list_write_data_t data = fss_embedded_list_write_data_t_initialize;
+
+ if (f_pipe_input_exists()) {
+ data.process_pipe = F_true;
+ }
+
+ if (F_status_is_error(fss_embedded_list_write_main(arguments, &data))) {
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+#include "fss_embedded_list_write.h"
+#include "private-fss_embedded_list_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_write_error_parameter_same_times_print_
+ void fss_embedded_list_write_error_parameter_same_times_print(const fss_embedded_list_write_data_t data) {
+
+ if (data.error.verbosity == f_console_verbosity_quiet) {
+ return;
+ }
+
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sMust specify both the '", fll_error_print_error);
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' parameter and the '");
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' parameter the same number of times when not specifying the ");
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_partial);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' parameter.%c", f_string_eol[0]);
+ }
+#endif // _di_fss_embedded_list_write_error_parameter_same_times_print_
+
+#ifndef _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_
+ void fss_embedded_list_write_error_parameter_unsupported_eol_print(const fss_embedded_list_write_data_t data) {
+
+ if (data.error.verbosity == f_console_verbosity_quiet) {
+ return;
+ }
+
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard does not support end of line character '", fll_error_print_error);
+ fl_color_print(data.error.to.stream, data.context.set.notable, "\\n");
+ fl_color_print(data.error.to.stream, data.context.set.error, "' in objects.%c", f_string_eol[0]);
+ }
+#endif // _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_
+
+#ifndef _di_fss_embedded_list_write_error_parameter_value_missing_print_
+ void fss_embedded_list_write_error_parameter_value_missing_print(const fss_embedded_list_write_data_t data, const f_string_t symbol, const f_string_t parameter) {
+
+ if (data.error.verbosity == f_console_verbosity_quiet) {
+ return;
+ }
+
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", symbol, parameter);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]);
+ }
+#endif // _di_fss_embedded_list_write_error_parameter_value_missing_print_
+
+#ifndef _di_fss_embedded_list_write_process_
+ f_return_status fss_embedded_list_write_process(const fss_embedded_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) {
+ f_status_t status = F_none;
+
+ f_string_range_t range = f_string_range_t_initialize;
+
+ if (object) {
+ uint8_t complete = f_fss_complete_none;
+
+ if (object->used) {
+ range.start = 0;
+ range.stop = object->used - 1;
+ }
+ else {
+ range.start = 1;
+ range.stop = 0;
+ }
+
+ if (content) {
+ if (data.parameters[fss_embedded_list_write_parameter_trim].result == f_console_result_found) {
+ complete = f_fss_complete_full_trim;
+ }
+ else {
+ complete = f_fss_complete_full;
+ }
+ }
+
+ status = fl_fss_embedded_list_object_write_string(*object, complete, &range, buffer);
+
+ if (F_status_set_fine(status) == F_none_eol) {
+ fss_embedded_list_write_error_parameter_unsupported_eol_print(data);
+
+ return F_status_set_error(F_unsupported);
+ }
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_fss_embedded_list_object_write_string", F_true);
+ return status;
+ }
+ }
+
+ if (content && content->used) {
+ range.start = 0;
+ range.stop = content->used - 1;
+
+ status = fl_fss_embedded_list_content_write_string(*content, object ? f_fss_complete_full : f_fss_complete_none, &data.prepend, ignore, &range, buffer);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_fss_embedded_list_content_write_string", F_true);
+ return status;
+ }
+ }
+
+ if (!object || !content) {
+ status = fl_string_append(f_string_eol, 1, buffer);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true);
+ return status;
+ }
+ }
+
+ f_print_dynamic(output.stream, *buffer);
+
+ buffer->used = 0;
+ return status;
+ }
+#endif // _di_fss_embedded_list_write_process_
+
+#ifndef _di_fss_embedded_list_write_process_pipe_
+ f_return_status fss_embedded_list_write_process_pipe(const fss_embedded_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) {
+ f_status_t status = F_none;
+ f_status_t status_pipe = F_none;
+
+ f_file_t input = f_file_t_initialize;
+
+ input.id = f_type_descriptor_input;
+ input.size_read = 2048;
+
+ f_string_length_t total = 0;
+ f_string_length_t previous = 0;
+
+ f_string_range_t range = f_string_range_t_initialize;
+ f_string_range_t range_ignore = f_string_range_t_initialize;
+
+ f_string_dynamic_t block = f_string_dynamic_t_initialize;
+ f_string_dynamic_t object = f_string_dynamic_t_initialize;
+ f_string_dynamic_t content = f_string_dynamic_t_initialize;
+
+ // 0x0 = start new object/content set, 0x1 = processing object, 0x2 = processing content, 0x3 = end object/content set.
+ uint8_t state = 0;
+
+ for (;;) {
+
+ if (range.start > range.stop) {
+ if (status_pipe == F_none_eof) break;
+
+ block.used = 0;
+
+ status_pipe = f_file_read_block(input, &block);
+
+ if (F_status_is_error(status_pipe)) {
+ fll_error_print(data.error, F_status_set_fine(status_pipe), "f_file_read_block", F_true);
+
+ status_pipe = F_status_set_error(F_pipe);
+ break;
+ }
+
+ if (!block.used) break;
+
+ range.start = 0;
+ range.stop = block.used - 1;
+ }
+
+ if (!state || state == 0x1) {
+ if (!state) {
+ object.used = 0;
+ content.used = 0;
+
+ state = 0x1;
+
+ range_ignore.start = 1;
+ range_ignore.stop = 0;
+ }
+
+ if (object.used + block.used > object.size) {
+ status = fl_string_dynamic_increase_by(block.used, &object);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_increase_by", F_true);
+ break;
+ }
+ }
+
+ for (; range.start <= range.stop; range.start++) {
+
+ if (block.string[range.start] == fss_embedded_list_write_pipe_content_start) {
+ state = 0x2;
+ range.start++;
+ break;
+ }
+
+ if (block.string[range.start] == fss_embedded_list_write_pipe_content_end) {
+ state = 0x3;
+ range.start++;
+ break;
+ }
+
+ if (block.string[range.start] == fss_embedded_list_write_pipe_content_ignore) {
+ // this is not used by objects.
+ continue;
+ }
+
+ object.string[object.used++] = block.string[range.start];
+ } // for
+
+ if (F_status_is_error(status)) break;
+
+ // if the start of content was not found, then fetch the next block.
+ if (state == 0x1) continue;
+
+ // if the end of the current block is reached, fetch the next block.
+ if (range.start > range.stop) continue;
+ }
+
+ if (state == 0x2) {
+ if (range.start <= range.stop) {
+ total = (range.stop - range.start) + 1;
+ }
+ else {
+ total = 0;
+ }
+
+ if (total) {
+ if (content.used + total > content.size) {
+ status = fl_string_dynamic_increase_by(total, &content);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_increase_by", F_true);
+ break;
+ }
+ }
+
+ for (; range.start <= range.stop; range.start++) {
+
+ if (block.string[range.start] == fss_embedded_list_write_pipe_content_start) {
+ if (data.error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard only supports one content per object.%c", fll_error_print_error, f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_unsupported);
+ break;
+ }
+
+ if (block.string[range.start] == fss_embedded_list_write_pipe_content_end) {
+ state = 0x3;
+ range.start++;
+ break;
+ }
+
+ if (block.string[range.start] == fss_embedded_list_write_pipe_content_ignore) {
+ if (ignore) {
+ if (range_ignore.start > range_ignore.stop) {
+ range_ignore.start = content.used;
+ range_ignore.stop = content.used;
+ }
+ else {
+ if (ignore->used + 1 > ignore->size) {
+ if (ignore->size + f_fss_default_allocation_step > f_array_length_t_size) {
+ if (ignore->size + 1 > f_array_length_t_size) {
+ fll_error_print(data.error, F_string_too_large, "fss_embedded_list_write_process_pipe", F_true);
+
+ status = F_status_set_error(F_string_too_large);
+ break;
+ }
+
+ f_macro_string_ranges_t_resize(status, (*ignore), ignore->size + 1);
+ }
+ else {
+ f_macro_string_ranges_t_resize(status, (*ignore), ignore->size + f_fss_default_allocation_step);
+ }
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_string_too_large, "fss_embedded_list_write_process_pipe", F_true);
+ break;
+ }
+ }
+
+ ignore->array[ignore->used].start = range_ignore.start;
+ ignore->array[ignore->used++].stop = content.used - 1;
+
+ range_ignore.start = 1;
+ range_ignore.stop = 0;
+ }
+ }
+
+ continue;
+ }
+
+ content.string[content.used++] = block.string[range.start];
+ } // for
+
+ if (F_status_is_error(status)) break;
+ }
+ else {
+ state = 0x3;
+ }
+ }
+
+ if (state == 0x3) {
+ status = fss_embedded_list_write_process(data, output, quote, &object, &content, ignore, buffer);
+ if (F_status_is_error(status)) break;
+
+ state = 0;
+ }
+ } // for
+
+ // if the pipe ended before finishing, then attempt to wrap up.
+ if (F_status_is_error_not(status) && status_pipe == F_none_eof && state) {
+ status = fss_embedded_list_write_process(data, output, quote, &object, &content, ignore, buffer);
+ }
+
+ f_macro_string_dynamic_t_delete_simple(block);
+ f_macro_string_dynamic_t_delete_simple(object);
+ f_macro_string_dynamic_t_delete_simple(content);
+ return status;
+ }
+#endif // _di_fss_embedded_list_write_process_pipe_
+
+#ifndef _di_fss_embedded_list_write_process_parameter_ignore_
+ f_return_status fss_embedded_list_write_process_parameter_ignore(const f_console_arguments_t arguments, const fss_embedded_list_write_data_t data, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) {
+ f_status_t status = F_none;
+
+ f_array_length_t i = 0;
+ f_array_length_t l = 0;
+ f_array_length_t index = 0;
+
+ f_string_range_t range = f_string_range_t_initialize;
+
+ f_number_unsigned_t number = 0;
+
+ range.start = 0;
+
+ for (; i < data.parameters[fss_embedded_list_write_parameter_ignore].locations.used; i++) {
+
+ l = data.parameters[fss_embedded_list_write_parameter_ignore].locations.array[i];
+
+ if (l < contents.array[location]) continue;
+ if (location + 1 < contents.used && l > contents.array[location + 1]) continue;
+
+ if (ignore->used + 1 > ignore->size) {
+ if (ignore->size + f_fss_default_allocation_step > f_array_length_t_size) {
+ if (ignore->size + 1 > f_array_length_t_size) {
+ fll_error_print(data.error, F_string_too_large, "fss_embedded_list_write_process_parameter_ignore", F_true);
+ return F_status_set_error(F_string_too_large);
+ }
+
+ f_macro_string_ranges_t_resize(status, (*ignore), ignore->size + 1);
+ }
+ else {
+ f_macro_string_ranges_t_resize(status, (*ignore), ignore->size + f_fss_default_allocation_step);
+ }
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fss_embedded_list_write_process_parameter_ignore", F_true);
+ return status;
+ }
+ }
+
+ index = data.parameters[fss_embedded_list_write_parameter_ignore].values.array[i * 2];
+
+ range.start = 0;
+ range.stop = strnlen(arguments.argv[index], f_console_length_size) - 1;
+
+ // allow and ignore the positive sign.
+ if (range.stop > 0 && arguments.argv[index][0] == '+') {
+ range.start = 1;
+ }
+
+ status = fl_conversion_string_to_number_unsigned(arguments.argv[index], &number, range);
+
+ if (F_status_is_error(status)) {
+ fll_error_parameter_integer_print(data.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_write_long_ignore, arguments.argv[index]);
+ return status;
+ }
+
+ ignore->array[ignore->used].start = number;
+
+ index = data.parameters[fss_embedded_list_write_parameter_ignore].values.array[(i * 2) + 1];
+
+ range.start = 0;
+ range.stop = strnlen(arguments.argv[index], f_console_length_size) - 1;
+
+ // allow and ignore the positive sign.
+ if (range.stop > 0 && arguments.argv[index][0] == '+') {
+ range.start = 1;
+ }
+
+ status = fl_conversion_string_to_number_unsigned(arguments.argv[index], &number, range);
+
+ if (F_status_is_error(status)) {
+ fll_error_parameter_integer_print(data.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_write_long_ignore, arguments.argv[index]);
+ return status;
+ }
+
+ ignore->array[ignore->used++].stop = number;
+ } // for
+
+ return F_none;
+ }
+#endif // _di_fss_embedded_list_write_process_parameter_ignore_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ */
+#ifndef _PRIVATE_fss_embedded_list_write_h
+#define _PRIVATE_fss_embedded_list_write_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print an message about the object and content parameters not being specified the same number of times.
+ *
+ * @param data
+ * The program data.
+ */
+#ifndef _di_fss_embedded_list_write_error_parameter_same_times_print_
+ void fss_embedded_list_write_error_parameter_same_times_print(const fss_embedded_list_write_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_error_parameter_same_times_print_
+
+/**
+ * Print an message about a parameter EOL being unsupported.
+ *
+ * @param data
+ * The program data.
+ */
+#ifndef _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_
+ void fss_embedded_list_write_error_parameter_unsupported_eol_print(const fss_embedded_list_write_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_
+
+/**
+ * Print an message about a parameter missing a value.
+ *
+ * @param data
+ * The program data.
+ * @param symbol
+ * The console symbol, such as "--" in "--help".
+ * @param parameter
+ * The parameter name, such as "help" in "--help".
+ */
+#ifndef _di_fss_embedded_list_write_error_parameter_value_missing_print_
+ void fss_embedded_list_write_error_parameter_value_missing_print(const fss_embedded_list_write_data_t data, const f_string_t symbol, const f_string_t parameter) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_error_parameter_value_missing_print_
+
+/**
+ * Process a given object and content, printing the FSS if valid or an error if invalid.
+ *
+ * @param data
+ * The program data.
+ * @param output
+ * The file to output to.
+ * @param quote
+ * The quote character to use.
+ * This is either single our double quote.
+ * @param object
+ * The object to validate and print.
+ * Set pointer address to 0 to not use.
+ * @param content
+ * The content to escape and print.
+ * Set pointer address to 0 to not use.
+ * @param ignore
+ * An array of ranges within the Content to ignore.
+ * Set pointer address to 0 to not use.
+ * @param buffer
+ * The buffer array used as a cache to construct the output before printing.
+ *
+ * @return
+ * F_none on success.
+ * F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_embedded_list_write_process_
+ extern f_return_status fss_embedded_list_write_process(const fss_embedded_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_process_
+
+/**
+ * Process the pipe, reading from the pipe and writing to the output.
+ *
+ * @param data
+ * The program data.
+ * @param output
+ * The file to output to.
+ * @param quote
+ * The quote character to use.
+ * This is either single our double quote.
+ * @param buffer
+ * The buffer array used as a cache to construct the output before printing.
+ * @param ignore
+ * An array of ranges within the Content to ignore.
+ * Set pointer address to 0 to not use.
+ *
+ * @return
+ * F_none on success.
+ * F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_embedded_list_write_process_pipe_
+ extern f_return_status fss_embedded_list_write_process_pipe(const fss_embedded_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_process_pipe_
+
+/**
+ * Process the ignore parameter associated with a specific content parameter.
+ *
+ * @param arguments
+ * The parameters passed to the process.
+ * @param data
+ * The program data.
+ * @param contents
+ * The console parameter locations array for the content parameter.
+ * @param location
+ * The specific location within the contents locations array.
+ * @param ignore
+ * An array of ranges within the Content to ignore.
+ *
+ * @return
+ * F_none on success.
+ * F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_embedded_list_write_process_parameter_ignore_
+ extern f_return_status fss_embedded_list_write_process_parameter_ignore(const f_console_arguments_t arguments, const fss_embedded_list_write_data_t data, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_process_parameter_ignore_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_fss_embedded_list_write_h
--- /dev/null
+# fss-0000
+
--- /dev/null
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
+f_utf
+f_color
+f_console
+f_directory
+f_environment
+f_file
+f_fss
+f_pipe
+f_print
+fl_color
+fl_console
+fl_conversion
+fl_fss
+fl_status
+fl_string
+fll_error
+fll_execute
+fll_file
+fll_fss
+fll_program
--- /dev/null
+# fss-0001
+
+project_name fss_embedded_list_write
+
+version_major 0
+version_minor 5
+version_micro 2
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual level monolithic
+modes_default monolithic
+
+build_compiler gcc
+build_indexer ar
+build_language c
+build_libraries -lc
+build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-level -lfll_2 -lfll_1 -lfll_0
+build_libraries-monolithic -lfll
+build_sources_library fss_embedded_list_write.c private-fss_embedded_list_write.c
+build_sources_program main.c
+build_sources_headers fss_embedded_list_write.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_3
+path_headers_preserve no
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+path_sources
+path_standard yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+defines_static
+defines_shared
+
+flags_all -z now -g -fdiagnostics-color=always
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE
* API Version: 0.5
* Licenses: lgplv2.1
*
- * This program provides fss basic list write functionality.
+ * This program provides FSS-0003 Extended List write functionality.
*/
#ifndef _fss_extended_list_write_h
#ifndef _di_fss_extended_list_write_name_
#define fss_extended_list_write_name "fss_extended_list_write"
- #define fss_extended_list_write_name_long "FSS Basic List Write"
+ #define fss_extended_list_write_name_long "FSS Extended List Write"
#endif // _di_fss_extended_list_write_name_
#ifndef _di_fss_extended_list_write_defines_