From d99864423a28031916a3c0648201bb407b94d54a Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 5 Oct 2020 23:22:11 -0500 Subject: [PATCH] Progress: fss write functions and programs. I reviewed, fixed, and cleaned up the write functions. I have only partially gotten to the basic list and have not so much as glanced at the extended list. These two I will start working on later. Several bugs and problems have been identified and resolved. Add back the UTF-8 processing. - This time check the width and add each 8-byte sequence until width is reached to correctly process the UTF-8 character. --- level_1/fl_fss/c/fss_basic.c | 12 +- level_1/fl_fss/c/fss_basic.h | 3 + level_1/fl_fss/c/fss_basic_list.c | 152 ++++++++++++--------- level_1/fl_fss/c/fss_basic_list.h | 10 +- level_1/fl_fss/c/fss_extended.c | 19 +-- level_1/fl_fss/c/fss_extended.h | 6 + level_1/fl_fss/c/fss_macro.h | 14 +- level_1/fl_fss/c/private-fss.c | 56 ++++++-- level_1/fl_fss/c/private-fss.h | 14 +- level_2/fll_fss/c/fss_basic.c | 2 +- level_2/fll_fss/c/fss_basic_list.c | 32 +---- level_2/fll_fss/c/fss_basic_list.h | 5 +- level_2/fll_fss/c/fss_extended.c | 12 +- .../fss_basic_list_write/c/fss_basic_list_write.c | 57 ++++++-- .../c/private-fss_basic_list_write.c | 44 +++--- level_3/fss_basic_write/c/fss_basic_write.c | 57 ++++++-- .../fss_basic_write/c/private-fss_basic_write.c | 61 +++++++-- .../fss_basic_write/c/private-fss_basic_write.h | 14 ++ level_3/fss_extended_write/c/fss_extended_write.c | 70 +++++++--- .../c/private-fss_extended_write.c | 142 +++++++++++++------ .../c/private-fss_extended_write.h | 14 ++ 21 files changed, 544 insertions(+), 252 deletions(-) diff --git a/level_1/fl_fss/c/fss_basic.c b/level_1/fl_fss/c/fss_basic.c index 220c9b7..969cf3b 100644 --- a/level_1/fl_fss/c/fss_basic.c +++ b/level_1/fl_fss/c/fss_basic.c @@ -98,7 +98,7 @@ extern "C" { if (!destination) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ - const f_status_t status = private_fl_fss_basic_object_write(object, quote ? quote : f_fss_delimit_quote_double, range, destination); + f_status_t status = private_fl_fss_basic_object_write(object, quote ? quote : f_fss_delimit_quote_double, range, destination); if (status == F_data_not_stop || status == F_data_not_eos) { @@ -108,16 +108,10 @@ extern "C" { destination->string[destination->used++] = quote ? quote : f_fss_delimit_quote_double; destination->string[destination->used++] = quote ? quote : f_fss_delimit_quote_double; - - if (status == F_data_not_stop) { - return F_none_stop; - } - - return F_none_eos; } if (complete == f_fss_complete_partial || complete == f_fss_complete_full) { - if (status == F_none_stop || status == F_none_eos) { + if (status == F_none_stop || status == F_none_eos || status == F_data_not_stop || status == F_data_not_eos) { const f_status_t status_allocation = private_fl_fss_destination_increase(destination); if (F_status_is_error(status_allocation)) return status_allocation; @@ -165,7 +159,7 @@ extern "C" { for (; range->start <= range->stop && range->start < content.used; range->start++) { - if (content.string[range->start] == f_string_eol[0]) { + if (content.string[range->start] == f_fss_eol) { destination->used = used_start; return F_status_set_error(F_none_eol); } diff --git a/level_1/fl_fss/c/fss_basic.h b/level_1/fl_fss/c/fss_basic.h index e19a35c..99ac0ae 100644 --- a/level_1/fl_fss/c/fss_basic.h +++ b/level_1/fl_fss/c/fss_basic.h @@ -149,12 +149,15 @@ extern "C" { * F_none_stop on success after reaching the range stop. * F_data_not_stop no data to write due start location being greater than stop location. * F_data_not_eos no data to write due start location being greater than or equal to buffer size. + * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete. * F_memory_reallocation (with error bit) on reallocation error. * F_none_eol (with error bit) after reaching an EOL, which is not supported by the standard. * F_parameter (with error bit) if a parameter is invalid. * F_string_too_large (with error bit) if appended string length is too large to store in the destination. + * F_utf (with error bit) is returned on failure to read/process a UTF-8 character. * * Errors (with error bit) from: f_fss_is_space(). + * Errors (with error bit) from: f_utf_buffer_increment(). */ #ifndef _di_fl_fss_basic_object_write_ extern f_return_status fl_fss_basic_object_write(const f_string_static_t object, const f_fss_quote_t quote, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination); diff --git a/level_1/fl_fss/c/fss_basic_list.c b/level_1/fl_fss/c/fss_basic_list.c index 0a3bfe2..da57001 100644 --- a/level_1/fl_fss/c/fss_basic_list.c +++ b/level_1/fl_fss/c/fss_basic_list.c @@ -395,141 +395,160 @@ extern "C" { #endif // _di_fl_fss_basic_list_content_read_ #ifndef _di_fl_fss_basic_list_object_write_ - f_return_status fl_fss_basic_list_object_write(const f_string_static_t object, const f_fss_quote_t quoted, f_string_range_t *range, f_string_dynamic_t *destination) { + f_return_status fl_fss_basic_list_object_write(const f_string_static_t object, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination) { #ifndef _di_level_1_parameter_checking_ if (!destination) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ f_status_t status = F_none; - f_string_range_t buffer_position = f_string_range_t_initialize; - f_string_length_t start_position = f_string_t_initialize; - f_string_length_t start_buffer = 0; - fl_macro_fss_skip_past_delimit_placeholders(object, (*range)) - if (range->start > range->stop) return F_data_not_stop; - else if (range->start >= object.used) return F_data_not_eos; + if (range->start > range->stop) { + status = F_data_not_stop; + } + else if (range->start >= object.used) { + status = F_data_not_eos; + } - start_position = range->start; + if (status == F_data_not_stop || status == F_data_not_eos) { + if (complete == f_fss_complete_partial || complete == f_fss_complete_full) { + const f_status_t status_allocation = private_fl_fss_destination_increase_by(2, destination); + if (F_status_is_error(status_allocation)) return status_allocation; - // ensure that there is room for the start and stop quotes or a slash delimit and the object open character. - f_string_length_t size_allocate = destination->used + (range->stop - range->start) + 3 + f_fss_default_allocation_step; + destination->string[destination->used++] = f_fss_basic_list_open; - if (size_allocate > destination->size) { - f_macro_string_dynamic_t_resize(status, (*destination), size_allocate); - if (F_status_is_error(status)) return status; + if (complete == f_fss_complete_full) { + destination->string[destination->used++] = f_fss_eol; + } + } + + return status; } - buffer_position.start = destination->used; - buffer_position.stop = destination->used; + // ensure that there is room for a slash delimit, the object open character, and the end of line character. + status = private_fl_fss_destination_increase_by(destination->used + (range->stop - range->start) + 3, destination); + if (F_status_is_error(status)) return status; - bool quote = quoted ? F_true : F_false; + const f_string_length_t input_start = range->start; + const f_string_length_t used_start = destination->used; - if (quoted) { - if (quoted == f_fss_quote_type_single) { - destination->string[destination->used] = f_fss_delimit_quote_single; - } - else { - destination->string[destination->used] = f_fss_delimit_quote_double; - } + f_string_length_t i = 0; - destination->used++; - } + uint8_t width = 0; + // find the first graph character. while (range->start <= range->stop && range->start < object.used) { if (object.string[range->start] == f_fss_comment) { + // @todo the standard may be updated to allow escaping comments. // comments are not allowed and this format has no way of "wrapping" a comment. - return F_status_set_error(FL_fss_found_comment); - } - else if ((status = f_fss_is_graph(object, *range)) == F_true) { + status = F_status_set_error(FL_fss_found_comment); break; } - else if (F_status_is_error(status)) { - return status; - } + + status = f_fss_is_graph(object, *range); + if (F_status_is_error(status)) break; + + if (status == F_true) break; if (object.string[range->start] != f_fss_delimit_placeholder) { - destination->string[buffer_position.stop] = object.string[range->start]; - buffer_position.stop++; + width = f_macro_utf_byte_width(object.string[range->start]); + + status = private_fl_fss_destination_increase_by(width, destination); + if (F_status_is_error(status)) break; + + for (i = 0; i < width; i++) { + destination->string[destination->used++] = object.string[range->start + i]; + } // for } status = f_utf_buffer_increment(object, range, 1); - if (F_status_is_error(status)) return status; + if (F_status_is_error(status)) break; } // while + if (F_status_is_error(status)) { + destination->used = used_start; + return status; + } + while (range->start <= range->stop && range->start < object.used) { if (object.string[range->start] == f_fss_delimit_slash) { f_string_length_t slash_count = 1; - destination->string[buffer_position.stop] = object.string[range->start]; - buffer_position.stop++; - - status = f_utf_buffer_increment(object, range, 1); - if (F_status_is_error(status)) return status; + destination->string[destination->used++] = object.string[range->start]; + range->start++; while (range->start <= range->stop && range->start < object.used) { if (object.string[range->start] == f_fss_delimit_placeholder) { - status = f_utf_buffer_increment(object, range, 1); - if (F_status_is_error(status)) return status; - + range->start++; continue; } else if (object.string[range->start] != f_fss_delimit_slash) { break; } - destination->string[buffer_position.stop] = object.string[range->start]; - buffer_position.stop++; - - status = f_utf_buffer_increment(object, range, 1); - if (F_status_is_error(status)) return status; + destination->string[destination->used++] = object.string[range->start]; + range->start++; slash_count++; } // while - if (range->start > range->stop || range->start >= object.used) { - size_allocate += slash_count; + if (F_status_is_error(status)) break; - if (size_allocate > destination->size) { - f_macro_string_dynamic_t_resize(status, (*destination), size_allocate + f_fss_default_allocation_step); - if (F_status_is_error(status)) return status; - } + if (range->start > range->stop || range->start >= object.used) { + status = private_fl_fss_destination_increase_by(slash_count, destination); + if (F_status_is_error(status)) break; while (slash_count > 0) { - destination->string[buffer_position.stop] = f_fss_delimit_slash; - buffer_position.stop++; + destination->string[destination->used++] = f_fss_delimit_slash; slash_count--; } // while break; } } - else if (object.string[range->start] == f_string_eol[0]) { - if (buffer_position.stop == buffer_position.start) { + else if (object.string[range->start] == f_fss_eol) { + if (destination->used == used_start) { return F_data_not_eol; } - break; + return F_none_eol; } if (object.string[range->start] != f_fss_delimit_placeholder) { - destination->string[buffer_position.stop] = object.string[range->start]; - buffer_position.stop++; + width = f_macro_utf_byte_width(object.string[range->start]); + + status = private_fl_fss_destination_increase_by(width, destination); + if (F_status_is_error(status)) break; + + for (i = 0; i < width; i++) { + destination->string[destination->used++] = object.string[range->start + i]; + } // for } status = f_utf_buffer_increment(object, range, 1); - if (F_status_is_error(status)) return status; + if (F_status_is_error(status)) break; } // while - destination->string[buffer_position.stop] = f_fss_basic_list_open; - destination->string[buffer_position.stop + 1] = f_string_eol[0]; - destination->used = buffer_position.stop + 2; + if (F_status_is_error(status)) { + destination->used = used_start; + return status; + } - if (range->start > range->stop) return F_none_stop; - else if (range->start >= object.used) return F_none_eos; + if (complete == f_fss_complete_partial || complete == f_fss_complete_full) { + destination->string[destination->used++] = f_fss_basic_list_open; + destination->string[destination->used++] = f_fss_eol; + } + + if (range->start > range->stop) { + return F_none_stop; + } + + if (range->start >= object.used) { + return F_none_eos; + } return F_none; } @@ -538,6 +557,7 @@ extern "C" { #ifndef _di_fl_fss_basic_list_content_write_ f_return_status fl_fss_basic_list_content_write(const f_string_static_t content, f_string_range_t *range, f_string_dynamic_t *destination) { #ifndef _di_level_1_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); if (!destination) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ diff --git a/level_1/fl_fss/c/fss_basic_list.h b/level_1/fl_fss/c/fss_basic_list.h index c327547..c061fd8 100644 --- a/level_1/fl_fss/c/fss_basic_list.h +++ b/level_1/fl_fss/c/fss_basic_list.h @@ -129,9 +129,10 @@ extern "C" { * * @param object * The string to write as (does not stop at NULLS, they are ignored and not written). - * @param quoted - * If 0, then double quotes are auto-inserted, when required. - * Otherwise, this is the type of quote to wrap the object in when writing. + * @param complete + * If f_fss_complete_none, then only the object name is written. + * If f_fss_complete_partial, this will write any appropriate open and close aspects of this object. + * If f_fss_complete_full, this will write any appropriate open and close aspects of this object. * @param range * The start/stop location within the object string to write as an object. * @param destination @@ -151,7 +152,7 @@ extern "C" { * Errors (with error bit) from: f_utf_buffer_increment(). */ #ifndef _di_fl_fss_basic_list_object_write_ - extern f_return_status fl_fss_basic_list_object_write(const f_string_static_t object, const f_fss_quote_t quoted, f_string_range_t *range, f_string_dynamic_t *destination); + extern f_return_status fl_fss_basic_list_object_write(const f_string_static_t object, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination); #endif // _di_fl_fss_basic_list_object_write_ /** @@ -171,6 +172,7 @@ extern "C" { * * @return * F_none on success. + * F_none_eol on success after reaching the end of the line. * F_none_eos on success after reaching the end of the buffer. * F_data_not_stop no data to write due start location being greater than stop location. * F_data_not_eos no data to write due start location being greater than or equal to buffer size. diff --git a/level_1/fl_fss/c/fss_extended.c b/level_1/fl_fss/c/fss_extended.c index edd1da3..f93a0f9 100644 --- a/level_1/fl_fss/c/fss_extended.c +++ b/level_1/fl_fss/c/fss_extended.c @@ -163,26 +163,20 @@ f_return_status fl_fss_extended_object_write(const f_string_static_t object, con if (!destination) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ - const f_status_t status = private_fl_fss_basic_object_write(object, quote ? quote : f_fss_delimit_quote_double, range, destination); + f_status_t status = private_fl_fss_basic_object_write(object, quote ? quote : f_fss_delimit_quote_double, range, destination); if (status == F_data_not_stop || status == F_data_not_eos) { // Objects cannot be empty, so write a quoted empty string. - const f_status_t status_allocation = private_fl_fss_destination_increase_by(2, destination); + const f_status_t status_allocation = private_fl_fss_destination_increase_by(3, destination); if (F_status_is_error(status_allocation)) return status_allocation; destination->string[destination->used++] = quote ? quote : f_fss_delimit_quote_double; destination->string[destination->used++] = quote ? quote : f_fss_delimit_quote_double; - - if (status == F_data_not_stop) { - return F_none_stop; - } - - return F_none_eos; } if (complete == f_fss_complete_partial || complete == f_fss_complete_full) { - if (status == F_none_stop || status == F_none_eos) { + if (status == F_none_stop || status == F_none_eos || status == F_data_not_stop || status == F_data_not_eos) { const f_status_t status_allocation = private_fl_fss_destination_increase(destination); if (F_status_is_error(status_allocation)) return status_allocation; @@ -207,6 +201,13 @@ f_return_status fl_fss_extended_object_write(const f_string_static_t object, con if (status == F_data_not_stop || status == F_data_not_eos) { f_status_t status_allocation = F_none; + // content that is empty must be represented by a quoted empty string. + status_allocation = private_fl_fss_destination_increase_by(3, destination); + if (F_status_is_error(status_allocation)) return status_allocation; + + destination->string[destination->used++] = quote ? quote : f_fss_delimit_quote_double; + destination->string[destination->used++] = quote ? quote : f_fss_delimit_quote_double; + // content should be terminated, even if empty. if (complete == f_fss_complete_partial || complete == f_fss_complete_full || complete == f_fss_complete_next) { status_allocation = private_fl_fss_destination_increase(destination); diff --git a/level_1/fl_fss/c/fss_extended.h b/level_1/fl_fss/c/fss_extended.h index 49aa5f2..4976456 100644 --- a/level_1/fl_fss/c/fss_extended.h +++ b/level_1/fl_fss/c/fss_extended.h @@ -152,12 +152,15 @@ extern "C" { * F_none_stop on success after reaching the range stop. * F_data_not_stop no data to write due start location being greater than stop location. * F_data_not_eos no data to write due start location being greater than or equal to buffer size. + * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete. * F_memory_reallocation (with error bit) on reallocation error. * F_none_eol (with error bit) after reaching an EOL, which is not supported by the standard. * F_parameter (with error bit) if a parameter is invalid. * F_string_too_large (with error bit) if appended string length is too large to store in the destination. + * F_utf (with error bit) is returned on failure to read/process a UTF-8 character. * * Errors (with error bit) from: f_fss_is_space(). + * Errors (with error bit) from: f_utf_buffer_increment(). */ #ifndef _di_fl_fss_extended_object_write_ extern f_return_status fl_fss_extended_object_write(const f_string_static_t object, const f_fss_quote_t quote, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination); @@ -191,12 +194,15 @@ extern "C" { * F_none_stop on success after reaching the range stop. * F_data_not_stop no data to write due start location being greater than stop location. * F_data_not_eos no data to write due start location being greater than or equal to buffer size. + * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete. * F_memory_reallocation (with error bit) on reallocation error. * F_none_eol (with error bit) after reaching an EOL, which is not supported by the standard. * F_parameter (with error bit) if a parameter is invalid. * F_string_too_large (with error bit) if appended string length is too large to store in the destination. + * F_utf (with error bit) is returned on failure to read/process a UTF-8 character. * * Errors (with error bit) from: f_fss_is_space(). + * Errors (with error bit) from: f_utf_buffer_increment(). */ #ifndef _di_fl_fss_extended_content_write_ extern f_return_status fl_fss_extended_content_write(const f_string_static_t content, const f_fss_quote_t quote, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination); diff --git a/level_1/fl_fss/c/fss_macro.h b/level_1/fl_fss/c/fss_macro.h index 69e3560..8364c63 100644 --- a/level_1/fl_fss/c/fss_macro.h +++ b/level_1/fl_fss/c/fss_macro.h @@ -26,12 +26,14 @@ extern "C" { #ifndef _di_fl_macro_fss_skip_past_delimit_placeholders_ #define fl_macro_fss_skip_past_delimit_placeholders(buffer, range) \ - while (buffer.string[range.start] == f_fss_delimit_placeholder) { \ - range.start++;\ - \ - if (range.start >= buffer.used) break; \ - if (range.start > range.stop) break; \ - } // while + if (buffer.used) { \ + while (buffer.string[range.start] == f_fss_delimit_placeholder) { \ + range.start++;\ + \ + if (range.start >= buffer.used) break; \ + if (range.start > range.stop) break; \ + } \ + } #endif // _di_fl_macro_fss_skip_past_delimit_placeholders_ #ifndef _di_fl_macro_fss_object_return_on_overflow_ diff --git a/level_1/fl_fss/c/private-fss.c b/level_1/fl_fss/c/private-fss.c index 290dec8..94ba99e 100644 --- a/level_1/fl_fss/c/private-fss.c +++ b/level_1/fl_fss/c/private-fss.c @@ -532,7 +532,9 @@ extern "C" { quoted = F_true; } - for (; range->start <= range->stop && range->start < object.used; range->start++) { + uint8_t width = 0; + + for (; range->start <= range->stop && range->start < object.used; ) { if (object.string[range->start] == f_fss_delimit_slash) { item_first = range->start++; @@ -614,7 +616,15 @@ extern "C" { } // for destination->string[destination->used++] = quote; - destination->string[destination->used++] = object.string[range->start]; + + width = f_macro_utf_byte_width(object.string[range->start]); + + status = private_fl_fss_destination_increase_by(width, destination); + if (F_status_is_error(status)) break; + + for (i = 0; i < width; i++) { + destination->string[destination->used++] = object.string[range->start + i]; + } // for } else { @@ -631,7 +641,14 @@ extern "C" { destination->string[destination->used++] = f_fss_delimit_slash; } // for - destination->string[destination->used++] = object.string[range->start]; + width = f_macro_utf_byte_width(object.string[range->start]); + + status = private_fl_fss_destination_increase_by(width, destination); + if (F_status_is_error(status)) break; + + for (i = 0; i < width; i++) { + destination->string[destination->used++] = object.string[range->start + i]; + } // for } } else if (object.string[range->start] == quote) { @@ -652,8 +669,7 @@ extern "C" { if (object.string[range->start] == quote) { destination->string[destination->used++] = quote; - // the next quote must also be checked. - range->start--; + // the next quote must also be checked, so do not increment. continue; } @@ -673,7 +689,15 @@ extern "C" { } destination->string[destination->used++] = quote; - destination->string[destination->used++] = object.string[range->start]; + + width = f_macro_utf_byte_width(object.string[range->start]); + + status = private_fl_fss_destination_increase_by(width, destination); + if (F_status_is_error(status)) break; + + for (i = 0; i < width; i++) { + destination->string[destination->used++] = object.string[range->start + i]; + } // for } else if (object.string[range->start] == f_fss_eol) { status = F_status_set_error(F_none_eol); @@ -690,8 +714,18 @@ extern "C" { } } - destination->string[destination->used++] = object.string[range->start]; + width = f_macro_utf_byte_width(object.string[range->start]); + + status = private_fl_fss_destination_increase_by(width, destination); + if (F_status_is_error(status)) break; + + for (i = 0; i < width; i++) { + destination->string[destination->used++] = object.string[range->start + i]; + } // for } + + status = f_utf_buffer_increment(object, range, 1); + if (F_status_is_error(status)) break; } // for if (F_status_is_error(status)) { @@ -737,7 +771,7 @@ extern "C" { } #endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) -#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) +#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) f_return_status private_fl_fss_destination_increase(f_string_dynamic_t *destination) { f_status_t status = F_none; @@ -756,9 +790,9 @@ extern "C" { return status; } -#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) +#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) -#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) +#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) f_return_status private_fl_fss_destination_increase_by(const f_string_length_t amount, f_string_dynamic_t *destination) { f_status_t status = F_none; @@ -772,7 +806,7 @@ extern "C" { return status; } -#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) +#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) #ifdef __cplusplus } // extern "C" diff --git a/level_1/fl_fss/c/private-fss.h b/level_1/fl_fss/c/private-fss.h index 6f62640..94a47c8 100644 --- a/level_1/fl_fss/c/private-fss.h +++ b/level_1/fl_fss/c/private-fss.h @@ -89,10 +89,14 @@ extern "C" { * F_none_stop on success after reaching the range stop. * F_data_not_stop no data to write due start location being greater than stop location. * F_data_not_eos no data to write due start location being greater than or equal to buffer size. + * F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete. * F_memory_reallocation (with error bit) on reallocation error. * F_none_eol (with error bit) after reaching an EOL, which is not supported by the standard. * F_parameter (with error bit) if a parameter is invalid. * F_string_too_large (with error bit) if appended string length is too large to store in the destination. + * F_utf (with error bit) is returned on failure to read/process a UTF-8 character. + * + * Errors (with error bit) from: f_utf_buffer_increment(). * * @see fl_fss_basic_object_write() * @see fl_fss_extended_object_write() @@ -115,12 +119,13 @@ extern "C" { * * @see fl_fss_basic_object_write() * @see fl_fss_basic_content_write() + * @see fl_fss_basic_list_object_write() * @see fl_fss_extended_object_write() * @see fl_fss_extended_content_write() */ -#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) +#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) extern f_return_status private_fl_fss_destination_increase(f_string_dynamic_t *destination) f_gcc_attribute_visibility_internal; -#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) +#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) /** * Increase the size of destination buffer by the given amount, but only if necessary. @@ -137,12 +142,13 @@ extern "C" { * * @see fl_fss_basic_object_write() * @see fl_fss_basic_content_write() + * @see fl_fss_basic_list_object_write() * @see fl_fss_extended_object_write() * @see fl_fss_extended_content_write() */ -#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) +#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) f_return_status private_fl_fss_destination_increase_by(const f_string_length_t amount, f_string_dynamic_t *destination); -#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) +#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) #ifdef __cplusplus } // extern "C" diff --git a/level_2/fll_fss/c/fss_basic.c b/level_2/fll_fss/c/fss_basic.c index 1b75d7c..9ba467d 100644 --- a/level_2/fll_fss/c/fss_basic.c +++ b/level_2/fll_fss/c/fss_basic.c @@ -187,7 +187,7 @@ extern "C" { } } - return F_none; + return status; } #endif // _di_fll_fss_basic_write_ diff --git a/level_2/fll_fss/c/fss_basic_list.c b/level_2/fll_fss/c/fss_basic_list.c index 0158aa3..eee66b3 100644 --- a/level_2/fll_fss/c/fss_basic_list.c +++ b/level_2/fll_fss/c/fss_basic_list.c @@ -134,48 +134,30 @@ extern "C" { #endif // _di_fll_fss_basic_list_read_ #ifndef _di_fll_fss_basic_list_write_ - f_return_status fll_fss_basic_list_write(const f_string_static_t object, const f_string_statics_t contents, const f_fss_quote_t quoted, f_string_dynamic_t *buffer) { + f_return_status fll_fss_basic_list_write(const f_string_static_t object, const f_string_statics_t contents, f_string_dynamic_t *destination) { #ifndef _di_level_2_parameter_checking_ - if (!buffer) return F_status_set_error(F_parameter); - if (contents.used > contents.size) return F_status_set_error(F_parameter); + if (!destination) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ f_status_t status = 0; - f_array_length_t current = 0; - f_string_range_t range = f_string_range_t_initialize; - - range.start = 0; - range.stop = object.used - 1; + f_string_range_t range = f_macro_string_range_t_initialize(object.used); - status = fl_fss_basic_list_object_write(object, quoted, &range, buffer); + status = fl_fss_basic_list_object_write(object, f_fss_complete_full, &range, destination); if (F_status_is_error(status) || status == F_data_not_stop || status == F_data_not_eos) { return status; } if (status == F_none || status == F_none_stop || status == F_none_eos || status == F_none_eol) { - if (contents.used > 0) { + if (contents.used && contents.array[0].used) { range.start = 0; range.stop = contents.array[0].used - 1; - status = fl_fss_basic_list_content_write(contents.array[0], &range, buffer); - - if (F_status_is_error(status) || status == F_data_not_stop || status == F_data_not_eos) { - return status; - } - } - else { - if (buffer->used == buffer->size) { - status = fl_string_dynamic_size_increase(f_fss_default_allocation_step, buffer); - if (F_status_is_error(status)) return status; - } - - buffer->string[buffer->used] = f_string_eol[0]; - buffer->used++; + status = fl_fss_basic_list_content_write(contents.array[0], &range, destination); } } - return F_none; + return status; } #endif // _di_fll_fss_basic_list_write_ diff --git a/level_2/fll_fss/c/fss_basic_list.h b/level_2/fll_fss/c/fss_basic_list.h index 9742bff..7e600b8 100644 --- a/level_2/fll_fss/c/fss_basic_list.h +++ b/level_2/fll_fss/c/fss_basic_list.h @@ -67,9 +67,6 @@ extern "C" { * A string representing the object. * @param contents * An array of strings representing multiple content to write. - * @param quoted - * If 0, then double quotes are auto-inserted, when required. - * Otherwise, this is the type of quote to wrap the object in when writing. * @param buffer * The buffer to write to. * @@ -89,7 +86,7 @@ extern "C" { * Errors (with error bit) from: fl_string_dynamic_size_increase(). */ #ifndef _di_fll_fss_basic_list_write_ - extern f_return_status fll_fss_basic_list_write(const f_string_static_t object, const f_string_statics_t contents, const f_fss_quote_t quoted, f_string_dynamic_t *buffer); + extern f_return_status fll_fss_basic_list_write(const f_string_static_t object, const f_string_statics_t contents, f_string_dynamic_t *buffer); #endif // _di_fll_fss_basic_list_write_ #ifdef __cplusplus diff --git a/level_2/fll_fss/c/fss_extended.c b/level_2/fll_fss/c/fss_extended.c index ce1b93a..98765e4 100644 --- a/level_2/fll_fss/c/fss_extended.c +++ b/level_2/fll_fss/c/fss_extended.c @@ -214,8 +214,14 @@ extern "C" { complete = f_fss_complete_end; } - range.start = 0; - range.stop = contents.array[i].used - 1; + if (contents.array[i].used) { + range.start = 0; + range.stop = contents.array[i].used - 1; + } + else { + range.start = 1; + range.stop = 0; + } status = fl_fss_extended_content_write(contents.array[i], quote, complete, &range, destination); @@ -225,7 +231,7 @@ extern "C" { } // for } - return F_none; + return status; } #endif // _di_fll_fss_extended_write_ diff --git a/level_3/fss_basic_list_write/c/fss_basic_list_write.c b/level_3/fss_basic_list_write/c/fss_basic_list_write.c index 9a26781..4bff84c 100644 --- a/level_3/fss_basic_list_write/c/fss_basic_list_write.c +++ b/level_3/fss_basic_list_write/c/fss_basic_list_write.c @@ -31,6 +31,28 @@ extern "C" { fll_program_print_help_usage(file, context, fss_basic_list_write_name, ""); + printf(" The pipe uses the NULL character '"); + fl_color_print(f_type_output, context.set.notable, "\\0"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+0000"); + printf(") to designate the start of a Content and uses the Form Feed character '"); + fl_color_print(f_type_output, context.set.notable, "\\f"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+000C"); + printf(") to designate the end of the last Content.%c", f_string_eol[0]); + printf(" For the pipe, an Object is terminated by either a NULL character '"); + fl_color_print(f_type_output, context.set.notable, "\\0"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+0000"); + printf(") or a Form Feed character '"); + fl_color_print(f_type_output, context.set.notable, "\\f"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+000C"); + printf(").%c", f_string_eol[0]); + printf(" The end of the pipe represents the end of any Object or Content.%c", f_string_eol[0]); + + printf("%c", f_string_eol[0]); + return F_none; } #endif // _di_fss_basic_list_write_print_help_ @@ -111,6 +133,7 @@ extern "C" { if (data->parameters[fss_basic_list_write_parameter_file].result == f_console_result_additional) { if (data->parameters[fss_basic_list_write_parameter_file].additional.used > 1) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_file); fl_color_print(data->error.to.stream, data->context.set.error, "' may only be specified once.%c", f_string_eol[0]); @@ -154,6 +177,7 @@ extern "C" { else if (data->parameters[fss_basic_list_write_parameter_content].locations.used && data->parameters[fss_basic_list_write_parameter_partial].locations.used) { if (data->parameters[fss_basic_list_write_parameter_content].result == f_console_result_additional) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_partial); fl_color_print(data->error.to.stream, data->context.set.error, "' parameter only allows either the '"); @@ -181,11 +205,14 @@ extern "C" { location_sub_content = data->parameters[fss_basic_list_write_parameter_content].locations_sub.array[i]; if (location_object > location_content || location_object == location_content && location_sub_object > location_sub_content) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_object); - fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must be specified before a '"); - fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_content); - fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_object); + fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must be specified before a '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_content); + fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]); + } status = F_status_set_error(F_parameter); break; @@ -207,6 +234,7 @@ extern "C" { } else if (!data->process_pipe) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThis requires either piped data or the use of the '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_object); fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '"); @@ -220,6 +248,7 @@ extern "C" { if (F_status_is_error_not(status) && data->process_pipe) { if (data->parameters[fss_basic_list_write_parameter_partial].result == f_console_result_found) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_partial); fl_color_print(data->error.to.stream, data->context.set.error, "' parameter cannot be used when processing a pipe.%c", f_string_eol[0]); @@ -256,9 +285,12 @@ extern "C" { status = fss_basic_list_write_process_pipe(*data, output, quote, &buffer); if (F_status_is_error(status)) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "input pipe"); - fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "input pipe"); + fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + } } } @@ -305,9 +337,12 @@ extern "C" { } if (F_status_is_error(status)) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "input arguments"); - fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "input arguments"); + fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + } } else if (data->error.verbosity != f_console_verbosity_quiet && data->parameters[fss_basic_list_write_parameter_file].result == f_console_result_none) { // ensure there is always a newline at the end, unless in quiet mode. diff --git a/level_3/fss_basic_list_write/c/private-fss_basic_list_write.c b/level_3/fss_basic_list_write/c/private-fss_basic_list_write.c index a189661..95324ee 100644 --- a/level_3/fss_basic_list_write/c/private-fss_basic_list_write.c +++ b/level_3/fss_basic_list_write/c/private-fss_basic_list_write.c @@ -12,6 +12,7 @@ extern "C" { return; } + fprintf(data.error.to.stream, "%c", f_string_eol[0]); fl_color_print(data.error.to.stream, data.context.set.error, "%sMust specify both the '", fll_error_print_error); fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_object); fl_color_print(data.error.to.stream, data.context.set.error, "' parameter and the '"); @@ -29,6 +30,7 @@ extern "C" { return; } + fprintf(data.error.to.stream, "%c", f_string_eol[0]); fl_color_print(data.error.to.stream, data.context.set.error, "%sThe parameter '", fll_error_print_error); fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", symbol, parameter); fl_color_print(data.error.to.stream, data.context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]); @@ -51,27 +53,17 @@ extern "C" { range.stop = 0; } - status = fl_fss_basic_list_object_write(*object, quote, &range, buffer); + status = fl_fss_basic_list_object_write(*object, content ? f_fss_complete_full : f_fss_complete_partial, &range, buffer); - if (status == F_data_not_stop || status == F_data_not_eos) { - fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard requires an object.%c", fll_error_print_error, f_string_eol[0]); - return F_status_set_error(status); - } - else if (F_status_is_error(status)) { + if (F_status_is_error(status)) { fll_error_print(data.error, F_status_set_fine(status), "fl_fss_basic_list_object_write", F_true); return status; } } - if (content) { - if (content->used) { - range.start = 0; - range.stop = content->used - 1; - } - else { - range.start = 1; - range.stop = 0; - } + if (content && content->used) { + range.start = 0; + range.stop = content->used - 1; status = fl_fss_basic_list_content_write(*content, &range, buffer); @@ -125,6 +117,8 @@ extern "C" { break; } + if (!block.used) break; + range.start = 0; range.stop = block.used - 1; } @@ -154,20 +148,26 @@ extern "C" { break; } + if (block.string[range.start] == fss_basic_list_write_pipe_content_end) { + state = 0x3; + range.start++; + break; + } + object.string[object.used++] = block.string[range.start]; } // for if (F_status_is_error(status)) break; // if the start of content was not found, then fetch the next block. - if (state != 0x2) continue; + if (state == 0x1) continue; // if the end of the current block is reached, fetch the next block. if (range.start > range.stop) continue; } if (state == 0x2) { - if (block.used && range.start <= range.stop) { + if (range.start <= range.stop) { total = (range.stop - range.start) + 1; } else { @@ -187,12 +187,16 @@ extern "C" { for (; range.start <= range.stop; range.start++) { if (block.string[range.start] == fss_basic_list_write_pipe_content_start) { - fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard only supports one content per object.%c", fll_error_print_error, f_string_eol[0]); + if (data.error.verbosity != f_console_verbosity_quiet) { + fprintf(data.error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard only supports one content per object.%c", fll_error_print_error, f_string_eol[0]); + } status = F_status_set_error(F_unsupported); break; } - else if (block.string[range.start] == fss_basic_list_write_pipe_content_end) { + + if (block.string[range.start] == fss_basic_list_write_pipe_content_end) { state = 0x3; range.start++; break; @@ -217,7 +221,7 @@ extern "C" { } // for // if the pipe ended before finishing, then attempt to wrap up. - if (status_pipe == F_none_eof && state) { + if (F_status_is_error_not(status) && status_pipe == F_none_eof && state) { status = fss_basic_list_write_process(data, output, quote, &object, &content, buffer); } diff --git a/level_3/fss_basic_write/c/fss_basic_write.c b/level_3/fss_basic_write/c/fss_basic_write.c index a0e7889..fc170ba 100644 --- a/level_3/fss_basic_write/c/fss_basic_write.c +++ b/level_3/fss_basic_write/c/fss_basic_write.c @@ -31,6 +31,28 @@ extern "C" { fll_program_print_help_usage(file, context, fss_basic_write_name, ""); + printf(" The pipe uses the NULL character '"); + fl_color_print(f_type_output, context.set.notable, "\\0"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+0000"); + printf(") to designate the start of a Content and uses the Form Feed character '"); + fl_color_print(f_type_output, context.set.notable, "\\f"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+000C"); + printf(") to designate the end of the last Content.%c", f_string_eol[0]); + printf(" For the pipe, an Object is terminated by either a NULL character '"); + fl_color_print(f_type_output, context.set.notable, "\\0"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+0000"); + printf(") or a Form Feed character '"); + fl_color_print(f_type_output, context.set.notable, "\\f"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+000C"); + printf(").%c", f_string_eol[0]); + printf(" The end of the pipe represents the end of any Object or Content.%c", f_string_eol[0]); + + printf("%c", f_string_eol[0]); + return F_none; } #endif // _di_fss_basic_write_print_help_ @@ -111,6 +133,7 @@ extern "C" { if (data->parameters[fss_basic_write_parameter_file].result == f_console_result_additional) { if (data->parameters[fss_basic_write_parameter_file].additional.used > 1) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_file); fl_color_print(data->error.to.stream, data->context.set.error, "' may only be specified once.%c", f_string_eol[0]); @@ -154,6 +177,7 @@ extern "C" { else if (data->parameters[fss_basic_write_parameter_content].locations.used && data->parameters[fss_basic_write_parameter_partial].locations.used) { if (data->parameters[fss_basic_write_parameter_content].result == f_console_result_additional) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_partial); fl_color_print(data->error.to.stream, data->context.set.error, "' parameter only allows either the '"); @@ -181,11 +205,14 @@ extern "C" { location_sub_content = data->parameters[fss_basic_write_parameter_content].locations_sub.array[i]; if (location_object > location_content || location_object == location_content && location_sub_object > location_sub_content) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_object); - fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must be specified before a '"); - fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_content); - fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_object); + fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must be specified before a '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_content); + fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]); + } status = F_status_set_error(F_parameter); break; @@ -207,6 +234,7 @@ extern "C" { } else if (!data->process_pipe) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThis requires either piped data or the use of the '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_object); fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '"); @@ -220,6 +248,7 @@ extern "C" { if (F_status_is_error_not(status) && data->process_pipe) { if (data->parameters[fss_basic_write_parameter_partial].result == f_console_result_found) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_partial); fl_color_print(data->error.to.stream, data->context.set.error, "' parameter cannot be used when processing a pipe.%c", f_string_eol[0]); @@ -256,9 +285,12 @@ extern "C" { status = fss_basic_write_process_pipe(*data, output, quote, &buffer); if (F_status_is_error(status)) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "input pipe"); - fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "input pipe"); + fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + } } } @@ -308,9 +340,12 @@ extern "C" { } if (F_status_is_error(status)) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "input arguments"); - fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "input arguments"); + fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + } } else if (data->error.verbosity != f_console_verbosity_quiet && data->parameters[fss_basic_write_parameter_file].result == f_console_result_none) { // ensure there is always a newline at the end, unless in quiet mode. diff --git a/level_3/fss_basic_write/c/private-fss_basic_write.c b/level_3/fss_basic_write/c/private-fss_basic_write.c index e05b2d1..6005c6f 100644 --- a/level_3/fss_basic_write/c/private-fss_basic_write.c +++ b/level_3/fss_basic_write/c/private-fss_basic_write.c @@ -12,6 +12,7 @@ extern "C" { return; } + fprintf(data.error.to.stream, "%c", f_string_eol[0]); fl_color_print(data.error.to.stream, data.context.set.error, "%sMust specify both the '", fll_error_print_error); fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_object); fl_color_print(data.error.to.stream, data.context.set.error, "' parameter and the '"); @@ -29,12 +30,27 @@ extern "C" { return; } + fprintf(data.error.to.stream, "%c", f_string_eol[0]); fl_color_print(data.error.to.stream, data.context.set.error, "%sThe parameter '", fll_error_print_error); fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", symbol, parameter); fl_color_print(data.error.to.stream, data.context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]); } #endif // _di_fss_basic_write_error_parameter_value_missing_print_ +#ifndef _di_fss_basic_write_error_parameter_unsupported_eol_print_ + void fss_basic_write_error_parameter_unsupported_eol_print(const fss_basic_write_data_t data) { + + if (data.error.verbosity == f_console_verbosity_quiet) { + return; + } + + fprintf(data.error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard does not support end of line character '", fll_error_print_error); + fl_color_print(data.error.to.stream, data.context.set.notable, "\\n"); + fl_color_print(data.error.to.stream, data.context.set.error, "'.%c", f_string_eol[0]); + } +#endif // _di_fss_basic_write_error_parameter_unsupported_eol_print_ + #ifndef _di_fss_basic_write_process_ f_return_status fss_basic_write_process(const fss_basic_write_data_t data, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) { f_status_t status = F_none; @@ -54,19 +70,13 @@ extern "C" { status = fl_fss_basic_object_write(*object, quote, content ? f_fss_complete_full : f_fss_complete_partial, &range, buffer); if (F_status_set_fine(status) == F_none_eol) { - fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard does not support end of line character '", fll_error_print_error); - fl_color_print(data.error.to.stream, data.context.set.notable, "\\n"); - fl_color_print(data.error.to.stream, data.context.set.error, "'.%c", f_string_eol[0]); + fss_basic_write_error_parameter_unsupported_eol_print(data); return F_status_set_error(F_unsupported); } - if (status == F_data_not_stop || status == F_data_not_eos) { - fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard requires an object.%c", fll_error_print_error, f_string_eol[0]); - return F_status_set_error(status); - } - else if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_fss_basic_list_object_write", F_true); + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "fl_fss_basic_object_write", F_true); return status; } } @@ -83,6 +93,12 @@ extern "C" { status = fl_fss_basic_content_write(*content, object ? f_fss_complete_full : f_fss_complete_partial, &range, buffer); + if (F_status_set_fine(status) == F_none_eol) { + fss_basic_write_error_parameter_unsupported_eol_print(data); + + return F_status_set_error(F_unsupported); + } + if (F_status_is_error(status)) { fll_error_print(data.error, F_status_set_fine(status), "fl_fss_basic_content_write", F_true); return status; @@ -93,7 +109,7 @@ extern "C" { status = fl_string_append(f_string_eol, 1, buffer); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_fss_basic_content_write", F_true); + fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true); return status; } } @@ -142,6 +158,8 @@ extern "C" { break; } + if (!block.used) break; + range.start = 0; range.stop = block.used - 1; } @@ -171,20 +189,26 @@ extern "C" { break; } + if (block.string[range.start] == fss_basic_write_pipe_content_end) { + state = 0x3; + range.start++; + break; + } + object.string[object.used++] = block.string[range.start]; } // for if (F_status_is_error(status)) break; // if the start of content was not found, then fetch the next block. - if (state != 0x2) continue; + if (state == 0x1) continue; // if the end of the current block is reached, fetch the next block. if (range.start > range.stop) continue; } if (state == 0x2) { - if (block.used && range.start <= range.stop) { + if (range.start <= range.stop) { total = (range.stop - range.start) + 1; } else { @@ -204,7 +228,10 @@ extern "C" { for (; range.start <= range.stop; range.start++) { if (block.string[range.start] == fss_basic_write_pipe_content_start) { - fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard only supports one content per object.%c", fll_error_print_error, f_string_eol[0]); + if (data.error.verbosity != f_console_verbosity_quiet) { + fprintf(data.error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard only supports one content per object.%c", fll_error_print_error, f_string_eol[0]); + } status = F_status_set_error(F_unsupported); break; @@ -214,6 +241,12 @@ extern "C" { range.start++; break; } + else if (F_status_set_fine(status) == F_none_eol) { + fss_basic_write_error_parameter_unsupported_eol_print(data); + + status = F_status_set_error(F_unsupported); + break; + } content.string[content.used++] = block.string[range.start]; } // for @@ -234,7 +267,7 @@ extern "C" { } // for // if the pipe ended before finishing, then attempt to wrap up. - if (status_pipe == F_none_eof && state) { + if (F_status_is_error_not(status) && status_pipe == F_none_eof && state) { status = fss_basic_write_process(data, output, quote, &object, &content, buffer); } diff --git a/level_3/fss_basic_write/c/private-fss_basic_write.h b/level_3/fss_basic_write/c/private-fss_basic_write.h index ad3f60d..768479b 100644 --- a/level_3/fss_basic_write/c/private-fss_basic_write.h +++ b/level_3/fss_basic_write/c/private-fss_basic_write.h @@ -45,6 +45,20 @@ extern "C" { #endif // _di_fss_basic_write_error_parameter_value_missing_print_ /** + * Print an message about a parameter EOL being unsupported. + * + * @param data + * The program data. + * + * @return + * F_none on success. + * F_failure (with error bit) for any othe failure. + */ +#ifndef _di_fss_basic_write_error_parameter_unsupported_eol_print_ + void fss_basic_write_error_parameter_unsupported_eol_print(const fss_basic_write_data_t data) f_gcc_attribute_visibility_internal; +#endif // _di_fss_basic_write_error_parameter_unsupported_eol_print_ + +/** * Process a given object and content, printing the FSS if valid or an error if invalid. * * @param data diff --git a/level_3/fss_extended_write/c/fss_extended_write.c b/level_3/fss_extended_write/c/fss_extended_write.c index e7efbf5..7c4a2e7 100644 --- a/level_3/fss_extended_write/c/fss_extended_write.c +++ b/level_3/fss_extended_write/c/fss_extended_write.c @@ -31,6 +31,28 @@ extern "C" { fll_program_print_help_usage(file, context, fss_extended_write_name, ""); + printf(" The pipe uses the NULL character '"); + fl_color_print(f_type_output, context.set.notable, "\\0"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+0000"); + printf(") to designate the start of a Content and uses the Form Feed character '"); + fl_color_print(f_type_output, context.set.notable, "\\f"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+000C"); + printf(") to designate the end of the last Content.%c", f_string_eol[0]); + printf(" For the pipe, an Object is terminated by either a NULL character '"); + fl_color_print(f_type_output, context.set.notable, "\\0"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+0000"); + printf(") or a Form Feed character '"); + fl_color_print(f_type_output, context.set.notable, "\\f"); + printf("' ("); + fl_color_print(f_type_output, context.set.notable, "U+000C"); + printf(").%c", f_string_eol[0]); + printf(" The end of the pipe represents the end of any Object or Content.%c", f_string_eol[0]); + + printf("%c", f_string_eol[0]); + return F_none; } #endif // _di_fss_extended_write_print_help_ @@ -111,6 +133,7 @@ extern "C" { if (data->parameters[fss_extended_write_parameter_file].result == f_console_result_additional) { if (data->parameters[fss_extended_write_parameter_file].additional.used > 1) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_file); fl_color_print(data->error.to.stream, data->context.set.error, "' may only be specified once.%c", f_string_eol[0]); @@ -154,6 +177,7 @@ extern "C" { else if (data->parameters[fss_extended_write_parameter_content].locations.used && data->parameters[fss_extended_write_parameter_partial].locations.used) { if (data->parameters[fss_extended_write_parameter_content].result == f_console_result_additional) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_partial); fl_color_print(data->error.to.stream, data->context.set.error, "' parameter only allows either the '"); @@ -175,11 +199,14 @@ extern "C" { f_array_length_t location_sub_content = data->parameters[fss_extended_write_parameter_content].locations_sub.array[0]; if (location_object > location_content || location_object == location_content && location_sub_object > location_sub_content) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_object); - fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must be specified before a '"); - fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_content); - fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_object); + fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must be specified before a '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_content); + fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]); + } status = F_status_set_error(F_parameter); } @@ -190,11 +217,14 @@ extern "C" { location_sub_content = data->parameters[fss_extended_write_parameter_content].locations_sub.array[data->parameters[fss_extended_write_parameter_content].locations_sub.used - 1]; if (location_object > location_content || location_object == location_content && location_sub_object > location_sub_content) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_object); - fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must have at least one '"); - fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_content); - fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_object); + fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must have at least one '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_content); + fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]); + } status = F_status_set_error(F_parameter); } @@ -215,6 +245,7 @@ extern "C" { } else if (!data->process_pipe) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThis requires either piped data or the use of the '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_object); fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '"); @@ -228,6 +259,7 @@ extern "C" { if (F_status_is_error_not(status) && data->process_pipe) { if (data->parameters[fss_extended_write_parameter_partial].result == f_console_result_found) { if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error); fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_partial); fl_color_print(data->error.to.stream, data->context.set.error, "' parameter cannot be used when processing a pipe.%c", f_string_eol[0]); @@ -264,9 +296,12 @@ extern "C" { status = fss_extended_write_process_pipe(*data, output, quote, &buffer); if (F_status_is_error(status)) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "input pipe"); - fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "input pipe"); + fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + } } } @@ -368,9 +403,12 @@ extern "C" { } if (F_status_is_error(status)) { - fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); - fl_color_print(data->error.to.stream, data->context.set.notable, "input arguments"); - fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error); + fl_color_print(data->error.to.stream, data->context.set.notable, "input arguments"); + fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]); + } } else if (data->error.verbosity != f_console_verbosity_quiet && data->parameters[fss_extended_write_parameter_file].result == f_console_result_none) { // ensure there is always a newline at the end, unless in quiet mode. diff --git a/level_3/fss_extended_write/c/private-fss_extended_write.c b/level_3/fss_extended_write/c/private-fss_extended_write.c index d03d49c..425b8f9 100644 --- a/level_3/fss_extended_write/c/private-fss_extended_write.c +++ b/level_3/fss_extended_write/c/private-fss_extended_write.c @@ -12,6 +12,7 @@ extern "C" { return; } + fprintf(data.error.to.stream, "%c", f_string_eol[0]); fl_color_print(data.error.to.stream, data.context.set.error, "%sMust specify the '", fll_error_print_error); fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_object); fl_color_print(data.error.to.stream, data.context.set.error, "' parameter at least once and the '"); @@ -29,12 +30,27 @@ extern "C" { return; } + fprintf(data.error.to.stream, "%c", f_string_eol[0]); fl_color_print(data.error.to.stream, data.context.set.error, "%sThe parameter '", fll_error_print_error); fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", symbol, parameter); fl_color_print(data.error.to.stream, data.context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]); } #endif // _di_fss_extended_write_error_parameter_value_missing_print_ +#ifndef _di_fss_extended_write_error_parameter_unsupported_eol_print_ + void fss_extended_write_error_parameter_unsupported_eol_print(const fss_extended_write_data_t data) { + + if (data.error.verbosity == f_console_verbosity_quiet) { + return; + } + + fprintf(data.error.to.stream, "%c", f_string_eol[0]); + fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard does not support end of line character '", fll_error_print_error); + fl_color_print(data.error.to.stream, data.context.set.notable, "\\n"); + fl_color_print(data.error.to.stream, data.context.set.error, "'.%c", f_string_eol[0]); + } +#endif // _di_fss_extended_write_error_parameter_unsupported_eol_print_ + #ifndef _di_fss_extended_write_process_ f_return_status fss_extended_write_process(const fss_extended_write_data_t data, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_statics_t *contents, f_string_dynamic_t *buffer) { f_status_t status = F_none; @@ -51,37 +67,56 @@ extern "C" { range.stop = 0; } - status = fl_fss_extended_object_write(*object, quote, contents ? f_fss_complete_full : f_fss_complete_partial, &range, buffer); + status = fl_fss_extended_object_write(*object, quote, contents && contents->used ? f_fss_complete_full : f_fss_complete_partial, &range, buffer); - if (status == F_data_not_stop || status == F_data_not_eos) { - fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard requires an object.%c", fll_error_print_error, f_string_eol[0]); - return F_status_set_error(status); + if (F_status_set_fine(status) == F_none_eol) { + fss_extended_write_error_parameter_unsupported_eol_print(data); + + return F_status_set_error(F_unsupported); } - else if (F_status_is_error(status)) { + + if (F_status_is_error(status)) { fll_error_print(data.error, F_status_set_fine(status), "fl_fss_extended_object_write", F_true); return F_status_set_error(status); } } if (contents) { - for (f_array_length_t i = 0; i < contents->used; i++) { + if (contents->used) { + for (f_array_length_t i = 0; i < contents->used; i++) { - if (contents->used) { - range.start = 0; - range.stop = contents->array[i].used - 1; - } - else { - range.start = 1; - range.stop = 0; - } + if (contents->array[i].used) { + range.start = 0; + range.stop = contents->array[i].used - 1; + } + else { + range.start = 1; + range.stop = 0; + } + + status = fl_fss_extended_content_write(contents->array[i], quote, i + 1 < contents->used ? f_fss_complete_next : f_fss_complete_end, &range, buffer); + + if (F_status_set_fine(status) == F_none_eol) { + fss_extended_write_error_parameter_unsupported_eol_print(data); + + return F_status_set_error(F_unsupported); + } - status = fl_fss_extended_content_write(contents->array[i], quote, i + 1 < contents->used ? f_fss_complete_next : f_fss_complete_end, &range, buffer); + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "fl_fss_extended_content_write", F_true); + return F_status_set_error(status); + } + } // for + } + else { + // objects in this standard do not have EOL, so add an EOL for printing purposes when there is no desired content. + status = fl_string_append(f_string_eol, 1, buffer); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_fss_extended_content_write", F_true); - return F_status_set_error(status); + fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true); + return status; } - } // for + } } f_print_dynamic(output.stream, *buffer); @@ -101,6 +136,8 @@ extern "C" { input.id = f_type_descriptor_input; input.size_read = 2048; + f_array_length_t i = 0; + f_string_length_t total = 0; f_string_length_t previous = 0; f_string_range_t range = f_string_range_t_initialize; @@ -109,7 +146,7 @@ extern "C" { f_string_dynamic_t object = f_string_dynamic_t_initialize; f_string_dynamics_t contents = f_string_dynamics_t_initialize; - // 0x0 = start new object/content set, 0x1 = processing object, 0x2 = processing content, 0x3 = end object/content set. + // 0x0 = start new object/content set, 0x1 = processing object, 0x2 = new individual content, 0x3 = processing content, 0x4 = end object/content set. uint8_t state = 0; for (;;) { @@ -128,12 +165,20 @@ extern "C" { break; } + if (!block.used) break; + range.start = 0; range.stop = block.used - 1; } if (!state || state == 0x1) { if (!state) { + if (contents.used) { + for (i = 0; i < contents.used; i++) { + contents.array[i].used = 0; + } // for + } + object.used = 0; contents.used = 0; @@ -157,20 +202,40 @@ extern "C" { break; } + if (block.string[range.start] == fss_extended_write_pipe_content_end) { + state = 0x4; + range.start++; + break; + } + object.string[object.used++] = block.string[range.start]; } // for if (F_status_is_error(status)) break; // if the start of content was not found, then fetch the next block. - if (state != 0x2) continue; + if (state == 0x1) continue; // if the end of the current block is reached, fetch the next block. if (range.start > range.stop) continue; } if (state == 0x2) { - if (block.used && range.start <= range.stop) { + if (contents.used + 1 > contents.size) { + status = fl_string_dynamics_size_increase(f_fss_default_allocation_step, &contents); + + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamics_size_increase", F_true); + break; + } + } + + state = 0x3; + contents.used++; + } + + if (state == 0x3) { + if (range.start <= range.stop) { total = (range.stop - range.start) + 1; } else { @@ -181,31 +246,32 @@ extern "C" { for (; range.start <= range.stop; range.start++) { if (block.string[range.start] == fss_extended_write_pipe_content_start) { - contents.used++; + if (contents.used + 1 > contents.size) { + status = fl_string_dynamics_size_increase(f_fss_default_allocation_step, &contents); - if (contents.used < contents.size && contents.array[contents.used].used) { - contents.array[contents.used].used = 0; + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamics_size_increase", F_true); + break; + } } + contents.used++; continue; } else if (block.string[range.start] == fss_extended_write_pipe_content_end) { - state = 0x3; + state = 0x4; range.start++; break; } + else if (F_status_set_fine(status) == F_none_eol) { + fss_extended_write_error_parameter_unsupported_eol_print(data); - if (contents.used + 1 > contents.size) { - status = fl_string_dynamics_size_increase(f_fss_default_allocation_step, &contents); - - if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamics_size_increase", F_true); - break; - } + status = F_status_set_error(F_unsupported); + break; } - if (contents.array[contents.used].used + 1 > contents.array[contents.used].size) { - status = fl_string_dynamic_size_increase(f_fss_default_allocation_step, &contents.array[contents.used]); + if (contents.array[contents.used - 1].used + 1 > contents.array[contents.used - 1].size) { + status = fl_string_dynamic_size_increase(f_fss_default_allocation_step, &contents.array[contents.used - 1]); if (F_status_is_error(status)) { fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_size_increase", F_true); @@ -213,17 +279,17 @@ extern "C" { } } - contents.array[contents.used].string[contents.array[contents.used].used++] = block.string[range.start]; + contents.array[contents.used - 1].string[contents.array[contents.used - 1].used++] = block.string[range.start]; } // for if (F_status_is_error(status)) break; } else { - state = 0x3; + state = 0x4; } } - if (state == 0x3) { + if (state == 0x4) { status = fss_extended_write_process(data, output, quote, &object, &contents, buffer); if (F_status_is_error(status)) break; @@ -232,7 +298,7 @@ extern "C" { } // for // if the pipe ended before finishing, then attempt to wrap up. - if (status_pipe == F_none_eof && state) { + if (F_status_is_error_not(status) && status_pipe == F_none_eof && state) { status = fss_extended_write_process(data, output, quote, &object, &contents, buffer); } diff --git a/level_3/fss_extended_write/c/private-fss_extended_write.h b/level_3/fss_extended_write/c/private-fss_extended_write.h index d884210..49522b4 100644 --- a/level_3/fss_extended_write/c/private-fss_extended_write.h +++ b/level_3/fss_extended_write/c/private-fss_extended_write.h @@ -45,6 +45,20 @@ extern "C" { #endif // _di_fss_extended_write_error_parameter_value_missing_print_ /** + * Print an message about a parameter EOL being unsupported. + * + * @param data + * The program data. + * + * @return + * F_none on success. + * F_failure (with error bit) for any othe failure. + */ +#ifndef _di_fss_extended_write_error_parameter_unsupported_eol_print_ + void fss_extended_write_error_parameter_unsupported_eol_print(const fss_extended_write_data_t data) f_gcc_attribute_visibility_internal; +#endif // _di_fss_extended_write_error_parameter_unsupported_eol_print_ + +/** * Process a given object and content, printing the FSS if valid or an error if invalid. * * @param data -- 1.8.3.1