From 1cd6387630507bc423aaea71332ec095bebb48b8 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 5 Aug 2021 22:45:17 -0500 Subject: [PATCH] Progress: Continue string and convert changes, fixing bugs. Document that the conversion operations are not ideal performance-wise. Switch from fputc() to fwrite_unlocked() for the conversion print functions. Use more bitwise operations rather than comparisons. Explicitly handle binary print mode as it is easy to optimize. (The binary optimization still uses much of the existing strategy and so likely can still be further optimized.) Use correct digits for binary print in byte_dump. Update the API documentation as it has fallen behind. Preemptively update some of the API documentation where fputc/fputc_unlocked has not yet been fully updated to fwrite_unlocked. --- level_0/f_conversion/c/conversion.c | 12 +- level_0/f_conversion/c/conversion.h | 37 +++-- level_0/f_conversion/c/private-conversion.c | 241 +++++++++++++++------------- level_0/f_conversion/c/private-conversion.h | 72 ++++++--- level_0/f_print/c/print.c | 2 +- level_0/f_print/c/print.h | 68 ++++---- level_0/f_print/c/private-print.c | 192 +++++++++++----------- level_0/f_print/c/private-print.h | 98 ++++++++--- level_1/fl_print/c/print.h | 20 +-- level_1/fl_print/c/private-print.c | 26 +-- level_1/fl_print/c/private-print.h | 8 +- level_3/byte_dump/c/private-byte_dump.c | 4 +- 12 files changed, 443 insertions(+), 337 deletions(-) diff --git a/level_0/f_conversion/c/conversion.c b/level_0/f_conversion/c/conversion.c index a5a4023..10d80ea 100644 --- a/level_0/f_conversion/c/conversion.c +++ b/level_0/f_conversion/c/conversion.c @@ -168,8 +168,8 @@ extern "C" { } #endif // _di_f_conversion_character_to_octal_ -#ifndef _di_f_conversion_number_signed_to_file_ - f_status_t f_conversion_number_signed_to_file(const f_number_signed_t number, const f_conversion_data_t data, FILE *output) { +#ifndef _di_f_conversion_number_signed_print_ + f_status_t f_conversion_number_signed_print(const f_number_signed_t number, const f_conversion_data_t data, FILE *output) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); if (data.base < 2 || data.base > 16) return F_status_set_error(F_parameter); @@ -181,7 +181,7 @@ extern "C" { return private_f_conversion_digit_to_file((f_number_unsigned_t) number, data, number ? 0 : 2, output); } -#endif // _di_f_conversion_number_signed_to_file_ +#endif // _di_f_conversion_number_signed_print_ #ifndef _di_f_conversion_number_signed_to_string_ f_status_t f_conversion_number_signed_to_string(const f_number_signed_t number, const f_conversion_data_t data, f_string_dynamic_t *destination) { @@ -198,8 +198,8 @@ extern "C" { } #endif // _di_f_conversion_number_signed_to_string_ -#ifndef _di_f_conversion_number_unsigned_to_file_ - f_status_t f_conversion_number_unsigned_to_file(const f_number_unsigned_t number, const f_conversion_data_t data, FILE *output) { +#ifndef _di_f_conversion_number_unsigned_print_ + f_status_t f_conversion_number_unsigned_print(const f_number_unsigned_t number, const f_conversion_data_t data, FILE *output) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); if (data.base < 2 || data.base > 16) return F_status_set_error(F_parameter); @@ -207,7 +207,7 @@ extern "C" { return private_f_conversion_digit_to_file(number, data, number ? 0 : 2, output); } -#endif // _di_f_conversion_number_unsigned_to_file_ +#endif // _di_f_conversion_number_unsigned_print_ #ifndef _di_f_conversion_number_unsigned_to_string_ f_status_t f_conversion_number_unsigned_to_string(const f_number_unsigned_t number, const f_conversion_data_t data, f_string_dynamic_t *destination) { diff --git a/level_0/f_conversion/c/conversion.h b/level_0/f_conversion/c/conversion.h index 82519ce..b39a601 100644 --- a/level_0/f_conversion/c/conversion.h +++ b/level_0/f_conversion/c/conversion.h @@ -6,6 +6,9 @@ * Licenses: lgplv2.1 * * Provide means to convert one data type to another, such as a string to an integer. + * + * @fixme Currently these functions are very inefficient. + * These will be improved once I have finished studying on the matter. */ #ifndef _F_conversion_h #define _F_conversion_h @@ -202,6 +205,8 @@ extern "C" { * This only supports the following base units: 2 through 16. * This only supports base prefixes for: 2, 8, 10, 12, and 16. * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param number * The number to convert. * @param data @@ -212,14 +217,19 @@ extern "C" { * @return * F_none if the number was converted to a string. * - * F_output (with error bit) on fputc() error. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see fwrite_unlocked() */ -#ifndef _di_f_conversion_number_signed_to_file_ - extern f_status_t f_conversion_number_signed_to_file(const f_number_signed_t number, const f_conversion_data_t data, FILE *output); -#endif // _di_f_conversion_number_signed_to_file_ +#ifndef _di_f_conversion_number_signed_print_ + extern f_status_t f_conversion_number_signed_print(const f_number_signed_t number, const f_conversion_data_t data, FILE *output); +#endif // _di_f_conversion_number_signed_print_ /** * Convert a signed number into the decimal digit string that it represents. @@ -257,6 +267,8 @@ extern "C" { * This only supports the following base units: 2 through 16. * This only supports base prefixes for: 2, 8, 10, 12, and 16. * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param number * The number to convert. * This number is unsigned to allow for unsigned integers to be used. @@ -269,14 +281,19 @@ extern "C" { * @return * F_none if the number was converted to a string. * - * F_output (with error bit) on fputc() error. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see fwrite_unlocked() */ -#ifndef _di_f_conversion_number_unsigned_to_file_ - extern f_status_t f_conversion_number_unsigned_to_file(const f_number_unsigned_t number, const f_conversion_data_t data, FILE *output); -#endif // _di_f_conversion_number_unsigned_to_file_ +#ifndef _di_f_conversion_number_unsigned_print_ + extern f_status_t f_conversion_number_unsigned_print(const f_number_unsigned_t number, const f_conversion_data_t data, FILE *output); +#endif // _di_f_conversion_number_unsigned_print_ /** * Convert an unsigned number into the decimal digit string that it represents. diff --git a/level_0/f_conversion/c/private-conversion.c b/level_0/f_conversion/c/private-conversion.c index bc9bff1..04b427a 100644 --- a/level_0/f_conversion/c/private-conversion.c +++ b/level_0/f_conversion/c/private-conversion.c @@ -5,7 +5,7 @@ extern "C" { #endif -#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#if !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) f_status_t private_f_conversion_digit_to_file(const f_number_unsigned_t number, const f_conversion_data_t data, const uint8_t negative, FILE *output) { int digits = 0; @@ -64,7 +64,14 @@ extern "C" { return F_status_set_error(F_output); } - if (!fputc(f_string_ascii_0_s[0], output)) { + if (fwrite_unlocked(f_string_ascii_0_s, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } @@ -106,7 +113,14 @@ extern "C" { } } else if (data.width) { - if (!fputc(f_string_ascii_0_s[0], output)) { + if (fwrite_unlocked(f_string_ascii_0_s, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } @@ -114,9 +128,9 @@ extern "C" { return F_none; } -#endif // !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#endif // !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) -#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#if !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) f_status_t private_f_conversion_digit_to_file_number(const f_conversion_data_t data, f_number_unsigned_t number, int digits, FILE *output) { f_number_unsigned_t power = 1; @@ -125,114 +139,137 @@ extern "C" { power *= data.base; } // for + if (data.base == 2) { + f_number_unsigned_t work = 0x1 << (digits - 1); + + while (digits--) { + + if (fwrite_unlocked((work & number) ? f_string_ascii_1_s : f_string_ascii_0_s, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + + return F_status_set_error(F_output); + } + + work >>= 1; + } // while + + return F_none; + } + f_number_unsigned_t current = number; f_number_unsigned_t work = 0; - for (char c = 0; power; --digits) { + for (char c = 0; digits; --digits) { work = current / power; current -= work * power; power /= data.base; - if (work < 8) { - if (work == 0) { - c = f_string_ascii_0_s[0]; - } - else if (work == 1) { - c = f_string_ascii_1_s[0]; - } - else if (work == 2) { - c = f_string_ascii_2_s[0]; - } - else if (work == 3) { - c = f_string_ascii_3_s[0]; - } - else if (work == 4) { - c = f_string_ascii_4_s[0]; - } - else if (work == 5) { - c = f_string_ascii_5_s[0]; - } - else if (work == 6) { - c = f_string_ascii_6_s[0]; - } - else { - c = f_string_ascii_7_s[0]; - } + if (work < 0xa) { + c = 0x30 + work; } else { - if (work == 8) { - c = f_string_ascii_8_s[0]; - } - else if (work == 9) { - c = f_string_ascii_8_s[0]; - } - else if (work == 10) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_A_s[0] : f_string_ascii_a_s[0]; - } - else if (work == 11) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_B_s[0] : f_string_ascii_b_s[0]; - } - else if (work == 12) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_C_s[0] : f_string_ascii_c_s[0]; - } - else if (work == 13) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_D_s[0] : f_string_ascii_d_s[0]; - } - else if (work == 14) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_E_s[0] : f_string_ascii_e_s[0]; + if (data.flag & f_conversion_data_flag_base_upper) { + c = 0x37 + work; } else { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_F_s[0] : f_string_ascii_f_s[0]; + c = 0x57 + work; } } - if (!fputc(c, output)) { + if (fwrite_unlocked(&c, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } // for return F_none; } -#endif // !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#endif // !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) -#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#if !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) f_status_t private_f_conversion_digit_to_file_pad(const f_conversion_data_t data, const char pad, int total, FILE *output) { for (; total; --total) { - if (!fputc(pad, output)) { + if (fwrite_unlocked(&pad, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } // for return F_none; } -#endif // !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#endif // !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) -#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#if !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) f_status_t private_f_conversion_digit_to_file_prefix(const f_conversion_data_t data, const uint8_t negative, FILE *output) { if (negative) { if (negative == 1) { - if (!fputc(f_string_ascii_minus_s[0], output)) { + if (fwrite_unlocked(f_string_ascii_minus_s, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } } else if (data.flag & f_conversion_data_flag_sign_always) { - if (!fputc(f_string_ascii_plus_s[0], output)) { + if (fwrite_unlocked(f_string_ascii_plus_s, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } else if (data.flag & f_conversion_data_flag_sign_pad) { - if (!fputc(f_string_ascii_space_s[0], output)) { + if (fwrite_unlocked(f_string_ascii_space_s, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } if (data.flag & f_conversion_data_flag_base_prepend) { - if (!fputc(f_string_ascii_0_s[0], output)) { + if (fwrite_unlocked(f_string_ascii_0_s, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } @@ -263,14 +300,23 @@ extern "C" { break; } - if (c && !fputc(c, output)) { - return F_status_set_error(F_output); + if (c) { + if (fwrite_unlocked(&c, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + + return F_status_set_error(F_output); + } } } return F_none; } -#endif // !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#endif // !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) #if !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) f_status_t private_f_conversion_digit_to_string(const f_number_unsigned_t number, const f_conversion_data_t data, const uint8_t negative, f_string_dynamic_t *destination) { @@ -360,65 +406,36 @@ extern "C" { power *= data.base; } // for + if (data.base == 2) { + f_number_unsigned_t work = 0x1 << (digits - 1); + + while (digits--) { + + destination->string[destination->used++] = (work & number) ? f_string_ascii_1_s[0] : f_string_ascii_0_s[1]; + work >>= 1; + } // while + + return; + } + f_number_unsigned_t current = number; f_number_unsigned_t work = 0; - for (char c = 0; power; --power) { + for (char c = 0; digits; --digits) { work = current / power; current -= work * power; power /= data.base; - if (work < 8) { - if (work == 0) { - c = f_string_ascii_0_s[0]; - } - else if (work == 1) { - c = f_string_ascii_1_s[0]; - } - else if (work == 2) { - c = f_string_ascii_2_s[0]; - } - else if (work == 3) { - c = f_string_ascii_3_s[0]; - } - else if (work == 4) { - c = f_string_ascii_4_s[0]; - } - else if (work == 5) { - c = f_string_ascii_5_s[0]; - } - else if (work == 6) { - c = f_string_ascii_6_s[0]; - } - else { - c = f_string_ascii_7_s[0]; - } + if (work < 0xa) { + c = 0x30 + work; } else { - if (work == 8) { - c = f_string_ascii_8_s[0]; - } - else if (work == 9) { - c = f_string_ascii_8_s[0]; - } - else if (work == 10) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_A_s[0] : f_string_ascii_a_s[0]; - } - else if (work == 11) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_B_s[0] : f_string_ascii_b_s[0]; - } - else if (work == 12) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_C_s[0] : f_string_ascii_c_s[0]; - } - else if (work == 13) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_D_s[0] : f_string_ascii_d_s[0]; - } - else if (work == 14) { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_E_s[0] : f_string_ascii_e_s[0]; + if (data.flag & f_conversion_data_flag_base_upper) { + c = 0x37 + work; } else { - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_f_s[0] : f_string_ascii_f_s[0]; + c = 0x57 + work; } } diff --git a/level_0/f_conversion/c/private-conversion.h b/level_0/f_conversion/c/private-conversion.h index cb3b43b..437496d 100644 --- a/level_0/f_conversion/c/private-conversion.h +++ b/level_0/f_conversion/c/private-conversion.h @@ -34,20 +34,26 @@ extern "C" { * @return * F_none on success. * - * F_output (with error bit) on failure to print to the output file. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. + * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see fwrite_unlocked() * - * @see f_conversion_number_signed_to_file() - * @see f_conversion_number_unsigned_to_file() + * @see f_conversion_number_signed_print() + * @see f_conversion_number_unsigned_print() * * @see private_f_conversion_digit_to_file_number() * @see private_f_conversion_digit_to_file_pad() * @see private_f_conversion_digit_to_file_prefix() */ -#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#if !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) extern f_status_t private_f_conversion_digit_to_file(const f_number_unsigned_t number, const f_conversion_data_t data, const uint8_t negative, FILE *output) f_attribute_visibility_internal; -#endif // !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#endif // !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) /** * Helper function for printing the number to the output file. @@ -67,16 +73,22 @@ extern "C" { * @return * F_none on success. * - * F_output (with error bit) on failure to print to the output file. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. + * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see fwrite_unlocked() * - * @see f_conversion_number_signed_to_file() - * @see f_conversion_number_unsigned_to_file() + * @see f_conversion_number_signed_print() + * @see f_conversion_number_unsigned_print() */ -#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#if !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) extern f_status_t private_f_conversion_digit_to_file_number(const f_conversion_data_t data, f_number_unsigned_t number, int digits, FILE *output) f_attribute_visibility_internal; -#endif // !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#endif // !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) /** * Helper function for printing the padding to the output file. @@ -95,16 +107,22 @@ extern "C" { * @return * F_none on success. * - * F_output (with error bit) on failure to print to the output file. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. + * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see fwrite_unlocked() * - * @see f_conversion_number_signed_to_file() - * @see f_conversion_number_unsigned_to_file() + * @see f_conversion_number_signed_print() + * @see f_conversion_number_unsigned_print() */ -#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#if !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) extern f_status_t private_f_conversion_digit_to_file_pad(const f_conversion_data_t data, const char pad, int total, FILE *output) f_attribute_visibility_internal; -#endif // !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#endif // !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) /** * Helper function for printing the prefix to the output file. @@ -124,16 +142,22 @@ extern "C" { * @return * F_none on success. * - * F_output (with error bit) on failure to print to the output file. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. + * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see fwrite_unlocked() * - * @see f_conversion_number_signed_to_file() - * @see f_conversion_number_unsigned_to_file() + * @see f_conversion_number_signed_print() + * @see f_conversion_number_unsigned_print() */ -#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#if !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) extern f_status_t private_f_conversion_digit_to_file_prefix(const f_conversion_data_t data, const uint8_t negative, FILE *output) f_attribute_visibility_internal; -#endif // !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) +#endif // !defined(_di_f_conversion_number_signed_print_) || !defined(_di_f_conversion_number_unsigned_print_) /** * Helper function for performing the entire process of printing to the output file. diff --git a/level_0/f_print/c/print.c b/level_0/f_print/c/print.c index 46e19ae..41be8f8 100644 --- a/level_0/f_print/c/print.c +++ b/level_0/f_print/c/print.c @@ -25,7 +25,7 @@ extern "C" { if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (fputc_unlocked(character, output)) { + if (fwrite_unlocked(&character, 1, 1, output) != -1) { return F_none; } diff --git a/level_0/f_print/c/print.h b/level_0/f_print/c/print.h index 3e6160e..0993ae9 100644 --- a/level_0/f_print/c/print.h +++ b/level_0/f_print/c/print.h @@ -58,7 +58,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_ extern f_status_t f_print(const f_string_t string, const f_array_length_t length, FILE *output); @@ -78,7 +78,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_character_ extern f_status_t f_print_character(const char character, FILE *output); @@ -104,7 +104,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_character_safely_ extern f_status_t f_print_character_safely(const char character, FILE *output); @@ -156,7 +156,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_ extern f_status_t f_print_dynamic(const f_string_static_t buffer, FILE *output); @@ -185,7 +185,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_raw_ extern f_status_t f_print_dynamic_raw(const f_string_static_t buffer, FILE *output); @@ -215,7 +215,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -246,7 +246,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_partial_ extern f_status_t f_print_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, FILE *output); @@ -277,7 +277,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_partial_raw_ extern f_status_t f_print_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, FILE *output); @@ -309,7 +309,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -344,7 +344,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_except_ extern f_status_t f_print_except(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output); @@ -379,7 +379,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_except_raw_ extern f_status_t f_print_except_raw(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output); @@ -415,7 +415,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -448,7 +448,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_except_dynamic_ extern f_status_t f_print_except_dynamic(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output); @@ -481,7 +481,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_except_dynamic_raw_ extern f_status_t f_print_except_dynamic_raw(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output); @@ -515,7 +515,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -554,7 +554,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_except_in_ extern f_status_t f_print_except_in(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output); @@ -593,7 +593,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_except_in_raw_ extern f_status_t f_print_except_in_raw(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output); @@ -633,7 +633,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -670,7 +670,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_except_in_dynamic_ extern f_status_t f_print_except_in_dynamic(const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output); @@ -707,7 +707,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_except_in_dynamic_raw_ extern f_status_t f_print_except_in_dynamic_raw(const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output); @@ -745,7 +745,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -784,7 +784,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_ extern f_status_t f_print_except_in_dynamic_partial(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, FILE *output); @@ -823,7 +823,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_raw_ extern f_status_t f_print_except_in_dynamic_partial_raw(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, FILE *output); @@ -860,7 +860,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -895,7 +895,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_ extern f_status_t f_print_except_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); @@ -930,7 +930,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_raw_ extern f_status_t f_print_except_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); @@ -963,7 +963,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_ extern f_status_t f_print_except_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); @@ -998,7 +998,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_dynamic_except_partial_raw_ extern f_status_t f_print_except_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); @@ -1034,7 +1034,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -1067,7 +1067,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_raw_ extern f_status_t f_print_raw(const f_string_t string, const f_array_length_t length, FILE *output); @@ -1094,7 +1094,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_raw_terminated_ extern f_status_t f_print_raw_terminated(const f_string_t string, FILE *output); @@ -1126,7 +1126,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -1160,7 +1160,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_utf_is_valid() */ @@ -1189,7 +1189,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() */ #ifndef _di_f_print_terminated_ extern f_status_t f_print_terminated(const f_string_t string, FILE *output); diff --git a/level_0/f_print/c/private-print.c b/level_0/f_print/c/private-print.c index 027092e..03d1b78 100644 --- a/level_0/f_print/c/private-print.c +++ b/level_0/f_print/c/private-print.c @@ -283,7 +283,7 @@ extern "C" { #if !defined(_di_f_print_except_) || !defined(_di_f_print_except_dynamic_) || !defined(_di_f_print_except_dynamic_partial_) f_status_t private_f_print_except(const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except, FILE *output) { - // @todo update logic to use fwrite() + // @todo update logic to use fwrite_unlocked() with more than 1 byte at a time. f_array_length_t i = offset; f_array_length_t j = 0; @@ -296,7 +296,14 @@ extern "C" { if (j < except.used && except.array[j] == i) continue; if (string[i]) { - if (!fputc_unlocked(string[i], output)) { + if (fwrite_unlocked(string + i, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } @@ -309,7 +316,7 @@ extern "C" { #if !defined(_di_f_print_except_raw_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_partial_raw_) f_status_t private_f_print_except_raw(const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except, FILE *output) { - // @todo update logic to use fwrite() + // @todo update logic to use fwrite_unlocked() with more than 1 byte at a time. f_array_length_t i = offset; f_array_length_t j = 0; @@ -321,7 +328,14 @@ extern "C" { if (j < except.used && except.array[j] == i) continue; - if (!fputc_unlocked(string[i], output)) { + if (fwrite_unlocked(string + i, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } // for @@ -333,7 +347,7 @@ extern "C" { #if !defined(_di_f_print_except_safely_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_dynamic_partial_safely_) f_status_t private_f_print_except_safely(const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except, FILE *output) { - // @todo update logic to use fwrite() + // @todo update logic to use fwrite_unlocked() with more than 1 byte at a time. f_array_length_t i = offset; f_array_length_t j = 0; @@ -355,15 +369,14 @@ extern "C" { s = private_f_print_character_safely_get(string[i]); if (s) { - if (!fputc_unlocked(s[i], output)) { - return F_status_set_error(F_output); - } - - if (!fputc_unlocked(s[i + 1], output)) { - return F_status_set_error(F_output); - } + if (fwrite_unlocked(s + i, 1, 3, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); - if (!fputc_unlocked(s[i + 2], output)) { return F_status_set_error(F_output); } @@ -373,15 +386,14 @@ extern "C" { status = f_utf_is_valid(string + i, stop - i); if (F_status_is_error(status) || status == F_false) { - if (!fputc_unlocked(f_print_sequence_unknown_s[0], output)) { - return F_status_set_error(F_output); - } - - if (!fputc_unlocked(f_print_sequence_unknown_s[1], output)) { - return F_status_set_error(F_output); - } + if (fwrite_unlocked(f_print_sequence_unknown_s, 1, 3, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); - if (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { return F_status_set_error(F_output); } @@ -390,15 +402,14 @@ extern "C" { } if (i + macro_f_utf_byte_width(string[i]) >= stop) { - if (!fputc_unlocked(f_print_sequence_unknown_s[0], output)) { - return F_status_set_error(F_output); - } - - if (!fputc_unlocked(f_print_sequence_unknown_s[1], output)) { - return F_status_set_error(F_output); - } + if (fwrite_unlocked(f_print_sequence_unknown_s, 1, 3, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); - if (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { return F_status_set_error(F_output); } @@ -406,26 +417,15 @@ extern "C" { continue; } - if (!fputc_unlocked(string[i], output)) { - return F_status_set_error(F_output); - } - - if (macro_f_utf_byte_width(string[i]) > 1) { - if (!fputc_unlocked(string[i + 1], output)) { - return F_status_set_error(F_output); - } - - if (macro_f_utf_byte_width(string[i]) > 2) { - if (!fputc_unlocked(string[i + 2], output)) { - return F_status_set_error(F_output); - } + if (fwrite_unlocked(string + i, 1, macro_f_utf_byte_width(string[i]), output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); - if (macro_f_utf_byte_width(string[i]) > 3) { - if (!fputc_unlocked(string[i + 3], output)) { - return F_status_set_error(F_output); - } - } - } + return F_status_set_error(F_output); } i += macro_f_utf_byte_width(string[i]); @@ -439,7 +439,7 @@ extern "C" { #if !defined(_di_f_print_except_in_) || !defined(_di_f_print_except_in_dynamic_) || !defined(_di_f_print_except_in_dynamic_partial_) f_status_t private_f_print_except_in(const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { - // @todo update logic to use fwrite() + // @todo update logic to use fwrite_unlocked() with more than 1 byte at a time. f_array_length_t i = offset; f_array_length_t at = 0; f_array_length_t in = 0; @@ -469,7 +469,14 @@ extern "C" { } if (string[i]) { - if (!fputc_unlocked(string[i], output)) { + if (fwrite_unlocked(string + i, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } } @@ -484,7 +491,7 @@ extern "C" { #if !defined(_di_f_print_except_in_raw_) || !defined(_di_f_print_except_in_dynamic_raw_) || !defined(_di_f_print_except_in_dynamic_partial_raw_) f_status_t private_f_print_except_in_raw(const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { - // @todo update logic to use fwrite() + // @todo update logic to use fwrite_unlocked() with more than 1 byte at a time. f_array_length_t i = offset; f_array_length_t at = 0; f_array_length_t in = 0; @@ -513,7 +520,14 @@ extern "C" { } } - if (!fputc_unlocked(string[i], output)) { + if (fwrite_unlocked(string + i, 1, 1, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + return F_status_set_error(F_output); } @@ -527,7 +541,7 @@ extern "C" { #if !defined(_di_f_print_except_in_safely_) || !defined(_di_f_print_except_in_dynamic_safely_) || !defined(_di_f_print_except_in_dynamic_partial_safely_) f_status_t private_f_print_except_in_safely(const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { - // @todo update logic to use fwrite() + // @todo update logic to use fwrite_unlocked() with more than 1 byte at a time. f_array_length_t i = offset; f_array_length_t at = 0; f_array_length_t in = 0; @@ -562,15 +576,14 @@ extern "C" { s = private_f_print_character_safely_get(string[i]); if (s) { - if (!fputc_unlocked(s[i], output)) { - return F_status_set_error(F_output); - } - - if (!fputc_unlocked(s[i + 1], output)) { - return F_status_set_error(F_output); - } + if (fwrite_unlocked(s + i, 1, 3, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); - if (!fputc_unlocked(s[i + 2], output)) { return F_status_set_error(F_output); } @@ -580,15 +593,14 @@ extern "C" { status = f_utf_is_valid(string + i, stop - i); if (F_status_is_error(status) || status == F_false) { - if (!fputc_unlocked(f_print_sequence_unknown_s[0], output)) { - return F_status_set_error(F_output); - } - - if (!fputc_unlocked(f_print_sequence_unknown_s[1], output)) { - return F_status_set_error(F_output); - } + if (fwrite_unlocked(f_print_sequence_unknown_s, 1, 3, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); - if (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { return F_status_set_error(F_output); } @@ -597,15 +609,14 @@ extern "C" { } if (i + macro_f_utf_byte_width(string[i]) >= stop) { - if (!fputc_unlocked(f_print_sequence_unknown_s[0], output)) { - return F_status_set_error(F_output); - } - - if (!fputc_unlocked(f_print_sequence_unknown_s[1], output)) { - return F_status_set_error(F_output); - } + if (fwrite_unlocked(f_print_sequence_unknown_s, 1, 3, output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); - if (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { return F_status_set_error(F_output); } @@ -613,26 +624,15 @@ extern "C" { continue; } - if (!fputc_unlocked(string[i], output)) { - return F_status_set_error(F_output); - } - - if (macro_f_utf_byte_width(string[i]) > 1) { - if (!fputc_unlocked(string[i + 1], output)) { - return F_status_set_error(F_output); - } - - if (macro_f_utf_byte_width(string[i]) > 2) { - if (!fputc_unlocked(string[i + 2], output)) { - return F_status_set_error(F_output); - } + if (fwrite_unlocked(string + i, 1, macro_f_utf_byte_width(string[i]), output) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); - if (macro_f_utf_byte_width(string[i]) > 3) { - if (!fputc_unlocked(string[i + 3], output)) { - return F_status_set_error(F_output); - } - } - } + return F_status_set_error(F_output); } i += macro_f_utf_byte_width(string[i]); diff --git a/level_0/f_print/c/private-print.h b/level_0/f_print/c/private-print.h index e9c4aa8..db92113 100644 --- a/level_0/f_print/c/private-print.h +++ b/level_0/f_print/c/private-print.h @@ -31,15 +31,15 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_block (with error bit) if output is set to non-block and the write would result in a blocking operation. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if output represents a directory. + * F_file_type_directory (with error bit) if file descriptor represents a directory. * F_input_output (with error bit) on I/O error. * F_interrupt (with error bit) if interrupt was received. - * F_output (with error bit) on failure. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_print() * @see f_print_dynamic() @@ -63,15 +63,15 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_block (with error bit) if output is set to non-block and the write would result in a blocking operation. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if output represents a directory. + * F_file_type_directory (with error bit) if file descriptor represents a directory. * F_input_output (with error bit) on I/O error. * F_interrupt (with error bit) if interrupt was received. - * F_output (with error bit) on failure. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_print_character_safely() * @see f_print_safely() @@ -130,10 +130,16 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * + * @see fwrite_unlocked() * * @see f_print_raw() * @see f_print_raw_dynamic() @@ -159,10 +165,16 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * + * @see fwrite_unlocked() * * @see f_print_safely() * @see f_print_safely_dynamic() @@ -194,10 +206,16 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * + * @see fwrite_unlocked() * * @see f_print_except() * @see f_print_except_dynamic() @@ -228,10 +246,16 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * + * @see fwrite_unlocked() * * @see f_print_except_raw() * @see f_print_except_dynamic_raw() @@ -262,10 +286,16 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * + * @see fwrite_unlocked() * * @see f_print_except_safely() * @see f_print_except_dynamic_safely() @@ -300,10 +330,16 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * + * @see fwrite_unlocked() * * @see f_print_except_in() * @see f_print_except_in_dynamic() @@ -337,10 +373,16 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * + * @see fwrite_unlocked() * * @see f_print_except_in_raw() * @see f_print_except_in_dynamic_raw() @@ -374,10 +416,16 @@ extern "C" { * F_none on success. * F_data_not if length is 0. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file stream 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_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_output (with error bit) on any other file output error. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * + * @see fwrite_unlocked() * * @see f_print_except_in_safely() * @see f_print_except_in_dynamic_safely() @@ -410,7 +458,7 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc_unlocked() + * @see fwrite_unlocked() * * @see f_print_terminated() * @see f_print_raw_terminated() diff --git a/level_1/fl_print/c/print.h b/level_1/fl_print/c/print.h index 906243c..0e3c809 100644 --- a/level_1/fl_print/c/print.h +++ b/level_1/fl_print/c/print.h @@ -156,8 +156,8 @@ extern "C" { * @see va_start() * @see va_end() * - * @see f_conversion_number_signed_to_file() - * @see f_conversion_number_unsigned_to_file() + * @see f_conversion_number_signed_print() + * @see f_conversion_number_unsigned_print() * @see f_print_dynamic() * @see f_print_dynamic_raw() * @see f_print_dynamic_safely() @@ -205,8 +205,8 @@ extern "C" { * Success from: f_print_safely(). * Success from: f_print_terminated(). * - * Errors (with error bit) from: f_conversion_number_signed_to_file(). - * Errors (with error bit) from: f_conversion_number_unsigned_to_file(). + * Errors (with error bit) from: f_conversion_number_signed_print(). + * Errors (with error bit) from: f_conversion_number_unsigned_print(). * Errors (with error bit) from: f_print_dynamic(). * Errors (with error bit) from: f_print_dynamic_raw(). * Errors (with error bit) from: f_print_dynamic_safely(). @@ -215,8 +215,8 @@ extern "C" { * * @see fputc_unlocked() * - * @see f_conversion_number_signed_to_file() - * @see f_conversion_number_unsigned_to_file() + * @see f_conversion_number_signed_print() + * @see f_conversion_number_unsigned_print() * @see f_print_dynamic() * @see f_print_dynamic_raw() * @see f_print_dynamic_safely() @@ -254,8 +254,8 @@ extern "C" { * Success from: f_print_safely(). * Success from: f_print_terminated(). * - * Errors (with error bit) from: f_conversion_number_signed_to_file(). - * Errors (with error bit) from: f_conversion_number_unsigned_to_file(). + * Errors (with error bit) from: f_conversion_number_signed_print(). + * Errors (with error bit) from: f_conversion_number_unsigned_print(). * Errors (with error bit) from: f_print_dynamic(). * Errors (with error bit) from: f_print_dynamic_raw(). * Errors (with error bit) from: f_print_dynamic_safely(). @@ -266,8 +266,8 @@ extern "C" { * @see va_start() * @see va_end() * - * @see f_conversion_number_signed_to_file() - * @see f_conversion_number_unsigned_to_file() + * @see f_conversion_number_signed_print() + * @see f_conversion_number_unsigned_print() * @see f_print_dynamic() * @see f_print_dynamic_raw() * @see f_print_dynamic_safely() diff --git a/level_1/fl_print/c/private-print.c b/level_1/fl_print/c/private-print.c index 3279f9e..63c07bc 100644 --- a/level_1/fl_print/c/private-print.c +++ b/level_1/fl_print/c/private-print.c @@ -593,51 +593,51 @@ extern "C" { } if (type == f_print_format_type_number) { - *status = f_conversion_number_signed_to_file(va_arg(*ap, f_number_signed_t), conversion_data, output); + *status = f_conversion_number_signed_print(va_arg(*ap, f_number_signed_t), conversion_data, output); } else if (type == f_print_format_type_signed_64) { - *status = f_conversion_number_signed_to_file((f_number_signed_t) va_arg(*ap, int64_t), conversion_data, output); + *status = f_conversion_number_signed_print((f_number_signed_t) va_arg(*ap, int64_t), conversion_data, output); } else if (type == f_print_format_type_signed_128) { - *status = f_conversion_number_signed_to_file((f_number_signed_t) va_arg(*ap, f_int_128_t), conversion_data, output); + *status = f_conversion_number_signed_print((f_number_signed_t) va_arg(*ap, f_int_128_t), conversion_data, output); } else if (type == f_print_format_type_signed_32) { - *status = f_conversion_number_signed_to_file((f_number_signed_t) va_arg(*ap, int32_t), conversion_data, output); + *status = f_conversion_number_signed_print((f_number_signed_t) va_arg(*ap, int32_t), conversion_data, output); } else if (type == f_print_format_type_signed_16) { const int16_t value = (int16_t) va_arg(*ap, int); - *status = f_conversion_number_signed_to_file((f_number_signed_t) value, conversion_data, output); + *status = f_conversion_number_signed_print((f_number_signed_t) value, conversion_data, output); } else if (type == f_print_format_type_signed_8) { const int8_t value = (int8_t) va_arg(*ap, int); - *status = f_conversion_number_signed_to_file((f_number_signed_t) value, conversion_data, output); + *status = f_conversion_number_signed_print((f_number_signed_t) value, conversion_data, output); } else if (type == f_print_format_type_size) { - *status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) va_arg(*ap, size_t), conversion_data, output); + *status = f_conversion_number_unsigned_print((f_number_unsigned_t) va_arg(*ap, size_t), conversion_data, output); } else if (type == f_print_format_type_unsigned_32) { - *status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) va_arg(*ap, uint32_t), conversion_data, output); + *status = f_conversion_number_unsigned_print((f_number_unsigned_t) va_arg(*ap, uint32_t), conversion_data, output); } else if (type == f_print_format_type_unsigned_16) { const uint16_t value = (uint16_t) va_arg(*ap, unsigned); - *status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) value, conversion_data, output); + *status = f_conversion_number_unsigned_print((f_number_unsigned_t) value, conversion_data, output); } else if (type == f_print_format_type_unsigned_8) { const uint8_t value = (uint8_t) va_arg(*ap, unsigned); - *status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) value, conversion_data, output); + *status = f_conversion_number_unsigned_print((f_number_unsigned_t) value, conversion_data, output); } else if (type == f_print_format_type_unsigned_64) { - *status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) va_arg(*ap, uint64_t), conversion_data, output); + *status = f_conversion_number_unsigned_print((f_number_unsigned_t) va_arg(*ap, uint64_t), conversion_data, output); } else if (type == f_print_format_type_unsigned_128) { - *status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) va_arg(*ap, f_uint_128_t), conversion_data, output); + *status = f_conversion_number_unsigned_print((f_number_unsigned_t) va_arg(*ap, f_uint_128_t), conversion_data, output); } else if (type == f_print_format_type_unsigned_number) { - *status = f_conversion_number_unsigned_to_file(va_arg(*ap, f_number_unsigned_t), conversion_data, output); + *status = f_conversion_number_unsigned_print(va_arg(*ap, f_number_unsigned_t), conversion_data, output); } return string; diff --git a/level_1/fl_print/c/private-print.h b/level_1/fl_print/c/private-print.h index 79b4e25..7ee0112 100644 --- a/level_1/fl_print/c/private-print.h +++ b/level_1/fl_print/c/private-print.h @@ -49,8 +49,8 @@ extern "C" { * Success from: f_print_safely(). * Success from: f_print_terminated(). * - * Errors (with error bit) from: f_conversion_number_signed_to_file(). - * Errors (with error bit) from: f_conversion_number_unsigned_to_file(). + * Errors (with error bit) from: f_conversion_number_signed_print(). + * Errors (with error bit) from: f_conversion_number_unsigned_print(). * Errors (with error bit) from: f_print_dynamic(). * Errors (with error bit) from: f_print_dynamic_raw(). * Errors (with error bit) from: f_print_dynamic_safely(). @@ -59,8 +59,8 @@ extern "C" { * * @see fputc_unlocked() * - * @see f_conversion_number_signed_to_file() - * @see f_conversion_number_unsigned_to_file() + * @see f_conversion_number_signed_print() + * @see f_conversion_number_unsigned_print() * @see f_print_dynamic() * @see f_print_dynamic_raw() * @see f_print_dynamic_safely() diff --git a/level_3/byte_dump/c/private-byte_dump.c b/level_3/byte_dump/c/private-byte_dump.c index 6ee4866..1d8f6de 100644 --- a/level_3/byte_dump/c/private-byte_dump.c +++ b/level_3/byte_dump/c/private-byte_dump.c @@ -463,10 +463,10 @@ extern "C" { } else if (main.mode == byte_dump_mode_binary) { if (invalid[character_current]) { - fl_print_string(" %[%09!uii%]", main.output.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); + fl_print_string(" %[%08!uii%]", main.output.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); } else { - fl_print_string(" %09!uii", main.output.stream, (uint8_t) byte); + fl_print_string(" %08!uii", main.output.stream, (uint8_t) byte); } } else if (main.mode == byte_dump_mode_decimal) { -- 1.8.3.1