From: Kevin Day Date: Fri, 8 May 2020 02:47:18 +0000 (-0500) Subject: Update: numerous fixes and additions, mostly string related X-Git-Tag: 0.5.0~284 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=161019c1baffd06c12a2c526c08618afce41a69a;p=fll Update: numerous fixes and additions, mostly string related Not sure how I let this one get through, but add missing return statement in a couple of private string functions where it is missing. In retrospect, it seems that I was overzealous with some of the parameter checks. Redo the parameter checks to not be as sting on string length and buffer size ranges. Instead, just return that there is nothing to do instead of erroring out. Add string terminate functions. These functions are designed to guarantee that an end of string exists at the end of some dynamic string. Add functions for appending one or more arguments to the arguments array for the execute functions. This functionality is common enough (used extensively by firewall and soon to be used by fake). Support providing an array of arguments to append. This greatly simplifies long-winded code. Minor fixes and cleanups in the execute functions: - Add missing parameter checks. - Rename results to result to be more accurate. Add length defines for console symbols. --- diff --git a/build/level_2/settings b/build/level_2/settings index 231da09..bc0aa1b 100644 --- a/build/level_2/settings +++ b/build/level_2/settings @@ -12,7 +12,7 @@ build_linker ar build_libraries -lc build_libraries_fll -lfll_0 -lfll_1 build_libraries_fll-level -lfll_0 -lfll_1 -build_sources_library execute.c file.c fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c program.c status.c +build_sources_library execute.c private-execute.c file.c fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c program.c status.c build_sources_program build_sources_headers execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h program.h status.h build_shared yes diff --git a/build/monolithic/settings b/build/monolithic/settings index 14bc65b..e79f99f 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -11,7 +11,7 @@ build_compiler gcc build_linker ar build_libraries -lc build_libraries_fll -build_sources_library level_0/console.c level_0/conversion.c level_0/file.c level_0/memory.c level_0/pipe.c level_0/print.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/directory.c level_1/file.c level_1/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/print.c level_1/serialized.c level_1/private-serialized.c level_1/socket.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_2/execute.c level_2/file.c level_2/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/program.c level_2/status.c +build_sources_library level_0/console.c level_0/conversion.c level_0/file.c level_0/memory.c level_0/pipe.c level_0/print.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/directory.c level_1/file.c level_1/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/print.c level_1/serialized.c level_1/private-serialized.c level_1/socket.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_2/execute.c level_2/private-execute.c level_2/file.c level_2/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/program.c level_2/status.c build_sources_program build_sources_headers level_0/color.h level_0/console.h level_0/conversion.h level_0/file.h level_0/fss.h level_0/memory.h level_0/path_fll.h level_0/path_filesystem.h level_0/pipe.h level_0/print.h level_0/serialized.h level_0/socket.h level_0/status.h level_0/string.h level_0/type.h level_0/type_array.h level_0/utf.h level_1/color.h level_1/console.h level_1/directory.h level_1/file.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_status.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/print.h level_1/serialized.h level_1/socket.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.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/program.h level_2/status.h build_sources_bash diff --git a/level_0/f_console/c/console.h b/level_0/f_console/c/console.h index 3ca9b6e..7f60c71 100644 --- a/level_0/f_console/c/console.h +++ b/level_0/f_console/c/console.h @@ -56,8 +56,14 @@ extern "C" { #define f_console_symbol_short_enable "-" #define f_console_symbol_short_disable "+" + #define f_console_symbol_short_enable_length 1 + #define f_console_symbol_short_disable_length 1 + #define f_console_symbol_long_enable "--" #define f_console_symbol_long_disable "++" + + #define f_console_symbol_long_enable_length 2 + #define f_console_symbol_long_disable_length 2 #endif // _di_f_console_symbols_ /** diff --git a/level_0/f_type/c/type.h b/level_0/f_type/c/type.h index 6a253ea..e70e840 100644 --- a/level_0/f_type/c/type.h +++ b/level_0/f_type/c/type.h @@ -189,7 +189,8 @@ extern "C" { #ifndef _di_f_array_ typedef f_number_unsigned f_array_length; - #define f_array_max_size f_type_number_size_unsigned + #define f_array_length_size f_type_number_size_unsigned + #define f_array_length_size_max f_type_number_size_max_unsigned #endif // _di_f_array_ /** diff --git a/level_1/fl_file/c/file.h b/level_1/fl_file/c/file.h index 65aded3..e3a6bf1 100644 --- a/level_1/fl_file/c/file.h +++ b/level_1/fl_file/c/file.h @@ -35,7 +35,7 @@ extern "C" { * f_file_error_read (with error bit) if file read failed. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_reallocation (with error bit) on memory reallocation error. - * f_string_too_large (with error bit) if string is too large to fit into buffer. + * f_string_too_large (with error bit) if string is too large to fit into the buffer. */ #ifndef _di_fl_file_read_ extern f_return_status fl_file_read(f_file *file, f_string_dynamic *buffer); @@ -59,7 +59,7 @@ extern "C" { * f_file_error_read (with error bit) if file read failed. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_reallocation (with error bit) on memory reallocation error. - * f_string_too_large (with error bit) if string is too large to fit into buffer. + * f_string_too_large (with error bit) if string is too large to fit into the buffer. */ #ifndef _di_fl_file_read_position_ extern f_return_status fl_file_read_position(f_file *file, f_string_dynamic *buffer, const f_file_position position); diff --git a/level_1/fl_string/c/private-string.c b/level_1/fl_string/c/private-string.c index 3643126..11e053b 100644 --- a/level_1/fl_string/c/private-string.c +++ b/level_1/fl_string/c/private-string.c @@ -117,6 +117,8 @@ extern "C" { for (; i2 < stop2; i2++) { if (string2[i2] != f_string_eos) return f_not_equal_to; } // for + + return f_equal_to; } #endif // !defined(_di_fl_string_compare_) || !defined(_di_fl_string_dynamic_compare_) || !defined(_di_fl_string_dynamic_partial_compare_) diff --git a/level_1/fl_string/c/string.c b/level_1/fl_string/c/string.c index 41bb209..84dd1ac 100644 --- a/level_1/fl_string/c/string.c +++ b/level_1/fl_string/c/string.c @@ -8,10 +8,11 @@ extern "C" { #ifndef _di_fl_string_append_ f_return_status fl_string_append(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (start > stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + return private_fl_string_append(source, start, stop, destination); } #endif // _di_fl_string_append_ @@ -19,54 +20,35 @@ extern "C" { #ifndef _di_fl_string_append_nulless_ f_return_status fl_string_append_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (start > stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + return private_fl_string_append_nulless(source, start, stop, destination); } #endif // _di_fl_string_append_nulless_ #ifndef _di_fl_string_compare_ f_return_status fl_string_compare(const f_string string1, const f_string string2, const f_string_length length1, const f_string_length length2) { - #ifndef _di_level_1_parameter_checking_ - if (length1 <= 0) return f_status_set_error(f_invalid_parameter); - if (length2 <= 0) return f_status_set_error(f_invalid_parameter); - #endif // _di_level_1_parameter_checking_ - return private_fl_string_compare(string1, string2, 0, 0, length1, length2); } #endif // _di_fl_string_compare_ #ifndef _di_fl_string_compare_trim_ f_return_status fl_string_compare_trim(const f_string string1, const f_string string2, const f_string_length length1, const f_string_length length2) { - #ifndef _di_level_1_parameter_checking_ - if (length1 <= 0) return f_status_set_error(f_invalid_parameter); - if (length2 <= 0) return f_status_set_error(f_invalid_parameter); - #endif // _di_level_1_parameter_checking_ - return private_fl_string_compare_trim(string1, string2, 0, 0, length1, length2); } #endif // _di_fl_string_compare_trim_ #ifndef _di_fl_string_dynamic_compare_ f_return_status fl_string_dynamic_compare(const f_string_dynamic string1, const f_string_dynamic string2) { - #ifndef _di_level_1_parameter_checking_ - if (string1.used <= 0) return f_status_set_error(f_invalid_parameter); - if (string2.used <= 0) return f_status_set_error(f_invalid_parameter); - #endif // _di_level_1_parameter_checking_ - return private_fl_string_compare(string1.string, string2.string, 0, 0, string1.used, string2.used); } #endif // _di_fl_string_dynamic_compare_ #ifndef _di_fl_string_dynamic_compare_trim_ f_return_status fl_string_dynamic_compare_trim(const f_string_dynamic string1, const f_string_dynamic string2) { - #ifndef _di_level_1_parameter_checking_ - if (string1.used <= 0) return f_status_set_error(f_invalid_parameter); - if (string2.used <= 0) return f_status_set_error(f_invalid_parameter); - #endif // _di_level_1_parameter_checking_ - return private_fl_string_compare_trim(string1.string, string2.string, 0, 0, string1.used, string2.used); } #endif // _di_fl_string_dynamic_compare_trim_ @@ -74,10 +56,11 @@ extern "C" { #ifndef _di_fl_string_dynamic_append_ f_return_status fl_string_dynamic_append(const f_string_dynamic source, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + return private_fl_string_append(source.string, 0, source.used - 1, destination); } #endif // _di_fl_string_dynamic_append_ @@ -85,10 +68,11 @@ extern "C" { #ifndef _di_fl_string_dynamic_append_nulless_ f_return_status fl_string_dynamic_append_nulless(const f_string_dynamic source, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + return private_fl_string_append_nulless(source.string, 0, source.used - 1, destination); } #endif // _di_fl_string_dynamic_append_nulless_ @@ -96,17 +80,15 @@ extern "C" { #ifndef _di_fl_string_dynamic_mash_ f_return_status fl_string_dynamic_mash(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_append(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_append(source.string, 0, source.used - 1, destination); @@ -116,17 +98,15 @@ extern "C" { #ifndef _di_fl_string_dynamic_mash_nulless_ f_return_status fl_string_dynamic_mash_nulless(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_append_nulless(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_append_nulless(source.string, 0, source.used - 1, destination); @@ -136,17 +116,15 @@ extern "C" { #ifndef _di_fl_string_dynamic_mish_ f_return_status fl_string_dynamic_mish(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_prepend(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_prepend(source.string, 0, source.used - 1, destination); @@ -156,17 +134,15 @@ extern "C" { #ifndef _di_fl_string_dynamic_mish_nulless_ f_return_status fl_string_dynamic_mish_nulless(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_prepend_nulless(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_prepend_nulless(source.string, 0, source.used - 1, destination); @@ -176,12 +152,13 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_append_ f_return_status fl_string_dynamic_partial_append(const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_string_append(source.string, range.start, range.stop, destination); } #endif // _di_fl_string_dynamic_partial_append_ @@ -189,12 +166,13 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_append_nulless_ f_return_status fl_string_dynamic_partial_append_nulless(const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_string_append_nulless(source.string, range.start, range.stop, destination); } #endif // _di_fl_string_dynamic_append_nulless_ @@ -202,12 +180,6 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_compare_ f_return_status fl_string_dynamic_partial_compare(const f_string_dynamic string1, const f_string_dynamic string2, const f_string_location range1, const f_string_location range2) { #ifndef _di_level_1_parameter_checking_ - if (string1.used <= 0) return f_status_set_error(f_invalid_parameter); - if (string2.used <= 0) return f_status_set_error(f_invalid_parameter); - - if (range1.start > range1.stop) return f_status_set_error(f_invalid_parameter); - if (range2.start > range2.stop) return f_status_set_error(f_invalid_parameter); - if (string1.used <= range1.stop) return f_status_set_error(f_invalid_parameter); if (string2.used <= range2.stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ @@ -219,12 +191,6 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_compare_trim_ f_return_status fl_string_dynamic_partial_compare_trim(const f_string_dynamic string1, const f_string_dynamic string2, const f_string_location range1, const f_string_location range2) { #ifndef _di_level_1_parameter_checking_ - if (string1.used <= 0) return f_status_set_error(f_invalid_parameter); - if (string2.used <= 0) return f_status_set_error(f_invalid_parameter); - - if (range1.start > range1.stop) return f_status_set_error(f_invalid_parameter); - if (range2.start > range2.stop) return f_status_set_error(f_invalid_parameter); - if (string1.used <= range1.stop) return f_status_set_error(f_invalid_parameter); if (string2.used <= range2.stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ @@ -236,19 +202,17 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_mash_ f_return_status fl_string_dynamic_partial_mash(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_append(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_append(source.string, range.start, range.stop, destination); @@ -258,19 +222,17 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_mash_nulless_ f_return_status fl_string_dynamic_partial_mash_nulless(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_append_nulless(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_append_nulless(source.string, range.start, range.stop, destination); @@ -280,19 +242,17 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_mish_ f_return_status fl_string_partial_dynamic_mish(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_prepend(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_prepend(source.string, range.start, range.stop, destination); @@ -302,19 +262,17 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_mish_nulless_ f_return_status fl_string_dynamic_partial_mish_nulless(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_prepend_nulless(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_prepend_nulless(source.string, range.start, range.stop, destination); @@ -324,12 +282,13 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_prepend_ f_return_status fl_string_dynamic_partial_prepend(const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_string_prepend(source.string, range.start, range.stop, destination); } #endif // _di_fl_string_dynamic_partial_prepend_ @@ -337,12 +296,13 @@ extern "C" { #ifndef _di_fl_string_dynamic_partial_prepend_nulless_ f_return_status fl_string_dynamic_partial_prepend_nulless(const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_string_prepend_nulless(source.string, range.start, range.stop, destination); } #endif // _di_fl_string_dynamic_partial_prepend_nulless @@ -350,10 +310,11 @@ extern "C" { #ifndef _di_fl_string_dynamic_prepend_ f_return_status fl_string_dynamic_prepend(const f_string_dynamic source, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + return private_fl_string_prepend(source.string, 0, source.used - 1, destination); } #endif // _di_fl_string_dynamic_prepend_ @@ -361,10 +322,11 @@ extern "C" { #ifndef _di_fl_string_dynamic_prepend_nulless_ f_return_status fl_string_dynamic_prepend_nulless(const f_string_dynamic source, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + return private_fl_string_prepend_nulless(source.string, 0, source.used - 1, destination); } #endif // _di_fl_string_dynamic_prepend_nulless_ @@ -372,13 +334,14 @@ extern "C" { #ifndef _di_fl_string_dynamic_rip_ f_return_status fl_string_dynamic_rip(const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (range.stop < range.start) return f_status_set_error(f_invalid_parameter); - if (source.used <= 0) return f_status_set_error(f_invalid_parameter); if (source.used <= range.start) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_string_append(source.string, range.start, range.stop, destination); } #endif // _di_fl_string_dynamic_rip_ @@ -386,13 +349,14 @@ extern "C" { #ifndef _di_fl_string_dynamic_rip_nulless_ f_return_status fl_string_dynamic_rip_nulless(const f_string_dynamic source, const f_string_location range, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (range.stop < range.start) return f_status_set_error(f_invalid_parameter); - if (source.used <= 0) return f_status_set_error(f_invalid_parameter); if (source.used <= range.start) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_string_append_nulless(source.string, range.start, range.stop, destination); } #endif // _di_fl_string_dynamic_rip_nulless_ @@ -401,13 +365,13 @@ extern "C" { f_return_status fl_string_dynamic_seek_line_to(const f_string_dynamic buffer, f_string_location *location, const int8_t seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + while (buffer.string[location->start] != seek_to_this) { if (buffer.string[location->start] == f_string_eol) return f_none_on_eol; @@ -425,13 +389,13 @@ extern "C" { f_return_status fl_string_dynamic_seek_line_to_utf_character(const f_string_dynamic buffer, f_string_location *location, const f_utf_character seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + const unsigned short seek_width = f_macro_utf_character_width(seek_to_this); f_status status = f_none; @@ -470,13 +434,8 @@ extern "C" { f_utf_character character = 0; status = f_utf_char_to_character(buffer.string + location->start, width_max, &character); - if (f_status_is_error(status)) { - return status; - } - - if (character == seek_to_this) { - return f_none; - } + if (f_status_is_error(status)) return status; + if (character == seek_to_this) return f_none; } } @@ -493,13 +452,13 @@ extern "C" { f_return_status fl_string_dynamic_seek_line_until_graph(const f_string_dynamic buffer, f_string_location *location, const int8_t placeholder) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + f_status status = f_none; unsigned short width = 0; @@ -510,10 +469,7 @@ extern "C" { } while (buffer.string[location->start] == placeholder || (status = f_utf_is_graph(buffer.string + location->start, width_max)) == f_false) { - if (f_status_is_error(status)) { - return status; - } - + if (f_status_is_error(status)) return status; if (buffer.string[location->start] == f_string_eol) return f_none_on_eol; width = f_macro_utf_byte_width_is(buffer.string[location->start]); @@ -542,9 +498,7 @@ extern "C" { } } // while - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; return f_none; } @@ -554,13 +508,13 @@ extern "C" { f_return_status fl_string_dynamic_seek_line_until_non_graph(const f_string_dynamic buffer, f_string_location *location, const int8_t placeholder) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + f_status status = f_none; unsigned short width = 0; @@ -571,10 +525,7 @@ extern "C" { } while (buffer.string[location->start] == placeholder || (status = f_utf_is_whitespace(buffer.string + location->start, width_max)) == f_false) { - if (f_status_is_error(status)) { - return status; - } - + if (f_status_is_error(status)) return status; if (buffer.string[location->start] == f_string_eol) return f_none_on_eol; width = f_macro_utf_byte_width_is(buffer.string[location->start]); @@ -603,9 +554,7 @@ extern "C" { } } // while - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; return f_none; } @@ -615,13 +564,13 @@ extern "C" { f_return_status fl_string_dynamic_seek_to(const f_string_dynamic buffer, f_string_location *location, const int8_t seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + while (buffer.string[location->start] != seek_to_this) { location->start++; @@ -637,13 +586,13 @@ extern "C" { f_return_status fl_string_dynamic_seek_to_utf_character(const f_string_dynamic buffer, f_string_location *location, const f_utf_character seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + const unsigned short seek_width = f_macro_utf_character_width(seek_to_this); f_status status = f_none; @@ -680,13 +629,8 @@ extern "C" { f_utf_character character = 0; status = f_utf_char_to_character(buffer.string + location->start, width_max, &character); - if (f_status_is_error(status)) { - return status; - } - - if (character == seek_to_this) { - return f_none; - } + if (f_status_is_error(status)) return status; + if (character == seek_to_this) return f_none; } } @@ -699,20 +643,45 @@ extern "C" { } #endif // _di_fl_string_dynamic_seek_to_utf_character_ +#ifndef _di_fl_string_dynamic_terminate_ + f_return_status fl_string_dynamic_terminate(f_string_dynamic *destination) { + #ifndef _di_level_1_parameter_checking_ + if (destination == 0) return f_status_set_error(f_invalid_parameter); + if (destination->used > destination->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_1_parameter_checking_ + + if (destination->used > 0 && destination->string[destination->used - 1] == f_string_eos) return f_none; + + if (destination->used + 1 > f_string_max_size) return f_status_set_error(f_string_too_large); + + const f_string_length total = destination->used + 1; + + if (total > destination->size) { + f_status status = f_none; + + f_macro_string_dynamic_resize(status, (*destination), total); + if (f_status_is_error(status)) return status; + } + + destination->string[destination->used] = f_string_eos; + destination->used = total; + + return f_none; + } +#endif // _di_fl_string_dynamic_terminate_ + #ifndef _di_fl_string_mash_ f_return_status fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (start > stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_append(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_append(source, start, stop, destination); @@ -722,17 +691,15 @@ extern "C" { #ifndef _di_fl_string_mash_nulless_ f_return_status fl_string_mash_nulless(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (start > stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_append_nulless(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_append_nulless(source, start, stop, destination); @@ -742,17 +709,15 @@ extern "C" { #ifndef _di_fl_string_mish_ f_return_status fl_string_mish(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (start > stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_prepend(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_prepend(source, start, stop, destination); @@ -762,17 +727,15 @@ extern "C" { #ifndef _di_fl_string_mish_nulless_ f_return_status fl_string_mish_nulless(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (start > stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_string_prepend_nulless(glue, 0, glue_length - 1, destination); - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; } return private_fl_string_prepend_nulless(source, start, stop, destination); @@ -782,10 +745,11 @@ extern "C" { #ifndef _di_fl_string_prepend_ f_return_status fl_string_prepend(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + return private_fl_string_prepend(source, start, stop, destination); } #endif // _di_fl_string_prepend_ @@ -793,10 +757,11 @@ extern "C" { #ifndef _di_fl_string_prepend_nulless_ f_return_status fl_string_prepend_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + return private_fl_string_prepend_nulless(source, start, stop, destination); } #endif // _di_fl_string_prepend_nulless_ @@ -804,10 +769,11 @@ extern "C" { #ifndef _di_fl_string_rip_ f_return_status fl_string_rip(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (start > stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + f_string_length begin = start; f_string_length end = stop; @@ -823,10 +789,11 @@ extern "C" { #ifndef _di_fl_string_rip_nulless_ f_return_status fl_string_rip_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (start > stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + f_string_length begin = start; f_string_length end = stop; @@ -843,10 +810,10 @@ extern "C" { f_return_status fl_string_seek_line_to(const f_string string, f_string_location *location, const int8_t seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + while (string[location->start] != seek_to_this) { if (string[location->start] == f_string_eol) return f_none_on_eol; @@ -863,10 +830,10 @@ extern "C" { f_return_status fl_string_seek_line_to_utf_character(const f_string string, f_string_location *location, const f_utf_character seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + const unsigned short seek_width = f_macro_utf_character_width(seek_to_this); f_status status = f_none; @@ -900,13 +867,8 @@ extern "C" { f_utf_character character = 0; status = f_utf_char_to_character(string + location->start, width_max, &character); - if (f_status_is_error(status)) { - return status; - } - - if (character == seek_to_this) { - return f_none; - } + if (f_status_is_error(status)) return status; + if (character == seek_to_this) return f_none; } } } // for @@ -919,20 +881,17 @@ extern "C" { f_return_status fl_string_seek_line_until_graph(const f_string string, f_string_location *location, const int8_t placeholder) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + f_status status = f_none; unsigned short width = 0; f_string_length width_max = (location->stop - location->start) + 1; while (string[location->start] == placeholder || (status = f_utf_is_graph(string + location->start, width_max)) == f_false) { - if (f_status_is_error(status)) { - return status; - } - + if (f_status_is_error(status)) return status; if (string[location->start] == f_string_eol) return f_none_on_eol; width = f_macro_utf_byte_width_is(string[location->start]); @@ -955,9 +914,7 @@ extern "C" { width_max = (location->stop - location->start) + 1; } // while - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; return f_none; } @@ -967,10 +924,10 @@ extern "C" { f_return_status fl_string_seek_line_until_non_graph(const f_string string, f_string_location *location, const int8_t placeholder) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + f_status status = f_none; unsigned short width = 0; @@ -1003,9 +960,7 @@ extern "C" { width_max = (location->stop - location->start) + 1; } // while - if (f_status_is_error(status)) { - return status; - } + if (f_status_is_error(status)) return status; return f_none; } @@ -1015,10 +970,10 @@ extern "C" { f_return_status fl_string_seek_to(const f_string string, f_string_location *location, const int8_t seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + while (string[location->start] != seek_to_this) { location->start++; @@ -1033,10 +988,10 @@ extern "C" { f_return_status fl_string_seek_to_utf_character(const f_string string, f_string_location *location, const f_utf_character seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + const unsigned short seek_width = f_macro_utf_character_width(seek_to_this); f_status status = f_none; @@ -1068,13 +1023,8 @@ extern "C" { f_utf_character character = 0; status = f_utf_char_to_character(string + location->start, width_max, &character); - if (f_status_is_error(status)) { - return status; - } - - if (character == seek_to_this) { - return f_none; - } + if (f_status_is_error(status)) return status; + if (character == seek_to_this) return f_none; } } } // for diff --git a/level_1/fl_string/c/string.h b/level_1/fl_string/c/string.h index d01393b..4f2ad97 100644 --- a/level_1/fl_string/c/string.h +++ b/level_1/fl_string/c/string.h @@ -48,6 +48,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -75,6 +76,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -155,6 +157,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -178,6 +181,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -256,6 +260,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -285,6 +290,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -312,6 +318,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -341,6 +348,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -364,6 +372,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -389,6 +398,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -477,6 +487,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -508,6 +519,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -537,6 +549,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -568,6 +581,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -593,6 +607,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -618,6 +633,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -641,6 +657,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -664,6 +681,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -895,6 +913,27 @@ extern "C" { #endif // _di_fl_string_dynamic_seek_to_utf_character_ /** + * Guarantee that an end of string (NULL) exists at the end of the string. + * + * This is intended to be used for anything requiring NULL terminated strings. + * This will reallocate more space if necessary. + * + * If destination size is 0, then it will be reallocated and have the NULL assigned at index 0. + * + * @param destination + * The new string, which will be allocated or reallocated as necessary. + * + * @return + * f_none on success. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_reallocation (with error bit) on memory reallocation error. + * f_string_too_large (with error bit) if string is too large to fit into the buffer. + */ +#ifndef _di_fl_string_dynamic_terminate_ + extern f_return_status fl_string_dynamic_terminate(f_string_dynamic *destination); +#endif // _di_fl_string_dynamic_terminate_ + +/** * Append the source string onto the destination with the glue in between. * * If the destination string is empty, then no glue is appended. @@ -914,6 +953,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -947,6 +987,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -978,6 +1019,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -1011,6 +1053,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -1038,6 +1081,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -1067,6 +1111,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. diff --git a/level_1/fl_utf/c/private-utf.c b/level_1/fl_utf/c/private-utf.c index d324f88..12046f9 100644 --- a/level_1/fl_utf/c/private-utf.c +++ b/level_1/fl_utf/c/private-utf.c @@ -117,6 +117,8 @@ extern "C" { for (; i2 < stop2; i2++) { if (string2[i2] != f_string_eos) return f_not_equal_to; } // for + + return f_equal_to; } #endif // !defined(_di_fl_utf_string_compare_) || !defined(_di_fl_utf_string_dynamic_compare_) || !defined(_di_fl_utf_string_dynamic_partial_compare_) diff --git a/level_1/fl_utf/c/utf.c b/level_1/fl_utf/c/utf.c index f2ec2f8..470ae07 100644 --- a/level_1/fl_utf/c/utf.c +++ b/level_1/fl_utf/c/utf.c @@ -8,10 +8,11 @@ extern "C" { #ifndef _di_fl_utf_string_append_ f_return_status fl_utf_string_append(const f_utf_string source, const f_string_length start, const f_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (start > stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + return private_fl_utf_string_append(source, start, stop, destination); } #endif // _di_fl_utf_string_append_ @@ -19,10 +20,11 @@ extern "C" { #ifndef _di_fl_utf_string_append_nulless_ f_return_status fl_utf_string_append_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (start > stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + return private_fl_utf_string_append_nulless(source, start, stop, destination); } #endif // _di_fl_utf_string_append_nulless_ @@ -30,8 +32,8 @@ extern "C" { #ifndef _di_fl_utf_string_compare_ f_return_status fl_utf_string_compare(const f_utf_string string1, const f_utf_string string2, const f_utf_string_length length1, const f_utf_string_length length2) { #ifndef _di_level_1_parameter_checking_ - if (length1 <= 0) return f_status_set_error(f_invalid_parameter); - if (length2 <= 0) return f_status_set_error(f_invalid_parameter); + if (length1 == 0) return f_status_set_error(f_invalid_parameter); + if (length2 == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ return private_fl_utf_string_compare(string1, string2, 0, 0, length1, length2); @@ -41,8 +43,8 @@ extern "C" { #ifndef _di_fl_utf_string_compare_trim_ f_return_status fl_utf_string_compare_trim(const f_utf_string string1, const f_utf_string string2, const f_utf_string_length length1, const f_utf_string_length length2) { #ifndef _di_level_1_parameter_checking_ - if (length1 <= 0) return f_status_set_error(f_invalid_parameter); - if (length2 <= 0) return f_status_set_error(f_invalid_parameter); + if (length1 == 0) return f_status_set_error(f_invalid_parameter); + if (length2 == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ return private_fl_utf_string_compare_trim(string1, string2, 0, 0, length1, length2); @@ -52,10 +54,11 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_append_ f_return_status fl_utf_string_dynamic_append(const f_utf_string_dynamic source, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + return private_fl_utf_string_append(source.string, 0, source.used - 1, destination); } #endif // _di_fl_utf_string_dynamic_append_ @@ -63,10 +66,11 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_append_nulless_ f_return_status fl_utf_string_dynamic_append_nulless(const f_utf_string_dynamic source, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + return private_fl_utf_string_append_nulless(source.string, 0, source.used - 1, destination); } #endif // _di_fl_utf_string_dynamic_append_nulless_ @@ -74,12 +78,12 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_mash_ f_return_status fl_utf_string_dynamic_mash(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_append(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -94,12 +98,12 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_mash_nulless_ f_return_status fl_utf_string_dynamic_mash_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_append_nulless(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -114,12 +118,12 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_mish_ f_return_status fl_utf_string_dynamic_mish(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_prepend(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -134,12 +138,12 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_mish_nulless_ f_return_status fl_utf_string_dynamic_mish_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_prepend_nulless(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -153,22 +157,12 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_compare_ f_return_status fl_utf_string_dynamic_compare(const f_utf_string_dynamic string1, const f_utf_string_dynamic string2) { - #ifndef _di_level_1_parameter_checking_ - if (string1.used <= 0) return f_status_set_error(f_invalid_parameter); - if (string2.used <= 0) return f_status_set_error(f_invalid_parameter); - #endif // _di_level_1_parameter_checking_ - return private_fl_utf_string_compare(string1.string, string2.string, 0, 0, string1.used, string2.used); } #endif // _di_fl_utf_string_dynamic_compare_ #ifndef _di_f_utf_string_dynamic_compare_trim_ f_return_status f_utf_string_dynamic_compare_trim(const f_utf_string_dynamic string1, const f_utf_string_dynamic string2) { - #ifndef _di_level_1_parameter_checking_ - if (string1.used <= 0) return f_status_set_error(f_invalid_parameter); - if (string2.used <= 0) return f_status_set_error(f_invalid_parameter); - #endif // _di_level_1_parameter_checking_ - return private_fl_utf_string_compare_trim(string1.string, string2.string, 0, 0, string1.used, string2.used); } #endif // _di_f_utf_string_dynamic_compare_trim_ @@ -176,12 +170,13 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_append_ f_return_status fl_utf_string_dynamic_partial_append(const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_utf_string_append(source.string, range.start, range.stop, destination); } #endif // _di_fl_utf_string_dynamic_partial_append_ @@ -189,12 +184,13 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_append_nulless_ f_return_status fl_utf_string_dynamic_partial_append_nulless(const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_utf_string_append_nulless(source.string, range.start, range.stop, destination); } #endif // _di_fl_utf_string_dynamic_partial_append_nulless_ @@ -202,12 +198,6 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_compare_ f_return_status fl_utf_string_dynamic_partial_compare(const f_utf_string_dynamic string1, const f_utf_string_dynamic string2, const f_utf_string_location range1, const f_utf_string_location range2) { #ifndef _di_level_1_parameter_checking_ - if (string1.used <= 0) return f_status_set_error(f_invalid_parameter); - if (string2.used <= 0) return f_status_set_error(f_invalid_parameter); - - if (range1.start > range1.stop) return f_status_set_error(f_invalid_parameter); - if (range2.start > range2.stop) return f_status_set_error(f_invalid_parameter); - if (string1.used <= range1.stop) return f_status_set_error(f_invalid_parameter); if (string2.used <= range2.stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ @@ -219,12 +209,6 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_compare_trim_ f_return_status fl_utf_string_dynamic_partial_comparetrim(const f_utf_string_dynamic string1, const f_utf_string_dynamic string2, const f_utf_string_location range1, const f_utf_string_location range2) { #ifndef _di_level_1_parameter_checking_ - if (string1.used <= 0) return f_status_set_error(f_invalid_parameter); - if (string2.used <= 0) return f_status_set_error(f_invalid_parameter); - - if (range1.start > range1.stop) return f_status_set_error(f_invalid_parameter); - if (range2.start > range2.stop) return f_status_set_error(f_invalid_parameter); - if (string1.used <= range1.stop) return f_status_set_error(f_invalid_parameter); if (string2.used <= range2.stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ @@ -236,14 +220,14 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_mash_ f_return_status fl_utf_string_dynamic_partial_mash(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_append(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -258,14 +242,14 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_mash_nulless_ f_return_status fl_utf_string_dynamic_partial_mash_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_append_nulless(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -280,14 +264,14 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_mish_ f_return_status fl_utf_string_dynamic_partial_mish(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_prepend(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -302,14 +286,14 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_mish_nulless_ f_return_status fl_utf_string_dynamic_partial_mish_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_prepend_nulless(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -324,12 +308,13 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_prepend_ f_return_status fl_utf_string_dynamic_partial_prepend(const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_utf_string_prepend(source.string, range.start, range.stop, destination); } #endif // _di_fl_utf_string_dynamic_partial_prepend_ @@ -337,12 +322,13 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_partial_prepend_nulless_ f_return_status fl_utf_string_dynamic_partial_prepend_nulless(const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); - if (range.start > range.stop) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_utf_string_prepend_nulless(source.string, range.start, range.stop, destination); } #endif // _di_fl_utf_string_dynamic_partial_prepend_nulless_ @@ -350,10 +336,11 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_prepend_ f_return_status fl_utf_string_dynamic_prepend(const f_utf_string_dynamic source, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + return private_fl_utf_string_prepend(source.string, 0, source.used - 1, destination); } #endif // _di_fl_utf_string_dynamic_prepend_ @@ -361,10 +348,11 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_prepend_nulless_ f_return_status fl_utf_string_dynamic_prepend_nulless(const f_utf_string_dynamic source, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (source.used < 1) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + return private_fl_utf_string_prepend_nulless(source.string, 0, source.used - 1, destination); } #endif // _di_fl_utf_string_dynamic_prepend_nulless_ @@ -372,13 +360,14 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_rip_ f_return_status fl_utf_string_dynamic_rip(const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (range.stop < range.start) return f_status_set_error(f_invalid_parameter); - if (source.used <= 0) return f_status_set_error(f_invalid_parameter); if (source.used <= range.start) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_utf_string_append(source.string, range.start, range.stop, destination); } #endif // _di_fl_utf_string_dynamic_rip_ @@ -386,13 +375,14 @@ extern "C" { #ifndef _di_fl_utf_string_dynamic_rip_nulless_ f_return_status fl_utf_string_dynamic_rip_nulless(const f_utf_string_dynamic source, const f_utf_string_location range, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (range.stop < range.start) return f_status_set_error(f_invalid_parameter); - if (source.used <= 0) return f_status_set_error(f_invalid_parameter); if (source.used <= range.start) return f_status_set_error(f_invalid_parameter); if (source.used <= range.stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (source.used == 0) return f_no_data; + if (range.start > range.stop) return f_no_data; + return private_fl_utf_string_append_nulless(source.string, range.start, range.stop, destination); } #endif // _di_fl_utf_string_dynamic_rip_nulless_ @@ -401,13 +391,13 @@ extern "C" { f_return_status fl_utf_string_dynamic_seek_line_to(const f_utf_string_dynamic buffer, f_utf_string_location *location, const f_utf_character seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + if (f_macro_utf_character_width_is(buffer.string[location->start]) == 1) { return f_status_set_error(f_invalid_utf); } @@ -433,13 +423,13 @@ extern "C" { f_return_status fl_utf_string_dynamic_seek_line_to_char(const f_utf_string_dynamic buffer, f_utf_string_location *location, const int8_t seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + f_utf_character seek_to_character = seek_to_this << 24; if (f_macro_utf_character_width_is(buffer.string[location->start]) == 1) { @@ -467,13 +457,13 @@ extern "C" { f_return_status fl_utf_string_dynamic_seek_line_until_graph(const f_utf_string_dynamic buffer, f_utf_string_location *location, const f_utf_character placeholder) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + f_status status = f_none; if (f_macro_utf_character_width_is(buffer.string[location->start]) == 1) { @@ -509,13 +499,13 @@ extern "C" { f_return_status fl_utf_string_dynamic_seek_line_until_non_graph(const f_utf_string_dynamic buffer, f_utf_string_location *location, const f_utf_character placeholder) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + f_status status = f_none; if (f_macro_utf_character_width_is(buffer.string[location->start]) == 1) { @@ -551,13 +541,13 @@ extern "C" { f_return_status fl_utf_string_dynamic_seek_to(const f_utf_string_dynamic buffer, f_utf_string_location *location, const f_utf_character seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + if (f_macro_utf_character_width_is(buffer.string[location->start]) == 1) { return f_status_set_error(f_invalid_utf); } @@ -581,13 +571,13 @@ extern "C" { f_return_status fl_utf_string_dynamic_seek_to_char(const f_utf_string_dynamic buffer, f_utf_string_location *location, const int8_t seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); - if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->start) return f_status_set_error(f_invalid_parameter); if (buffer.used <= location->stop) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (buffer.used == 0) return f_none_on_eos; + if (location->start > location->stop) return f_none_on_stop; + f_utf_character seek_to_character = seek_to_this << 24; if (f_macro_utf_character_width_is(buffer.string[location->start]) == 1) { @@ -609,15 +599,42 @@ extern "C" { } #endif // _di_fl_utf_string_dynamic_seek_to_char_ +#ifndef _di_fl_utf_string_dynamic_terminate_ + f_return_status fl_utf_string_dynamic_terminate(f_utf_string_dynamic *destination) { + #ifndef _di_level_1_parameter_checking_ + if (destination == 0) return f_status_set_error(f_invalid_parameter); + if (destination->used > destination->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_1_parameter_checking_ + + if (destination->used > 0 && destination->string[destination->used - 1] == f_utf_character_eos) return f_none; + + if (destination->used + 1 > f_utf_string_max_size) return f_status_set_error(f_string_too_large); + + const f_utf_string_length total = destination->used + 1; + + if (total > destination->size) { + f_status status = f_none; + + f_macro_string_dynamic_resize(status, (*destination), total); + if (f_status_is_error(status)) return status; + } + + destination->string[destination->used] = f_string_eos; + destination->used = total; + + return f_none; + } +#endif // _di_fl_utf_string_dynamic_terminate_ + #ifndef _di_fl_utf_string_mash_ f_return_status fl_utf_string_mash(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (start > stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_append(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -632,12 +649,12 @@ extern "C" { #ifndef _di_fl_utf_string_mash_nulless_ f_return_status fl_utf_string_mash_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (start > stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_append_nulless(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -652,12 +669,12 @@ extern "C" { #ifndef _di_fl_utf_string_mish_ f_return_status fl_utf_string_mish(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (start > stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_prepend(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -672,12 +689,12 @@ extern "C" { #ifndef _di_fl_utf_string_mish_nulless_ f_return_status fl_utf_string_mish_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (glue_length < 1) return f_status_set_error(f_invalid_parameter); - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ - if (destination->used > 0) { + if (start > stop) return f_no_data; + + if (glue_length > 0 && destination->used > 0) { f_status status = private_fl_utf_string_prepend_nulless(glue, 0, glue_length - 1, destination); if (f_status_is_error(status)) { @@ -692,10 +709,11 @@ extern "C" { #ifndef _di_fl_utf_string_prepend_ f_return_status fl_utf_string_prepend(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + return private_fl_utf_string_prepend(source, start, stop, destination); } #endif // _di_fl_utf_string_prepend_ @@ -703,10 +721,11 @@ extern "C" { #ifndef _di_fl_utf_string_prepend_nulless_ f_return_status fl_utf_string_prepend_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (stop > start) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + return private_fl_utf_string_prepend_nulless(source, start, stop, destination); } #endif // _di_fl_utf_string_prepend_nulless_ @@ -714,10 +733,11 @@ extern "C" { #ifndef _di_fl_utf_string_rip_ f_return_status fl_utf_string_rip(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (start > stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + f_utf_string_length begin = start; f_utf_string_length end = stop; @@ -733,10 +753,11 @@ extern "C" { #ifndef _di_fl_utf_string_rip_nulless_ f_return_status fl_utf_string_rip_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) { #ifndef _di_level_1_parameter_checking_ - if (start > stop) return f_status_set_error(f_invalid_parameter); if (destination == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (start > stop) return f_no_data; + f_utf_string_length begin = start; f_utf_string_length end = stop; @@ -753,10 +774,10 @@ extern "C" { f_return_status fl_utf_string_seek_line_to(const f_utf_string string, f_utf_string_location *location, const f_utf_character seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + if (f_macro_utf_character_width_is(string[location->start]) == 1) { return f_status_set_error(f_invalid_utf); } @@ -781,10 +802,10 @@ extern "C" { f_return_status fl_utf_string_seek_line_to_char(const f_utf_string string, f_utf_string_location *location, const int8_t seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + f_utf_character seek_to_character = seek_to_this << 24; f_status status = f_none; @@ -806,10 +827,10 @@ extern "C" { f_return_status fl_utf_string_seek_line_until_graph(const f_utf_string string, f_utf_string_location *location, const f_utf_character placeholder) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + f_status status = f_none; if (f_macro_utf_character_width_is(string[location->start]) == 1) { @@ -844,10 +865,10 @@ extern "C" { f_return_status fl_utf_string_seek_line_until_non_graph(const f_utf_string string, f_utf_string_location *location, const f_utf_character placeholder) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + f_status status = f_none; if (f_macro_utf_character_width_is(string[location->start]) == 1) { @@ -882,10 +903,10 @@ extern "C" { f_return_status fl_utf_string_seek_to(const f_utf_string string, f_utf_string_location *location, const f_utf_character seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + if (f_macro_utf_character_width_is(string[location->start]) == 1) { return f_status_set_error(f_invalid_utf); } @@ -908,10 +929,10 @@ extern "C" { f_return_status fl_utf_string_seek_to_char(const f_utf_string string, f_utf_string_location *location, const int8_t seek_to_this) { #ifndef _di_level_1_parameter_checking_ if (location == 0) return f_status_set_error(f_invalid_parameter); - if (location->start < 0) return f_status_set_error(f_invalid_parameter); - if (location->stop < location->start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ + if (location->start > location->stop) return f_none_on_stop; + f_utf_character seek_to_character = seek_to_this << 24; f_status status = f_none; diff --git a/level_1/fl_utf/c/utf.h b/level_1/fl_utf/c/utf.h index fd42bfd..23064cf 100644 --- a/level_1/fl_utf/c/utf.h +++ b/level_1/fl_utf/c/utf.h @@ -48,6 +48,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -75,6 +76,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -157,6 +159,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -180,6 +183,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -260,6 +264,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -290,6 +295,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -318,6 +324,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -348,6 +355,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -372,6 +380,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -397,6 +406,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -487,6 +497,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -518,6 +529,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -547,6 +559,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -578,6 +591,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -603,6 +617,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -628,6 +643,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 or range is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -651,6 +667,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -674,6 +691,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0. * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -919,6 +937,27 @@ extern "C" { #endif // _di_fl_utf_string_dynamic_seek_to_utf_character_ /** + * Guarantee that an end of UTF-8 string (NULL) exists at the end of the string. + * + * This is intended to be used for anything requiring NULL terminated strings. + * This will reallocate more space if necessary. + * + * If destination size is 0, then it will be reallocated and have the NULL assigned at index 0. + * + * @param destination + * The new string, which will be allocated or reallocated as necessary. + * + * @return + * f_none on success. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_reallocation (with error bit) on memory reallocation error. + * f_string_too_large (with error bit) if string is too large to fit into the buffer. + */ +#ifndef _di_fl_utf_string_dynamic_terminate_ + extern f_return_status fl_utf_string_dynamic_terminate(f_utf_string_dynamic *destination); +#endif // _di_fl_utf_string_dynamic_terminate_ + +/** * Append the UTF-8 source string onto the destination with the glue in between. * * If the destination string is empty, then no glue is appended. @@ -938,6 +977,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -971,6 +1011,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -1002,6 +1043,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -1035,6 +1077,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -1062,6 +1105,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. @@ -1091,6 +1135,7 @@ extern "C" { * * @return * f_none on success. + * f_no_data if source length is 0 (start > stop). * f_string_max_size (with error bit) if the combined string is too large. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_allocation (with error bit) on memory allocation error. diff --git a/level_1/fl_utf_file/c/utf_file.h b/level_1/fl_utf_file/c/utf_file.h index ca97550..94e9f86 100644 --- a/level_1/fl_utf_file/c/utf_file.h +++ b/level_1/fl_utf_file/c/utf_file.h @@ -41,7 +41,7 @@ extern "C" { * f_file_error_read (with error bit) if file read failed. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_reallocation (with error bit) on memory reallocation error. - * f_string_too_large (with error bit) if string is too large to fit into buffer. + * f_string_too_large (with error bit) if string is too large to fit into the buffer. * f_incomplete_utf_on_eof (with error bit) if UTF-8 character was incomplete at the end of the file. */ #ifndef _di_fl_utf_file_read_ @@ -68,7 +68,7 @@ extern "C" { * f_file_error_read (with error bit) if file read failed. * f_invalid_parameter (with error bit) if a parameter is invalid. * f_error_reallocation (with error bit) on memory reallocation error. - * f_string_too_large (with error bit) if string is too large to fit into buffer. + * f_string_too_large (with error bit) if string is too large to fit into the buffer. * f_incomplete_utf_on_eof (with error bit) if UTF-8 character was incomplete at the end of the file. */ #ifndef _di_fl_utf_file_read_position_ diff --git a/level_2/fll_execute/c/execute.c b/level_2/fll_execute/c/execute.c index 0fc4cc9..ab779e8 100644 --- a/level_2/fll_execute/c/execute.c +++ b/level_2/fll_execute/c/execute.c @@ -1,15 +1,194 @@ #include +#include "private-execute.h" #ifdef __cplusplus extern "C" { #endif -#ifndef _di_fll_execute_path_ - f_return_status fll_execute_path(const f_string program_path, const f_string_dynamics arguments, int *results) { +#ifndef _di_fll_execute_arguments_add_ + f_return_status fll_execute_arguments_add(const f_string source, const f_string_length length, f_string_dynamics *arguments) { + #ifndef _di_level_2_parameter_checking_ + if (arguments == 0) return f_status_set_error(f_invalid_parameter); + if (arguments->used > arguments->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ + + if (length == 0) return f_no_data; + + f_status status = f_none; + + status = private_fll_execute_arguments_add(source, length, arguments); + + if (f_status_is_error(status)) return status; + + return f_none; + } +#endif // _di_fll_execute_arguments_add_ + +#ifndef _di_fll_execute_arguments_add_parameter_ + f_return_status fll_execute_arguments_add_parameter(const f_string prefix, const f_string_length prefix_length, const f_string name, const f_string_length name_length, const f_string value, const f_string_length value_length, f_string_dynamics *arguments) { + #ifndef _di_level_2_parameter_checking_ + if (arguments == 0) return f_status_set_error(f_invalid_parameter); + if (arguments->used > arguments->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ + + if (name_length == 0) return f_no_data; + if (value_length == 0) return f_no_data; + + f_status status = f_none; + + status = private_fll_execute_arguments_add_parameter(prefix, prefix_length, name, name_length, value, value_length, arguments); + + if (f_status_is_error(status)) return status; + + return f_none; + } +#endif // _di_fll_execute_arguments_add_parameter_ + +#ifndef _di_fll_execute_arguments_add_parameter_set_ + f_return_status fll_execute_arguments_add_parameter_set(const f_string prefix[], const f_string_length prefix_length[], const f_string name[], const f_string_length name_length[], const f_string value[], const f_string_length value_length[], const f_array_length size, f_string_dynamics *arguments) { + #ifndef _di_level_2_parameter_checking_ + if (arguments == 0) return f_status_set_error(f_invalid_parameter); + if (arguments->used > arguments->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ + + if (size == 0) return f_no_data; + + f_status status = f_none; + + for (f_array_length i = 0; i < size; i++) { + if (name_length[i] == 0) continue; + if (value_length[i] == 0) continue; + + status = private_fll_execute_arguments_add_parameter(prefix[i], prefix_length[i], name[i], name_length[i], value[i], value_length[i], arguments); + + if (f_status_is_error(status)) return status; + } // for + + return status; + } +#endif // _di_fll_execute_arguments_add_parameter_set_ + +#ifndef _di_fll_execute_arguments_add_set_ + f_return_status fll_execute_arguments_add_set(const f_string source[], const f_string_length length[], const f_array_length size, f_string_dynamics *arguments) { + #ifndef _di_level_2_parameter_checking_ + if (arguments == 0) return f_status_set_error(f_invalid_parameter); + if (arguments->used > arguments->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ + + if (size == 0) return f_no_data; + + f_status status = f_none; + + for (f_array_length i = 0; i < size; i++) { + if (length[i] == 0) continue; + + status = private_fll_execute_arguments_add(source[i], length[i], arguments); + + if (f_status_is_error(status)) return status; + } // for + + return status; + } +#endif // _di_fll_execute_arguments_add_set_ + +#ifndef _di_fll_execute_arguments_dynamic_add_ + f_return_status fll_execute_arguments_dynamic_add(const f_string_dynamic source, f_string_dynamics *arguments) { #ifndef _di_level_2_parameter_checking_ - if (results == 0) return f_status_set_error(f_invalid_parameter); + if (source.used > source.size) return f_status_set_error(f_invalid_parameter); + if (arguments == 0) return f_status_set_error(f_invalid_parameter); + if (arguments->used > arguments->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ - if (arguments.used < 0) return f_status_set_error(f_invalid_parameter); + if (source.used == 0) return f_no_data; + + f_status status = f_none; + + status = private_fll_execute_arguments_add(source.string, source.used, arguments); + + if (f_status_is_error(status)) return status; + + return f_none; + } +#endif // _di_fll_execute_arguments_dynamic_add_ + +#ifndef _di_fll_execute_arguments_dynamic_add_parameter_ + f_return_status fll_execute_arguments_dynamic_add_parameter(const f_string_dynamic prefix, const f_string_dynamic name, const f_string_dynamic value, f_string_dynamics *arguments) { + #ifndef _di_level_2_parameter_checking_ + if (prefix.used > prefix.size) return f_status_set_error(f_invalid_parameter); + if (name.used > name.size) return f_status_set_error(f_invalid_parameter); + if (value.used > value.size) return f_status_set_error(f_invalid_parameter); + if (arguments == 0) return f_status_set_error(f_invalid_parameter); + if (arguments->used > arguments->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ + + if (name.used == 0) return f_no_data; + if (value.used == 0) return f_no_data; + + f_status status = f_none; + + status = private_fll_execute_arguments_add_parameter(prefix.string, prefix.used, name.string, name.used, value.string, value.used, arguments); + + if (f_status_is_error(status)) return status; + + return f_none; + } +#endif // _di_fll_execute_arguments_dynamic_add_parameter_ + +#ifndef _di_fll_execute_arguments_dynamic_add_parameter_set_ + f_return_status fll_execute_arguments_dynamic_add_parameter_set(const f_string_dynamic prefix[], const f_string_dynamic name[], const f_string_dynamic value[], const f_array_length size, f_string_dynamics *arguments) { + #ifndef _di_level_2_parameter_checking_ + if (arguments == 0) return f_status_set_error(f_invalid_parameter); + if (arguments->used > arguments->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ + + if (size == 0) return f_no_data; + + f_status status = f_none; + + for (f_array_length i = 0; i < size; i++) { + if (prefix[i].used > prefix[i].size) continue; + if (name[i].used == 0) continue; + if (name[i].used > name[i].size) continue; + if (value[i].used == 0) continue; + if (value[i].used > value[i].size) continue; + + status = private_fll_execute_arguments_add_parameter(prefix[i].string, prefix[i].used, name[i].string, name[i].used, value[i].string, value[i].used, arguments); + + if (f_status_is_error(status)) return status; + } // for + + return status; + } +#endif // _di_fll_execute_arguments_dynamic_add_parameter_set_ + +#ifndef _di_fll_execute_arguments_dynamic_add_set_ + f_return_status fll_execute_arguments_dynamic_add_set(const f_string_dynamic source[], const f_array_length size, f_string_dynamics *arguments) { + #ifndef _di_level_2_parameter_checking_ + if (arguments == 0) return f_status_set_error(f_invalid_parameter); + if (arguments->used > arguments->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ + + if (size == 0) return f_no_data; + + f_status status = f_none; + + for (f_array_length i = 0; i < size; i++) { + if (source[i].used == 0) continue; + if (source[i].used > source[i].size) continue; + + status = private_fll_execute_arguments_add(source[i].string, source[i].used, arguments); + + if (f_status_is_error(status)) return status; + } // for + + return status; + } +#endif // _di_fll_execute_arguments_dynamic_add_set_ + +#ifndef _di_fll_execute_path_ + f_return_status fll_execute_path(const f_string program_path, const f_string_dynamics arguments, int *result) { + #ifndef _di_level_2_parameter_checking_ + if (result == 0) return f_status_set_error(f_invalid_parameter); if (arguments.used > arguments.size) return f_status_set_error(f_invalid_parameter); #endif // _di_level_2_parameter_checking_ @@ -70,7 +249,7 @@ extern "C" { // insert the required array terminated fixed_arguments[arguments.used + 2] = 0; - // TODO: validate that the file at program_path actually exists before attempting to fork and execute + // @todo validate that the file at program_path actually exists before attempting to fork and execute int process_id = 0; process_id = vfork(); @@ -94,7 +273,7 @@ extern "C" { } // have the parent wait for the child process to finish - waitpid(process_id, results, 0); + waitpid(process_id, result, 0); if (name_size > 0) f_macro_string_delete_simple(program_name, name_size); @@ -102,18 +281,16 @@ extern "C" { f_macro_string_delete_simple(fixed_arguments[i + 1], arguments.array[i].used + 1); } // for - if (*results != 0) return f_status_set_error(f_failure); + if (*result != 0) return f_status_set_error(f_failure); return f_none; } #endif // _di_fll_execute_path_ #ifndef _di_fll_execute_program_ - f_return_status fll_execute_program(const f_string program_name, const f_string_dynamics arguments, int *results) { + f_return_status fll_execute_program(const f_string program_name, const f_string_dynamics arguments, int *result) { #ifndef _di_level_2_parameter_checking_ - if (results == 0) return f_status_set_error(f_invalid_parameter); - - if (arguments.used < 0) return f_status_set_error(f_invalid_parameter); + if (result == 0) return f_status_set_error(f_invalid_parameter); if (arguments.used > arguments.size) return f_status_set_error(f_invalid_parameter); #endif // _di_level_2_parameter_checking_ @@ -124,6 +301,7 @@ extern "C" { fixed_arguments[0] = program_name; f_status status = f_none; + for (f_string_length i = 0; i < arguments.used; i++) { f_macro_string_new(status, fixed_arguments[i + 1], arguments.array[i].used + 1); @@ -142,7 +320,7 @@ extern "C" { // insert the required array terminated fixed_arguments[arguments.used + 2] = 0; - // TODO: validate that the file at program_path actually exists before attempting to fork and execute + // @todo validate that the file at program_path actually exists before attempting to fork and execute int process_id = 0; process_id = vfork(); @@ -164,13 +342,13 @@ extern "C" { } // have the parent wait for the child process to finish - waitpid(process_id, results, 0); + waitpid(process_id, result, 0); for (f_string_length i = 0; i < arguments.used; i++) { f_macro_string_delete_simple(fixed_arguments[i + 1], arguments.array[i].used + 1); } // for - if (*results != 0) return f_status_set_error(f_failure); + if (*result != 0) return f_status_set_error(f_failure); return f_none; } diff --git a/level_2/fll_execute/c/execute.h b/level_2/fll_execute/c/execute.h index 1520235..cc8dcde 100644 --- a/level_2/fll_execute/c/execute.h +++ b/level_2/fll_execute/c/execute.h @@ -25,23 +25,304 @@ #include // fll-1 includes +#include #ifdef __cplusplus extern "C" { #endif +/** + * Add an argument to the execution arguments array. + * + * This guarantees that an end of string exists at the end of the copied string. + * This does not check for NULL characters anywhere else in the string. + * + * @param source + * The string to add to the arguments array. + * @param length + * Length of string to prepend. + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if source length is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + */ +#ifndef _di_fll_execute_arguments_add_ + extern f_return_status fll_execute_arguments_add(const f_string source, const f_string_length length, f_string_dynamics *arguments); +#endif // _di_fll_execute_arguments_add_ +/** + * Add parameters as arguments to the execution arguments array. + * + * This is intended to simplify adding arguments that have prefixes and values such as those common in console parameters. + * For example, a pefix of '--', a name of 'do', and a value of 'something' would result in two arguments added: + * '--do' and 'something'. + * + * The arguments are only appended if the length of name and value are not 0. + * + * This guarantees that an end of string exists at the end of each argument. + * This does not check for NULL characters anywhere else in the string. + * + * @param prefix + * The string prepend to the name. + * @param prefix_length + * Length of prefix to prepend. + * @param name + * The string to add to the arguments array. + * @param name_length + * Length of name to prepend. + * @param value + * The string to add to the arguments array. + * @param value_length + * Length of value to prepend. + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if source length is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + */ +#ifndef _di_fll_execute_arguments_add_parameter_ + extern f_return_status fll_execute_arguments_add_parameter(const f_string prefix, const f_string_length prefix_length, const f_string name, const f_string_length name_length, const f_string value, const f_string_length value_length, f_string_dynamics *arguments); +#endif // _di_fll_execute_arguments_add_parameter_ + +/** + * Add set of parameters as arguments to the execution arguments array. + * + * This is intended to simplify adding arguments that have prefixes and values such as those common in console parameters. + * For example, a pefix of '--', a name of 'do', and a value of 'something' would result in two arguments added: + * '--do' and 'something'. + * + * The arguments are only appended if the length of name and value are not 0. + * + * This guarantees that an end of string exists at the end of each argument. + * This does not check for NULL characters anywhere else in the string. + * + * @param prefix + * An array of the strings prepend to the name. + * @param prefix_length + * Length of prefix to prepend. + * @param name + * An array of the strings to add to the arguments array. + * @param name_length + * Length of name to prepend. + * @param value + * An array of the strings to add to the arguments array. + * @param value_length + * Length of value to prepend. + * @param size + * The array size of prefix, prefix_length, name, name_length, value, and value_length (all of which must be of the same array size). + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if size is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + */ +#ifndef _di_fll_execute_arguments_add_parameter_set_ + extern f_return_status fll_execute_arguments_add_parameter_set(const f_string prefix[], const f_string_length prefix_length[], const f_string name[], const f_string_length name_length[], const f_string value[], const f_string_length value_length[], const f_array_length size, f_string_dynamics *arguments); +#endif // _di_fll_execute_arguments_add_parameter_set_ + +/** + * Add a set of arguments to the execution arguments array. + * + * This guarantees that an end of string exists at the end of the copied string. + * This does not check for NULL characters anywhere else in the string. + * + * @param source + * An array of strings to add to the arguments array. + * @param length + * An array of lengths of each string to prepend. + * @param size + * The array size of source and length (all of which must be of the same array size). + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if size is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + */ +#ifndef _di_fll_execute_arguments_add_set_ + extern f_return_status fll_execute_arguments_add_set(const f_string source[], const f_string_length length[], const f_array_length size, f_string_dynamics *arguments); +#endif // _di_fll_execute_arguments_add_set_ + +/** + * Add an argument to the execution arguments array. + * + * This guarantees that an end of string exists at the end of the copied string. + * This does not check for NULL characters anywhere else in the string. + * + * @param source + * The string to add to the arguments array. + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if source length is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + */ +#ifndef _di_fll_execute_arguments_dynamic_add_ + extern f_return_status fll_execute_arguments_dynamic_add(const f_string_dynamic source, f_string_dynamics *arguments); +#endif // _di_fll_execute_arguments_dynamic_add_ + +/** + * Add parameters as arguments to the execution arguments array. + * + * This is intended to simplify adding arguments that have prefixes and values such as those common in console parameters. + * For example, a pefix of '--', a name of 'do', and a value of 'something' would result in two arguments added: + * '--do' and 'something'. + * + * The arguments are only appended if the length of name and value are not 0. + * + * This guarantees that an end of string exists at the end of each argument. + * This does not check for NULL characters anywhere else in the string. + * + * @param prefix + * The string prepend to the name. + * @param name + * The string to add to the arguments array. + * @param value + * The string to add to the arguments array. + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if source length is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + */ +#ifndef _di_fll_execute_arguments_dynamic_add_parameter_ + extern f_return_status fll_execute_arguments_dynamic_add_parameter(const f_string_dynamic prefix, const f_string_dynamic name, const f_string_dynamic value, f_string_dynamics *arguments); +#endif // _di_fll_execute_arguments_dynamic_add_parameter_ + +/** + * Add set of parameters as arguments to the execution arguments array. + * + * This is intended to simplify adding arguments that have prefixes and values such as those common in console parameters. + * For example, a pefix of '--', a name of 'do', and a value of 'something' would result in two arguments added: + * '--do' and 'something'. + * + * The arguments are only appended if the length of name and value are not 0. + * + * This guarantees that an end of string exists at the end of each argument. + * This does not check for NULL characters anywhere else in the string. + * + * @param prefix + * The string prepend to the name. + * @param name + * The string to add to the arguments array. + * @param value + * The string prepend to the name. + * @param size + * The array size of buffer. + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if source length is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + */ +#ifndef _di_fll_execute_arguments_dynamic_add_parameter_set_ + extern f_return_status fll_execute_arguments_dynamic_add_parameter_set(const f_string_dynamic prefix[], const f_string_dynamic name[], const f_string_dynamic value[], const f_array_length size, f_string_dynamics *arguments); +#endif // _di_fll_execute_arguments_dynamic_add_parameter_set_ + +/** + * Add a set of arguments to the execution arguments array. + * + * This guarantees that an end of string exists at the end of the copied string. + * This does not check for NULL characters anywhere else in the string. + * + * @param source + * An array of strings to add to the arguments array. + * @param size + * The array size of buffer. + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if source length is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + */ +#ifndef _di_fll_execute_arguments_dynamic_add_set_ + extern f_return_status fll_execute_arguments_dynamic_add_set(const f_string_dynamic source[], const f_array_length size, f_string_dynamics *arguments); +#endif // _di_fll_execute_arguments_dynamic_add_set_ + +/** + * Execute a program given some path + program name (such as "/bin/bash"). + * + * @param program_path + * The entire path to the program. + * @param arguments + * An array of strings representing the arguments. + * @param result + * The code returned after finishing execution of program_path. + * + * @return + * f_none on success. + * f_failure (with error bit) if result is non-zero. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * + * @see execv() + */ #ifndef _di_fll_execute_path_ - /** - * This will execute a program given some path + program name (such as "/bin/bash"). - */ - extern f_return_status fll_execute_path(const f_string program_path, const f_string_dynamics arguments, int *results); + extern f_return_status fll_execute_path(const f_string program_path, const f_string_dynamics arguments, int *result); #endif // _di_fll_execute_path_ +/** + * Execute a program given by name found in the PATH environment (such as "bash"). + * + * @param program_name + * The name of the program. + * @param arguments + * An array of strings representing the arguments. + * @param result + * The code returned after finishing execution of program. + * + * @return + * f_none on success. + * f_failure (with error bit) if result is non-zero. + * f_fork_failed (with error bit) on fork failure. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * + * @see execvp() + */ #ifndef _di_fll_execute_program_ - /** - * This will find the program based on PATH environment so that static paths do not have to be used as with f_execute_path. - */ - extern f_return_status fll_execute_program(const f_string program_name, const f_string_dynamics arguments, int *results); + extern f_return_status fll_execute_program(const f_string program_name, const f_string_dynamics arguments, int *result); #endif // _di_fll_execute_program_ #ifdef __cplusplus diff --git a/level_2/fll_execute/c/private-execute.c b/level_2/fll_execute/c/private-execute.c new file mode 100644 index 0000000..7f71d29 --- /dev/null +++ b/level_2/fll_execute/c/private-execute.c @@ -0,0 +1,115 @@ +#include +#include "private-execute.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_di_fll_execute_arguments_add_) || !defined(_di_fll_execute_arguments_add_set_) || !defined(_di_fll_execute_arguments_dynamic_add_) || !defined(_di_fll_execute_arguments_dynamic_add_set_) + f_return_status private_fll_execute_arguments_add(const f_string source, const f_string_length length, f_string_dynamics *arguments) { + f_status status = f_none; + + if (arguments->used >= arguments->size) { + if (arguments->size + f_memory_default_allocation_step > f_array_length_size) { + if (arguments->size + 1 > f_array_length_size) return f_array_too_large; + f_macro_string_dynamics_resize(status, (*arguments), arguments->size + 1); + } + else { + f_macro_string_dynamics_resize(status, (*arguments), arguments->size + f_memory_default_allocation_step); + } + + if (f_status_is_error(status)) return status; + } + + f_string_dynamic argument = f_string_dynamic_initialize; + + status = fl_string_append(source, 0, length - 1, &argument); + if (f_status_is_error(status)) { + f_macro_string_dynamic_delete_simple(argument); + return status; + } + + status = fl_string_dynamic_terminate(&argument); + if (f_status_is_error(status)) { + f_macro_string_dynamic_delete_simple(argument); + return status; + } + + arguments->array[arguments->used].string = argument.string; + arguments->array[arguments->used].used = argument.used; + arguments->array[arguments->used].size = argument.size; + arguments->used++; + + return f_none; + } +#endif // !defined(_di_fll_execute_arguments_add_) || !defined(_di_fll_execute_arguments_add_set_) || !defined(_di_fll_execute_arguments_dynamic_add_) || !defined(_di_fll_execute_arguments_dynamic_add_set_) + +#if !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_) + f_return_status private_fll_execute_arguments_add_parameter(const f_string prefix, const f_string_length prefix_length, const f_string name, const f_string_length name_length, const f_string value, const f_string_length value_length, f_string_dynamics *arguments) { + f_status status = f_none; + + if (arguments->used + 1 >= arguments->size) { + if (arguments->size + f_memory_default_allocation_step > f_array_length_size) { + if (arguments->size + 2 > f_array_length_size) return f_array_too_large; + f_macro_string_dynamics_resize(status, (*arguments), arguments->size + 2); + } + else { + f_macro_string_dynamics_resize(status, (*arguments), arguments->size + f_memory_default_allocation_step + 1); + } + + if (f_status_is_error(status)) return status; + } + + f_string_dynamic argument = f_string_dynamic_initialize; + + if (prefix_length > 0) { + status = fl_string_append(prefix, 0, prefix_length - 1, &argument); + if (f_status_is_error(status)) { + f_macro_string_dynamic_delete_simple(argument); + return status; + } + } + + status = fl_string_append(name, 0, name_length - 1, &argument); + if (f_status_is_error(status)) { + f_macro_string_dynamic_delete_simple(argument); + return status; + } + + status = fl_string_dynamic_terminate(&argument); + if (f_status_is_error(status)) { + f_macro_string_dynamic_delete_simple(argument); + return status; + } + + arguments->array[arguments->used].string = argument.string; + arguments->array[arguments->used].used = argument.used; + arguments->array[arguments->used].size = argument.size; + arguments->used++; + + f_macro_string_dynamic_clear(argument); + + status = fl_string_append(value, 0, value_length - 1, &argument); + if (f_status_is_error(status)) { + f_macro_string_dynamic_delete_simple(argument); + return status; + } + + status = fl_string_dynamic_terminate(&argument); + if (f_status_is_error(status)) { + f_macro_string_dynamic_delete_simple(argument); + return status; + } + + arguments->array[arguments->used].string = argument.string; + arguments->array[arguments->used].used = argument.used; + arguments->array[arguments->used].size = argument.size; + arguments->used++; + + return f_none; + } +#endif // !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_2/fll_execute/c/private-execute.h b/level_2/fll_execute/c/private-execute.h new file mode 100644 index 0000000..0c0af7b --- /dev/null +++ b/level_2/fll_execute/c/private-execute.h @@ -0,0 +1,104 @@ +/** + * FLL - Level 2 + * + * Project: Execute + * 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_FLL_execute_h +#define _PRIVATE_FLL_execute_h + +// libc includes +#include // defines PATH_MAX +#include +#include +#include +#include +#include + +// fll-0 includes +#include +#include +#include +#include + +// fll-1 includes + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Private implementation of fll_execute_arguments_add(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param source + * The string to add to the arguments array. + * @param length + * Length of string to prepend. + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if length is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + * + * @see fll_execute_arguments_add() + * @see fll_execute_arguments_add_set() + * @see fll_execute_arguments_dynamic_add() + * @see fll_execute_arguments_dynamic_add_set() + */ +#if !defined(_di_fll_execute_arguments_add_) || !defined(_di_fll_execute_arguments_add_set_) || !defined(_di_fll_execute_arguments_dynamic_add_) || !defined(_di_fll_execute_arguments_dynamic_add_set_) + extern f_return_status private_fll_execute_arguments_add(const f_string source, const f_string_length length, f_string_dynamics *arguments) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fll_execute_arguments_add_) || !defined(_di_fll_execute_arguments_add_set_) || !defined(_di_fll_execute_arguments_dynamic_add_) || !defined(_di_fll_execute_arguments_dynamic_add_set_) + +/** + * Private implementation of fll_execute_arguments_add_parameter(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param prefix + * The string prepend to the name. + * @param prefix_length + * Length of prefix to prepend. + * @param name + * The string to add to the arguments array. + * @param name_length + * Length of name to prepend. + * @param value + * The string prepend to the name. + * @param value_length + * Length of value to prepend. + * @param arguments + * The array of string arguments intended to pass to the execute functions. + * + * @return + * f_none on success. + * f_no_data if name_length is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * f_array_too_large (with error bit) if arguments array is too larger for further allocation. + * + * @see fll_execute_arguments_add_parameter() + * @see fll_execute_arguments_add_parameter_set() + * @see fll_execute_arguments_dynamic_add_parameter() + * @see fll_execute_arguments_dynamic_add_parameter_set() + */ +#if !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_) + extern f_return_status private_fll_execute_arguments_add_parameter(const f_string prefix, const f_string_length prefix_length, const f_string name, const f_string_length name_length, const f_string value, const f_string_length value_length, f_string_dynamics *arguments) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_FLL_execute_h diff --git a/level_2/fll_execute/data/build/dependencies b/level_2/fll_execute/data/build/dependencies index d8175f5..4804427 100644 --- a/level_2/fll_execute/data/build/dependencies +++ b/level_2/fll_execute/data/build/dependencies @@ -2,3 +2,4 @@ f_type f_status f_memory f_string +fl_string diff --git a/level_2/fll_execute/data/build/settings b/level_2/fll_execute/data/build/settings index 40d9aef..c51b88d 100644 --- a/level_2/fll_execute/data/build/settings +++ b/level_2/fll_execute/data/build/settings @@ -10,9 +10,9 @@ version_micro 0 build_compiler gcc build_linker ar build_libraries -lc -build_libraries_fll -lf_memory -build_sources_library execute.c -build_sources_program +build_libraries_fll -lfl_string -lf_memory +build_sources_library execute.c private-execute.c +build_sources_program build_sources_headers execute.h build_sources_bash build_sources_settings