From 5efda9d01d0f6a9cbf5028fc7e819452d3e14085 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sat, 28 May 2022 22:04:46 -0500 Subject: [PATCH] Bugfix: Fix problems exposed by unit tests in f_print. Swap the length a string checks, the length has priority over string. When performing the character safely prints, the F_utf should only be returned for UTF-8 characters whose width is greater than 1. The ASCII characters are now no longer returning F_utf. Some functions are missing the clearerr_unlocked() and ferror_unlocked() calls that are needed for proper fwrite_unlocked() error checks. Update the documentation comments, adding missing information. Some of the *_to* functions are not checking if the counter "i" exceeds the length before checking for NULL. The *_to* functions for *_raw_safely* do not exist and should to be consistent with the regular print functions. Add the missing *_to*_raw_safely* functions. Several of the *_to_except* functions are missing the offset parameter which should be passed for consistency with the regular print functions. Random functions are missing the final print that should exist outside of the loop. The "total" needs to be checked and if it represents that unprinted data is present, then print that data. --- level_0/f_print/c/print.c | 134 ++++++---- level_0/f_print/c/print.h | 98 +++++++- level_0/f_print/c/print/private-to.c | 29 ++- level_0/f_print/c/print/private-to.h | 1 + level_0/f_print/c/print/to.c | 207 ++++++++++++--- level_0/f_print/c/print/to.h | 474 ++++++++++++++++++++++++++++++++++- level_0/f_print/c/private-print.c | 39 +++ 7 files changed, 879 insertions(+), 103 deletions(-) diff --git a/level_0/f_print/c/print.c b/level_0/f_print/c/print.c index c36e435..8bfdfb5 100644 --- a/level_0/f_print/c/print.c +++ b/level_0/f_print/c/print.c @@ -11,7 +11,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -49,11 +49,16 @@ extern "C" { return F_none; } } - else if (macro_f_utf_byte_width_is(character) > 1 || character > 0x1f) { + else if (macro_f_utf_byte_width_is(character) > 1) { if (fwrite_unlocked(&character, 1, 1, output)) { return F_utf; } } + else if (character > 0x1f) { + if (fwrite_unlocked(&character, 1, 1, output)) { + return F_none; + } + } else { if (fwrite_unlocked(f_print_sequence_set_control_s[(unsigned int) character].string, 1, f_print_sequence_set_control_s[(unsigned int) character].used, output) == f_print_sequence_set_control_s[(unsigned int) character].used) { return F_none; @@ -77,7 +82,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -91,7 +96,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -111,7 +116,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -131,7 +136,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -151,7 +156,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -171,7 +176,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -185,7 +190,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -199,7 +204,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -213,7 +218,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -227,7 +232,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_except(buffer.string, 0, buffer.used, except, output); } @@ -239,7 +244,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -259,7 +264,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -279,7 +284,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -299,7 +304,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -319,7 +324,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_except_raw(buffer.string, 0, buffer.used, except, output); } @@ -331,7 +336,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_except_raw_safely(buffer.string, 0, buffer.used, except, output); } @@ -343,7 +348,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_except_safely(buffer.string, 0, buffer.used, except, output); } @@ -355,7 +360,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -369,7 +374,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_except_in(buffer.string, 0, buffer.used, except_at, except_in, output); } @@ -381,7 +386,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -401,7 +406,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -421,7 +426,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -441,7 +446,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -461,7 +466,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_except_in_raw(buffer.string, 0, buffer.used, except_at, except_in, output); } @@ -473,7 +478,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_except_in_raw_safely(buffer.string, 0, buffer.used, except_at, except_in, output); } @@ -485,7 +490,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_except_in_safely(buffer.string, 0, buffer.used, except_at, except_in, output); } @@ -497,7 +502,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -511,7 +516,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -525,7 +530,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -539,7 +544,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -553,7 +558,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -567,7 +572,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -581,7 +586,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -595,7 +600,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -624,7 +629,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -651,11 +656,14 @@ extern "C" { f_array_length_t start = 0; f_array_length_t total = 0; + f_array_length_t count = 0; f_string_static_t safe = f_string_empty_s; uint8_t width = 0; + clearerr_unlocked(output); + for (register f_array_length_t i = 0; string[i]; ) { safe.used = 0; @@ -687,31 +695,50 @@ extern "C" { if (safe.used) { if (total) { - if (fwrite_unlocked(string + start, 1, total, output) < total) { - return F_status_set_error(F_output); - } + count = 0; + + do { + count += fwrite_unlocked(string + start + count, 1, total - count, output); + + if (ferror_unlocked(output)) { + return F_status_set_error(F_output); + } + + } while (count < total); total = 0; } - if (fwrite_unlocked(safe.string, 1, safe.used, output) < safe.used) { - return F_status_set_error(F_output); - } + count = 0; + + do { + count += fwrite_unlocked(safe.string + count, 1, safe.used - count, output); + + if (ferror_unlocked(output)) { + return F_status_set_error(F_output); + } + + } while (count < safe.used); i += width; start = i; + continue; } if (total + width >= F_print_write_max_d) { - if (total) { - if (fwrite_unlocked(string + start, 1, total, output) < total) { + count = 0; + + do { + count += fwrite_unlocked(string + start + count, 1, total - count, output); + + if (ferror_unlocked(output)) { return F_status_set_error(F_output); } - total = 0; - } + } while (count < total); + total = 0; i += width; start = i - 1; @@ -723,9 +750,16 @@ extern "C" { } // for if (total) { - if (fwrite_unlocked(string + start, 1, total, output) < total) { - return F_status_set_error(F_output); - } + count = 0; + + do { + count += fwrite_unlocked(string + start + count, 1, total - count, output); + + if (ferror_unlocked(output)) { + return F_status_set_error(F_output); + } + + } while (count < total); } return F_none; diff --git a/level_0/f_print/c/print.h b/level_0/f_print/c/print.h index a267490..5d59bb4 100644 --- a/level_0/f_print/c/print.h +++ b/level_0/f_print/c/print.h @@ -59,6 +59,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_ @@ -70,6 +72,8 @@ extern "C" { * * This will print NULL characters and is essentially a "raw" print. * + * This does not call clearerr_unlocked(). + * * @param character * The character to verify as safe or not and then print. * @param output @@ -79,7 +83,7 @@ extern "C" { * F_none on success. * F_data_not if there is nothing to print. * - * F_output (with error bit) on failure. + * F_output (with error bit) on failure (fwrite_unlocked() returns 0). * F_parameter (with error bit) if a parameter is invalid. * * @see fwrite_unlocked() @@ -100,6 +104,8 @@ extern "C" { * * This should only be called for the first 1-byte character of a multibyte character. * + * This does not call clearerr_unlocked(). + * * @param character * The character to verify as safe or not and then print. * @param output @@ -107,10 +113,10 @@ extern "C" { * * @return * F_none on success. - * F_utf on success, but character is a UTF-8 character. * F_data_not if there is nothing to print. + * F_utf on success, but character is a UTF-8 character. * - * F_output (with error bit) on failure. + * F_output (with error bit) on failure (fwrite_unlocked() returns 0). * F_parameter (with error bit) if a parameter is invalid. * * @see fwrite_unlocked() @@ -124,7 +130,7 @@ extern "C" { * * Control characters are converted to the Unicode control character symbols, including NULL. * UTF-8 sequences with a width of 1 are converted to the unknown character '�'. - * For all other UTF-8 sequences, an empty string is returned. + * For all other UTF-8 sequences (including non-control character ASCII symbols), an empty string is returned. * * The returned string will either be an empty string (for characters that are already safe) or a string representing the replacement. * This can result in a 3-byte character being returned as a string of 3 1-bytes. @@ -164,6 +170,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_ @@ -193,6 +201,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_partial_ @@ -224,6 +234,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_partial_raw_ @@ -258,6 +270,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -292,6 +306,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -323,6 +339,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_raw_ @@ -355,6 +373,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -387,6 +407,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -426,6 +448,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_except_ @@ -457,6 +481,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_except_dynamic_ @@ -490,6 +516,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_ @@ -525,6 +553,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_raw_ @@ -563,6 +593,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -601,6 +633,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -636,6 +670,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_except_dynamic_raw_ @@ -672,6 +708,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -708,6 +746,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -719,7 +759,7 @@ extern "C" { /** * Similar to a c-library printf, except that this will only print a specific range. * - * An offset is provided because the except_at/except_int positions are expected to be relative to the start position, without the offset applied. + * An offset is provided because the except_at/except_in positions are expected to be relative to the start position, without the offset applied. * * Will not stop at NULL. * Will not print NULL. @@ -751,6 +791,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_except_in_ @@ -786,6 +828,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_except_in_dynamic_ @@ -823,6 +867,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_ @@ -862,6 +908,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_raw_ @@ -901,6 +949,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -940,6 +990,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -979,6 +1031,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_except_in_dynamic_raw_ @@ -1019,6 +1073,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -1059,6 +1115,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -1070,7 +1128,7 @@ extern "C" { /** * Similar to a c-library printf, except that this will only print a specific range. * - * An offset is provided because the except_at/except_int positions are expected to be relative to the start position, without the offset applied. + * An offset is provided because the except_at/except_in positions are expected to be relative to the start position, without the offset applied. * * Will not stop at NULL. * Will print NULL. @@ -1104,6 +1162,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_except_in_raw_ @@ -1118,7 +1178,7 @@ extern "C" { * Control characters are converted to the Unicode control character symbols, excluding NULL. * UTF-8 sequences with invalid widths are converted to the unknown character '�'. * - * An offset is provided because the except_at/except_int positions are expected to be relative to the start position, without the offset applied. + * An offset is provided because the except_at/except_in positions are expected to be relative to the start position, without the offset applied. * * Will not stop at NULL. * Will print NULL. @@ -1150,6 +1210,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -1164,7 +1226,7 @@ extern "C" { * Control characters are converted to the Unicode control character symbols, excluding NULL. * UTF-8 sequences with invalid widths are converted to the unknown character '�'. * - * An offset is provided because the except_at/except_int positions are expected to be relative to the start position, without the offset applied. + * An offset is provided because the except_at/except_in positions are expected to be relative to the start position, without the offset applied. * * Will not stop at NULL. * Will not print NULL. @@ -1196,6 +1258,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -1237,6 +1301,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_except_raw_ @@ -1277,6 +1343,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -1317,6 +1385,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -1350,6 +1420,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_raw_ @@ -1384,6 +1456,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -1413,6 +1487,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_raw_terminated_ @@ -1445,6 +1521,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -1506,6 +1584,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() * * @see f_utf_is_valid() @@ -1535,6 +1615,8 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see clearerr_unlocked() + * @see ferror_unlocked() * @see fwrite_unlocked() */ #ifndef _di_f_print_terminated_ diff --git a/level_0/f_print/c/print/private-to.c b/level_0/f_print/c/print/private-to.c index 5332178..0e902b7 100644 --- a/level_0/f_print/c/print/private-to.c +++ b/level_0/f_print/c/print/private-to.c @@ -54,11 +54,9 @@ static inline f_status_t private_inline_f_print_to_error(void) { total = 0; } - if (!string[i]) { - do { - ++i; - } while (i < length && !string[i]); - } + while (i < length && !string[i]) { + ++i; + } // while } // for return F_none; @@ -78,7 +76,12 @@ static inline f_status_t private_inline_f_print_to_error(void) { return F_none; } } - else if (macro_f_utf_byte_width_is(character) > 1 || character > 0x1f) { + else if (macro_f_utf_byte_width_is(character) > 1) { + if (write(id, &character, 1) != -1) { + return F_utf; + } + } + else if (character > 0x1f) { if (write(id, &character, 1) != -1) { return F_none; } @@ -420,6 +423,12 @@ static inline f_status_t private_inline_f_print_to_error(void) { } } // while + if (total) { + if (write(id, string + start, total) == -1) { + return private_inline_f_print_to_error(); + } + } + return F_none; } #endif // !defined(_di_f_print_to_except_in_) || !defined(_di_f_print_to_except_in_dynamic_) || !defined(_di_f_print_to_except_in_dynamic_partial_) @@ -492,6 +501,12 @@ static inline f_status_t private_inline_f_print_to_error(void) { } } // while + if (total) { + if (write(id, string + start, total) == -1) { + return private_inline_f_print_to_error(); + } + } + return F_none; } #endif // !defined(_di_f_print_to_except_in_raw_) || !defined(_di_f_print_to_except_in_dynamic_raw_) || !defined(_di_f_print_to_except_in_dynamic_partial_raw_) @@ -739,7 +754,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { } // Print all NULL characters. - if (!string[i]) { + if (i < length && !string[i]) { start = i; do { diff --git a/level_0/f_print/c/print/private-to.h b/level_0/f_print/c/print/private-to.h index 8a447fc..6caff8b 100644 --- a/level_0/f_print/c/print/private-to.h +++ b/level_0/f_print/c/print/private-to.h @@ -70,6 +70,7 @@ extern "C" { * @return * F_none on success. * F_data_not if there is nothing to print. + * F_utf on success, but character is a UTF-8 character. * * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. * F_buffer (with error bit) if the buffer is invalid. diff --git a/level_0/f_print/c/print/to.c b/level_0/f_print/c/print/to.c index 264ded3..1bfc310 100644 --- a/level_0/f_print/c/print/to.c +++ b/level_0/f_print/c/print/to.c @@ -15,6 +15,7 @@ extern "C" { * The appropriate status. */ static inline f_status_t private_inline_f_print_to_error(void) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); if (errno == EBADF) return F_status_set_error(F_file_descriptor); if (errno == EDESTADDRREQ) return F_status_set_error(F_socket_not); @@ -37,7 +38,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -75,7 +76,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -89,7 +90,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -109,7 +110,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -123,13 +124,33 @@ static inline f_status_t private_inline_f_print_to_error(void) { } #endif // _di_f_print_to_dynamic_partial_raw_ +#ifndef _di_f_print_to_dynamic_partial_raw_safely_ + f_status_t f_print_to_dynamic_partial_raw_safely(const f_string_static_t buffer, const f_string_range_t range, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_to_raw_safely(buffer.string + range.start, length, id); + } +#endif // _di_f_print_to_dynamic_partial_raw_safely_ + #ifndef _di_f_print_to_dynamic_partial_safely_ f_status_t f_print_to_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -149,7 +170,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -157,13 +178,27 @@ static inline f_status_t private_inline_f_print_to_error(void) { } #endif // _di_f_print_to_dynamic_raw_ +#ifndef _di_f_print_to_dynamic_raw_safely_ + f_status_t f_print_to_dynamic_raw_safely(const f_string_static_t buffer, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used || !buffer.string) { + return F_data_not; + } + + return private_f_print_to_raw_safely(buffer.string, buffer.used, id); + } +#endif // _di_f_print_to_dynamic_raw_safely_ + #ifndef _di_f_print_to_dynamic_safely_ f_status_t f_print_to_dynamic_safely(const f_string_static_t buffer, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -172,16 +207,16 @@ static inline f_status_t private_inline_f_print_to_error(void) { #endif // _di_f_print_to_dynamic_safely_ #ifndef _di_f_print_to_except_ - f_status_t f_print_to_except(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id) { + f_status_t f_print_to_except(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } - return private_f_print_to_except(string, 0, length, except, id); + return private_f_print_to_except(string, offset, length, except, id); } #endif // _di_f_print_to_except_ @@ -191,7 +226,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -205,7 +240,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -225,7 +260,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -239,13 +274,33 @@ static inline f_status_t private_inline_f_print_to_error(void) { } #endif // _di_f_print_to_except_dynamic_partial_raw_ +#ifndef _di_f_print_to_except_dynamic_partial_raw_safely_ + f_status_t f_print_to_except_dynamic_partial_raw_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_to_except_raw_safely(buffer.string, range.start, range.start + length, except, id); + } +#endif // _di_f_print_to_except_dynamic_partial_raw_safely_ + #ifndef _di_f_print_to_except_dynamic_partial_safely_ f_status_t f_print_to_except_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -265,7 +320,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -273,13 +328,27 @@ static inline f_status_t private_inline_f_print_to_error(void) { } #endif // _di_f_print_to_except_dynamic_raw_ +#ifndef _di_f_print_to_except_dynamic_raw_safely_ + f_status_t f_print_to_except_dynamic_raw_safely(const f_string_static_t buffer, const f_array_lengths_t except, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used || !buffer.string) { + return F_data_not; + } + + return private_f_print_to_except_raw_safely(buffer.string, 0, buffer.used, except, id); + } +#endif // _di_f_print_to_except_dynamic_raw_safely_ + #ifndef _di_f_print_to_except_dynamic_safely_ f_status_t f_print_to_except_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) { + if (!buffer.used || !buffer.string) { return F_data_not; } @@ -293,7 +362,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -319,7 +388,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -339,7 +408,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -353,13 +422,33 @@ static inline f_status_t private_inline_f_print_to_error(void) { } #endif // _di_f_print_to_except_in_dynamic_partial_raw_ +#ifndef _di_f_print_to_except_in_dynamic_partial_raw_safely_ + f_status_t f_print_to_except_in_dynamic_partial_raw_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except_at, const f_string_ranges_t except_in, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_to_except_in_raw_safely(buffer.string, range.start, range.start + length, except_at, except_in, id); + } +#endif // _di_f_print_to_except_in_dynamic_partial_raw_safely_ + #ifndef _di_f_print_to_except_in_dynamic_partial_safely_ f_status_t f_print_to_except_in_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except_at, const f_string_ranges_t except_in, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.used || range.start > range.stop || range.start >= buffer.used || !buffer.string) { return F_data_not; } @@ -379,19 +468,31 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_to_except_in_raw(buffer.string, 0, buffer.used, except_at, except_in, id); } #endif // _di_f_print_to_except_in_dynamic_raw_ +#ifndef _di_f_print_to_except_in_dynamic_raw_safely_ + f_status_t f_print_to_except_in_dynamic_raw_safely(const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used || !buffer.string) return F_data_not; + + return private_f_print_to_except_in_raw_safely(buffer.string, 0, buffer.used, except_at, except_in, id); + } +#endif // _di_f_print_to_except_in_dynamic_raw_safely_ + #ifndef _di_f_print_to_except_in_dynamic_safely_ f_status_t f_print_to_except_in_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.string || !buffer.used) return F_data_not; + if (!buffer.used || !buffer.string) return F_data_not; return private_f_print_to_except_in_safely(buffer.string, 0, buffer.used, except_at, except_in, id); } @@ -403,7 +504,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -411,13 +512,27 @@ static inline f_status_t private_inline_f_print_to_error(void) { } #endif // _di_f_print_to_except_in_raw_ +#ifndef _di_f_print_to_except_in_raw_safely_ + f_status_t f_print_to_except_in_raw_safely(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except_at, const f_string_ranges_t except_in, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!length || !string) { + return F_data_not; + } + + return private_f_print_to_except_in_raw_safely(string, offset, length, except_at, except_in, id); + } +#endif // _di_f_print_to_except_in_raw_safely_ + #ifndef _di_f_print_to_except_in_safely_ f_status_t f_print_to_except_in_safely(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except_at, const f_string_ranges_t except_in, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -426,30 +541,44 @@ static inline f_status_t private_inline_f_print_to_error(void) { #endif // _di_f_print_to_except_in_safely_ #ifndef _di_f_print_to_except_raw_ - f_status_t f_print_to_except_raw(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id) { + f_status_t f_print_to_except_raw(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } - return private_f_print_to_except_raw(string, 0, length, except, id); + return private_f_print_to_except_raw(string, offset, length, except, id); } #endif // _di_f_print_to_except_raw_ +#ifndef _di_f_print_to_except_raw_safely_ + f_status_t f_print_to_except_raw_safely(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!length || !string) { + return F_data_not; + } + + return private_f_print_to_except_raw_safely(string, offset, length, except, id); + } +#endif // _di_f_print_to_except_raw_safely_ + #ifndef _di_f_print_to_except_safely_ - f_status_t f_print_to_except_safely(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id) { + f_status_t f_print_to_except_safely(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } - return private_f_print_to_except_safely(string, 0, length, except, id); + return private_f_print_to_except_safely(string, offset, length, except, id); } #endif // _di_f_print_to_except_safely_ @@ -459,7 +588,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } @@ -467,6 +596,20 @@ static inline f_status_t private_inline_f_print_to_error(void) { } #endif // _di_f_print_to_raw_ +#ifndef _di_f_print_to_raw_safely_ + f_status_t f_print_to_raw_safely(const f_string_t string, const f_array_length_t length, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!length || !string) { + return F_data_not; + } + + return private_f_print_to_raw_safely(string, length, id); + } +#endif // _di_f_print_to_raw_safely_ + #ifndef _di_f_print_to_raw_terminated_ f_status_t f_print_to_raw_terminated(const f_string_t string, const int id) { #ifndef _di_level_0_parameter_checking_ @@ -488,7 +631,7 @@ static inline f_status_t private_inline_f_print_to_error(void) { if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!string || !length) { + if (!length || !string) { return F_data_not; } diff --git a/level_0/f_print/c/print/to.h b/level_0/f_print/c/print/to.h index d5d43c3..c1b68bc 100644 --- a/level_0/f_print/c/print/to.h +++ b/level_0/f_print/c/print/to.h @@ -255,6 +255,53 @@ extern "C" { #endif // _di_f_print_to_dynamic_partial_raw_ /** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * This is essentually a "safe" print that also prints NULL. + * + * Control characters are converted to the Unicode control character symbols, excluding NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_filesystem_quota_block (with error bit) if quota is reached or exceeded. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_number_overflow (with error bit) if maximum size reached while writing or attempting to write beyond maximum allowed offset. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if a connected pipe or socket is closed. + * F_space_not (with error bit) cannot write, out of space. + * F_socket_not (with error bit) if socket is not connected. + * + * F_output (with error bit) on any other failure. + * + * @see write() + */ +#ifndef _di_f_print_to_dynamic_partial_raw_safely_ + extern f_status_t f_print_to_dynamic_partial_raw_safely(const f_string_static_t buffer, const f_string_range_t range, const int id); +#endif // _di_f_print_to_dynamic_partial_raw_safely_ + +/** * Similar to a c-library dprintf, except that this will only print a specific range in a given dynamic string. * * Control characters are converted to the Unicode control character symbols, excluding NULL. @@ -338,6 +385,51 @@ extern "C" { #endif // _di_f_print_to_dynamic_raw_ /** + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * This is essentually a "safe" print that also prints NULL. + * + * Control characters are converted to the Unicode control character symbols, excluding NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_filesystem_quota_block (with error bit) if quota is reached or exceeded. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_number_overflow (with error bit) if maximum size reached while writing or attempting to write beyond maximum allowed offset. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if a connected pipe or socket is closed. + * F_space_not (with error bit) cannot write, out of space. + * F_socket_not (with error bit) if socket is not connected. + * + * F_output (with error bit) on any other failure. + * + * @see write() + */ +#ifndef _di_f_print_to_dynamic_raw_safely_ + extern f_status_t f_print_to_dynamic_raw_safely(const f_string_static_t buffer, const int id); +#endif // _di_f_print_to_dynamic_raw_safely_ + +/** * Similar to a c-library dprintf, except that this prints a given dynamic string. * * Control characters are converted to the Unicode control character symbols, excluding NULL. @@ -388,6 +480,8 @@ extern "C" { * * @param string * The string to output. + * @param offset + * The inclusive start point to start printing. * @param length * The total number of characters to print. * @param except @@ -419,7 +513,7 @@ extern "C" { * @see write() */ #ifndef _di_f_print_to_except_ - extern f_status_t f_print_to_except(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id); + extern f_status_t f_print_to_except(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except, const int id); #endif // _di_f_print_to_except_ /** @@ -555,6 +649,57 @@ extern "C" { #endif // _di_f_print_to_except_dynamic_partial_raw_ /** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * This is essentually a "safe" print that also prints NULL. + * + * Control characters are converted to the Unicode control character symbols, excluding NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_filesystem_quota_block (with error bit) if quota is reached or exceeded. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_number_overflow (with error bit) if maximum size reached while writing or attempting to write beyond maximum allowed offset. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if a connected pipe or socket is closed. + * F_space_not (with error bit) cannot write, out of space. + * F_socket_not (with error bit) if socket is not connected. + * + * F_output (with error bit) on any other failure. + * + * @see write() + */ +#ifndef _di_f_print_to_except_dynamic_partial_raw_safely_ + extern f_status_t f_print_to_except_dynamic_partial_raw_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_dynamic_partial_raw_safely_ + +/** * Similar to a c-library dprintf, except that this will only print a specific range in a given dynamic string. * * Control characters are converted to the Unicode control character symbols, excluding NULL. @@ -646,6 +791,55 @@ extern "C" { #endif // _di_f_print_to_except_dynamic_raw_ /** + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * This is essentually a "safe" print that also prints NULL. + * + * Control characters are converted to the Unicode control character symbols, excluding NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_filesystem_quota_block (with error bit) if quota is reached or exceeded. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_number_overflow (with error bit) if maximum size reached while writing or attempting to write beyond maximum allowed offset. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if a connected pipe or socket is closed. + * F_space_not (with error bit) cannot write, out of space. + * F_socket_not (with error bit) if socket is not connected. + * + * F_output (with error bit) on any other failure. + * + * @see write() + */ +#ifndef _di_f_print_to_except_dynamic_raw_safely_ + extern f_status_t f_print_to_except_dynamic_raw_safely(const f_string_static_t buffer, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_dynamic_raw_safely_ + +/** * Similar to a c-library dprintf, except that this prints a given dynamic string. * * Control characters are converted to the Unicode control character symbols, excluding NULL. @@ -693,7 +887,7 @@ extern "C" { /** * Similar to a c-library printf, except that this will only print a specific range. * - * An offset is provided because the except_at/except_int positions are expected to be relative to the start position, without the offset applied. + * An offset is provided because the except_at/except_in positions are expected to be relative to the start position, without the offset applied. * * Will not stop at NULL. * Will not print NULL. @@ -897,6 +1091,58 @@ extern "C" { /** * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. * + * This is essentually a "safe" print that also prints NULL. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_filesystem_quota_block (with error bit) if quota is reached or exceeded. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_number_overflow (with error bit) if maximum size reached while writing or attempting to write beyond maximum allowed offset. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if a connected pipe or socket is closed. + * F_space_not (with error bit) cannot write, out of space. + * F_socket_not (with error bit) if socket is not connected. + * + * F_output (with error bit) on any other failure. + * + * @see write() + */ +#ifndef _di_f_print_dynamic_except_partial_raw_safely_ + extern f_status_t f_print_to_except_in_dynamic_partial_raw_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except_at, const f_string_ranges_t except_in, const int id); +#endif // _di_f_print_to_except_in_dynamic_partial_raw_safely_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * * Will not stop at NULL. * Will not print NULL. * Will not print any 1-byte character at a location specified in except_at array. @@ -999,6 +1245,59 @@ extern "C" { /** * Similar to a c-library printf, except that this prints a given dynamic string. * + * This is essentually a "safe" print that also prints NULL. + * + * Control characters are converted to the Unicode control character symbols, excluding NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to the length of the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_filesystem_quota_block (with error bit) if quota is reached or exceeded. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_number_overflow (with error bit) if maximum size reached while writing or attempting to write beyond maximum allowed offset. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if a connected pipe or socket is closed. + * F_space_not (with error bit) cannot write, out of space. + * F_socket_not (with error bit) if socket is not connected. + * + * F_output (with error bit) on any other failure. + * + * @see write() + */ +#ifndef _di_f_print_to_except_in_dynamic_raw_safely_ + extern f_status_t f_print_to_except_in_dynamic_raw_safely(const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, const int id); +#endif // _di_f_print_to_except_in_dynamic_raw_safely_ + +/** + * Similar to a c-library printf, except that this prints a given dynamic string. + * * Control characters are converted to the Unicode control character symbols, excluding NULL. * UTF-8 sequences with invalid widths are converted to the unknown character '�'. * @@ -1052,7 +1351,7 @@ extern "C" { /** * Similar to a c-library printf, except that this will only print a specific range. * - * An offset is provided because the except_at/except_int positions are expected to be relative to the start position, without the offset applied. + * An offset is provided because the except_at/except_in positions are expected to be relative to the start position, without the offset applied. * * Will not stop at NULL. * Will print NULL. @@ -1108,10 +1407,69 @@ extern "C" { /** * Similar to a c-library printf, except that this will only print a specific range. * + * This is essentually a "safe" print that also prints NULL. + * + * Control characters are converted to the Unicode control character symbols, excluding NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * An offset is provided because the except_at/except_in positions are expected to be relative to the start position, without the offset applied. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param length + * The total number of characters to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_filesystem_quota_block (with error bit) if quota is reached or exceeded. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_number_overflow (with error bit) if maximum size reached while writing or attempting to write beyond maximum allowed offset. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if a connected pipe or socket is closed. + * F_space_not (with error bit) cannot write, out of space. + * F_socket_not (with error bit) if socket is not connected. + * + * F_output (with error bit) on any other failure. + * + * @see write() + */ +#ifndef _di_f_print_to_except_in_raw_safely_ + extern f_status_t f_print_to_except_in_raw_safely(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except_at, const f_string_ranges_t except_in, const int id); +#endif // _di_f_print_to_except_in_raw_safely_ + +/** + * Similar to a c-library printf, except that this will only print a specific range. + * * Control characters are converted to the Unicode control character symbols, excluding NULL. * UTF-8 sequences with invalid widths are converted to the unknown character '�'. * - * An offset is provided because the except_at/except_int positions are expected to be relative to the start position, without the offset applied. + * An offset is provided because the except_at/except_in positions are expected to be relative to the start position, without the offset applied. * * Will not stop at NULL. * Will not print NULL. @@ -1176,6 +1534,8 @@ extern "C" { * * @param string * The string to output. + * @param offset + * The inclusive start point to start printing. * @param length * The total number of characters to print. * @param except @@ -1207,10 +1567,63 @@ extern "C" { * @see write() */ #ifndef _di_f_print_to_except_raw_ - extern f_status_t f_print_to_except_raw(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id); + extern f_status_t f_print_to_except_raw(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except, const int id); #endif // _di_f_print_to_except_raw_ /** + * Similar to a c-library printf, except that this will only print a specific range. + * + * This is essentually a "safe" print that also prints NULL. + * + * Control characters are converted to the Unicode control character symbols, excluding NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param length + * The total number of characters to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_filesystem_quota_block (with error bit) if quota is reached or exceeded. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_number_overflow (with error bit) if maximum size reached while writing or attempting to write beyond maximum allowed offset. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if a connected pipe or socket is closed. + * F_space_not (with error bit) cannot write, out of space. + * F_socket_not (with error bit) if socket is not connected. + * + * F_output (with error bit) on any other failure. + * + * @see write() + */ +#ifndef _di_f_print_to_except_raw_safely_ + extern f_status_t f_print_to_except_raw_safely(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_raw_safely_ + +/** * Similar to a c-library dprintf, except that this will only print a specific range. * * Control characters are converted to the Unicode control character symbols, excluding NULL. @@ -1223,6 +1636,8 @@ extern "C" { * * @param string * The string to output. + * @param offset + * The inclusive start point to start printing. * @param length * The total number of characters to print. * @param except @@ -1254,7 +1669,7 @@ extern "C" { * @see write() */ #ifndef _di_f_print_to_except_safely_ - extern f_status_t f_print_to_except_safely(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id); + extern f_status_t f_print_to_except_safely(const f_string_t string, const f_array_length_t offset, const f_array_length_t length, const f_array_lengths_t except, const int id); #endif // _di_f_print_to_except_safely_ /** @@ -1300,6 +1715,53 @@ extern "C" { #endif // _di_f_print_to_raw_ /** + * Similar to a c-library printf, except that this will only print a specific range. + * + * This is essentually a "safe" print that also prints NULL. + * + * Control characters are converted to the Unicode control character symbols, excluding NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_filesystem_quota_block (with error bit) if quota is reached or exceeded. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_number_overflow (with error bit) if maximum size reached while writing or attempting to write beyond maximum allowed offset. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if a connected pipe or socket is closed. + * F_space_not (with error bit) cannot write, out of space. + * F_socket_not (with error bit) if socket is not connected. + * + * F_output (with error bit) on any other failure. + * + * @see write() + */ +#ifndef _di_f_print_to_raw_safely_ + extern f_status_t f_print_to_raw_safely(const f_string_t string, const f_array_length_t length, const int id); +#endif // _di_f_print_to_raw_safely_ + +/** * Similar to a c-library printf. * * Will stop at NULL. diff --git a/level_0/f_print/c/private-print.c b/level_0/f_print/c/private-print.c index f6dd92b..75ee862 100644 --- a/level_0/f_print/c/private-print.c +++ b/level_0/f_print/c/private-print.c @@ -711,6 +711,19 @@ extern "C" { } } // while + if (total) { + count = 0; + + do { + count += fwrite_unlocked(string + start + count, 1, total - count, output); + + if (ferror_unlocked(output)) { + return F_status_set_error(F_output); + } + + } while (count < total); + } + return F_none; } #endif // !defined(_di_f_print_except_raw_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_partial_raw_) @@ -820,6 +833,19 @@ extern "C" { i += width; } // while + if (total) { + count = 0; + + do { + count += fwrite_unlocked(string + start + count, 1, total - count, output); + + if (ferror_unlocked(output)) { + return F_status_set_error(F_output); + } + + } while (count < total); + } + return F_none; } #endif // !defined(_di_f_print_except_raw_safely_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_partial_raw_) @@ -945,6 +971,19 @@ extern "C" { i += width; } // while + if (total) { + count = 0; + + do { + count += fwrite_unlocked(string + start + count, 1, total - count, output); + + if (ferror_unlocked(output)) { + return F_status_set_error(F_output); + } + + } while (count < total); + } + return F_none; } #endif // !defined(_di_f_print_except_safely_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_dynamic_partial_safely_) -- 1.8.3.1