From 1cb11264a7337d5973f1fac1cdc6a8a4337ec842 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sat, 24 Oct 2020 08:36:54 -0500 Subject: [PATCH] Feature: provide string "except" functions. The FSS Read functions utilize matching and printing on potentially delimited data. If the delimits are not applied, then the matches and prints will be incorrect. To avoid this, it seems that I need some way to not print the delimited data. Provide "except" functions that accept and "except" array of strings representing locations within some string that are to be ignored. The printing functions and comparison functions now have "except" equivalents. The level_1 fl_print project appears outdated and needed updating anyway. Restructure this project to use the private function practice, hopefully reducing the code size (and ideally binary size). The "_string" part can be removed from the fl_print function names. The parameter checks are loosened and now more closely match the approaches used in level_0 f_print. --- build/level_1/settings | 2 +- build/monolithic/settings | 2 +- level_0/f_print/c/print.c | 12 +- level_0/f_print/c/print.h | 12 +- level_0/f_print/c/private-print.c | 34 +-- level_0/f_print/c/private-print.h | 20 +- level_1/fl_fss/c/private-fss.c | 1 - level_1/fl_print/c/print.c | 499 ++++++++--------------------------- level_1/fl_print/c/print.h | 240 +++++++++++++++-- level_1/fl_print/c/private-print.c | 384 +++++++++++++++++++++++++++ level_1/fl_print/c/private-print.h | 152 +++++++++++ level_1/fl_print/data/build/settings | 2 +- level_1/fl_string/c/private-string.c | 289 +++++++++++++++++++- level_1/fl_string/c/private-string.h | 76 ++++++ level_1/fl_string/c/string.c | 98 +++++++ level_1/fl_string/c/string.h | 399 ++++++++++++++++++++++++++++ 16 files changed, 1763 insertions(+), 459 deletions(-) create mode 100644 level_1/fl_print/c/private-print.c create mode 100644 level_1/fl_print/c/private-print.h diff --git a/build/level_1/settings b/build/level_1/settings index 86d8ee5..d34a818 100644 --- a/build/level_1/settings +++ b/build/level_1/settings @@ -20,7 +20,7 @@ build_indexer ar build_language c build_libraries -lc build_libraries-level -lfll_0 -build_sources_library color.c console.c conversion.c directory.c private-directory.c environment.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c iki.c print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c +build_sources_library color.c console.c conversion.c directory.c private-directory.c environment.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c iki.c print.c private-print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c build_sources_program build_sources_headers color.h console.h conversion.h directory.h environment.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h iki.h print.h status.h string.h utf.h utf_file.h build_sources_script diff --git a/build/monolithic/settings b/build/monolithic/settings index 30ee620..152db49 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -20,7 +20,7 @@ build_indexer ar build_language c build_libraries -lc build_libraries-monolithic -build_sources_library level_0/account.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c +build_sources_library level_0/account.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c build_sources_program build_sources_headers level_0/account.h level_0/account-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h build_sources_script diff --git a/level_0/f_print/c/print.c b/level_0/f_print/c/print.c index ecd47c4..2499ae6 100644 --- a/level_0/f_print/c/print.c +++ b/level_0/f_print/c/print.c @@ -55,7 +55,7 @@ extern "C" { if (!string || length == 0) return F_data_not; - return private_f_print_except(output, string, length, except); + return private_f_print_except(output, string, 0, length, except); } #endif // _di_f_print_except_ @@ -67,7 +67,7 @@ extern "C" { if (!buffer.used) return F_data_not; - return private_f_print_except(output, buffer.string, buffer.used, except); + return private_f_print_except(output, buffer.string, 0, buffer.used, except); } #endif // _di_f_print_except_dynamic_ @@ -85,7 +85,7 @@ extern "C" { length = buffer.used - range.start; } - return private_f_print_except(output, buffer.string + range.start, length, except); + return private_f_print_except(output, buffer.string, range.start, range.start + length, except); } #endif // _di_f_print_except_dynamic_partial_ @@ -139,7 +139,7 @@ extern "C" { if (!string || length == 0) return F_data_not; - return private_f_print_to_except(id, string, length, except); + return private_f_print_to_except(id, string, 0, length, except); } #endif // _di_f_print_to_except_ @@ -151,7 +151,7 @@ extern "C" { if (!buffer.used) return F_data_not; - return private_f_print_to_except(id, buffer.string, buffer.used, except); + return private_f_print_to_except(id, buffer.string, 0, buffer.used, except); } #endif // _di_f_print_to_except_dynamic_ @@ -169,7 +169,7 @@ extern "C" { length = buffer.used - range.start; } - return private_f_print_to_except(id, buffer.string + range.start, length, except); + return private_f_print_to_except(id, buffer.string, range.start, range.start + length, except); } #endif // _di_f_print_to_except_dynamic_partial_ diff --git a/level_0/f_print/c/print.h b/level_0/f_print/c/print.h index 0c11f4e..95c0c68 100644 --- a/level_0/f_print/c/print.h +++ b/level_0/f_print/c/print.h @@ -121,7 +121,7 @@ extern "C" { * The total number of characters to print. * @param except * An array of locations within the given string to not print. - * The array of locations is assumed to be in linear order. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. @@ -149,7 +149,7 @@ extern "C" { * The string to output. * @param except * An array of locations within the given string to not print. - * The array of locations is assumed to be in linear order. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. @@ -179,7 +179,7 @@ extern "C" { * The range within the provided string to print. * @param except * An array of locations within the given string to not print. - * The array of locations is assumed to be in linear order. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. @@ -306,7 +306,7 @@ extern "C" { * The total number of characters to print. * @param except * An array of locations within the given string to not print. - * The array of locations is assumed to be in linear order. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. @@ -342,7 +342,7 @@ extern "C" { * The string to output. * @param except * An array of locations within the given string to not print. - * The array of locations is assumed to be in linear order. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. @@ -380,7 +380,7 @@ extern "C" { * The range within the provided string to print. * @param except * An array of locations within the given string to not print. - * The array of locations is assumed to be in linear order. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. diff --git a/level_0/f_print/c/private-print.c b/level_0/f_print/c/private-print.c index 2b5319e..54e6b6d 100644 --- a/level_0/f_print/c/private-print.c +++ b/level_0/f_print/c/private-print.c @@ -7,10 +7,8 @@ extern "C" { #if !defined(_di_f_print_) || !defined(_di_f_print_dynamic_) || !defined(_di_f_print_dynamic_partial_) f_return_status private_f_print(FILE *output, const f_string_t string, const f_string_length_t length) { - - if (!length) return F_data_not; - for (register f_string_length_t i = 0; i < length; ++i) { + if (string[i]) { if (!fputc(string[i], output)) { return F_status_set_error(F_output); @@ -23,15 +21,13 @@ extern "C" { #endif // !defined(_di_f_print_) || !defined(_di_f_print_dynamic_) || !defined(_di_f_print_dynamic_partial_) #if !defined(_di_f_print_except_) || !defined(_di_f_print_except_dynamic_) || !defined(_di_f_print_except_dynamic_partial_) - f_return_status private_f_print_except(FILE *output, const f_string_t string, const f_string_length_t length, const f_string_lengths_t except) { - - if (!length) return F_data_not; - + f_return_status private_f_print_except(FILE *output, const f_string_t string, const f_string_length_t offset, const f_string_length_t stop, const f_string_lengths_t except) { f_string_length_t j = 0; - for (register f_string_length_t i = 0; i < length; ++i) { - for (; j < except.used; j++) { - if (except.array[j] >= i) break; + for (register f_string_length_t i = offset; i < stop; ++i) { + + for (; j < except.used && except.array[j] < i; ++j) { + // do nothing. } // for if (j < except.used && except.array[j] == i) continue; @@ -49,10 +45,8 @@ extern "C" { #if !defined(_di_f_print_to_) || !defined(_di_f_print_dynamic_to_) || !defined(_di_f_print_dynamic_partial_to_) f_return_status private_f_print_to(const int id, const f_string_t string, const f_string_length_t length) { - - if (!length) return F_data_not; - register f_string_length_t i = 0; + f_string_length_t start = 0; f_string_length_t total = 0; @@ -100,19 +94,17 @@ extern "C" { #endif // !defined(_di_f_print_to_) || !defined(_di_f_print_dynamic_to_) || !defined(_di_f_print_dynamic_partial_to_) #if !defined(_di_f_print_to_except_) || !defined(_di_f_print_to_except_dynamic_) || !defined(_di_f_print_to_except_dynamic_partial_) - f_return_status private_f_print_to_except(const int id, const f_string_t string, const f_string_length_t length, const f_string_lengths_t except) { - - if (!length) return F_data_not; + f_return_status private_f_print_to_except(const int id, const f_string_t string, const f_string_length_t offset, const f_string_length_t stop, const f_string_lengths_t except) { + register f_string_length_t i = offset; - register f_string_length_t i = 0; f_string_length_t j = 0; - f_string_length_t start = 0; + f_string_length_t start = offset; f_string_length_t total = 0; - for (; i < length; ++i) { + for (; i < stop; ++i) { - for (; j < except.used; j++) { - if (except.array[j] >= i) break; + for (; j < except.used && except.array[j] < i; ++j) { + // do nothing. } // for if (j >= except.used || except.array[j] != i) { diff --git a/level_0/f_print/c/private-print.h b/level_0/f_print/c/private-print.h index 0dbc316..4106702 100644 --- a/level_0/f_print/c/private-print.h +++ b/level_0/f_print/c/private-print.h @@ -50,11 +50,13 @@ extern "C" { * The file to output to, including standard streams such as stdout and stderr. * @param string * The string to output. - * @param length - * The total number of characters to print. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. * @param except * An array of locations within the given string to not print. - * The array of locations is assumed to be in linear order. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. @@ -67,7 +69,7 @@ extern "C" { * @see f_print_except_dynamic_partial() */ #if !defined(_di_f_print_except_) || !defined(_di_f_print_except_dynamic_) || !defined(_di_f_print_except_dynamic_partial_) - extern f_return_status private_f_print_except(FILE *output, const f_string_t string, const f_string_length_t length, const f_string_lengths_t except) f_gcc_attribute_visibility_internal; + extern f_return_status private_f_print_except(FILE *output, const f_string_t string, const f_string_length_t offset, const f_string_length_t stop, const f_string_lengths_t except) f_gcc_attribute_visibility_internal; #endif // !defined(_di_f_print_except_) || !defined(_di_f_print_except_dynamic_) || !defined(_di_f_print_except_dynamic_partial_) /** @@ -111,11 +113,13 @@ extern "C" { * The file to output to, including standard streams such as stdout and stderr. * @param string * The string to output. - * @param length - * The total number of characters to print. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. * @param except * An array of locations within the given string to not print. - * The array of locations is assumed to be in linear order. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. @@ -134,7 +138,7 @@ extern "C" { * @see f_print_to_except_dynamic_partial() */ #if !defined(_di_f_print_to_except_) || !defined(_di_f_print_to_except_dynamic_) || !defined(_di_f_print_to_except_dynamic_partial_) - extern f_return_status private_f_print_to_except(const int id, const f_string_t string, const f_string_length_t length, const f_string_lengths_t except) f_gcc_attribute_visibility_internal; + extern f_return_status private_f_print_to_except(const int id, const f_string_t string, const f_string_length_t offset, const f_string_length_t stop, const f_string_lengths_t except) f_gcc_attribute_visibility_internal; #endif // !defined(_di_f_print_to_except_) || !defined(_di_f_print_to_except_dynamic_) || !defined(_di_f_print_to_except_dynamic_partial_) #ifdef __cplusplus diff --git a/level_1/fl_fss/c/private-fss.c b/level_1/fl_fss/c/private-fss.c index 4a2e02a..e9e9dde 100644 --- a/level_1/fl_fss/c/private-fss.c +++ b/level_1/fl_fss/c/private-fss.c @@ -120,7 +120,6 @@ extern "C" { } #endif // !defined(_di_fl_fss_basic_list_content_write_string_) || !defined(_di_fl_fss_extended_list_content_write_string_) - #if !defined(_di_fl_fss_basic_list_object_write_string_) || !defined(_di_fl_fss_extended_list_object_write_string_) f_return_status private_fl_fss_basic_list_write_object_trim(const f_string_length_t used_start, f_string_dynamic_t *destination) { f_status_t status = F_none; diff --git a/level_1/fl_print/c/print.c b/level_1/fl_print/c/print.c index f1d6479..6c847d0 100644 --- a/level_1/fl_print/c/print.c +++ b/level_1/fl_print/c/print.c @@ -1,462 +1,177 @@ #include "print.h" +#include "private-print.h" #ifdef __cplusplus extern "C" { #endif -#ifndef _di_fl_print_trim_string_ - f_return_status fl_print_trim_string(FILE *output, const f_string_t string, const f_string_length_t length) { +#ifndef _di_fl_print_trim_except_ + f_return_status fl_print_trim_except(FILE *output, const f_string_t string, const f_string_length_t length, const f_string_lengths_t except) { #ifndef _di_level_1_parameter_checking_ - if (!string) return F_status_set_error(F_parameter); - if (length < 1) return F_status_set_error(F_parameter); + if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ - register f_string_length_t i = 0; - f_status_t status = F_none; - uint8_t width_max = 0; + if (!string || !length) return F_data_not; - for (; i < length; i += f_macro_utf_byte_width(string[i])) { - - width_max = (length - i) + 1; - status = f_utf_is_whitespace(string + i, width_max); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - if (status == F_false) break; - } // for - - for (; i < length; i += f_macro_utf_byte_width(string[i])) { - if (!string[i]) continue; - - width_max = (length - i) + 1; - status = f_utf_is_whitespace(string + i, width_max); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - if (status == F_true) { - f_string_length_t j = i + f_macro_utf_byte_width(string[i]); - - if (j == length) return F_none; - - for (; j < length; j += f_macro_utf_byte_width(string[j])) { - width_max = (length - j) + 1; - status = f_utf_is_whitespace(string + j, width_max); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - // all whitespaces found so far must be printed when a non-whitespace is found. - if (status == F_false) { - for (; i < j; i++) { - if (!string[i]) continue; - - if (!fputc(string[i], output)) return F_status_set_error(F_output); - } // for - - break; - } - } // for - - if (status == F_true) break; - } - - if (!fputc(string[i], output)) return F_status_set_error(F_output); - } // for - - return F_none; + return private_fl_print_trim_except(output, string, 0, length, except); } -#endif // _di_fl_print_trim_string_ +#endif // _di_fl_print_trim_except_ -#ifndef _di_fl_print_trim_string_dynamic_ - f_return_status fl_print_trim_string_dynamic(FILE *output, const f_string_static_t buffer) { +#ifndef _di_fl_print_trim_except_dynamic_ + f_return_status fl_print_trim_except_dynamic(FILE *output, const f_string_static_t buffer, const f_string_lengths_t except) { #ifndef _di_level_1_parameter_checking_ - if (!buffer.used) return F_status_set_error(F_parameter); + if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ - register f_string_length_t i = 0; - f_status_t status = F_none; - uint8_t width_max = 0; - - for (; i < buffer.used; i += f_macro_utf_byte_width(buffer.string[i])) { - width_max = (buffer.used - i) + 1; - status = f_utf_is_whitespace(buffer.string + i, width_max); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - if (status == F_false) break; - } // for - - for (; i < buffer.used; i += f_macro_utf_byte_width(buffer.string[i])) { - if (!buffer.string[i]) continue; - - width_max = (buffer.used - i) + 1; - status = f_utf_is_whitespace(buffer.string + i, width_max); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); + if (!buffer.used) return F_data_not; - return status; - } - - if (status == F_true) { - f_string_length_t j = i + f_macro_utf_byte_width(buffer.string[i]); - - if (j == buffer.used) return F_none; - - for (; j < buffer.used; j += f_macro_utf_byte_width(buffer.string[j])) { - width_max = (buffer.used - j) + 1; - status = f_utf_is_whitespace(buffer.string + j, width_max); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - // all whitespaces found so far must be printed when a non-whitespace is found. - if (status == F_false) { - for (; i < j; i++) { - if (!buffer.string[i]) continue; - - if (!fputc(buffer.string[i], output)) return F_status_set_error(F_output); - } // for - - break; - } - } // for - - if (status == F_true) { - break; - } - } - - if (!fputc(buffer.string[i], output)) return F_status_set_error(F_output); - } // for - - return F_none; + return private_fl_print_trim_except(output, buffer.string, 0, buffer.used, except); } -#endif // _di_fl_print_trim_string_dynamic_ +#endif // _di_fl_print_trim_except_dynamic_ -#ifndef _di_fl_print_trim_string_dynamic_partial_ - f_return_status fl_print_trim_string_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range) { +#ifndef _di_fl_print_trim_except_dynamic_partial_ + f_return_status fl_print_trim_except_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range, const f_string_lengths_t except) { #ifndef _di_level_1_parameter_checking_ - if (range.start < 0) return F_status_set_error(F_parameter); - if (range.stop < range.start) return F_status_set_error(F_parameter); - if (!buffer.used) return F_status_set_error(F_parameter); - if (range.start >= buffer.used) return F_status_set_error(F_parameter); - if (range.stop >= buffer.used) return F_status_set_error(F_parameter); + if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ - register f_string_length_t i = range.start; - f_status_t status = F_none; - - uint8_t width_max = 0; - - for (; i <= range.stop; i += f_macro_utf_byte_width(buffer.string[i])) { - width_max = (range.stop - i) + 1; - status = f_utf_is_whitespace(buffer.string + i, width_max); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - if (status == F_false) break; - } // for - - for (uint8_t width_i = f_macro_utf_byte_width(buffer.string[i]); i <= range.stop; i += width_i) { - if (!buffer.string[i]) { - width_i = 1; - continue; - } - - width_i = f_macro_utf_byte_width(buffer.string[i]); - width_max = (range.stop - i) + 1; - status = f_utf_is_whitespace(buffer.string + i, width_max); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) { - return F_status_set_error(F_utf); - } - - return status; - } - - if (status == F_true) { - f_string_length_t j = i + width_i; - - if (j == range.stop) return F_none; - - for (uint8_t width_j = f_macro_utf_byte_width(buffer.string[j]); j <= range.stop; j += width_j) { - width_j = f_macro_utf_byte_width(buffer.string[j]); - width_max = (range.stop - j) + 1; - status = f_utf_is_whitespace(buffer.string + j, width_max); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - // all whitespaces found so far must be printed when a non-whitespace is found. - if (status == F_false) { - for (; i <= j; i += width_i) { - if (!buffer.string[i]) { - width_i = 1; - continue; - } + if (!buffer.used || range.start > range.stop || range.start >= buffer.used) return F_data_not; - width_i = f_macro_utf_byte_width(buffer.string[i]); + f_string_length_t length = (range.stop - range.start) + 1; - for (uint8_t k = 0; k < width_i; k++) { - if (!fputc(buffer.string[i + k], output)) return F_status_set_error(F_output); - } // for - } // for + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } - break; - } - } // for - - if (status == F_true) { - break; - } - } - - for (uint8_t k = 0; k < width_i; k++) { - if (!fputc(buffer.string[i + k], output)) return F_status_set_error(F_output); - } // for - } // for - - return F_none; + return private_fl_print_trim_except(output, buffer.string, range.start, range.start + length, except); } -#endif // _di_fl_print_trim_string_dynamic_partial_ +#endif // _di_fl_print_trim_except_dynamic_partial_ -#ifndef _di_fl_print_trim_utf_string_ - f_return_status fl_print_trim_utf_string(FILE *output, const f_utf_string_t string, const f_utf_string_length_t length) { +#ifndef _di_fl_print_trim_except_utf_ + f_return_status fl_print_trim_except_utf(FILE *output, const f_utf_string_t string, const f_utf_string_length_t length, const f_utf_string_lengths_t except) { #ifndef _di_level_1_parameter_checking_ - if (!string) return F_status_set_error(F_parameter); - if (length < 1) return F_status_set_error(F_parameter); + if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ - register f_string_length_t i = 0; - f_status_t status = F_none; - - for (; i < length; i++) { - status = f_utf_character_is_whitespace(string[i]); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - if (status == F_false) break; - } // for - - for (; i < length; i++) { - if (!string[i]) continue; - - status = f_utf_character_is_whitespace(string[i]); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - if (status == F_true) { - f_string_length_t j = i + 1; - - if (j == length) return F_none; + if (!string || !length) return F_data_not; - for (; j < length; j++) { - status = f_utf_character_is_whitespace(string[j]); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - // all whitespaces found so far must be printed when a non-whitespace is found. - if (status == F_false) { - for (; i < j; i++) { - if (!string[i]) continue; - - if (!fputc(string[i], output)) return F_status_set_error(F_output); - } // for - - break; - } - } // for - - if (status == F_true) break; - } - - if (!fputc(string[i], output)) return F_status_set_error(F_output); - } // for - - return F_none; + return private_fl_print_trim_except_utf(output, string, 0, length, except); } -#endif // _di_fl_print_trim_utf_string_ +#endif // _di_fl_print_trim_except_utf_ -#ifndef _di_fl_print_trim_utf_string_dynamic_ - f_return_status fl_print_trim_utf_string_dynamic(FILE *output, const f_utf_string_static_t buffer) { +#ifndef _di_fl_print_trim_except_utf_dynamic_ + f_return_status fl_print_trim_except_utf_dynamic(FILE *output, const f_utf_string_static_t buffer, const f_utf_string_lengths_t except) { #ifndef _di_level_1_parameter_checking_ - if (!buffer.used) return F_status_set_error(F_parameter); + if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ - register f_utf_string_length_t i = 0; - f_status_t status = F_none; - - for (; i < buffer.used; i++) { - status = f_utf_character_is_whitespace(buffer.string[i]); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - if (status == F_false) break; - } // for - - for (; i < buffer.used; i++) { - if (!buffer.string[i]) continue; + if (!buffer.used) return F_data_not; - status = f_utf_character_is_whitespace(buffer.string[i]); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); - - return status; - } - - if (status == F_true) { - f_string_length_t j = i + 1; - - if (j == buffer.used) return F_none; - - for (; j < buffer.used; j++) { - status = f_utf_character_is_whitespace(buffer.string[j]); + return private_fl_print_trim_except_utf(output, buffer.string, 0, buffer.used, except); + } +#endif // _di_fl_print_trim_except_utf_dynamic_ - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); +#ifndef _di_fl_print_trim_except_utf_dynamic_partial_ + f_return_status fl_print_trim_except_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_utf_string_range_t range, const f_utf_string_lengths_t except) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ - return status; - } + if (!buffer.used || range.start > range.stop || range.start >= buffer.used) return F_data_not; - // all whitespaces found so far must be printed when a non-whitespace is found. - if (status == F_false) { - for (; i < j; i++) { - if (!buffer.string[i]) continue; + f_string_length_t length = (range.stop - range.start) + 1; - if (!fputc(buffer.string[i], output)) return F_status_set_error(F_output); - } // for + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } - break; - } - } // for + return private_fl_print_trim_except_utf(output, buffer.string, range.start, range.start + length, except); + } +#endif // _di_fl_print_trim_except_utf_dynamic_partial_ - if (status == F_true) { - break; - } - } +#ifndef _di_fl_print_trim_ + f_return_status fl_print_trim(FILE *output, const f_string_t string, const f_string_length_t length) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ - if (!fputc(buffer.string[i], output)) return F_status_set_error(F_output); - } // for + if (!string || !length) return F_data_not; - return F_none; + return private_fl_print_trim(output, string, length); } -#endif // _di_fl_print_trim_utf_string_dynamic_ +#endif // _di_fl_print_trim_ -#ifndef _di_fl_print_trim_utf_string_dynamic_partial_ - f_return_status fl_print_trim_utf_string_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_utf_string_range_t range) { +#ifndef _di_fl_print_trim_dynamic_ + f_return_status fl_print_trim_dynamic(FILE *output, const f_string_static_t buffer) { #ifndef _di_level_1_parameter_checking_ - if (range.start < 0) return F_status_set_error(F_parameter); - if (range.stop < range.start) return F_status_set_error(F_parameter); - if (!buffer.used) return F_status_set_error(F_parameter); - if (range.start >= buffer.used) return F_status_set_error(F_parameter); - if (range.stop >= buffer.used) return F_status_set_error(F_parameter); + if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ - register f_string_length_t i = range.start; - f_status_t status = F_none; - - for (; i <= range.stop; i++) { - status = f_utf_character_is_whitespace(buffer.string[i]); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); + if (!buffer.used) return F_data_not; - return status; - } + return private_fl_print_trim(output, buffer.string, buffer.used); + } +#endif // _di_fl_print_trim_dynamic_ - if (status == F_false) break; - } // for +#ifndef _di_fl_print_trim_dynamic_partial_ + f_return_status fl_print_trim_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ - for (; i <= range.stop; i++) { - if (!buffer.string[i]) continue; + if (!buffer.used || range.start > range.stop || range.start >= buffer.used) return F_data_not; - status = f_utf_character_is_whitespace(buffer.string[i]); + f_string_length_t length = (range.stop - range.start) + 1; - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } - return status; - } + return private_fl_print_trim(output, buffer.string + range.start, length); + } +#endif // _di_fl_print_trim_dynamic_partial_ - if (status == F_true) { - f_string_length_t j = i + 1; +#ifndef _di_fl_print_trim_utf_ + f_return_status fl_print_trim_utf(FILE *output, const f_utf_string_t string, const f_utf_string_length_t length) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ - if (j == range.stop) return F_none; + if (!string || !length) return F_data_not; - for (; j <= range.stop; j++) { - status = f_utf_character_is_whitespace(buffer.string[j]); + return private_fl_print_trim_utf(output, string, length); + } +#endif // _di_fl_print_trim_utf_ - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); +#ifndef _di_fl_print_trim_utf_dynamic_ + f_return_status fl_print_trim_utf_dynamic(FILE *output, const f_utf_string_static_t buffer) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ - return status; - } + if (!buffer.used) return F_data_not; - // all whitespaces found so far must be printed when a non-whitespace is found. - if (status == F_false) { - for (; i <= j; i++) { - if (!buffer.string[i]) continue; + return private_fl_print_trim_utf(output, buffer.string, buffer.used); + } +#endif // _di_fl_print_trim_utf_dynamic_ - if (!fputc(buffer.string[i], output)) return F_status_set_error(F_output); - } // for +#ifndef _di_fl_print_trim_utf_dynamic_partial_ + f_return_status fl_print_trim_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_utf_string_range_t range) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ - break; - } - } // for + if (!buffer.used || range.start > range.stop || range.start >= buffer.used) return F_data_not; - if (status == F_true) break; - } + f_string_length_t length = (range.stop - range.start) + 1; - if (!fputc(buffer.string[i], output)) return F_status_set_error(F_output); - } // for + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } - return F_none; + return private_fl_print_trim_utf(output, buffer.string + range.start, length); } -#endif // _di_fl_print_trim_utf_string_dynamic_partial_ +#endif // _di_fl_print_trim_utf_dynamic_partial_ #ifdef __cplusplus } // extern "C" diff --git a/level_1/fl_print/c/print.h b/level_1/fl_print/c/print.h index 0683a3a..6fbd652 100644 --- a/level_1/fl_print/c/print.h +++ b/level_1/fl_print/c/print.h @@ -31,6 +31,7 @@ extern "C" { * * Will not stop at \0. * Will not print \0. + * Will not print any 1-byte character at a location specified in except array. * * @param output * The file to output to, including standard streams such as stdout and stderr. @@ -38,9 +39,13 @@ extern "C" { * The string to output. * @param length * The total number of characters to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. + * F_data_not on success but there is nothing to print. * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. * F_output (with error bit) on error when printing to output. * F_parameter (with error bit) if a parameter is invalid. @@ -48,9 +53,9 @@ extern "C" { * * Errors (with error bit) from: f_utf_is_whitespace(). */ -#ifndef _di_fl_print_trim_string_ - extern f_return_status fl_print_trim_string(FILE *output, const f_string_t string, const f_string_length_t length); -#endif // _di_fl_print_trim_string_ +#ifndef _di_fl_print_trim_except_ + extern f_return_status fl_print_trim_except(FILE *output, const f_string_t string, const f_string_length_t length, const f_string_lengths_t except); +#endif // _di_fl_print_trim_except_ /** * Print a dynamic string, stripping leading and trailing whitespace. @@ -60,14 +65,19 @@ extern "C" { * Will not stop at \0. * Will not print \0. * Will print the entire dynamic string, except for leading/trailing whitespace. + * Will not print any 1-byte character at a location specified in except array. * * @param output * The file to output to, including standard streams such as stdout and stderr. * @param buffer * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. + * F_data_not on success but there is nothing to print. * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. * F_output (with error bit) on error when printing to output. * F_parameter (with error bit) if a parameter is invalid. @@ -75,9 +85,9 @@ extern "C" { * * Errors (with error bit) from: f_utf_is_whitespace(). */ -#ifndef _di_fl_print_trim_string_dynamic_ - extern f_return_status fl_print_trim_string_dynamic(FILE *output, const f_string_static_t buffer); -#endif // _di_fl_print_trim_string_dynamic_ +#ifndef _di_fl_print_trim_except_dynamic_ + extern f_return_status fl_print_trim_except_dynamic(FILE *output, const f_string_static_t buffer, const f_string_lengths_t except); +#endif // _di_fl_print_trim_except_dynamic_ /** * Print a partial dynamic string, stripping leading and trailing whitespace. @@ -86,6 +96,7 @@ extern "C" { * * Will not stop at \0. * Will not print \0. + * Will not print any 1-byte character at a location specified in except array. * Will print the only the buffer range specified by range, except for leading/trailing whitespace. * * @param output @@ -94,9 +105,13 @@ extern "C" { * The string to output. * @param range * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. + * F_data_not on success but there is nothing to print. * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. * F_output (with error bit) on error when printing to output. * F_parameter (with error bit) if a parameter is invalid. @@ -104,9 +119,9 @@ extern "C" { * * Errors (with error bit) from: f_utf_is_whitespace(). */ -#ifndef _di_fl_print_trim_string_dynamic_partial_ - extern f_return_status fl_print_trim_string_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range); -#endif // _di_fl_print_trim_string_dynamic_partial_ +#ifndef _di_fl_print_trim_except_dynamic_partial_ + extern f_return_status fl_print_trim_except_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range, const f_string_lengths_t except); +#endif // _di_fl_print_trim_except_dynamic_partial_ /** * Print a string, stripping leading and trailing whitespace. @@ -115,6 +130,7 @@ extern "C" { * * Will not stop at \0. * Will not print \0. + * Will not print any 1 UTF character at a location specified in except array. * * @param output * The file to output to, including standard streams such as stdout and stderr. @@ -122,9 +138,13 @@ extern "C" { * The string to output. * @param length * The total number of characters to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. + * F_data_not on success but there is nothing to print. * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. * F_output (with error bit) on error when printing to output. * F_parameter (with error bit) if a parameter is invalid. @@ -132,9 +152,9 @@ extern "C" { * * Errors (with error bit) from: f_utf_character_is_whitespace(). */ -#ifndef _di_fl_print_trim_utf_string_ - extern f_return_status fl_print_trim_utf_string(FILE *output, const f_utf_string_t string, const f_utf_string_length_t length); -#endif // _di_fl_print_trim_utf_string_ +#ifndef _di_fl_print_trim_except_utf_ + extern f_return_status fl_print_trim_except_utf(FILE *output, const f_utf_string_t string, const f_utf_string_length_t length, const f_utf_string_lengths_t except); +#endif // _di_fl_print_trim_except_utf_ /** * Print a dynamic string, stripping leading and trailing whitespace. @@ -143,15 +163,20 @@ extern "C" { * * Will not stop at \0. * Will not print \0. + * Will not print any 1 UTF character at a location specified in except array. * Will print the entire dynamic string, except for leading/trailing whitespace. * * @param output * The file to output to, including standard streams such as stdout and stderr. * @param buffer * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. + * F_data_not on success but there is nothing to print. * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. * F_output (with error bit) on error when printing to output. * F_parameter (with error bit) if a parameter is invalid. @@ -159,9 +184,9 @@ extern "C" { * * Errors (with error bit) from: f_utf_character_is_whitespace(). */ -#ifndef _di_fl_print_trim_utf_string_dynamic_ - extern f_return_status fl_print_trim_utf_string_dynamic(FILE *output, const f_utf_string_static_t buffer); -#endif // _di_fl_print_trim_utf_string_dynamic_ +#ifndef _di_fl_print_trim_except_utf_dynamic_ + extern f_return_status fl_print_trim_except_utf_dynamic(FILE *output, const f_utf_string_static_t buffer, const f_utf_string_lengths_t except); +#endif // _di_fl_print_trim_except_utf_dynamic_ /** * Print a partial dynamic string, stripping leading and trailing whitespace. @@ -170,6 +195,7 @@ extern "C" { * * Will not stop at \0. * Will not print \0. + * Will not print any 1 UTF character at a location specified in except array. * Will print the only the buffer range specified by range, except for leading/trailing whitespace. * * @param output @@ -178,9 +204,13 @@ extern "C" { * The string to output. * @param range * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. * * @return * F_none on success. + * F_data_not on success but there is nothing to print. * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. * F_output (with error bit) on error when printing to output. * F_parameter (with error bit) if a parameter is invalid. @@ -188,9 +218,183 @@ extern "C" { * * Errors (with error bit) from: f_utf_character_is_whitespace(). */ -#ifndef _di_fl_print_trim_utf_string_dynamic_partial_ - extern f_return_status fl_print_trim_utf_string_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_utf_string_range_t range); -#endif // _di_fl_print_trim_utf_string_dynamic_partial_ +#ifndef _di_fl_print_trim_except_utf_dynamic_partial_ + extern f_return_status fl_print_trim_except_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_utf_string_range_t range, const f_utf_string_lengths_t except); +#endif // _di_fl_print_trim_except_utf_dynamic_partial_ + +/** + * Print a string, stripping leading and trailing whitespace. + * + * Except for leading/trailing whitespace, the string is printed as-is without interpretation. + * + * Will not stop at \0. + * Will not print \0. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + */ +#ifndef _di_fl_print_trim_ + extern f_return_status fl_print_trim(FILE *output, const f_string_t string, const f_string_length_t length); +#endif // _di_fl_print_trim_ + +/** + * Print a dynamic string, stripping leading and trailing whitespace. + * + * Except for leading/trailing whitespace, the string is printed as-is without interpretation. + * + * Will not stop at \0. + * Will not print \0. + * Will print the entire dynamic string, except for leading/trailing whitespace. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param buffer + * The string to output. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + */ +#ifndef _di_fl_print_trim_dynamic_ + extern f_return_status fl_print_trim_dynamic(FILE *output, const f_string_static_t buffer); +#endif // _di_fl_print_trim_dynamic_ + +/** + * Print a partial dynamic string, stripping leading and trailing whitespace. + * + * Except for leading/trailing whitespace, the string is printed as-is without interpretation. + * + * Will not stop at \0. + * Will not print \0. + * Will print the only the buffer range specified by range, except for leading/trailing whitespace. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + */ +#ifndef _di_fl_print_trim_dynamic_partial_ + extern f_return_status fl_print_trim_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range); +#endif // _di_fl_print_trim_dynamic_partial_ + +/** + * Print a string, stripping leading and trailing whitespace. + * + * Except for leading/trailing whitespace, the string is printed as-is without interpretation. + * + * Will not stop at \0. + * Will not print \0. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_character_is_whitespace(). + */ +#ifndef _di_fl_print_trim_utf_ + extern f_return_status fl_print_trim_utf(FILE *output, const f_utf_string_t string, const f_utf_string_length_t length); +#endif // _di_fl_print_trim_utf_ + +/** + * Print a dynamic string, stripping leading and trailing whitespace. + * + * Except for leading/trailing whitespace, the string is printed as-is without interpretation. + * + * Will not stop at \0. + * Will not print \0. + * Will print the entire dynamic string, except for leading/trailing whitespace. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param buffer + * The string to output. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_character_is_whitespace(). + */ +#ifndef _di_fl_print_trim_utf_dynamic_ + extern f_return_status fl_print_trim_utf_dynamic(FILE *output, const f_utf_string_static_t buffer); +#endif // _di_fl_print_trim_utf_dynamic_ + +/** + * Print a partial dynamic string, stripping leading and trailing whitespace. + * + * Except for leading/trailing whitespace, the string is printed as-is without interpretation. + * + * Will not stop at \0. + * Will not print \0. + * Will print the only the buffer range specified by range, except for leading/trailing whitespace. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_character_is_whitespace(). + */ +#ifndef _di_fl_print_trim_utf_dynamic_partial_ + extern f_return_status fl_print_trim_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_utf_string_range_t range); +#endif // _di_fl_print_trim_utf_dynamic_partial_ #ifdef __cplusplus } // extern "C" diff --git a/level_1/fl_print/c/private-print.c b/level_1/fl_print/c/private-print.c new file mode 100644 index 0000000..bc957fd --- /dev/null +++ b/level_1/fl_print/c/private-print.c @@ -0,0 +1,384 @@ +#include "print.h" +#include "private-print.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_di_fl_print_trim_except_) || !defined(_di_fl_print_trim_except_dynamic_) || !defined(_di_fl_print_trim_except_dynamic_partial_) + f_return_status private_fl_print_trim_except(FILE *output, const f_string_t string, const f_string_length_t start, const f_string_length_t stop, const f_string_lengths_t except) { + register f_string_length_t i = start; + + f_string_length_t j = 0; + f_string_length_t e = 0; + f_string_length_t ej = 0; + + f_status_t status = F_none; + uint8_t width_max = 0; + + while (i < stop) { + + for (; e < except.used && except.array[e] < i; ++e) { + // do nothing. + } // for + + if (e < except.used && except.array[e] == i) { + i++; + continue; + } + + width_max = (stop - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + + i += f_macro_utf_byte_width(string[i]); + } // while + + while (i < stop) { + + if (!string[i]) continue; + + for (; e < except.used && except.array[e] < i; ++e) { + // do nothing. + } // for + + if (e < except.used && except.array[e] == i) { + i++; + continue; + } + + width_max = (stop - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + f_macro_utf_byte_width(string[i]); + + if (j == stop) return F_none; + + ej = e; + + while (j < stop) { + + for (; ej < except.used && except.array[ej] < j; ++ej) { + // do nothing. + } // for + + if (ej < except.used && except.array[ej] == j) { + j++; + continue; + } + + width_max = (stop - j) + 1; + status = f_utf_is_whitespace(string + j, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + for (; i < j; i++) { + if (!string[i]) continue; + + for (; e < except.used && except.array[e] < i; ++e) { + // do nothing. + } // for + + if (e < except.used && except.array[e] == i) continue; + + if (!fputc(string[i], output)) return F_status_set_error(F_output); + } // for + + break; + } + + j += f_macro_utf_byte_width(string[j]); + } // while + + if (status == F_true) break; + } + + if (!fputc(string[i], output)) return F_status_set_error(F_output); + + i += f_macro_utf_byte_width(string[i]); + } // while + + return F_none; + } +#endif // !defined(_di_fl_print_trim_except_) || !defined(_di_fl_print_trim_except_dynamic_) || !defined(_di_fl_print_trim_except_dynamic_partial_) + +#if !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) + f_return_status private_fl_print_trim_except_utf(FILE *output, const f_utf_string_t string, const f_utf_string_length_t start, const f_utf_string_length_t stop, const f_utf_string_lengths_t except) { + register f_string_length_t i = start; + + f_string_length_t j = 0; + f_string_length_t e = 0; + f_string_length_t ej = 0; + + f_status_t status = F_none; + + for (; i < stop; ++i) { + + for (; e < except.used && except.array[e] < i; ++e) { + // do nothing. + } // for + + if (e < except.used && except.array[e] == i) continue; + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + } // for + + for (; i < stop; ++i) { + if (!string[i]) continue; + + for (; e < except.used && except.array[e] < i; ++e) { + // do nothing. + } // for + + if (e < except.used && except.array[e] == i) continue; + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + 1; + + if (j == stop) return F_none; + + for (ej = e; j < stop; j++) { + + for (; ej < except.used && except.array[ej] < j; ++ej) { + // do nothing. + } // for + + if (ej < except.used && except.array[ej] == j) continue; + + status = f_utf_character_is_whitespace(string[j]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + for (; i < j; i++) { + if (!string[i]) continue; + + for (; e < except.used && except.array[e] < i; ++e) { + // do nothing. + } // for + + if (e < except.used && except.array[e] == i) continue; + + if (!fputc(string[i], output)) return F_status_set_error(F_output); + } // for + + break; + } + } // for + + if (status == F_true) break; + } + + if (!fputc(string[i], output)) return F_status_set_error(F_output); + } // for + + return F_none; + } +#endif // !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) + +#if !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) + f_return_status private_fl_print_trim(FILE *output, const f_string_t string, const f_string_length_t length) { + register f_string_length_t i = 0; + + f_string_length_t j = 0; + + f_status_t status = F_none; + uint8_t width_max = 0; + + for (; i < length; i += f_macro_utf_byte_width(string[i])) { + + width_max = (length - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + } // for + + for (; i < length; i += f_macro_utf_byte_width(string[i])) { + if (!string[i]) continue; + + width_max = (length - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + f_macro_utf_byte_width(string[i]); + + if (j == length) return F_none; + + for (; j < length; j += f_macro_utf_byte_width(string[j])) { + + width_max = (length - j) + 1; + status = f_utf_is_whitespace(string + j, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + for (; i < j; i++) { + if (!string[i]) continue; + if (!fputc(string[i], output)) return F_status_set_error(F_output); + } // for + + break; + } + } // for + + if (status == F_true) break; + } + + if (!fputc(string[i], output)) return F_status_set_error(F_output); + } // for + + return F_none; + } +#endif // !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) + +#if !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) + f_return_status private_fl_print_trim_utf(FILE *output, const f_utf_string_t string, const f_utf_string_length_t length) { + register f_string_length_t i = 0; + + f_string_length_t j = 0; + + f_status_t status = F_none; + + for (; i < length; i++) { + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + } // for + + for (; i < length; i++) { + if (!string[i]) continue; + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); + + return status; + } + + if (status == F_true) { + j = i + 1; + + if (j == length) return F_none; + + for (; j < length; j++) { + + status = f_utf_character_is_whitespace(string[j]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + for (; i < j; i++) { + if (!string[i]) continue; + if (!fputc(string[i], output)) return F_status_set_error(F_output); + } // for + + break; + } + } // for + + if (status == F_true) break; + } + + if (!fputc(string[i], output)) return F_status_set_error(F_output); + } // for + + return F_none; + } +#endif // !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_1/fl_print/c/private-print.h b/level_1/fl_print/c/private-print.h new file mode 100644 index 0000000..45edce2 --- /dev/null +++ b/level_1/fl_print/c/private-print.h @@ -0,0 +1,152 @@ +/** + * FLL - Level 1 + * + * Project: Print + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * These are provided for internal reduction in redundant code. + * These should not be exposed/used outside of this project. + */ +#ifndef _PRIVATE_FL_print_h +#define _PRIVATE_FL_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Private implementation of fl_print_trim_except(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fl_print_trim_except() + * @see fl_print_trim_except_dynamic() + * @see fl_print_trim_except_dynamic_partial() + */ +#if !defined(_di_fl_print_trim_except_) || !defined(_di_fl_print_trim_except_dynamic_) || !defined(_di_fl_print_trim_except_dynamic_partial_) + extern f_return_status private_fl_print_trim_except(FILE *output, const f_string_t string, const f_string_length_t start, const f_string_length_t stop, const f_string_lengths_t except) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_except_) || !defined(_di_fl_print_trim_except_dynamic_) || !defined(_di_fl_print_trim_except_dynamic_partial_) + +/** + * Private implementation of fl_print_trim_except_utf(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fl_print_trim_except_utf() + * @see fl_print_trim_except_utf_dynamic() + * @see fl_print_trim_except_utf_dynamic_partial() + */ +#if !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) + extern f_return_status private_fl_print_trim_except_utf(FILE *output, const f_utf_string_t string, const f_string_length_t start, const f_utf_string_length_t stop, const f_utf_string_lengths_t except) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) + +/** + * Private implementation of fl_print_trim(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fl_print_trim() + * @see fl_print_trim_dynamic() + * @see fl_print_trim_dynamic_partial() + */ +#if !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) + extern f_return_status private_fl_print_trim(FILE *output, const f_string_t string, const f_string_length_t length) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) + +/** + * Private implementation of fl_print_trim_utf(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param output + * The file to output to, including standard streams such as stdout and stderr. + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * F_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fl_print_trim_utf() + * @see fl_print_trim_utf_dynamic() + * @see fl_print_trim_utf_dynamic_partial() + */ +#if !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) + extern f_return_status private_fl_print_trim_utf(FILE *output, const f_utf_string_t string, const f_utf_string_length_t length) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_FL_print_h diff --git a/level_1/fl_print/data/build/settings b/level_1/fl_print/data/build/settings index dcfb180..f32b467 100644 --- a/level_1/fl_print/data/build/settings +++ b/level_1/fl_print/data/build/settings @@ -20,7 +20,7 @@ build_indexer ar build_language c build_libraries -lc build_libraries-individual -lf_conversion -lf_memory -lf_print -lf_utf -build_sources_library print.c +build_sources_library print.c private-print.c build_sources_program build_sources_headers print.h build_sources_script diff --git a/level_1/fl_string/c/private-string.c b/level_1/fl_string/c/private-string.c index cd27d98..325e5e0 100644 --- a/level_1/fl_string/c/private-string.c +++ b/level_1/fl_string/c/private-string.c @@ -108,6 +108,279 @@ extern "C" { } #endif // !defined(_di_fl_string_compare_) || !defined(_di_fl_string_dynamic_compare_) || !defined(_di_fl_string_dynamic_partial_compare_) +#if !defined(_di_fl_string_compare_except_) || !defined(_di_fl_string_dynamic_compare_except_) || !defined(_di_fl_string_dynamic_partial_compare_except_) + f_return_status private_fl_string_compare_except(const f_string_t string1, const f_string_t string2, const f_string_length_t offset1, const f_string_length_t offset2, const f_string_length_t stop1, const f_string_length_t stop2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + f_string_length_t i1 = offset1; + f_string_length_t i2 = offset2; + + f_string_length_t e1 = 0; + f_string_length_t e2 = 0; + + while (i1 < stop1 && i2 < stop2) { + + // skip past NULL in string1. + while (i1 < stop1 && !string1[i1]) i1++; + if (i1 == stop1) break; + + // skip past NULL in string2. + while (i2 < stop2 && !string2[i2]) i2++; + if (i2 == stop2) break; + + // skip past except characters in string1. + while (e1 < except1.used && except1.array[e1] < i1) e1++; + if (e1 < except1.used && except1.array[e1] == i1) { + i1++; + continue; + } + + // skip past except characters in string2. + while (e2 < except2.used && except2.array[e2] < i2) e2++; + if (e2 < except2.used && except2.array[e2] == i2) { + i2++; + continue; + } + + if (string1[i1] != string2[i2]) return F_equal_to_not; + + i1++; + i2++; + } // while + + // only return F_equal_to if all remaining characters are NULL or are designated to be ignored. + for (; i1 < stop1; i1++) { + + // skip past except characters in string1. + while (e1 < except1.used && except1.array[e1] < i1) e1++; + if (e1 < except1.used && except1.array[e1] == i1) continue; + + if (string1[i1] != 0) return F_equal_to_not; + } // for + + for (; i2 < stop2; i2++) { + + // skip past except characters in string2. + while (e2 < except2.used && except2.array[e2] < i2) e2++; + if (e2 < except2.used && except2.array[e2] == i2) continue; + + if (string2[i2] != 0) return F_equal_to_not; + } // for + + return F_equal_to; + } +#endif // !defined(_di_fl_string_compare_except_) || !defined(_di_fl_string_dynamic_compare_except_) || !defined(_di_fl_string_dynamic_partial_compare_except_) + +#if !defined(_di_fl_string_compare_except_trim_) || !defined(_di_fl_string_dynamic_compare_except_trim_) || !defined(_di_fl_string_dynamic_partial_compare_except_trim_) + f_return_status private_fl_string_compare_except_trim(const f_string_t string1, const f_string_t string2, const f_string_length_t offset1, const f_string_length_t offset2, const f_string_length_t stop1, const f_string_length_t stop2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + f_string_length_t i1 = offset1; + f_string_length_t i2 = offset2; + + f_string_length_t e1 = 0; + f_string_length_t e2 = 0; + + uint8_t width = 0; + uint8_t width_max = 0; + f_status_t status = F_none; + + // skip past leading whitespace in string1. + for (; i1 < stop1; i1 += width) { + + // skip past NULL in string1. + while (i1 < stop1 && !string1[i1]) i1++; + if (i1 == stop1) break; + + // skip past except characters in string1. + while (e1 < except1.used && except1.array[e1] < i1) e1++; + if (e1 < except1.used && except1.array[e1] == i1) { + width = 1; + continue; + } + + width_max = (stop1 - i1) + 1; + status = f_utf_is_whitespace(string1 + i1, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + + width = f_macro_utf_byte_width(string1[i1]); + } // for + + // skip past leading whitespace in string2. + for (; i2 < stop2; i2 += width) { + + // skip past NULL in string2. + while (i2 < stop2 && !string2[i2]) i2++; + if (i2 == stop2) break; + + // skip past except characters in string2. + while (e2 < except2.used && except2.array[e2] < i2) e2++; + if (e2 < except2.used && except2.array[e2] == i2) { + width = 1; + continue; + } + + width_max = (stop2 - i2) + 1; + status = f_utf_is_whitespace(string2 + i2, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + + width = f_macro_utf_byte_width(string2[i2]); + } // for + + f_string_length_t last1 = i1; + f_string_length_t last2 = i2; + + { + // size1 and size2 are to represent to total number of characters after trim. + f_string_length_t size1 = 0; + f_string_length_t size2 = 0; + + f_string_length_t ej = e1; + + // determine where the last non-whitespace is in string1. + for (f_string_length_t j = i1; j < stop1; j += width) { + + // skip past NULL in string1. + while (j < stop1 && !string1[j]) j++; + if (j == stop1) break; + + // skip past except characters in string1. + while (ej < except1.used && except1.array[ej] < j) ej++; + if (ej < except1.used && except1.array[ej] == j) { + width = 1; + continue; + } + + width_max = (stop1 - j) + 1; + status = f_utf_is_whitespace(string1 + j, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + width = f_macro_utf_byte_width(string1[j]); + + if (status == F_false) { + last1 = j; + size1++; + } + } // for + + ej = e2; + + // determine where the last non-whitespace is in string2. + for (f_string_length_t j = i2; j < stop2; j += width) { + + // skip past NULL in string2. + while (j < stop2 && !string2[j]) j++; + if (j == stop2) break; + + // skip past except characters in string2. + while (ej < except2.used && except2.array[ej] < j) ej++; + if (ej < except2.used && except2.array[ej] == j) { + width = 1; + continue; + } + + width_max = (stop2 - j) + 1; + status = f_utf_is_whitespace(string2 + j, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + width = f_macro_utf_byte_width(string2[j]); + + if (status == F_false) { + last2 = j; + size2++; + } + } // for + + if (size1 != size2) return F_equal_to_not; + } + + while (i1 < last1 && i2 < last2) { + + // skip past NULL in string1. + while (i1 < last1 && !string1[i1]) i1++; + if (i1 == last1) break; + + // skip past NULL in string2. + while (i2 < last2 && !string2[i2]) i2++; + if (i2 == last2) break; + + // skip past except characters in string1. + while (e1 < except1.used && except1.array[e1] < i1) e1++; + if (e1 < except1.used && except1.array[e1] == i1) { + i1++; + continue; + } + + // skip past except characters in string2. + while (e2 < except2.used && except2.array[e2] < i2) e2++; + if (e2 < except2.used && except2.array[e2] == i2) { + i2++; + continue; + } + + if (string1[i1] != string2[i2]) return F_equal_to_not; + + i1++; + i2++; + } // while + + // only return F_equal_to if all remaining characters are NULL. + for (; i1 < last1; i1++) { + + if (string1[i1] != 0) { + + // skip past except characters in string1. + while (e1 < except1.used && except1.array[e1] < i1) e1++; + if (e1 < except1.used && except1.array[e1] == i1) continue; + + return F_equal_to_not; + } + } // for + + for (; i2 < last2; i2++) { + + if (string2[i2] != 0) { + + // skip past except characters in string1. + while (e2 < except2.used && except2.array[e2] < i2) e2++; + if (e2 < except2.used && except2.array[e2] == i2) continue; + + return F_equal_to_not; + } + } // for + + return F_equal_to; + } +#endif // !defined(_di_fl_string_compare_except_trim_) || !defined(_di_fl_string_dynamic_compare_except_trim_) || !defined(_di_fl_string_dynamic_partial_compare_except_trim_) + #if !defined(_di_fl_string_compare_trim_) || !defined(_di_fl_string_dynamic_compare_trim_) || !defined(_di_fl_string_dynamic_partial_compare_trim_) f_return_status private_fl_string_compare_trim(const f_string_t string1, const f_string_t string2, const f_string_length_t offset1, const f_string_length_t offset2, const f_string_length_t stop1, const f_string_length_t stop2) { f_string_length_t i1 = offset1; @@ -128,7 +401,9 @@ extern "C" { status = f_utf_is_whitespace(string1 + i1, width_max); if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } return status; } @@ -149,7 +424,9 @@ extern "C" { status = f_utf_is_whitespace(string2 + i2, width_max); if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } return status; } @@ -178,7 +455,9 @@ extern "C" { status = f_utf_is_whitespace(string1 + j, width_max); if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } return status; } @@ -202,7 +481,9 @@ extern "C" { status = f_utf_is_whitespace(string2 + j, width_max); if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_utf); + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } return status; } diff --git a/level_1/fl_string/c/private-string.h b/level_1/fl_string/c/private-string.h index ee9aab0..824bd90 100644 --- a/level_1/fl_string/c/private-string.h +++ b/level_1/fl_string/c/private-string.h @@ -105,6 +105,82 @@ extern "C" { #endif // !defined(_di_fl_string_compare_) || !defined(_di_fl_string_dynamic_compare_) || !defined(_di_fl_string_dynamic_partial_compare_) /** + * Private implementation of fl_string_compare_except(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param offset1 + * Offset of string1 to start at. + * @param offset2 + * Offset of string2 to start at. + * @param stop1 + * Exclusive stop position for string1. + * @param stop2 + * Exclusive stop position for string2. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fl_string_compare_except() + * @see fl_string_dynamic_compare_except() + * @see fl_string_dynamic_partial_compare_except() + */ +#if !defined(_di_fl_string_compare_except_) || !defined(_di_fl_string_dynamic_compare_except_) || !defined(_di_fl_string_dynamic_partial_compare_except_) + extern f_return_status private_fl_string_compare_except(const f_string_t string1, const f_string_t string2, const f_string_length_t offset1, const f_string_length_t offset2, const f_string_length_t stop1, const f_string_length_t stop2, const f_string_lengths_t except1, const f_string_lengths_t except2) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fl_string_compare_except_) || !defined(_di_fl_string_dynamic_compare_except_) || !defined(_di_fl_string_dynamic_partial_compare_except_) + +/** + * Private implementation of fl_string_compare_except_trim(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param offset1 + * Offset of string1 to start at. + * @param offset2 + * Offset of string2 to start at. + * @param stop1 + * Exclusive stop position for string1. + * @param stop2 + * Exclusive stop position for string2. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fl_string_compare_except_trim() + * @see fl_string_dynamic_compare_except_trim() + * @see fl_string_dynamic_partial_compare_except_trim() + */ +#if !defined(_di_fl_string_compare_except_trim_) || !defined(_di_fl_string_dynamic_compare_except_trim_) || !defined(_di_fl_string_dynamic_partial_compare_except_trim_) + extern f_return_status private_fl_string_compare_except_trim(const f_string_t string1, const f_string_t string2, const f_string_length_t offset1, const f_string_length_t offset2, const f_string_length_t stop1, const f_string_length_t stop2, const f_string_lengths_t except1, const f_string_lengths_t except2) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fl_string_compare_except_trim_) || !defined(_di_fl_string_dynamic_compare_except_trim_) || !defined(_di_fl_string_dynamic_partial_compare_except_trim_) + +/** * Private implementation of fl_string_compare_trim(). * * Intended to be shared to each of the different implementation variations. diff --git a/level_1/fl_string/c/string.c b/level_1/fl_string/c/string.c index 0300ce8..0f6816c 100644 --- a/level_1/fl_string/c/string.c +++ b/level_1/fl_string/c/string.c @@ -108,6 +108,18 @@ extern "C" { } #endif // _di_fl_string_compare_ +#ifndef _di_fl_string_compare_except_ + f_return_status fl_string_compare_except(const f_string_t string1, const f_string_t string2, const f_string_length_t length1, const f_string_length_t length2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + return private_fl_string_compare_except(string1, string2, 0, 0, length1, length2, except1, except2); + } +#endif // _di_fl_string_compare_except_ + +#ifndef _di_fl_string_compare_except_trim_ + f_return_status fl_string_compare_except_trim(const f_string_t string1, const f_string_t string2, const f_string_length_t length1, const f_string_length_t length2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + return private_fl_string_compare_except_trim(string1, string2, 0, 0, length1, length2, except1, except2); + } +#endif // _di_fl_string_compare_except_trim_ + #ifndef _di_fl_string_compare_trim_ f_return_status fl_string_compare_trim(const f_string_t string1, const f_string_t string2, const f_string_length_t length1, const f_string_length_t length2) { return private_fl_string_compare_trim(string1, string2, 0, 0, length1, length2); @@ -220,6 +232,30 @@ extern "C" { } #endif // _di_fl_string_dynamic_compare_ +#ifndef _di_fl_string_dynamic_compare_except_ + f_return_status fl_string_dynamic_compare_except(const f_string_static_t string1, const f_string_static_t string2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + return private_fl_string_compare_except(string1.string, string2.string, 0, 0, string1.used, string2.used, except1, except2); + } +#endif // _di_fl_string_dynamic_compare_except_ + +#ifndef _di_fl_string_dynamic_compare_except_string_ + f_return_status fl_string_dynamic_compare_except_string(const f_string_t string1, const f_string_static_t string2, const f_string_length_t length1, const f_string_lengths_t except1, const f_string_lengths_t except2) { + return private_fl_string_compare_except(string1, string2.string, 0, 0, length1, string2.used, except1, except2); + } +#endif // _di_fl_string_dynamic_compare_except_string_ + +#ifndef _di_fl_string_dynamic_compare_except_trim_ + f_return_status fl_string_dynamic_compare_except_trim(const f_string_static_t string1, const f_string_static_t string2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + return private_fl_string_compare_except_trim(string1.string, string2.string, 0, 0, string1.used, string2.used, except1, except2); + } +#endif // _di_fl_string_dynamic_compare_except_trim_ + +#ifndef _di_fl_string_dynamic_compare_except_trim_string_ + f_return_status fl_string_dynamic_compare_except_trim_string(const f_string_t string1, const f_string_static_t string2, const f_string_length_t length1, const f_string_lengths_t except1, const f_string_lengths_t except2) { + return private_fl_string_compare_except_trim(string1, string2.string, 0, 0, length1, string2.used, except1, except2); + } +#endif // _di_fl_string_dynamic_compare_except_trim_string_ + #ifndef _di_fl_string_dynamic_compare_string_ f_return_status fl_string_dynamic_compare_string(const f_string_t string1, const f_string_static_t string2, const f_string_length_t length1) { return private_fl_string_compare(string1, string2.string, 0, 0, length1, string2.used); @@ -445,6 +481,68 @@ extern "C" { } #endif // _di_fl_string_dynamic_partial_compare_string_ +#ifndef _di_fl_string_dynamic_partial_compare_except_ + f_return_status fl_string_dynamic_partial_compare_except(const f_string_static_t string1, const f_string_static_t string2, const f_string_range_t range1, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + #ifndef _di_level_1_parameter_checking_ + if (string1.used <= range1.stop) return F_status_set_error(F_parameter); + if (string2.used <= range2.stop) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_string_compare_except(string1.string, string2.string, range1.start, range2.start, range1.stop + 1, range2.stop + 1, except1, except2); + } +#endif // _di_fl_string_dynamic_partial_compare_except_ + +#ifndef _di_fl_string_dynamic_partial_compare_except_dynamic_ + f_return_status fl_string_dynamic_partial_compare_except_dynamic(const f_string_static_t string1, const f_string_static_t string2, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + #ifndef _di_level_1_parameter_checking_ + if (string2.used <= range2.stop) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_string_compare_except(string1.string, string2.string, 0, range2.start, string1.used, range2.stop + 1, except1, except2); + } +#endif // _di_fl_string_dynamic_partial_compare_except_dynamic_ + +#ifndef _di_fl_string_dynamic_partial_compare_except_string_ + f_return_status fl_string_dynamic_partial_compare_except_string(const f_string_t string1, const f_string_static_t string2, const f_string_length_t length1, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + #ifndef _di_level_1_parameter_checking_ + if (string2.used <= range2.stop) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_string_compare_except(string1, string2.string, 0, range2.start, length1, range2.stop + 1, except1, except2); + } +#endif // _di_fl_string_dynamic_partial_compare_except_string_ + +#ifndef _di_fl_string_dynamic_partial_compare_except_trim_ + f_return_status fl_string_dynamic_partial_compare_except_trim(const f_string_static_t string1, const f_string_static_t string2, const f_string_range_t range1, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + #ifndef _di_level_1_parameter_checking_ + if (string1.used <= range1.stop) return F_status_set_error(F_parameter); + if (string2.used <= range2.stop) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_string_compare_except_trim(string1.string, string2.string, range1.start, range2.start, range1.stop + 1, range2.stop + 1, except1, except2); + } +#endif // _di_fl_string_dynamic_partial_compare_except_trim_ + +#ifndef _di_fl_string_dynamic_partial_compare_except_trim_dynamic_ + f_return_status fl_string_dynamic_partial_compare_except_trim_dynamic(const f_string_static_t string1, const f_string_static_t string2, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + #ifndef _di_level_1_parameter_checking_ + if (string2.used <= range2.stop) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_string_compare_except_trim(string1.string, string2.string, 0, range2.start, string1.used, range2.stop + 1, except1, except2); + } +#endif // _di_fl_string_dynamic_partial_compare_except_trim_dynamic_ + +#ifndef _di_fl_string_dynamic_partial_compare_except_trim_string_ + f_return_status fl_string_dynamic_partial_compare_except_trim_string(const f_string_t string1, const f_string_static_t string2, const f_string_length_t length1, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2) { + #ifndef _di_level_1_parameter_checking_ + if (string2.used <= range2.stop) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_string_compare_except_trim(string1, string2.string, 0, range2.start, length1, range2.stop + 1, except1, except2); + } +#endif // _di_fl_string_dynamic_partial_compare_except_trim_string_ + #ifndef _di_fl_string_dynamic_partial_compare_trim_ f_return_status fl_string_dynamic_partial_compare_trim(const f_string_static_t string1, const f_string_static_t string2, const f_string_range_t range1, const f_string_range_t range2) { #ifndef _di_level_1_parameter_checking_ diff --git a/level_1/fl_string/c/string.h b/level_1/fl_string/c/string.h index 5510d1b..c157dc2 100644 --- a/level_1/fl_string/c/string.h +++ b/level_1/fl_string/c/string.h @@ -158,6 +158,73 @@ extern "C" { * * This does not stop on NULL. * NULL characters are ignored. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param length1 + * Length of string1. + * @param length2 + * Length of string2. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fl_string_compare_except_ + extern f_return_status fl_string_compare_except(const f_string_t string1, const f_string_t string2, const f_string_length_t length1, const f_string_length_t length2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_compare_except_ + +/** + * Compare two strings, similar to strncmp(). + * + * This does not stop on NULL. + * NULL characters are ignored. + * Ignores leading and trailing whitespace. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param length1 + * Length of string1. + * @param length2 + * Length of string2. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see f_utf_is_whitespace() + */ +#ifndef _di_fl_string_compare_except_trim_ + extern f_return_status fl_string_compare_except_trim(const f_string_t string1, const f_string_t string2, const f_string_length_t length1, const f_string_length_t length2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_compare_except_trim_ + +/** + * Compare two strings, similar to strncmp(). + * + * This does not stop on NULL. + * NULL characters are ignored. * Ignores leading and trailing whitespace. * * @param string1 @@ -289,6 +356,137 @@ extern "C" { /** * Compare two strings, similar to strncmp(). * + * This does not stop on NULL. + * NULL characters are ignored. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fl_string_dynamic_compare_except_ + extern f_return_status fl_string_dynamic_compare_except(const f_string_static_t string1, const f_string_static_t string2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_compare_except_ + +/** + * Compare two strings, similar to strncmp(). + * + * This operates with the first string being a traditional string. + * + * This does not stop on NULL. + * NULL characters are ignored. + * Ignores leading and trailing whitespace. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param length1 + * The length of string1. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see f_utf_is_whitespace() + */ +#ifndef _di_fl_string_dynamic_compare_except_string_ + extern f_return_status fl_string_dynamic_compare_except_string(const f_string_t string1, const f_string_static_t string2, const f_string_length_t length1, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_compare_except_string_ + +/** + * Compare two strings, similar to strncmp(). + * + * This does not stop on NULL. + * NULL characters are ignored. + * Ignores leading and trailing whitespace. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see f_utf_is_whitespace() + */ +#ifndef _di_fl_string_dynamic_compare_except_trim_ + extern f_return_status fl_string_dynamic_compare_except_trim(const f_string_static_t string1, const f_string_static_t string2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_compare_except_trim_ + +/** + * Compare two strings, similar to strncmp(). + * + * This operates with the first string being a traditional string. + * + * This does not stop on NULL. + * NULL characters are ignored. + * Ignores leading and trailing whitespace. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param length1 + * The length of string1. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see f_utf_is_whitespace() + */ +#ifndef _di_fl_string_dynamic_compare_except_trim_string_ + extern f_return_status fl_string_dynamic_compare_except_trim_string(const f_string_t string1, const f_string_static_t string2, const f_string_length_t length1, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_compare_except_trim_string_ + +/** + * Compare two strings, similar to strncmp(). + * * This operates with the first string being a traditional string. * * This does not stop on NULL. @@ -602,6 +800,207 @@ extern "C" { #endif // _di_fl_string_dynamic_partial_compare_ /** + * Compare two strings, similar to strncmp(), but restricted to the given ranges. + * + * This does not stop on NULL. + * NULL characters are ignored. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param range1 + * A range within the string1 to restrict the comparison to. + * @param range2 + * A range within the string2 to restrict the comparison to. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fl_string_dynamic_partial_compare_except_ + extern f_return_status fl_string_dynamic_partial_compare_except(const f_string_static_t string1, const f_string_static_t string2, const f_string_range_t range1, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_partial_compare_except_ + +/** + * Compare two strings, similar to strncmp(), but restricted to the given range for the second string. + * + * This does not stop on NULL. + * NULL characters are ignored. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param range2 + * A range within the string2 to restrict the comparison to. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fl_string_dynamic_partial_compare_except_dynamic_ + extern f_return_status fl_string_dynamic_partial_compare_except_dynamic(const f_string_static_t string1, const f_string_static_t string2, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_partial_compare_except_dynamic_ + +/** + * Compare two strings, similar to strncmp(), but restricted to the given range for the second string. + * + * This operates with the first string being a traditional string. + * + * This does not stop on NULL. + * NULL characters are ignored. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param length1 + * The length of string1. + * @param range2 + * A range within the string2 to restrict the comparison to. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fl_string_dynamic_partial_compare_except_string_ + extern f_return_status fl_string_dynamic_partial_compare_except_string(const f_string_t string1, const f_string_static_t string2, const f_string_length_t length1, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_partial_compare_except_string_ + +/** + * Compare two strings, similar to strncmp(), but restricted to the given range for the second string. + * + * This does not stop on NULL. + * NULL characters are ignored. + * Ignores leading and trailing whitespace. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param range2 + * A range within the string2 to restrict the comparison to. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see f_utf_is_whitespace() + */ +#ifndef _di_fl_string_dynamic_partial_compare_except_trim_dynamic_ + extern f_return_status fl_string_dynamic_partial_compare_except_trim_dynamic(const f_string_static_t string1, const f_string_static_t string2, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_partial_compare_except_trim_dynamic_ + +/** + * Compare two strings, similar to strncmp(), but restricted to the given range for the second string. + * + * This operates with the first string being a traditional string. + * + * This does not stop on NULL. + * NULL characters are ignored. + * Ignores leading and trailing whitespace. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param length1 + * The length of string1. + * @param range2 + * A range within the string2 to restrict the comparison to. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see f_utf_is_whitespace() + */ +#ifndef _di_fl_string_dynamic_partial_compare_except_trim_string_ + extern f_return_status fl_string_dynamic_partial_compare_except_trim_string(const f_string_t string1, const f_string_static_t string2, const f_string_length_t length1, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_partial_compare_except_trim_string_ + +/** + * Compare two strings, similar to strncmp(), but restricted to the given ranges. + * + * This does not stop on NULL. + * NULL characters are ignored. + * Ignores leading and trailing whitespace. + * All 1-byte characters in except1 and except2 are ignored. + * + * @param string1 + * String to compare. + * @param string2 + * String to compare. + * @param range1 + * A range within the string1 to restrict the comparison to. + * @param range2 + * A range within the string2 to restrict the comparison to. + * @param except1 + * A set of locations within string1 to ignore. + * This assumes/requires that the locations be in linear order. + * @param except2 + * A set of locations within string2 to ignore. + * This assumes/requires that the locations be in linear order. + * + * @return + * F_equal_to when both strings equal. + * F_equal_to_not when both strings do not equal. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see f_utf_is_whitespace() + */ +#ifndef _di_fl_string_dynamic_partial_compare_except_trim_ + extern f_return_status fl_string_dynamic_partial_compare_except_trim(const f_string_static_t string1, const f_string_static_t string2, const f_string_range_t range1, const f_string_range_t range2, const f_string_lengths_t except1, const f_string_lengths_t except2); +#endif // _di_fl_string_dynamic_partial_compare_except_trim_ + +/** * Compare two strings, similar to strncmp(), but restricted to the given range for the second string. * * This does not stop on NULL. -- 1.8.3.1