From: Kevin Day Date: Wed, 5 May 2021 05:22:23 +0000 (-0500) Subject: Update: Get FSS Basic List Read in sync with FSS Basic Read changes. X-Git-Tag: 0.5.4~52 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=8eac2971453f4bcd12a69f5c6e8145d887349b5e;p=fll Update: Get FSS Basic List Read in sync with FSS Basic Read changes. Apply all changes recently performed on FSS Basic Read as appropriate. --- diff --git a/level_3/fss_basic_list_read/c/fss_basic_list_read.c b/level_3/fss_basic_list_read/c/fss_basic_list_read.c index 8bad606..5bf946b 100644 --- a/level_3/fss_basic_list_read/c/fss_basic_list_read.c +++ b/level_3/fss_basic_list_read/c/fss_basic_list_read.c @@ -23,18 +23,18 @@ extern "C" { fprintf(output.stream, "%c", f_string_eol_s[0]); - fll_program_print_help_option(output, context, fss_basic_list_read_short_at, fss_basic_list_read_long_at, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select object at this numeric index."); - fll_program_print_help_option(output, context, fss_basic_list_read_short_content, fss_basic_list_read_long_content, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the content (default)."); + fll_program_print_help_option(output, context, fss_basic_list_read_short_at, fss_basic_list_read_long_at, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); + fll_program_print_help_option(output, context, fss_basic_list_read_short_content, fss_basic_list_read_long_content, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); fll_program_print_help_option(output, context, fss_basic_list_read_short_delimit, fss_basic_list_read_long_delimit, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); - fll_program_print_help_option(output, context, fss_basic_list_read_short_depth, fss_basic_list_read_long_depth, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select object at this numeric depth."); - fll_program_print_help_option(output, context, fss_basic_list_read_short_empty, fss_basic_list_read_long_empty, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty content when processing."); - fll_program_print_help_option(output, context, fss_basic_list_read_short_line, fss_basic_list_read_long_line, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the content at the given line."); - fll_program_print_help_option(output, context, fss_basic_list_read_short_name, fss_basic_list_read_long_name, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select object with this name."); - fll_program_print_help_option(output, context, fss_basic_list_read_short_object, fss_basic_list_read_long_object, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the object."); + fll_program_print_help_option(output, context, fss_basic_list_read_short_depth, fss_basic_list_read_long_depth, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); + fll_program_print_help_option(output, context, fss_basic_list_read_short_empty, fss_basic_list_read_long_empty, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); + fll_program_print_help_option(output, context, fss_basic_list_read_short_line, fss_basic_list_read_long_line, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); + fll_program_print_help_option(output, context, fss_basic_list_read_short_name, fss_basic_list_read_long_name, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); + fll_program_print_help_option(output, context, fss_basic_list_read_short_object, fss_basic_list_read_long_object, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); fll_program_print_help_option(output, context, fss_basic_list_read_short_pipe, fss_basic_list_read_long_pipe, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); - fll_program_print_help_option(output, context, fss_basic_list_read_short_select, fss_basic_list_read_long_select, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-content at this index."); + fll_program_print_help_option(output, context, fss_basic_list_read_short_select, fss_basic_list_read_long_select, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); fll_program_print_help_option(output, context, fss_basic_list_read_short_total, fss_basic_list_read_long_total, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); - fll_program_print_help_option(output, context, fss_basic_list_read_short_trim, fss_basic_list_read_long_trim, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim object names on select or print."); + fll_program_print_help_option(output, context, fss_basic_list_read_short_trim, fss_basic_list_read_long_trim, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); fll_program_print_help_usage(output, context, fss_basic_list_read_name, "filename(s)"); @@ -42,7 +42,12 @@ extern "C" { fprintf(output.stream, "%c", f_string_eol_s[0]); - fprintf(output.stream, " This program will print the content associated with the given object and content main based on the FSS-0002 Basic List standard.%c", f_string_eol_s[0]); + fprintf(output.stream, " This program will print the Content associated with the given Object and Content main based on the FSS-0002 Basic List standard.%c", f_string_eol_s[0]); + + fprintf(output.stream, "%c", f_string_eol_s[0]); + + fprintf(output.stream, " All numeric positions (indexes) start at 0 instead of 1.%c", f_string_eol_s[0]); + fprintf(output.stream, " For example, a file of 17 lines would range from 0 to 16.%c", f_string_eol_s[0]); fprintf(output.stream, "%c", f_string_eol_s[0]); @@ -54,7 +59,7 @@ extern "C" { fprintf(output.stream, " "); f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_at); - fprintf(output.stream, ": An object index at the specified depth.%c", f_string_eol_s[0]); + fprintf(output.stream, ": An Object index at the specified depth.%c", f_string_eol_s[0]); fprintf(output.stream, " "); f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_depth); @@ -62,7 +67,7 @@ extern "C" { fprintf(output.stream, " "); f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_name); - fprintf(output.stream, ": An object name at the specified depth.%c", f_string_eol_s[0]); + fprintf(output.stream, ": An Object name at the specified depth.%c", f_string_eol_s[0]); fprintf(output.stream, "%c", f_string_eol_s[0]); @@ -76,8 +81,8 @@ extern "C" { fprintf(output.stream, " The parameter "); f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_select); - fprintf(output.stream, " selects a content index at a given depth.%c", f_string_eol_s[0]); - fprintf(output.stream, " (This parameter is not synonymous with the depth parameter and does not relate to nested content).%c", f_string_eol_s[0]); + fprintf(output.stream, " selects a Content index at a given depth.%c", f_string_eol_s[0]); + fprintf(output.stream, " (This parameter is not synonymous with the depth parameter and does not relate to nested Content).%c", f_string_eol_s[0]); fprintf(output.stream, "%c", f_string_eol_s[0]); @@ -112,11 +117,11 @@ extern "C" { fprintf(output.stream, " For parameters like "); f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_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_s[0]); + fprintf(output.stream, ", if the standard doesn't support nested Content, then only a depth of 0 would be valid.%c", f_string_eol_s[0]); fprintf(output.stream, " For parameters like "); f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_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_s[0]); + 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_s[0]); fprintf(output.stream, "%c", f_string_eol_s[0]); @@ -130,9 +135,9 @@ extern "C" { f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_object); fprintf(output.stream, " parameter and the "); f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_content); - fprintf(output.stream, " parameter, the entire object and content are printed, including the formatting.%c", f_string_eol_s[0]); - fprintf(output.stream, " Both the object and content printed are already escaped.%c", f_string_eol_s[0]); - fprintf(output.stream, " Both the object and content are separated by an EOL.%c", f_string_eol_s[0]); + fprintf(output.stream, " parameter, the entire Object and Content are printed, including the formatting.%c", f_string_eol_s[0]); + fprintf(output.stream, " Both the Object and Content printed are already escaped.%c", f_string_eol_s[0]); + fprintf(output.stream, " Both the Object and Content are separated by an EOL.%c", f_string_eol_s[0]); fprintf(output.stream, "%c", f_string_eol_s[0]); @@ -144,14 +149,31 @@ extern "C" { fprintf(output.stream, ": Do not apply delimits.%c", f_string_eol_s[0]); fprintf(output.stream, " - "); f_color_print(output.stream, context.set.notable, "%s", fss_basic_list_read_delimit_mode_name_all); - fprintf(output.stream, ": (default) apply all delimits.%c", f_string_eol_s[0]); - fprintf(output.stream, " - a number, 0 or greater: apply delimits for the specified depth.%c", f_string_eol_s[0]); - fprintf(output.stream, " - a number, 0 or greater, followed by a "); + fprintf(output.stream, ": (default) Apply all delimits.%c", f_string_eol_s[0]); + fprintf(output.stream, " - "); + f_color_print(output.stream, context.set.notable, "%s", fss_basic_list_read_delimit_mode_name_object); + fprintf(output.stream, ": Apply delimits for Objects.%c", f_string_eol_s[0]); + fprintf(output.stream, " - A number, 0 or greater: apply delimits for Content at the specified depth.%c", f_string_eol_s[0]); + fprintf(output.stream, " - A number, 0 or greater, followed by a "); f_color_print(output.stream, context.set.notable, "%s", fss_basic_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_s[0]); - fprintf(output.stream, " - a number, 0 or greater, followed by a "); + fprintf(output.stream, ": (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%c", f_string_eol_s[0]); + fprintf(output.stream, " - A number, 0 or greater, followed by a "); f_color_print(output.stream, context.set.notable, "%s", fss_basic_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_s[0]); + fprintf(output.stream, ": (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%c", f_string_eol_s[0]); + + fprintf(output.stream, "%c", f_string_eol_s[0]); + + fprintf(output.stream, " The "); + f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit); + fprintf(output.stream, " parameter may be specified multiple times to customize the delimit behavior.%c", f_string_eol_s[0]); + + fprintf(output.stream, " The "); + f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit); + fprintf(output.stream, " values "); + f_color_print(output.stream, context.set.notable, "%s", fss_basic_list_read_delimit_mode_name_none); + fprintf(output.stream, " and "); + f_color_print(output.stream, context.set.notable, "%s", fss_basic_list_read_delimit_mode_name_all); + fprintf(output.stream, ", overrule all other delimit values.%c", f_string_eol_s[0]); fprintf(output.stream, "%c", f_string_eol_s[0]); @@ -160,7 +182,8 @@ extern "C" { #endif // _di_fss_basic_list_read_print_help_ #ifndef _di_fss_basic_list_read_main_ - f_status_t fss_basic_list_read_main(const f_console_arguments_t arguments, fss_basic_list_read_main_t *main) { + f_status_t fss_basic_list_read_main(f_console_arguments_t * const arguments, fss_basic_list_read_main_t *main) { + f_status_t status = F_none; { @@ -170,7 +193,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fss_basic_list_read_parameter_no_color, fss_basic_list_read_parameter_light, fss_basic_list_read_parameter_dark }; const f_console_parameter_ids_t choices = { ids, 3 }; - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); if (main->context.set.error.before) { main->error.context = main->context.set.error; @@ -184,6 +207,7 @@ extern "C" { if (F_status_is_error(status)) { fss_basic_list_read_main_delete(main); + return F_status_set_error(status); } } @@ -198,6 +222,7 @@ extern "C" { if (F_status_is_error(status)) { fss_basic_list_read_main_delete(main); + return status; } @@ -232,154 +257,207 @@ extern "C" { return status; } - if (main->remaining.used > 0 || main->process_pipe) { - if (main->parameters[fss_basic_list_read_parameter_at].result == f_console_result_found) { - f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter '", fll_error_print_error); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_at); - f_color_print(main->error.to.stream, main->context.set.error, "' requires a positive number.%c", f_string_eol_s[0]); - - status = F_status_set_error(F_parameter); - } - - if (F_status_is_error_not(status) && main->parameters[fss_basic_list_read_parameter_depth].result == f_console_result_found) { - f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter '", fll_error_print_error); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_depth); - f_color_print(main->error.to.stream, main->context.set.error, "' requires a positive number.%c", f_string_eol_s[0]); - - status = F_status_set_error(F_parameter); - } - - if (F_status_is_error_not(status) && main->parameters[fss_basic_list_read_parameter_line].result == f_console_result_found) { - f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter '", fll_error_print_error); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_line); - f_color_print(main->error.to.stream, main->context.set.error, "' requires a positive number.%c", f_string_eol_s[0]); + // Provide a range designating where within the buffer a particular file exists, using a statically allocated array. + fss_basic_list_read_file_t files_array[main->remaining.used + 1]; + fss_basic_list_read_data_t data = fss_basic_list_read_data_t_initialize; - status = F_status_set_error(F_parameter); - } - - if (F_status_is_error_not(status) && main->parameters[fss_basic_list_read_parameter_name].result == f_console_result_found) { - f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter '", fll_error_print_error); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_name); - f_color_print(main->error.to.stream, main->context.set.error, "' requires a string.%c", f_string_eol_s[0]); - - status = F_status_set_error(F_parameter); - } + data.files.array = files_array; + data.files.used = 1; + data.files.size = main->remaining.used + 1; - if (F_status_is_error_not(status) && main->parameters[fss_basic_list_read_parameter_select].result == f_console_result_found) { - f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter '", fll_error_print_error); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_select); - f_color_print(main->error.to.stream, main->context.set.error, "' requires a positive number.%c", f_string_eol_s[0]); + if (main->remaining.used || main->process_pipe) { + { + const f_array_length_t parameter_code[] = { + fss_basic_list_read_parameter_at, + fss_basic_list_read_parameter_depth, + fss_basic_list_read_parameter_line, + fss_basic_list_read_parameter_select, + fss_basic_list_read_parameter_name, + fss_basic_list_read_parameter_delimit, + }; + + const f_string_t parameter_name[] = { + fss_basic_list_read_long_at, + fss_basic_list_read_long_depth, + fss_basic_list_read_long_line, + fss_basic_list_read_long_select, + fss_basic_list_read_long_name, + fss_basic_list_read_long_delimit, + }; + + const f_string_t message_positive_number = "positive number"; + const f_string_t message_string = "string"; + const f_string_t message_value = "value"; + + const f_string_t parameter_message[] = { + message_positive_number, + message_positive_number, + message_positive_number, + message_positive_number, + message_string, + message_value, + }; + + for (f_array_length_t i = 0; i < 6; ++i) { + + if (main->parameters[parameter_code[i]].result == f_console_result_found) { + f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter '", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, parameter_name[i]); + f_color_print(main->error.to.stream, main->context.set.error, "' requires a %s.%c", parameter_message[i], f_string_eol_s[0]); - status = F_status_set_error(F_parameter); + status = F_status_set_error(F_parameter); + break; + } + } // for } - if (F_status_is_error_not(status) && main->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { + if (F_status_is_error_not(status) && main->parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { f_color_print(main->error.to.stream, main->context.set.error, "%sCannot specify the '", fll_error_print_error); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_line); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_pipe); f_color_print(main->error.to.stream, main->context.set.error, "' parameter with the '"); f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_total); f_color_print(main->error.to.stream, main->context.set.error, "' parameter.%c", f_string_eol_s[0]); status = F_status_set_error(F_parameter); } - } - - if (F_status_is_error_not(status) && main->parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { - if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { + else if (main->parameters[fss_basic_list_read_parameter_line].result == f_console_result_found) { f_color_print(main->error.to.stream, main->context.set.error, "%sCannot specify the '", fll_error_print_error); f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_pipe); f_color_print(main->error.to.stream, main->context.set.error, "' parameter with the '"); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_total); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_line); f_color_print(main->error.to.stream, main->context.set.error, "' parameter.%c", f_string_eol_s[0]); status = F_status_set_error(F_parameter); } } - if (F_status_is_error_not(status)) { - if (main->parameters[fss_basic_list_read_parameter_delimit].result == f_console_result_found) { - f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter '", fll_error_print_error); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit); - f_color_print(main->error.to.stream, main->context.set.error, "' requires a value.%c", f_string_eol_s[0]); + if (F_status_is_error_not(status) && main->parameters[fss_basic_list_read_parameter_delimit].result == f_console_result_additional) { + f_array_length_t location = 0; + f_array_length_t length = 0; - status = F_status_set_error(F_parameter); - } - else if (main->parameters[fss_basic_list_read_parameter_delimit].result == f_console_result_additional) { - const f_array_length_t location = main->parameters[fss_basic_list_read_parameter_delimit].values.array[0]; - f_array_length_t length = strnlen(arguments.argv[location], f_console_parameter_size); + // Set the value to 0 to allow for detecting mode based on what is provided. + data.delimit_mode = 0; + + for (f_array_length_t i = 0; i < main->parameters[fss_basic_list_read_parameter_delimit].values.used; ++i) { - if (length == 0) { + location = main->parameters[fss_basic_list_read_parameter_delimit].values.array[i]; + length = strnlen(arguments->argv[location], f_console_parameter_size); + + if (!length) { f_color_print(main->error.to.stream, main->context.set.error, "%sThe value for the parameter '", fll_error_print_error); f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit); f_color_print(main->error.to.stream, main->context.set.error, "' must not be empty.%c", f_string_eol_s[0]); status = F_status_set_error(F_parameter); + break; } - else if (fl_string_compare(arguments.argv[location], fss_basic_list_read_delimit_mode_name_none, length, fss_basic_list_read_delimit_mode_name_none_length) == F_equal_to) { - main->delimit_mode = fss_basic_list_read_delimit_mode_none; + else if (fl_string_compare(arguments->argv[location], fss_basic_list_read_delimit_mode_name_none, length, fss_basic_list_read_delimit_mode_name_none_length) == F_equal_to) { + data.delimit_mode = fss_basic_list_read_delimit_mode_none; } - else if (fl_string_compare(arguments.argv[location], fss_basic_list_read_delimit_mode_name_all, length, fss_basic_list_read_delimit_mode_name_all_length) == F_equal_to) { - main->delimit_mode = fss_basic_list_read_delimit_mode_all; + else if (fl_string_compare(arguments->argv[location], fss_basic_list_read_delimit_mode_name_all, length, fss_basic_list_read_delimit_mode_name_all_length) == F_equal_to) { + data.delimit_mode = fss_basic_list_read_delimit_mode_all; + } + else if (fl_string_compare(arguments->argv[location], fss_basic_list_read_delimit_mode_name_object, length, fss_basic_list_read_delimit_mode_name_object_length) == F_equal_to) { + switch (data.delimit_mode) { + case 0: + data.delimit_mode = fss_basic_list_read_delimit_mode_object; + break; + + case fss_basic_list_read_delimit_mode_none: + case fss_basic_list_read_delimit_mode_all: + case fss_basic_list_read_delimit_mode_content_greater_object: + case fss_basic_list_read_delimit_mode_content_lesser_object: + case fss_basic_list_read_delimit_mode_object: + break; + + case fss_basic_list_read_delimit_mode_content: + data.delimit_mode = fss_basic_list_read_delimit_mode_content_object; + break; + + case fss_basic_list_read_delimit_mode_content_greater: + data.delimit_mode = fss_basic_list_read_delimit_mode_content_greater_object; + break; + + case fss_basic_list_read_delimit_mode_content_lesser: + data.delimit_mode = fss_basic_list_read_delimit_mode_content_lesser_object; + break; + + default: + break; + } } else { - main->delimit_mode = fss_basic_list_read_delimit_mode_depth; + if (!data.delimit_mode) { + data.delimit_mode = fss_basic_list_read_delimit_mode_content; + } + else if (data.delimit_mode == fss_basic_list_read_delimit_mode_object) { + data.delimit_mode = fss_basic_list_read_delimit_mode_content_object; + } - if (arguments.argv[location][length - 1] == fss_basic_list_read_delimit_mode_name_greater[0]) { - main->delimit_mode = fss_basic_list_read_delimit_mode_depth_greater; + if (arguments->argv[location][length - 1] == fss_basic_list_read_delimit_mode_name_greater[0]) { + if (!(data.delimit_mode == fss_basic_list_read_delimit_mode_none || data.delimit_mode == fss_basic_list_read_delimit_mode_all)) { + if (data.delimit_mode == fss_basic_list_read_delimit_mode_content_object) { + data.delimit_mode = fss_basic_list_read_delimit_mode_content_greater_object; + } + else { + data.delimit_mode = fss_basic_list_read_delimit_mode_content_greater; + } + } // shorten the length to better convert the remainder to a number. - length--; + --length; } - else if (arguments.argv[location][length - 1] == fss_basic_list_read_delimit_mode_name_lesser[0]) { - main->delimit_mode = fss_basic_list_read_delimit_mode_depth_lesser; + else if (arguments->argv[location][length - 1] == fss_basic_list_read_delimit_mode_name_lesser[0]) { + if (!(data.delimit_mode == fss_basic_list_read_delimit_mode_none || data.delimit_mode == fss_basic_list_read_delimit_mode_all)) { + if (data.delimit_mode == fss_basic_list_read_delimit_mode_content_object) { + data.delimit_mode = fss_basic_list_read_delimit_mode_content_lesser_object; + } + else { + data.delimit_mode = fss_basic_list_read_delimit_mode_content_lesser; + } + } // shorten the length to better convert the remainder to a number. - length--; + --length; } f_string_range_t range = macro_f_string_range_t_initialize(length); // ignore leading plus sign. - if (arguments.argv[location][0] == '+') { - range.start++; + if (arguments->argv[location][0] == '+') { + ++range.start; } - status = fl_conversion_string_to_number_unsigned(arguments.argv[location], range, &main->delimit_depth); + status = fl_conversion_string_to_number_unsigned(arguments->argv[location], range, &data.delimit_depth); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_basic_list_read_long_delimit, arguments.argv[location]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_basic_list_read_long_delimit, arguments->argv[location]); + + break; } } + } // for + + // Guarantee the default value is "all". + if (!data.delimit_mode) { + data.delimit_mode = fss_basic_list_read_delimit_mode_all; } } - fss_basic_list_read_depths_t depths = fss_basic_list_read_depths_t_initialize; - - f_fss_delimits_t delimits = f_fss_delimits_t_initialize; - f_fss_comments_t comments = f_fss_comments_t_initialize; - - f_array_length_t original_size = main->quantity.total; - if (F_status_is_error_not(status)) { - status = fss_basic_list_read_main_preprocess_depth(arguments, *main, &depths); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "fss_basic_list_read_main_preprocess_depth", F_true); - } + status = fss_basic_list_read_depth_process(arguments, main, &data); } // This standard does not support nesting, so any depth greater than 0 can be predicted without processing the file. - if (F_status_is_error_not(status) && depths.array[0].depth > 0) { - macro_fss_basic_list_read_depths_t_delete_simple(depths); - macro_f_fss_delimits_t_delete_simple(delimits); - macro_f_fss_comments_t_delete_simple(comments); - + if (F_status_is_error_not(status) && data.depths.array[0].depth > 0) { if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { - fprintf(main->output.stream, "0%c", f_string_eol_s[0]); + fss_basic_list_read_print_zero(main); } + fss_basic_list_read_data_delete_simple(&data); fss_basic_list_read_main_delete(main); + return F_none; } @@ -388,106 +466,127 @@ extern "C" { f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_select); f_color_print(main->error.to.stream, main->context.set.error, "' parameter requires a positive number.%c", f_string_eol_s[0]); + fss_basic_list_read_depths_resize(0, &data.depths); + status = F_status_set_error(F_parameter); } + if (F_status_is_error_not(status)) { + for (f_array_length_t i = 0; i < data.files.used; ++i) { + macro_f_string_range_t_clear(data.files.array[i].range); + } // for + } + if (F_status_is_error_not(status) && main->process_pipe) { f_file_t file = f_file_t_initialize; file.id = f_type_descriptor_input; + file.stream = f_type_input; + + data.files.array[0].name = 0; + data.files.array[0].range.start = 0; - status = f_file_read(file, &main->buffer); + status = f_file_stream_read(file, &data.buffer); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_read", F_true, "-", "read", fll_error_file_type_pipe); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_read", F_true, "-", "read", fll_error_file_type_pipe); } - else { - status = fss_basic_list_read_main_process_file(arguments, main, "-", depths, &delimits, &comments); + else if (data.buffer.used) { + data.files.array[0].range.stop = data.buffer.used - 1; + + // This standard is newline sensitive, when appending files to the buffer if the file lacks a final newline then this could break the format for files appended thereafter. + // Guarantee that a newline exists at the end of the buffer. + status = f_string_append_assure(f_string_eol_s, 1, &data.buffer); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "fss_basic_list_read_main_process_file", F_true, "-", "read", fll_error_file_type_pipe); + fll_error_file_print(main->error, F_status_set_fine(status), "f_string_append_assure", F_true, "-", "read", fll_error_file_type_pipe); } } - - // Clear buffers before continuing. - macro_f_fss_contents_t_delete_simple(main->contents); - macro_f_fss_objects_t_delete_simple(main->objects); - macro_f_string_dynamic_t_delete_simple(main->buffer); + else { + data.files.array[0].range.start = 1; + } } if (F_status_is_error_not(status) && main->remaining.used > 0) { - for (f_array_length_t i = 0; i < main->remaining.used; i++) { - f_file_t file = f_file_t_initialize; + f_file_t file = f_file_t_initialize; + f_array_length_t size_file = 0; + + for (f_array_length_t i = 0; i < main->remaining.used; ++i) { - status = f_file_open(arguments.argv[main->remaining.array[i]], 0, &file); + data.files.array[data.files.used].range.start = data.buffer.used; + file.stream = 0; + file.id = -1; - main->quantity.total = original_size; + status = f_file_stream_open(arguments->argv[main->remaining.array[i]], 0, &file); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_open", F_true, arguments.argv[main->remaining.array[i]], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments->argv[main->remaining.array[i]], "open", fll_error_file_type_file); + break; } - if (!main->quantity.total) { - status = f_file_size_by_id(file.id, &main->quantity.total); + size_file = 0; + status = f_file_size_by_id(file.id, &size_file); + + if (F_status_is_error(status)) { + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_size_by_id", F_true, arguments->argv[main->remaining.array[i]], "read", fll_error_file_type_file); + + break; + } + + if (size_file) { + status = f_string_dynamic_resize(data.buffer.size + size_file, &data.buffer); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_size_by_id", F_true, arguments.argv[main->remaining.array[i]], "read", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_string_dynamic_resize", F_true, arguments->argv[main->remaining.array[i]], "read", fll_error_file_type_file); - f_file_stream_close(F_true, &file); break; } - // Skip past empty files. - if (!main->quantity.total) { - if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { - fprintf(main->output.stream, "0%c", f_string_eol_s[0]); - } + status = f_file_stream_read(file, &data.buffer); - f_file_stream_close(F_true, &file); - continue; - } - } + if (F_status_is_error(status)) { + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_read", F_true, arguments->argv[main->remaining.array[i]], "read", fll_error_file_type_file); - status = f_file_read_until(file, main->quantity.total, &main->buffer); + break; + } + else if (data.buffer.used > data.files.array[data.files.used].range.start) { + data.files.array[data.files.used].name = arguments->argv[main->remaining.array[i]]; + data.files.array[data.files.used++].range.stop = data.buffer.used - 1; - f_file_stream_close(F_true, &file); + // This standard is newline sensitive, when appending files to the buffer if the file lacks a final newline then this could break the format for files appended thereafter. + // Guarantee that a newline exists at the end of the buffer. + status = f_string_append_assure(f_string_eol_s, 1, &data.buffer); - if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_read_until", F_true, arguments.argv[main->remaining.array[i]], "read", fll_error_file_type_file); - break; + if (F_status_is_error(status)) { + fll_error_file_print(main->error, F_status_set_fine(status), "f_string_append_assure", F_true, "-", "read", fll_error_file_type_pipe); + } + } } - - status = fss_basic_list_read_main_process_file(arguments, main, arguments.argv[main->remaining.array[i]], depths, &delimits, &comments); - - if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "fss_basic_list_read_main_process_file", F_true, arguments.argv[main->remaining.array[i]], "read", fll_error_file_type_file); - break; + else { + data.files.array[data.files.used].range.start = 1; } - // Clear buffers before repeating the loop. - macro_f_fss_contents_t_delete_simple(main->contents); - macro_f_fss_objects_t_delete_simple(main->objects); - macro_f_string_dynamic_t_delete_simple(main->buffer); + f_file_stream_close(F_true, &file); } // for - if (F_status_is_error(status)) { - macro_f_fss_contents_t_delete_simple(main->contents); - macro_f_fss_objects_t_delete_simple(main->objects); - macro_f_string_dynamic_t_delete_simple(main->buffer); - } + f_file_stream_close(F_true, &file); } - macro_fss_basic_list_read_depths_t_delete_simple(depths); - macro_f_fss_delimits_t_delete_simple(delimits); - macro_f_fss_comments_t_delete_simple(comments); + if (F_status_is_error_not(status)) { + status = fss_basic_list_read_process(arguments, main, &data); + } + + fss_basic_list_read_data_delete_simple(&data); } else { f_color_print(main->error.to.stream, main->context.set.error, "%sYou failed to specify one or more files.%c", fll_error_print_error, f_string_eol_s[0]); status = F_status_set_error(F_parameter); } + fss_basic_list_read_data_delete_simple(&data); fss_basic_list_read_main_delete(main); + return status; } #endif // _di_fss_basic_list_read_main_ @@ -495,17 +594,13 @@ extern "C" { #ifndef _di_fss_basic_list_read_main_delete_ f_status_t fss_basic_list_read_main_delete(fss_basic_list_read_main_t *main) { - for (f_array_length_t i = 0; i < fss_basic_list_read_total_parameters; i++) { + for (f_array_length_t i = 0; i < fss_basic_list_read_total_parameters; ++i) { macro_f_array_lengths_t_delete_simple(main->parameters[i].locations); macro_f_array_lengths_t_delete_simple(main->parameters[i].locations_sub); macro_f_array_lengths_t_delete_simple(main->parameters[i].values); } // for - macro_f_fss_contents_t_delete_simple(main->contents); - macro_f_fss_objects_t_delete_simple(main->objects); - macro_f_string_dynamic_t_delete_simple(main->buffer); macro_f_array_lengths_t_delete_simple(main->remaining); - macro_f_color_context_t_delete_simple(main->context); return F_none; diff --git a/level_3/fss_basic_list_read/c/fss_basic_list_read.h b/level_3/fss_basic_list_read/c/fss_basic_list_read.h index 7541f36..f89640e 100644 --- a/level_3/fss_basic_list_read/c/fss_basic_list_read.h +++ b/level_3/fss_basic_list_read/c/fss_basic_list_read.h @@ -145,23 +145,42 @@ extern "C" { #define fss_basic_list_read_total_parameters 21 #endif // _di_fss_basic_list_read_defines_ +/** + * FSS Delimit Parameter data. + * + * fss_basic_list_read_delimit_mode_*: + * - all: All delimits are to be aplied. + * - content: Content are to have delimits applied. + * - content_greater: Content at this number or higher are to have delimits applied. + * - content_greater_object: Objects and Content at this number or higher are to have delimits applied. + * - content_lesser: Content at this number or lower are to have delimits applied. + * - content_lesser_object: Objects and Content at this number or lower are to have delimits applied. + * - content_object: Objects and Content are to have delimits applied + * - object: Objects arre to have delimits applied. + */ #ifndef _di_fss_basic_list_read_delimit_mode_ #define fss_basic_list_read_delimit_mode_name_none "none" #define fss_basic_list_read_delimit_mode_name_all "all" + #define fss_basic_list_read_delimit_mode_name_object "object" #define fss_basic_list_read_delimit_mode_name_greater "+" #define fss_basic_list_read_delimit_mode_name_lesser "-" #define fss_basic_list_read_delimit_mode_name_none_length 4 #define fss_basic_list_read_delimit_mode_name_all_length 3 + #define fss_basic_list_read_delimit_mode_name_object_length 6 #define fss_basic_list_read_delimit_mode_name_greater_length 1 #define fss_basic_list_read_delimit_mode_name_lesser_length 1 enum { fss_basic_list_read_delimit_mode_none = 1, fss_basic_list_read_delimit_mode_all, - fss_basic_list_read_delimit_mode_depth, - fss_basic_list_read_delimit_mode_depth_greater, - fss_basic_list_read_delimit_mode_depth_lesser, + fss_basic_list_read_delimit_mode_content, + fss_basic_list_read_delimit_mode_content_greater, + fss_basic_list_read_delimit_mode_content_greater_object, + fss_basic_list_read_delimit_mode_content_lesser, + fss_basic_list_read_delimit_mode_content_lesser_object, + fss_basic_list_read_delimit_mode_content_object, + fss_basic_list_read_delimit_mode_object, }; #endif // _di_fss_basic_list_read_delimit_modes_ @@ -175,14 +194,6 @@ extern "C" { f_file_t output; fll_error_print_t error; - f_string_dynamic_t buffer; - f_fss_objects_t objects; - f_fss_contents_t contents; - f_string_quantity_t quantity; - - uint8_t delimit_mode; - f_array_length_t delimit_depth; - f_color_context_t context; } fss_basic_list_read_main_t; @@ -193,12 +204,6 @@ extern "C" { F_false, \ macro_f_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \ fll_error_print_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_fss_objects_t_initialize, \ - f_fss_contents_t_initialize, \ - f_string_quantity_t_initialize, \ - fss_basic_list_read_delimit_mode_all, \ - 0, \ f_color_context_t_initialize, \ } #endif // _di_fss_basic_list_read_main_t_ @@ -236,7 +241,7 @@ extern "C" { * @see fss_basic_list_read_main_delete() */ #ifndef _di_fss_basic_list_read_main_ - extern f_status_t fss_basic_list_read_main(const f_console_arguments_t arguments, fss_basic_list_read_main_t *main); + extern f_status_t fss_basic_list_read_main(f_console_arguments_t * const arguments, fss_basic_list_read_main_t *main); #endif // _di_fss_basic_list_read_main_ /** diff --git a/level_3/fss_basic_list_read/c/main.c b/level_3/fss_basic_list_read/c/main.c index c519638..a018daf 100644 --- a/level_3/fss_basic_list_read/c/main.c +++ b/level_3/fss_basic_list_read/c/main.c @@ -2,14 +2,14 @@ int main(const int argc, const f_string_t *argv) { - const f_console_arguments_t arguments = { argc, argv }; + f_console_arguments_t arguments = { argc, argv }; fss_basic_list_read_main_t data = fss_basic_list_read_main_t_initialize; if (f_pipe_input_exists()) { data.process_pipe = F_true; } - const f_status_t status = fss_basic_list_read_main(arguments, &data); + const f_status_t status = fss_basic_list_read_main(&arguments, &data); // flush output pipes before closing. fflush(f_type_output); diff --git a/level_3/fss_basic_list_read/c/private-common.c b/level_3/fss_basic_list_read/c/private-common.c index 745408c..8258046 100644 --- a/level_3/fss_basic_list_read/c/private-common.c +++ b/level_3/fss_basic_list_read/c/private-common.c @@ -5,6 +5,59 @@ extern "C" { #endif +#ifndef _di_fss_basic_list_read_data_delete_simple_ + void fss_basic_list_read_data_delete_simple(fss_basic_list_read_data_t *data) { + + if (!data) return; + + // data->files is expected to be statically loaded and cannot be deallocated. + + fss_basic_list_read_depths_resize(0, &data->depths); + + macro_f_string_dynamic_t_delete_simple(data->buffer); + macro_f_fss_contents_t_delete_simple(data->contents); + macro_f_fss_objects_t_delete_simple(data->objects); + macro_f_fss_delimits_t_delete_simple(data->delimits_object); + macro_f_fss_delimits_t_delete_simple(data->delimits_content); + macro_f_fss_comments_t_delete_simple(data->comments); + } +#endif // _di_fss_basic_list_read_data_delete_simple_ + +#ifndef _di_fss_basic_list_read_depth_delete_simple_ + void fss_basic_list_read_depth_delete_simple(fss_basic_list_read_depth_t *depth) { + + if (!depth) return; + + f_string_dynamic_resize(0, &depth->value_name); + } +#endif // _di_fss_basic_list_read_depth_delete_simple_ + +#ifndef _di_fss_basic_list_read_depths_resize_ + f_status_t fss_basic_list_read_depths_resize(const f_array_length_t length, fss_basic_list_read_depths_t *depths) { + + if (!depths) { + return F_status_set_error(F_parameter); + } + + for (f_array_length_t i = length; i < depths->size; ++i) { + fss_basic_list_read_depth_delete_simple(&depths->array[i]); + } // for + + const f_status_t status = f_memory_resize(depths->size, length, sizeof(fss_basic_list_read_depth_t), (void **) & depths->array); + + if (F_status_is_error_not(status)) { + depths->size = length; + + if (depths->used > depths->size) { + depths->used = length; + } + } + + return status; + } +#endif // _di_fss_basic_list_read_depths_resize_ + + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_read/c/private-common.h b/level_3/fss_basic_list_read/c/private-common.h index 93ad6b7..692ae8a 100644 --- a/level_3/fss_basic_list_read/c/private-common.h +++ b/level_3/fss_basic_list_read/c/private-common.h @@ -15,13 +15,13 @@ extern "C" { /** * A structure of parameters applied at some depth. * - * depth: the depth number in which this is to be processed at. + * 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. + * 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. + * 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_basic_list_read_depth_t_ typedef struct { @@ -49,16 +49,14 @@ extern "C" { structure.index_name = 0; \ structure.value_at = 0; \ macro_f_string_dynamic_t_clear(structure.value_name) - - #define macro_fss_basic_list_read_depth_t_delete_simple(structure) macro_f_string_dynamic_t_delete_simple(structure.value_name); #endif // _di_fss_basic_list_read_depth_t_ /** * An array of depth parameters. * - * array: the array of depths. - * size: total amount of allocated space. - * used: total number of allocated spaces used. + * array: The array of depths. + * size: Total amount of allocated space. + * used: Total number of allocated spaces used. */ #ifndef _di_fss_basic_list_read_depths_t_ typedef struct { @@ -71,43 +69,166 @@ extern "C" { #define fss_basic_list_read_depths_t_initialize { 0, 0, 0 } #define macro_fss_basic_list_read_depths_t_clear(depths) macro_f_memory_structure_clear(depths) +#endif // _di_fss_basic_list_read_depths_t_ + +/** + * A structure for designating where within the buffer a particular file exists, using a statically allocated array. + * + * name: The name of the file representing the range. Set string to NULL to represent the STDIN pipe. + * range: A range within the buffer representing the file. + */ +#ifndef _di_fss_basic_list_read_file_t_ + typedef struct { + f_string_t name; + f_string_range_t range; + } fss_basic_list_read_file_t; - #define macro_fss_basic_list_read_depths_t_delete_simple(depths) \ - depths.used = depths.size; \ - while (depths.used > 0) { \ - depths.used--; \ - macro_fss_basic_list_read_depth_t_delete_simple(depths.array[depths.used]); \ - } \ - if (!depths.used) macro_f_memory_structure_delete_simple(depths, fss_basic_list_read_depth_t) - - #define macro_fss_basic_list_read_depths_t_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_basic_list_read_depth_t_delete_simple(depths.array[i]); \ - } \ - } \ - if (status == F_none) status = f_memory_resize(depths.size, new_length, sizeof(fss_basic_list_read_depth_t), (void **) & depths.array); \ - if (status == F_none) { \ - depths.size = new_length; \ - if (depths.used > depths.size) depths.used = new_length; \ + #define fss_basic_list_read_file_t_initialize \ + { \ + f_string_t_initialize, \ + f_string_range_t_initialize, \ } +#endif // _di_fss_basic_list_read_file_t_ - #define macro_fss_basic_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_basic_list_read_depth_t_delete_simple(depths.array[i]); \ - } \ - } \ - if (status == F_none) status = f_memory_adjust(depths.size, new_length, sizeof(fss_basic_list_read_depth_t), (void **) & depths.array); \ - if (status == F_none) { \ - depths.size = new_length; \ - if (depths.used > depths.size) depths.used = new_length; \ +/** + * An array of files. + * + * This is intended to be defined and used statically allocated and as such no dynamic allocation or dynamic deallocation methods are provided. + * + * The STDIN pipe is reserved for index 0 and as such size and used must be initialized to 1. + * + * array: The array of depths. + * size: Total amount of allocated space. + * used: Total number of allocated spaces used. + */ +#ifndef _di_fss_basic_list_read_files_t_ + typedef struct { + fss_basic_list_read_file_t *array; + + f_array_length_t size; + f_array_length_t used; + } fss_basic_list_read_files_t; + + #define fss_basic_list_read_files_t_initialize { 0, 1, 1 } +#endif // _di_fss_basic_list_read_files_t_ + +/** + * The data structure for FSS Basic Read. + * + * fss_basic_list_read_data_option_*: + * - at: The object at the given position is being selected (Think of this as select a row for some Object). + * - content: The Content is to be printed. + * - empty: Empty Content will be printed (Objects that have no Content will have their empty Content printed). + * - line: A specific Content at a given line is to be selected (Think of this as select a row for some Content). + * - name: A specific Object name has been requested. + * - object: The Object is to be printed. + * - select: A specific Content at a given position is to be selected (Think of this as select a column for some Content). + * - total: The total lines found and selected is printed instead of the Content. + * - trim: Empty space before and after Objects and Content will not be printed (They will be trimmed). + * + * options: Bitwise flags representing parameters. + * delimit_mode: The delimit mode. + * delimit_depth: The delimit depth. + * select: The Content to select (column number). + * line: The Content to select (row number). + * files: A statically allocated array of files for designating where in the buffer a file is represented. + * depths: The array of parameters for each given depth. + * buffer: The buffer containing all loaded files (and STDIN pipe). + * objects: The positions within the buffer representing Objects. + * contents: The positions within the buffer representing Contents. + * delimits_object: The positions within the buffer representing Object character delimits. + * delimits_content: The positions within the buffer representing Content character delimits. + */ +#ifndef _di_fss_basic_list_read_data_t_ + #define fss_basic_list_read_data_option_at 0x1 + #define fss_basic_list_read_data_option_content 0x2 + #define fss_basic_list_read_data_option_empty 0x4 + #define fss_basic_list_read_data_option_line 0x8 + #define fss_basic_list_read_data_option_name 0x10 + #define fss_basic_list_read_data_option_object 0x20 + #define fss_basic_list_read_data_option_select 0x40 + #define fss_basic_list_read_data_option_total 0x80 + #define fss_basic_list_read_data_option_trim 0x100 + + typedef struct { + uint16_t option; + uint8_t delimit_mode; + f_array_length_t delimit_depth; + f_number_unsigned_t select; + f_number_unsigned_t line; + + fss_basic_list_read_files_t files; + fss_basic_list_read_depths_t depths; + + f_string_dynamic_t buffer; + f_fss_objects_t objects; + f_fss_contents_t contents; + f_fss_delimits_t delimits_object; + f_fss_delimits_t delimits_content; + f_fss_comments_t comments; + } fss_basic_list_read_data_t; + + #define fss_basic_list_read_data_t_initialize \ + { \ + 0, \ + fss_basic_list_read_delimit_mode_all, \ + 0, \ + 0, \ + 0, \ + fss_basic_list_read_files_t_initialize, \ + fss_basic_list_read_depths_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_fss_objects_t_initialize, \ + f_fss_contents_t_initialize, \ + f_fss_delimits_t_initialize, \ + f_fss_delimits_t_initialize, \ + f_fss_comments_t_initialize, \ } -#endif // _di_fss_basic_list_read_depths_t_ +#endif // _di_fss_basic_list_read_data_t_ + +/** + * Fully deallocate all memory for the given data without caring about return status. + * + * @param data + * The data to deallocate. + */ +#ifndef _di_fss_basic_list_read_data_delete_simple_ + extern void fss_basic_list_read_data_delete_simple(fss_basic_list_read_data_t *daa) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_data_delete_simple_ + +/** + * Fully deallocate all memory for the given depth without caring about return status. + * + * @param depth + * The depth to deallocate. + */ +#ifndef _di_fss_basic_list_read_depth_delete_simple_ + extern void fss_basic_list_read_depth_delete_simple(fss_basic_list_read_depth_t *depth) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_depth_delete_simple_ + +/** + * Resize the depth array. + * + * @param length + * The new size to use. + * @param depths + * The depth array to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * Errors (with error bit) from: fss_basic_list_read_depths_increase(). + * + * @see f_memory_resize() + * + * @see fss_basic_list_read_depth_delete_simple() + * @see fss_basic_list_read_depths_increase() + */ +#ifndef _di_fss_basic_list_read_depths_resize_ + extern f_status_t fss_basic_list_read_depths_resize(const f_array_length_t length, fss_basic_list_read_depths_t *depths) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_depths_resize_ #ifdef __cplusplus } // extern "C" diff --git a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c index 8b70e6e..a659303 100644 --- a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c +++ b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c @@ -6,132 +6,166 @@ extern "C" { #endif -#ifndef _di_fss_basic_list_read_main_preprocess_depth_ - f_status_t fss_basic_list_read_main_preprocess_depth(const f_console_arguments_t arguments, const fss_basic_list_read_main_t main, fss_basic_list_read_depths_t *depths) { +#ifndef _di_fss_basic_list_read_delimit_content_is_ + f_status_t fss_basic_list_read_delimit_content_is(const f_array_length_t depth, fss_basic_list_read_data_t * const data) { + + if (data->delimit_mode == fss_basic_list_read_delimit_mode_none) { + return F_false; + } + + if (data->delimit_mode == fss_basic_list_read_delimit_mode_all) { + return F_true; + } + + if (depth < data->delimit_depth) { + return data->delimit_mode == fss_basic_list_read_delimit_mode_content_lesser; + } + + if (depth == data->delimit_depth) { + return F_true; + } + + return data->delimit_mode == fss_basic_list_read_delimit_mode_content_greater; + } +#endif // _di_fss_basic_list_read_delimit_content_is_ + +#ifndef _di_fss_basic_list_read_delimit_object_is_ + f_status_t fss_basic_list_read_delimit_object_is(const f_array_length_t depth, fss_basic_list_read_data_t * const data) { + + switch (data->delimit_mode) { + case fss_basic_list_read_delimit_mode_none: + case fss_basic_list_read_delimit_mode_content: + case fss_basic_list_read_delimit_mode_content_greater: + case fss_basic_list_read_delimit_mode_content_lesser: + return F_false; + + case fss_basic_list_read_delimit_mode_all: + case fss_basic_list_read_delimit_mode_content_object: + case fss_basic_list_read_delimit_mode_content_greater_object: + case fss_basic_list_read_delimit_mode_content_lesser_object: + case fss_basic_list_read_delimit_mode_object: + return F_true; + + default: + break; + } + + return depth == data->delimit_depth || data->delimit_mode == fss_basic_list_read_delimit_mode_content_lesser; + } +#endif // _di_fss_basic_list_read_delimit_object_is_ + +#ifndef _di_fss_basic_list_read_depth_process_ + f_status_t fss_basic_list_read_depth_process(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) { + f_status_t status = F_none; { f_array_length_t depth_size = 1; - if (main.parameters[fss_basic_list_read_parameter_depth].result == f_console_result_additional) { - depth_size = main.parameters[fss_basic_list_read_parameter_depth].values.used; + if (main->parameters[fss_basic_list_read_parameter_depth].result == f_console_result_additional) { + depth_size = main->parameters[fss_basic_list_read_parameter_depth].values.used; } - macro_fss_basic_list_read_depths_t_resize(status, (*depths), depth_size); + if (depth_size > data->depths.size) { + status = fss_basic_list_read_depths_resize(depth_size, &data->depths); - if (F_status_is_error(status)) { - f_color_print(main.error.to.stream, main.context.set.error, "%sUnable to allocate memory.%c", fll_error_print_error, f_string_eol_s[0]); - return status; + if (F_status_is_error(status)) { + fll_error_print(main->error, F_status_set_fine(status), "fss_basic_list_read_depths_resize", F_true); + + return status; + } } - depths->used = depth_size; + data->depths.used = depth_size; } f_array_length_t position_depth = 0; f_array_length_t position_at = 0; f_array_length_t position_name = 0; - for (f_array_length_t i = 0; i < depths->used; i++) { - depths->array[i].depth = 0; - depths->array[i].index_at = 0; - depths->array[i].index_name = 0; - depths->array[i].value_at = 0; + for (f_array_length_t i = 0; i < data->depths.used; ++i) { + + data->depths.array[i].depth = 0; + data->depths.array[i].index_at = 0; + data->depths.array[i].index_name = 0; + data->depths.array[i].value_at = 0; - macro_f_string_dynamic_t_clear(depths->array[i].value_name); + macro_f_string_dynamic_t_clear(data->depths.array[i].value_name); - if (!main.parameters[fss_basic_list_read_parameter_depth].values.used) { + if (!main->parameters[fss_basic_list_read_parameter_depth].values.used) { position_depth = 0; } else { - position_depth = main.parameters[fss_basic_list_read_parameter_depth].values.array[i]; + position_depth = main->parameters[fss_basic_list_read_parameter_depth].values.array[i]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[position_depth])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[position_depth])); - status = fl_conversion_string_to_number_unsigned(arguments.argv[position_depth], range, &depths->array[i].depth); + status = fl_conversion_string_to_number_unsigned(arguments->argv[position_depth], range, &data->depths.array[i].depth); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_basic_list_read_long_depth, arguments.argv[position_depth]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_basic_list_read_long_depth, arguments->argv[position_depth]); + return status; } } - if (main.parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { - for (; position_at < main.parameters[fss_basic_list_read_parameter_at].values.used; position_at++) { + if (main->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { + for (; position_at < main->parameters[fss_basic_list_read_parameter_at].values.used; ++position_at) { - if (main.parameters[fss_basic_list_read_parameter_at].values.array[position_at] < position_depth) { + if (main->parameters[fss_basic_list_read_parameter_at].values.array[position_at] < position_depth) { continue; } - if (i + 1 < depths->used && main.parameters[fss_basic_list_read_parameter_at].values.array[position_at] > main.parameters[fss_basic_list_read_parameter_depth].values.array[i + 1]) { + if (i + 1 < data->depths.used && main->parameters[fss_basic_list_read_parameter_at].values.array[position_at] > main->parameters[fss_basic_list_read_parameter_depth].values.array[i + 1]) { break; } - depths->array[i].index_at = main.parameters[fss_basic_list_read_parameter_at].values.array[position_at]; + data->depths.array[i].index_at = main->parameters[fss_basic_list_read_parameter_at].values.array[position_at]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[depths->array[i].index_at])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[data->depths.array[i].index_at])); - status = fl_conversion_string_to_number_unsigned(arguments.argv[depths->array[i].index_at], range, &depths->array[i].value_at); + status = fl_conversion_string_to_number_unsigned(arguments->argv[data->depths.array[i].index_at], range, &data->depths.array[i].value_at); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_basic_list_read_long_at, arguments.argv[depths->array[i].index_at]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_basic_list_read_long_at, arguments->argv[data->depths.array[i].index_at]); + return status; } } // for } - if (main.parameters[fss_basic_list_read_parameter_name].result == f_console_result_additional) { - for (; position_name < main.parameters[fss_basic_list_read_parameter_name].values.used; position_name++) { + if (main->parameters[fss_basic_list_read_parameter_name].result == f_console_result_additional) { + for (; position_name < main->parameters[fss_basic_list_read_parameter_name].values.used; position_name++) { - if (main.parameters[fss_basic_list_read_parameter_name].values.array[position_name] < position_depth) { + if (main->parameters[fss_basic_list_read_parameter_name].values.array[position_name] < position_depth) { continue; } - if (i + 1 < depths->used && main.parameters[fss_basic_list_read_parameter_name].values.array[position_name] > main.parameters[fss_basic_list_read_parameter_depth].values.array[i + 1]) { + if (i + 1 < data->depths.used && main->parameters[fss_basic_list_read_parameter_name].values.array[position_name] > main->parameters[fss_basic_list_read_parameter_depth].values.array[i + 1]) { break; } - depths->array[i].index_name = main.parameters[fss_basic_list_read_parameter_name].values.array[position_name]; + data->depths.array[i].index_name = main->parameters[fss_basic_list_read_parameter_name].values.array[position_name]; - if (main.parameters[fss_basic_list_read_parameter_trim].result == f_console_result_found) { - status = fl_string_rip(arguments.argv[depths->array[i].index_name], strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name); + if (main->parameters[fss_basic_list_read_parameter_trim].result == f_console_result_found) { + status = fl_string_rip(arguments->argv[data->depths.array[i].index_name], strlen(arguments->argv[data->depths.array[i].index_name]), &data->depths.array[i].value_name); } else { - status = f_string_append(arguments.argv[depths->array[i].index_name], strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name); + status = f_string_append(arguments->argv[data->depths.array[i].index_name], strlen(arguments->argv[data->depths.array[i].index_name]), &data->depths.array[i].value_name); } if (F_status_is_error(status)) { - f_status_t status_code = F_status_set_fine(status); - - // @todo: move error printing into common function. - if (status_code == F_memory_not) { - f_color_print(main.error.to.stream, main.context.set.error, "%sUnable to allocate memory.%c", fll_error_print_error, f_string_eol_s[0]); - } - else if (status_code == F_string_too_large) { - f_color_print(main.error.to.stream, main.context.set.error, "%sUnable to process '", fll_error_print_error); - f_color_print(main.error.to.stream, main.context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_trim); - f_color_print(main.error.to.stream, main.context.set.error, "' because the maximum buffer size was reached.%c", f_string_eol_s[0]); - } - else { - f_string_t function = "f_string_append"; - - if (main.parameters[fss_basic_list_read_parameter_trim].result == f_console_result_found) { - function = "fl_string_rip"; - } - - f_color_print(main.error.to.stream, main.context.set.error, "%sAn unhandled error (", fll_error_print_error); - f_color_print(main.error.to.stream, main.context.set.notable, "%u", status_code); - f_color_print(main.error.to.stream, main.context.set.error, ") has occurred while calling "); - f_color_print(main.error.to.stream, main.context.set.notable, "%s()", function); - f_color_print(main.error.to.stream, main.context.set.error, ".%c", f_string_eol_s[0]); - } + fll_error_print(main->error, F_status_set_fine(status), main->parameters[fss_basic_list_read_parameter_trim].result == f_console_result_found ? "fl_string_rip" : "f_string_append", F_true); return status; } - if (!depths->array[i].value_name.used) { - f_color_print(main.error.to.stream, main.context.set.error, "%sThe '", fll_error_print_error); - f_color_print(main.error.to.stream, main.context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_name); - f_color_print(main.error.to.stream, main.context.set.error, "' must not be an empty string.%c", f_string_eol_s[0]); + if (!data->depths.array[i].value_name.used) { + if (main->error.verbosity != f_console_verbosity_quiet) { + f_color_print(main->error.to.stream, main->context.set.error, "%sThe '", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_name); + f_color_print(main->error.to.stream, main->context.set.error, "' must not be an empty string.%c", f_string_eol_s[0]); + } return F_status_set_error(F_parameter); } @@ -139,27 +173,31 @@ extern "C" { } } // for - for (f_array_length_t i = 0; i < depths->used; i++) { + for (f_array_length_t i = 0; i < data->depths.used; ++i) { - for (f_array_length_t j = i + 1; j < depths->used; j++) { + for (f_array_length_t j = i + 1; j < data->depths.used; ++j) { - if (depths->array[i].depth == depths->array[j].depth) { - f_color_print(main.error.to.stream, main.context.set.error, "%sThe value '", fll_error_print_error); - f_color_print(main.error.to.stream, main.context.set.notable, "%llu", depths->array[i].depth); - f_color_print(main.error.to.stream, main.context.set.error, "' may only be specified once for the parameter '"); - f_color_print(main.error.to.stream, main.context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_depth); - f_color_print(main.error.to.stream, main.context.set.error, "'.%c", f_string_eol_s[0]); + if (data->depths.array[i].depth == data->depths.array[j].depth) { + if (main->error.verbosity != f_console_verbosity_quiet) { + f_color_print(main->error.to.stream, main->context.set.error, "%sThe value '", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%llu", data->depths.array[i].depth); + f_color_print(main->error.to.stream, main->context.set.error, "' may only be specified once for the parameter '"); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_depth); + f_color_print(main->error.to.stream, main->context.set.error, "'.%c", f_string_eol_s[0]); + } return F_status_set_error(F_parameter); } - else if (depths->array[i].depth > depths->array[j].depth) { - f_color_print(main.error.to.stream, main.context.set.error, "%sThe parameter '", fll_error_print_error); - f_color_print(main.error.to.stream, main.context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_depth); - f_color_print(main.error.to.stream, main.context.set.error, "' may not have the value '"); - f_color_print(main.error.to.stream, main.context.set.notable, "%llu", depths->array[i].depth); - f_color_print(main.error.to.stream, main.context.set.error, "' before the value '"); - f_color_print(main.error.to.stream, main.context.set.notable, "%llu", depths->array[j].depth); - f_color_print(main.error.to.stream, main.context.set.error, "'.%c", f_string_eol_s[0]); + else if (data->depths.array[i].depth > data->depths.array[j].depth) { + if (main->error.verbosity != f_console_verbosity_quiet) { + f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter '", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_basic_list_read_long_depth); + f_color_print(main->error.to.stream, main->context.set.error, "' may not have the value '"); + f_color_print(main->error.to.stream, main->context.set.notable, "%llu", data->depths.array[i].depth); + f_color_print(main->error.to.stream, main->context.set.error, "' before the value '"); + f_color_print(main->error.to.stream, main->context.set.notable, "%llu", data->depths.array[j].depth); + f_color_print(main->error.to.stream, main->context.set.error, "'.%c", f_string_eol_s[0]); + } return F_status_set_error(F_parameter); } @@ -168,480 +206,547 @@ extern "C" { return F_none; } -#endif // _di_fss_basic_list_read_main_preprocess_depth_ - -#ifndef _di_fss_basic_list_read_main_process_file_ - f_status_t fss_basic_list_read_main_process_file(const f_console_arguments_t arguments, fss_basic_list_read_main_t *main, const f_string_t filename, const fss_basic_list_read_depths_t depths, f_fss_delimits_t *delimits, f_fss_comments_t *comments) { - f_status_t status = F_none; +#endif // _di_fss_basic_list_read_depth_process_ - const f_array_lengths_t except_none = f_array_lengths_t_initialize; - bool delimited = F_true; +#ifndef _di_fss_basic_list_read_file_identify_ + f_string_t fss_basic_list_read_file_identify(const f_array_length_t at, const fss_basic_list_read_files_t files) { - // for this standard, delimits would always be applied, except for when delimit_depth is greater than 0. - if (main->delimit_mode == fss_basic_list_read_delimit_mode_none || (main->delimit_depth && (main->delimit_mode == fss_basic_list_read_delimit_mode_depth || main->delimit_mode == fss_basic_list_read_delimit_mode_depth_greater))) { - delimited = F_false; - } + for (f_array_length_t i = 0; i < files.used; ++i) { - { - f_string_range_t input = macro_f_string_range_t_initialize(main->buffer.used); + if (at >= files.array[i].range.start && at <= files.array[i].range.stop) { + return files.array[i].name; + } + } // for - delimits->used = 0; - comments->used = 0; + return ""; + } +#endif // _di_fss_basic_list_read_file_identify_ - status = fll_fss_basic_list_read(main->buffer, &input, &main->objects, &main->contents, delimits, 0, comments); +#ifndef _di_fss_basic_list_read_load_number_ + f_status_t fss_basic_list_read_load_number(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, f_number_unsigned_t *number) { - 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(main->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true, filename, "process", fll_error_file_type_file); - } - else if (status == F_data_not_stop || status == F_data_not_eos) { - macro_f_fss_contents_t_delete_simple(main->contents); - macro_f_fss_objects_t_delete_simple(main->objects); - macro_f_string_dynamic_t_delete_simple(main->buffer); - - if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { - fprintf(main->output.stream, "0%c", f_string_eol_s[0]); - return F_none; - } + if (main->parameters[parameter].result == f_console_result_additional) { + const f_array_length_t index = main->parameters[parameter].values.array[main->parameters[parameter].values.used - 1]; + const f_string_range_t range = macro_f_string_range_t_initialize(strnlen(arguments->argv[index], f_console_parameter_size)); - return F_status_set_warning(status); - } + const f_status_t status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, number); if (F_status_is_error(status)) { - macro_f_fss_contents_t_delete_simple(main->contents); - macro_f_fss_objects_t_delete_simple(main->objects); - macro_f_string_dynamic_t_delete_simple(main->buffer); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, name, arguments->argv[index]); 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) { - main->buffer.string[j] = f_fss_delimit_placeholder; - } // for - } // for + return F_true; } - f_number_unsigned_t select = 0; + return F_false; + } +#endif // _di_fss_basic_list_read_load_number_ - if (main->parameters[fss_basic_list_read_parameter_select].result == f_console_result_additional) { - const f_array_length_t index = main->parameters[fss_basic_list_read_parameter_select].values.array[main->parameters[fss_basic_list_read_parameter_select].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[index])); +#ifndef _di_fss_basic_list_read_print_at_ + void fss_basic_list_read_print_at(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t * const data, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content) { - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &select); + if (at >= data->contents.used) { + return; + } - if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_basic_list_read_long_select, arguments.argv[index]); - return status; + if ((data->option & fss_basic_list_read_data_option_object) || (data->option & fss_basic_list_read_data_option_content) && (data->contents.array[at].used || (data->option & fss_basic_list_read_data_option_empty))) { + if (data->option & fss_basic_list_read_data_option_object) { + if (data->option & fss_basic_list_read_data_option_trim) { + fl_print_trim_except_dynamic_partial(main->output.stream, data->buffer, data->objects.array[at], delimits_object); + } + else { + f_print_except_dynamic_partial(main->output.stream, data->buffer, data->objects.array[at], delimits_object); + } + + fss_basic_list_read_print_object_end(main); } - // This standard does not support multiple content groups. - if (select > 0) { - return F_none; + if (data->option & fss_basic_list_read_data_option_content) { + if (data->contents.array[at].used) { + fss_basic_list_read_print_content_ignore(main); + f_print_except_dynamic_partial(main->output.stream, data->buffer, data->contents.array[at].array[0], delimits_content); + fss_basic_list_read_print_content_ignore(main); + } } - } - f_array_length_t line = 0; + fss_basic_list_read_print_set_end(main); + } + } +#endif // _di_fss_basic_list_read_print_at_ - if (main->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { - const f_array_length_t index = main->parameters[fss_basic_list_read_parameter_line].values.array[main->parameters[fss_basic_list_read_parameter_line].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[index])); +#ifndef _di_fss_basic_list_read_print_at_object_ + void fss_basic_list_read_print_at_object(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t * const data, const f_array_length_t at, const f_fss_delimits_t delimits_object) { - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &line); + if (at >= data->objects.used) { + return; + } - if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_basic_list_read_long_line, arguments.argv[index]); - return status; - } + if (data->option & fss_basic_list_read_data_option_trim) { + fl_print_trim_except_dynamic_partial(main->output.stream, data->buffer, data->objects.array[at], delimits_object); + } + else { + f_print_except_dynamic_partial(main->output.stream, data->buffer, data->objects.array[at], delimits_object); } - bool names[main->objects.used]; + fss_basic_list_read_print_object_end(main); + } +#endif // _di_fss_basic_list_read_print_at_object_ - f_array_length_t i = 0; - f_array_length_t j = 0; +#ifndef _di_fss_basic_list_read_print_content_end_ + void fss_basic_list_read_print_content_end(fss_basic_list_read_main_t * const main) { - if (depths.array[0].index_name > 0) { - memset(names, 0, sizeof(bool) * main->objects.used); + // @todo remove this function from fss basic list read. - if (main->parameters[fss_basic_list_read_parameter_trim].result == f_console_result_found) { - for (i = 0; i < main->objects.used; i++) { + if (main->parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { + fprintf(main->output.stream, "%c", fss_basic_list_read_pipe_content_start); + } + } +#endif // _di_fss_basic_list_read_print_content_end_ - if (fl_string_dynamic_partial_compare_except_trim_dynamic(depths.array[0].value_name, main->buffer, main->objects.array[i], except_none, *delimits) == F_equal_to) { - names[i] = 1; - } - } // for +#ifndef _di_fss_basic_list_read_print_content_ignore_ + void fss_basic_list_read_print_content_ignore(fss_basic_list_read_main_t * const main) { + + if (main->parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { + fprintf(main->output.stream, "%c", fss_basic_list_read_pipe_content_ignore); + } + } +#endif // _di_fss_basic_list_read_print_content_ignore_ + +#ifndef _di_fss_basic_list_read_print_object_end_ + void fss_basic_list_read_print_object_end(fss_basic_list_read_main_t * const main) { + + if (main->parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { + fprintf(main->output.stream, "%c", fss_basic_list_read_pipe_content_start); + } + else { + if (main->parameters[fss_basic_list_read_parameter_content].result == f_console_result_found) { + fprintf(main->output.stream, "%c%c", f_fss_basic_list_open, f_fss_basic_list_open_end); } else { - for (i = 0; i < main->objects.used; i++) { - if (fl_string_dynamic_partial_compare_except_dynamic(depths.array[0].value_name, main->buffer, main->objects.array[i], except_none, *delimits) == F_equal_to) { - names[i] = 1; - } - } // for + fprintf(main->output.stream, "%c", f_fss_eol); } } - else { - memset(names, 1, sizeof(bool) * main->objects.used); - } + } +#endif // _di_fss_basic_list_read_print_object_end_ - bool include_empty = 0; +#ifndef _di_fss_basic_list_read_print_set_end_ + void fss_basic_list_read_print_set_end(fss_basic_list_read_main_t * const main) { - if (main->parameters[fss_basic_list_read_parameter_empty].result == f_console_result_found) { - include_empty = 1; + if (main->parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { + fprintf(main->output.stream, "%c", fss_basic_list_read_pipe_content_end); } + } +#endif // _di_fss_basic_list_read_print_set_end_ - if (main->parameters[fss_basic_list_read_parameter_object].result == f_console_result_found) { - if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { - if (depths.array[0].index_at > 0) { - if (depths.array[0].value_at < main->objects.used && names[depths.array[0].value_at]) { - fprintf(main->output.stream, "1%c", f_string_eol_s[0]); - } - else { - fprintf(main->output.stream, "0%c", f_string_eol_s[0]); - } - } - else if (depths.array[0].index_name > 0) { - f_array_length_t total = 0; +#ifndef _di_fss_basic_list_read_print_one_ + void fss_basic_list_read_print_one(fss_basic_list_read_main_t * const main) { + fprintf(main->output.stream, "1%c", f_string_eol_s[0]); + } +#endif // _di_fss_basic_list_read_print_one_ - for (i = 0; i < main->objects.used; i++) { - if (!names[i]) continue; +#ifndef _di_fss_basic_list_read_print_zero_ + void fss_basic_list_read_print_zero(fss_basic_list_read_main_t * const main) { + fprintf(main->output.stream, "0%c", f_string_eol_s[0]); + } +#endif // _di_fss_basic_list_read_print_zero_ - total++; - } // for +#ifndef _di_fss_basic_list_read_load_ + f_status_t fss_basic_list_read_load(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) { - fprintf(main->output.stream, "%llu%c", total, f_string_eol_s[0]); - } - else { - fprintf(main->output.stream, "%llu%c", main->objects.used, f_string_eol_s[0]); - } + f_string_range_t input = macro_f_string_range_t_initialize(data->buffer.used); + + data->delimits_object.used = 0; + data->delimits_content.used = 0; + + const f_status_t status = fll_fss_basic_list_read(data->buffer, &input, &data->objects, &data->contents, &data->delimits_object, &data->delimits_content, &data->comments); + + if (F_status_is_error(status)) { + const f_string_t file_name = fss_basic_list_read_file_identify(input.start, data->files); + + fll_error_file_print(main->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true, file_name ? file_name : "-", "process", fll_error_file_type_file); + + return status; + } + else if (status == F_data_not_stop || status == F_data_not_eos) { + if (data->option & fss_basic_list_read_data_option_total) { + fss_basic_list_read_print_zero(main); return F_none; } - f_status_t (*print_object)(FILE *, const f_string_static_t, const f_string_range_t, const f_array_lengths_t) = &f_print_except_dynamic_partial; + return F_status_set_warning(status); + } + + return F_none; + } +#endif // _di_fss_basic_list_read_load_ + +#ifndef _di_fss_basic_list_read_process_ + f_status_t fss_basic_list_read_process(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) { + + f_status_t status = fss_basic_list_read_process_option(arguments, main, data); + if (F_status_is_error(status)) return status; - if (main->parameters[fss_basic_list_read_parameter_trim].result == f_console_result_found) { - print_object = &fl_print_trim_except_dynamic_partial; + // This standard does not support multiple content groups. + if ((data->option & fss_basic_list_read_data_option_select) && data->select) { + if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { + fss_basic_list_read_print_zero(main); } - if (depths.array[0].index_at > 0) { - f_array_length_t at = 0; - f_array_length_t i = 0; + return F_none; + } - for (; i < main->objects.used; i++) { + status = fss_basic_list_read_load(main, data); + if (F_status_is_error(status)) return status; - if (names[i]) { - if (at == depths.array[0].value_at) { - print_object(main->output.stream, main->buffer, main->objects.array[i], delimited ? *delimits : except_none); + bool names[data->objects.used]; - fss_basic_list_read_print_object_end(*main); + status = fss_basic_list_read_process_name(data, names); + if (F_status_is_error(status)) return status; - if (main->parameters[fss_basic_list_read_parameter_content].result == f_console_result_found) { - if (main->contents.array[i].used) { - fss_basic_list_read_print_content_ignore(*main); - f_print_except_dynamic_partial(main->output.stream, main->buffer, main->contents.array[i].array[0], delimited ? *delimits : except_none); - fss_basic_list_read_print_content_ignore(*main); - } - } + if (data->depths.array[0].index_at) { + return fss_basic_list_read_process_at(main, data, names); + } - fss_basic_list_read_print_set_end(*main); - break; - } + if (data->option & fss_basic_list_read_data_option_total) { + return fss_basic_list_read_process_total(main, data, names); + } - at++; - } - } // for + if (data->option & fss_basic_list_read_data_option_line) { + return fss_basic_list_read_process_line(main, data, names); + } - return F_none; - } + f_array_lengths_t except_none = f_array_lengths_t_initialize; + f_array_lengths_t *delimits_object = fss_basic_list_read_delimit_object_is(0, data) ? &data->delimits_object : &except_none; + f_array_lengths_t *delimits_content = fss_basic_list_read_delimit_content_is(0, data) ? &data->delimits_content : &except_none; - for (i = 0; i < main->objects.used; i++) { + for (f_array_length_t i = 0; i < data->contents.used; ++i) { - if (!names[i]) continue; + if (!names[i]) continue; - print_object(main->output.stream, main->buffer, main->objects.array[i], delimited ? *delimits : except_none); + fss_basic_list_read_print_at(main, data, i, *delimits_object, *delimits_content); + } // for - fss_basic_list_read_print_object_end(*main); + return F_none; + } +#endif // _di_fss_basic_list_read_process_ - if (main->parameters[fss_basic_list_read_parameter_content].result == f_console_result_found) { - if (main->contents.array[i].used) { - fss_basic_list_read_print_content_ignore(*main); - f_print_except_dynamic_partial(main->output.stream, main->buffer, main->contents.array[i].array[0], delimited ? *delimits : except_none); - fss_basic_list_read_print_content_ignore(*main); - } - } +#ifndef _di_fss_basic_list_read_process_at_ + f_status_t fss_basic_list_read_process_at(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, bool names[]) { - fss_basic_list_read_print_set_end(*main); - } // for + if (data->depths.array[0].value_at >= data->objects.used) { + if (names[data->depths.array[0].value_at] && (data->option & fss_basic_list_read_data_option_total)) { + fss_basic_list_read_print_zero(main); + } return F_none; } - if (depths.array[0].index_at > 0) { - if (depths.array[0].value_at >= main->objects.used) { - if (names[depths.array[0].value_at] && main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { - fprintf(main->output.stream, "0%c", f_string_eol_s[0]); + f_array_lengths_t except_none = f_array_lengths_t_initialize; + f_array_lengths_t *delimits_object = fss_basic_list_read_delimit_object_is(0, data) ? &data->delimits_object : &except_none; + f_array_lengths_t *delimits_content = fss_basic_list_read_delimit_content_is(0, data) ? &data->delimits_content : &except_none; + + f_array_length_t at = 0; + f_array_length_t line = 0; + f_status_t status = F_none; + + for (f_array_length_t i = 0; i < data->objects.used; ++i) { + + if (!names[i]) continue; + + if (at == data->depths.array[0].value_at) { + if (data->option & fss_basic_list_read_data_option_line) { + status = fss_basic_list_read_process_at_line(at, *delimits_object, *delimits_content, main, data, &line); + if (status == F_success) return F_none; + } + else if (data->option & fss_basic_list_read_data_option_total) { + if (data->contents.array[i].used) { + fss_basic_list_read_print_one(main); + } + else { + fss_basic_list_read_print_zero(main); + } + } + else { + fss_basic_list_read_print_at(main, data, i, *delimits_object, *delimits_content); } - return F_none; + break; } - f_array_length_t at = 0; - f_array_length_t total = 0; - f_array_length_t line_current = 0; + ++at; + } // for - for (; i < main->objects.used; i++) { + // The line was never found. + if (data->option & fss_basic_list_read_data_option_line) { + if (data->option & fss_basic_list_read_data_option_total) { + fss_basic_list_read_print_zero(main); + } + } - if (names[i]) { - if (at == depths.array[0].value_at) { - if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { - if (!main->contents.array[i].used) { - fprintf(main->output.stream, "0%c", f_string_eol_s[0]); - } - else { - total = 1; + return F_none; + } +#endif // _di_fss_basic_list_read_process_at_ - for (j = main->contents.array[i].array[0].start; j <= main->contents.array[i].array[0].stop; j++) { - if (!main->buffer.string[j]) continue; +#ifndef _di_fss_basic_list_read_process_at_line_ + f_status_t fss_basic_list_read_process_at_line(const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, f_array_length_t *line) { - if (main->buffer.string[j] == f_string_eol_s[0]) { - total++; - } - } // for + if (data->option & fss_basic_list_read_data_option_object) { + if (*line == data->line) { + if (data->option & fss_basic_list_read_data_option_total) { + fss_basic_list_read_print_one(main); + } + else { + fss_basic_list_read_print_at_object(main, data, at, delimits_object); + } - fprintf(main->output.stream, "%llu%c", total, f_string_eol_s[0]); - } + return F_success; + } - return F_none; - } + ++(*line); + } - if (main->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { - if (!main->contents.array[i].used) { - if (include_empty && !line) { - fprintf(main->output.stream, "%c", f_string_eol_s[0]); - fss_basic_list_read_print_set_end(*main); - } - } - else { - i = main->contents.array[i].array[0].start; - - if (!line) { - for (; i <= main->contents.array[i].array[0].stop; i++) { - if (!main->buffer.string[i]) continue; - if (main->buffer.string[i] == f_string_eol_s[0]) { - fprintf(main->output.stream, "%c", f_string_eol_s[0]); - break; - } - - fprintf(main->output.stream, "%c", main->buffer.string[i]); - } // for - } - else { - line_current = 0; - - for (; i <= main->contents.array[i].array[0].stop; i++) { - if (!main->buffer.string[i]) continue; - - if (main->buffer.string[i] == f_string_eol_s[0]) { - line_current++; - - if (line_current == line) { - i++; - - for (; i <= main->contents.array[i].array[0].stop; i++) { - if (!main->buffer.string[i]) continue; - - if (main->buffer.string[i] == f_string_eol_s[0]) { - fprintf(main->output.stream, "%c", f_string_eol_s[0]); - break; - } - - fprintf(main->output.stream, "%c", main->buffer.string[i]); - } // for - - break; - } - } - } // for - } - } - - return F_none; - } + // There is only a single Content column for this standard. + if (data->option & fss_basic_list_read_data_option_content) { + if (!data->contents.array[at].used) { + return F_none; + } + + f_string_range_t range = f_string_range_t_initialize; + f_array_length_t i = 0; + + range.start = data->contents.array[at].array[0].start; + range.stop = data->contents.array[at].array[0].stop; + + // This content has no data, do not even check "include empty" because it cannot be counted as a line. + if (range.start > range.stop) { + return F_none; + } - if (main->contents.array[i].used > 0) { - fss_basic_list_read_print_content_ignore(*main); - f_print_except_dynamic_partial(main->output.stream, main->buffer, main->contents.array[i].array[0], delimited ? *delimits : except_none); - fss_basic_list_read_print_content_ignore(*main); + for (i = range.start; i <= range.stop; ++i) { - fss_basic_list_read_print_set_end(*main); + if (data->buffer.string[i] == f_string_eol_s[0]) { + if (*line == data->line) { + range.stop = i; + + if (data->option & fss_basic_list_read_data_option_total) { + fss_basic_list_read_print_one(main); } - else if (include_empty) { - fprintf(main->output.stream, "%c", f_string_eol_s[0]); - fss_basic_list_read_print_set_end(*main); + else { + f_print_except_dynamic_partial(main->output.stream, data->buffer, range, delimits_content); } - break; + return F_success; } - at++; + range.start = i + 1; + + if (i <= range.stop) { + ++(*line); + } } } // for - return F_none; - } - - if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { - f_array_length_t total = 0; + // If Content does not end with a newline, it still must be treated as the last line. + if (data->buffer.string[range.stop] != f_string_eol_s[0]) { + ++(*line); - for (i = 0; i < main->objects.used; i++) { - if (!names[i]) continue; + if (*line == data->line) { + if (data->option & fss_basic_list_read_data_option_total) { + fss_basic_list_read_print_one(main); + } + else { + range.stop = data->contents.array[at].array[0].stop; - if (!main->contents.array[i].used) { - if (include_empty) { - total++; + f_print_except_dynamic_partial(main->output.stream, data->buffer, range, delimits_content); + fprintf(main->output.stream, "%c", f_string_eol_s[0]); } - continue; + return F_success; } + } + } - for (j = main->contents.array[i].array[0].start; j <= main->contents.array[i].array[0].stop; j++) { - if (!main->buffer.string[j]) continue; + return F_none; + } +#endif // _di_fss_basic_list_read_process_at_line_ - if (main->buffer.string[j] == f_string_eol_s[0]) { - total++; - } - } // for - } // for +#ifndef _di_fss_basic_list_read_process_line_ + f_status_t fss_basic_list_read_process_line(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, bool names[]) { - fprintf(main->output.stream, "%llu%c", total, f_string_eol_s[0]); - return F_none; - } + f_array_lengths_t except_none = f_array_lengths_t_initialize; + f_array_lengths_t *delimits_object = fss_basic_list_read_delimit_object_is(0, data) ? &data->delimits_object : &except_none; + f_array_lengths_t *delimits_content = fss_basic_list_read_delimit_content_is(0, data) ? &data->delimits_content : &except_none; - if (main->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { - for (f_array_length_t line_current = 0; i < main->contents.used; i++) { - if (!names[i]) continue; - - if (!main->contents.array[i].used) { - if (include_empty) { - if (line_current == line) { - fprintf(main->output.stream, "%c", f_string_eol_s[0]); - fss_basic_list_read_print_set_end(*main); - break; - } + f_array_length_t line = 0; + f_status_t status = F_none; - line_current++; - } + for (f_array_length_t i = 0; i < data->contents.used; ++i) { - continue; - } - - j = main->contents.array[i].array[0].start; + if (!names[i]) continue; - if (line_current != line) { - for (; j <= main->contents.array[i].array[0].stop; j++) { + status = fss_basic_list_read_process_at_line(i, *delimits_object, *delimits_content, main, data, &line); + if (status == F_success) break; + } // for - if (main->buffer.string[j] == f_string_eol_s[0]) { - line_current++; + return F_none; + } +#endif // _di_fss_basic_list_read_process_line_ - if (line_current == line) { - j++; - break; - } - } - } // for - } +#ifndef _di_fss_basic_list_read_process_name_ + f_status_t fss_basic_list_read_process_name(fss_basic_list_read_data_t *data, bool names[]) { - if (line_current == line) { - if (j > main->contents.array[i].array[0].stop) continue; + f_array_lengths_t except_none = f_array_lengths_t_initialize; - for (; j <= main->contents.array[i].array[0].stop; j++) { - if (!main->buffer.string[j]) continue; + if (data->depths.array[0].index_name > 0) { + f_array_length_t i = 0; - if (main->buffer.string[j] == f_string_eol_s[0]) { - fprintf(main->output.stream, "%c", f_string_eol_s[0]); - break; - } + memset(names, F_false, sizeof(bool) * data->objects.used); - fprintf(main->output.stream, "%c", main->buffer.string[j]); - } // for + if (data->option & fss_basic_list_read_data_option_trim) { + for (i = 0; i < data->objects.used; ++i) { - break; - } - } // for + if (fl_string_dynamic_partial_compare_except_trim_dynamic(data->depths.array[0].value_name, data->buffer, data->objects.array[i], except_none, data->delimits_object) == F_equal_to) { + names[i] = F_true; + } + } // for + } + else { + for (i = 0; i < data->objects.used; ++i) { - return F_none; + if (fl_string_dynamic_partial_compare_except_dynamic(data->depths.array[0].value_name, data->buffer, data->objects.array[i], except_none, data->delimits_object) == F_equal_to) { + names[i] = F_true; + } + } // for + } + } + else { + memset(names, F_true, sizeof(bool) * data->objects.used); } - for (i = 0; i < main->contents.used; i++) { - if (!names[i]) continue; + return F_none; + } +#endif // _di_fss_basic_list_read_process_name_ - if (!main->contents.array[i].used) { - if (include_empty) { - fprintf(main->output.stream, "%c", f_string_eol_s[0]); - fss_basic_list_read_print_set_end(*main); - } +#ifndef _di_fss_basic_list_read_process_option_ + f_status_t fss_basic_list_read_process_option(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) { - continue; - } + f_status_t status = F_none; - fss_basic_list_read_print_content_ignore(*main); - f_print_except_dynamic_partial(main->output.stream, main->buffer, main->contents.array[i].array[0], delimited ? *delimits : except_none); - fss_basic_list_read_print_content_ignore(*main); + if (main->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { + data->option |= fss_basic_list_read_data_option_at; + } - fss_basic_list_read_print_set_end(*main); - } // for + if (main->parameters[fss_basic_list_read_parameter_content].result == f_console_result_found) { + data->option |= fss_basic_list_read_data_option_content; + } - return F_none; - } -#endif // _di_fss_basic_list_read_main_process_file_ + if (main->parameters[fss_basic_list_read_parameter_empty].result == f_console_result_found) { + data->option |= fss_basic_list_read_data_option_empty; + } -#ifndef _di_fss_basic_list_read_print_object_end_ - void fss_basic_list_read_print_object_end(const fss_basic_list_read_main_t main) { + if (main->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { + data->option |= fss_basic_list_read_data_option_line; - if (main.parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { - fprintf(main.output.stream, "%c", fss_basic_list_read_pipe_content_start); + status = fss_basic_list_read_load_number(arguments, main, fss_basic_list_read_parameter_line, fss_basic_list_read_long_line, &data->line); + if (F_status_is_error(status)) return status; } - else { - if (main.parameters[fss_basic_list_read_parameter_content].result == f_console_result_found) { - fprintf(main.output.stream, "%c%c", f_fss_basic_list_open, f_fss_basic_list_open_end); - } - else { - fprintf(main.output.stream, "%c", f_fss_eol); - } + + if (main->parameters[fss_basic_list_read_parameter_name].result == f_console_result_additional) { + data->option |= fss_basic_list_read_data_option_name; } - } -#endif // _di_fss_basic_list_read_print_object_end_ -#ifndef _di_fss_basic_list_read_print_content_end_ - void fss_basic_list_read_print_content_end(const fss_basic_list_read_main_t main) { + if (main->parameters[fss_basic_list_read_parameter_object].result == f_console_result_found) { + data->option |= fss_basic_list_read_data_option_object; + } + + if (main->parameters[fss_basic_list_read_parameter_select].result == f_console_result_additional) { + data->option |= fss_basic_list_read_data_option_select; - if (main.parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { - fprintf(main.output.stream, "%c", fss_basic_list_read_pipe_content_start); + status = fss_basic_list_read_load_number(arguments, main, fss_basic_list_read_parameter_select, fss_basic_list_read_long_select, &data->select); + if (F_status_is_error(status)) return status; } - } -#endif // _di_fss_basic_list_read_print_content_end_ -#ifndef _di_fss_basic_list_read_print_content_ignore_ - void fss_basic_list_read_print_content_ignore(const fss_basic_list_read_main_t main) { + if (main->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { + data->option |= fss_basic_list_read_data_option_total; + } - if (main.parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { - fprintf(main.output.stream, "%c", fss_basic_list_read_pipe_content_ignore); + if (main->parameters[fss_basic_list_read_parameter_trim].result == f_console_result_found) { + data->option |= fss_basic_list_read_data_option_trim; } + + // Default to content if neither Object nor Content is explicitly requested. + if (!(data->option & (fss_basic_list_read_data_option_content | fss_basic_list_read_data_option_object))) { + data->option |= fss_basic_list_read_data_option_content; + } + + return F_none; } -#endif // _di_fss_basic_list_read_print_content_ignore_ +#endif // _di_fss_basic_list_read_process_option_ -#ifndef _di_fss_basic_list_read_print_set_end_ - void fss_basic_list_read_print_set_end(const fss_basic_list_read_main_t main) { +#ifndef _di_fss_basic_list_read_process_total_ + f_status_t fss_basic_list_read_process_total(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, bool names[]) { + + f_array_length_t total = 0; + f_string_range_t range = f_string_range_t_initialize; + f_array_length_t i = 0; + + for (f_array_length_t at = 0; at < data->contents.used; ++at) { + + if (!names[at]) continue; + + if (data->option & fss_basic_list_read_data_option_object) { + ++total; + } + + // There is only a single Content column for this standard. + if (data->option & fss_basic_list_read_data_option_content) { + + if (!data->contents.array[at].used) continue; + + range.start = data->contents.array[at].array[0].start; + range.stop = data->contents.array[at].array[0].stop; + + // This content has no data, do not even check "include empty" because it cannot be counted as a line. + if (range.start > range.stop) { + continue; + } + + for (i = range.start; i <= range.stop; ++i) { - if (main.parameters[fss_basic_list_read_parameter_pipe].result == f_console_result_found) { - fprintf(main.output.stream, "%c", fss_basic_list_read_pipe_content_end); + if (data->buffer.string[i] == f_string_eol_s[0]) { + range.start = i + 1; + + if (i <= range.stop) { + ++total; + } + } + } // for + + // If Content does not end with a newline, it still must be treated as the last line. + if (data->buffer.string[range.stop] != f_string_eol_s[0]) { + ++total; + } + } + } // for + + if (data->option & fss_basic_list_read_data_option_line) { + if (data->line < total) { + fss_basic_list_read_print_one(main); + } + else { + fss_basic_list_read_print_zero(main); + } } + else { + fprintf(main->output.stream, "%llu%c", total, f_string_eol_s[0]); + } + + return F_none; } -#endif // _di_fss_basic_list_read_print_set_end_ +#endif // _di_fss_basic_list_read_process_total_ #ifdef __cplusplus } // extern "C" diff --git a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h index 53e834f..db4b473 100644 --- a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h +++ b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h @@ -13,66 +13,154 @@ extern "C" { #endif /** - * Pre-process the parameters, parsing out and handling the depth and depth related parameters. + * Determine if the given depth is to be delimited or not for Content. + * + * @param depth + * The depth to check. + * @param data + * The program data. + * + * @return + * F_true if to apply delimits. + * F_false if to not apply delimits. + */ +#ifndef _di_fss_basic_list_read_delimit_content_is_ + extern f_status_t fss_basic_list_read_delimit_content_is(const f_array_length_t depth, fss_basic_list_read_data_t * const data) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_delimit_content_is_ + +/** + * Determine if the given depth is to be delimited or not for an Object. + * + * @param depth + * The depth to check. + * @param data + * The program data. + * + * @return + * F_true if to apply delimits. + * F_false if to not apply delimits. + */ +#ifndef _di_fss_basic_list_read_delimit_object_is_ + extern f_status_t fss_basic_list_read_delimit_object_is(const f_array_length_t depth, fss_basic_list_read_data_t * const data) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_delimit_object_is_ + +/** + * 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. + * The parameters passed to the process. * @param main * The main data. - * @param depths - * This stores the pre-processed depth parameters. + * @param data + * The program data. * * @return * F_none on success. * - * Status codes (with error bit) are returned on any problem. + * Errors (with error bit) from: f_string_append(). + * Errors (with error bit) from: fl_string_rip(). + * Errors (with error bit) from: fl_conversion_string_to_number_unsigned(). + * + * Errors (with error bit) from: fss_basic_list_read_depths_resize(). + * + * @see f_string_append() + * @see fl_string_rip() + * @see fl_conversion_string_to_number_unsigned() + * + * @see fss_basic_list_read_depths_resize() */ -#ifndef _di_fss_basic_list_read_main_preprocess_depth_ - extern f_status_t fss_basic_list_read_main_preprocess_depth(const f_console_arguments_t arguments, const fss_basic_list_read_main_t main, fss_basic_list_read_depths_t *depths) f_attribute_visibility_internal; -#endif // _di_fss_basic_list_read_main_preprocess_depth_ +#ifndef _di_fss_basic_list_read_depth_process_ + extern f_status_t fss_basic_list_read_depth_process(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_depth_process_ /** - * Process a given file. + * Get the name of the file the given position represents within the buffer. + * + * @param at + * The position within the buffer. + * @param files + * The representation of files and their respective ranges within the buffer. + * + * @return + * A string with the name when found. + * NULL is returned if the range represents the STDIN pipe. + * + * On failure to identify, an empty string is returned. + */ +#ifndef _di_fss_basic_list_read_file_identify_ + extern f_string_t fss_basic_list_read_file_identify(const f_array_length_t at, const fss_basic_list_read_files_t files) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_file_identify_ + +/** + * Load a given number parameter. + * + * This will print an error message on error. * * @param arguments * The console arguments passed to the program. * @param main * The main data. - * @param file_name - * The name of the file being processed. - * @param depths - * The processed depth parameters. - * @param delimits - * An array of delimits detected during processing. - * @param comments - * An array of ranges representing where comments are found within any valid content. - * This only stores comments found within valid content only. + * @param parameter + * An ID representing the parameter. + * @param name + * The parameter name to print on error. + * @param number + * The location to store the loaded number. * * @return - * F_none on success. + * F_true on success and the parameter was found (and is valid). + * F_false on success and the parameter was not found. + * + * Errors (with error bit) from: fl_conversion_string_to_number_unsigned(). * - * Status codes (with error bit) are returned on any problem. + * @see fl_conversion_string_to_number_unsigned() * - * @see fss_basic_list_read_main_preprocess_depth() + * @see fss_basic_list_read_depths_resize() */ -#ifndef _di_fss_basic_list_read_main_process_file_ - extern f_status_t fss_basic_list_read_main_process_file(const f_console_arguments_t arguments, fss_basic_list_read_main_t *main, const f_string_t file_name, const fss_basic_list_read_depths_t depths, f_fss_delimits_t *delimits, f_fss_comments_t *comments) f_attribute_visibility_internal; -#endif // _di_fss_basic_list_read_main_process_file_ +#ifndef _di_fss_basic_list_read_load_number_ + extern f_status_t fss_basic_list_read_load_number(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, f_number_unsigned_t *number) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_load_number_ /** - * Print the end of an object (which is essentially the start of a content). + * Print the Object and Content at the given position. + * + * Only what is requested to print (Object, Content, both, or neither) will be printed, if there is something to print. * * @param main * The main data. + * @param data + * The program data. + * @param at + * The index in the Objects and Contents to print. + * @param delimits_object + * The delimits to be applied to an Object. + * @param delimits_content + * The delimits to be applied to Content. */ -#ifndef _di_fss_basic_list_read_print_object_end_ - extern void fss_basic_list_read_print_object_end(const fss_basic_list_read_main_t main) f_attribute_visibility_internal; -#endif // _di_fss_basic_list_read_print_object_end_ +#ifndef _di_fss_basic_list_read_print_at_ + extern void fss_basic_list_read_print_at(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t * const data, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_print_at_ + +/** + * Explicitly print the Object at the given position. + * + * @param main + * The main data. + * @param data + * The program data. + * @param at + * The index in the Objects and Contents to print. + * @param delimits_object + * The delimits to be applied to an Object. + */ +#ifndef _di_fss_basic_list_read_print_at_object_ + extern void fss_basic_list_read_print_at_object(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t * const data, const f_array_length_t at, const f_fss_delimits_t delimits_object) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_print_at_object_ /** - * Print the ignore character for content. + * Print the ignore character for Content. * * This is only used in pipe output mode. * @@ -80,29 +168,230 @@ extern "C" { * The main data. */ #ifndef _di_fss_basic_list_read_print_content_ignore_ - extern void fss_basic_list_read_print_content_ignore(const fss_basic_list_read_main_t main) f_attribute_visibility_internal; + extern void fss_basic_list_read_print_content_ignore(fss_basic_list_read_main_t * const main) f_attribute_visibility_internal; #endif // _di_fss_basic_list_read_print_content_ignore_ /** - * Print the end of an content. + * Print the end of Content. * * @param main * The main data. */ #ifndef _di_fss_basic_list_read_print_content_end_ - extern void fss_basic_list_read_print_content_end(const fss_basic_list_read_main_t main) f_attribute_visibility_internal; + extern void fss_basic_list_read_print_content_end(fss_basic_list_read_main_t * const main) f_attribute_visibility_internal; #endif // _di_fss_basic_list_read_print_content_end_ /** - * Print the end of an object/content set. + * Print the end of an Object (which is essentially the start of Content). + * + * @param main + * The main data. + */ +#ifndef _di_fss_basic_list_read_print_object_end_ + extern void fss_basic_list_read_print_object_end(fss_basic_list_read_main_t * const main) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_print_object_end_ + +/** + * Print the number one and a newline. + * + * @param main + * The main data. + */ +#ifndef _di_fss_basic_list_read_print_one_ + extern void fss_basic_list_read_print_one(fss_basic_list_read_main_t * const main) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_print_one_ + +/** + * Print the end of an Object/Content set. * * @param main * The main data. */ #ifndef _di_fss_basic_list_read_print_set_end_ - extern void fss_basic_list_read_print_set_end(const fss_basic_list_read_main_t main) f_attribute_visibility_internal; + extern void fss_basic_list_read_print_set_end(fss_basic_list_read_main_t * const main) f_attribute_visibility_internal; #endif // _di_fss_basic_list_read_print_set_end_ +/** + * Print the number zero and a newline. + * + * @param main + * The main data. + */ +#ifndef _di_fss_basic_list_read_print_zero_ + extern void fss_basic_list_read_print_zero(fss_basic_list_read_main_t * const main) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_print_zero_ + +/** + * Process the buffer, loading the FSS data. + * + * This will print an error message on error. + * + * @param main + * The main data. + * @param data + * The program data. + * + * @return + * F_none on success. + * + * F_data_not_stop (with warning bit) on no valid FSS data found and reached stopping point. + * F_data_not_eos (with warning bit) on no valid FSS data found and reached end of string. + * + * Errors (with error bit) from: fll_fss_basic_list_read() + * + * @see fll_fss_basic_list_read() + * + * @see fss_basic_list_read_process_option() + */ +#ifndef _di_fss_basic_list_read_load_ + extern f_status_t fss_basic_list_read_load(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_load_ + +/** + * Perform the basic read processing on the buffer. + * + * This will print an error message on error. + * + * @param arguments + * The parameters passed to the process. + * @param main + * The main data. + * @param data + * The program data. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: fss_basic_list_read_load() + * Errors (with error bit) from: fss_basic_list_read_process_option() + * + * @see fss_basic_list_read_load() + * @see fss_basic_list_read_process_option() + */ +#ifndef _di_fss_basic_list_read_process_ + extern f_status_t fss_basic_list_read_process(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_process_ + +/** + * Process based on at parameter. + * + * @param main + * The main data. + * @param data + * The program data. + * @param names + * An array of booleans representing whether or not some Object name is to be used. + * (If TRUE, then the name is to be used and if FALSE, then the name is not to be used.) + * + * @return + * F_none on success. + * + * @see fss_basic_list_read_process_at_line() + */ +#ifndef _di_fss_basic_list_read_process_at_ + extern f_status_t fss_basic_list_read_process_at(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, bool names[]) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_process_at_ + +/** + * Process based on at parameter for some line. + * + * @param main + * The main data. + * @param delimits_object + * The delimits to be applied to an Object. + * @param delimits_content + * The delimits to be applied to Content. + * @param data + * The program data. + * @param line + * The current line being processed. + * This will be incremented as necessary. + * + * @return + * F_none on success but no line was matched (and possibly printed). + * F_success on success and the line was matched (and possibly printed). + */ +#ifndef _di_fss_basic_list_read_process_at_line_ + extern f_status_t fss_basic_list_read_process_at_line(const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, f_array_length_t *line) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_process_at_line_ + +/** + * Process based on line parameter. + * + * @param main + * The main data. + * @param data + * The program data. + * @param names + * An array of booleans representing whether or not some Object name is to be used. + * (If TRUE, then the name is to be used and if FALSE, then the name is not to be used.) + * + * @return + * F_none on success. + */ +#ifndef _di_fss_basic_list_read_process_line_ + extern f_status_t fss_basic_list_read_process_line(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, bool names[]) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_process_line_ + +/** + * Process the Objects in the buffer, determining if the Object name is to be used or not. + * + * How an Object name is determined to be used or not is dependent on several parameters, such as --name, --depth, --at, and --line. + * + * @param data + * The program data. + * @param names + * An array of booleans representing whether or not some Object name is to be used. + * (If TRUE, then the name is to be used and if FALSE, then the name is not to be used.) + * + * @return + * F_none on success. + */ +#ifndef _di_fss_basic_list_read_process_name_ + extern f_status_t fss_basic_list_read_process_name(fss_basic_list_read_data_t *data, bool names[]) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_process_name_ + +/** + * Process the parameters, populating the option property of the program data. + * + * @param arguments + * The parameters passed to the process. + * @param main + * The main data. + * @param data + * The program data. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: fss_basic_list_read_load_setting() + * + * @see fll_fss_basic_list_read() + * + * @see fss_basic_list_read_load_setting() + */ +#ifndef _di_fss_basic_list_read_process_option_ + extern f_status_t fss_basic_list_read_process_option(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_process_option_ + +/** + * Process based on total parameter. + * + * @param main + * The main data. + * @param data + * The program data. + * @param names + * An array of booleans representing whether or not some Object name is to be used. + * (If TRUE, then the name is to be used and if FALSE, then the name is not to be used.) + * + * @return + * F_none on success. + */ +#ifndef _di_fss_basic_list_read_process_total_ + extern f_status_t fss_basic_list_read_process_total(fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, bool names[]) f_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_process_total_ + #ifdef __cplusplus } // extern "C" #endif