From 1ce18c644bb595f7d66264e4a5f3a416920a718a Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 3 Aug 2021 22:36:34 -0500 Subject: [PATCH] Progress: Continue string and convert changes, fixing bugs. Fix some bitwise operation comparison mistakes. I used the wrong ASCII reference for the '@' and possibly others. This broke octal representation. This improves handling of Unicode characters in the safely print functions. It seems there are Control characters with widths greater than one. This complicates the code but what must be done, must be done. Begin adding back some of the color print functions as f_print_color() etc... There are still more to create. --- build/level_0/settings | 2 +- build/level_1/settings | 2 +- build/level_2/settings | 2 +- build/monolithic/settings | 2 +- level_0/f_conversion/c/private-conversion.c | 193 ++++++-------- level_0/f_print/c/print.c | 105 +++++++- level_0/f_print/c/print.h | 25 +- level_0/f_print/c/private-print.c | 125 ++++++--- level_0/f_print/c/private-print.h | 2 +- level_1/fl_conversion/c/conversion.c | 40 +-- level_1/fl_print/c/print.c | 86 +++++++ level_1/fl_print/c/print.h | 102 ++++++++ level_1/fl_print/c/private-print.c | 41 +-- level_2/fll_print/c/print.c | 126 +++++++++ level_2/fll_print/c/print.h | 102 ++++++++ level_3/byte_dump/c/private-byte_dump.c | 385 ++++++++++++---------------- 16 files changed, 917 insertions(+), 423 deletions(-) diff --git a/build/level_0/settings b/build/level_0/settings index a0d2dea..19a332c 100644 --- a/build/level_0/settings +++ b/build/level_0/settings @@ -53,7 +53,7 @@ defines_all-level_threadless -D_di_pthread_support_ defines_static defines_shared -flags_all -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-logical-op-parentheses -Wno-parentheses +flags_all -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-logical-op-parentheses -Wno-parentheses flags_all-level -pthread flags_shared flags_static diff --git a/build/level_1/settings b/build/level_1/settings index 2cbfaac..fc13651 100644 --- a/build/level_1/settings +++ b/build/level_1/settings @@ -53,7 +53,7 @@ defines_all-level_threadless -D_di_pthread_support_ defines_static defines_shared -flags_all -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-logical-op-parentheses -Wno-parentheses +flags_all -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-logical-op-parentheses -Wno-parentheses flags_all-level -pthread flags_shared flags_static diff --git a/build/level_2/settings b/build/level_2/settings index 9dca932..ea3706c 100644 --- a/build/level_2/settings +++ b/build/level_2/settings @@ -53,7 +53,7 @@ defines_all-level_threadless -D_di_pthread_support_ defines_static defines_shared -flags_all -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-logical-op-parentheses -Wno-parentheses +flags_all -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-logical-op-parentheses -Wno-parentheses flags_all-level -pthread flags_shared flags_static diff --git a/build/monolithic/settings b/build/monolithic/settings index c73cedb..00364bd 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -53,7 +53,7 @@ defines_all-monolithic_threadless -D_di_pthread_support_ defines_static defines_shared -flags_all -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-logical-op-parentheses -Wno-parentheses +flags_all -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-logical-op-parentheses -Wno-parentheses flags_all-monolithic -pthread flags_shared flags_static diff --git a/level_0/f_conversion/c/private-conversion.c b/level_0/f_conversion/c/private-conversion.c index 41d9b09..bc9bff1 100644 --- a/level_0/f_conversion/c/private-conversion.c +++ b/level_0/f_conversion/c/private-conversion.c @@ -8,7 +8,6 @@ extern "C" { #if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) 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) { - // @fixme this has a performance problems. int digits = 0; if (number) { @@ -71,7 +70,7 @@ extern "C" { } } else { - const int used = digits + (data.flag & f_conversion_data_flag_sign_always & f_conversion_data_flag_sign_pad ? 1 : 0); + const int used = digits + (data.flag & (f_conversion_data_flag_sign_always | f_conversion_data_flag_sign_pad) ? 1 : 0); if (data.width > used) { if (data.flag & f_conversion_data_flag_zeros_leading) { @@ -135,77 +134,60 @@ extern "C" { current -= work * power; power /= data.base; - switch (work) { - case 0: + if (work < 8) { + if (work == 0) { c = f_string_ascii_0_s[0]; - break; - - case 1: + } + else if (work == 1) { c = f_string_ascii_1_s[0]; - break; - - case 2: + } + else if (work == 2) { c = f_string_ascii_2_s[0]; - break; - - case 3: + } + else if (work == 3) { c = f_string_ascii_3_s[0]; - break; - - case 4: + } + else if (work == 4) { c = f_string_ascii_4_s[0]; - break; - - case 5: + } + else if (work == 5) { c = f_string_ascii_5_s[0]; - break; - - case 6: + } + else if (work == 6) { c = f_string_ascii_6_s[0]; - break; - - case 7: + } + else { c = f_string_ascii_7_s[0]; - break; - - case 8: + } + } + else { + if (work == 8) { c = f_string_ascii_8_s[0]; - break; - - case 9: - c = f_string_ascii_9_s[0]; - break; - - case 10: + } + 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]; - break; - - case 11: + } + 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]; - break; - - case 12: + } + 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]; - break; - - case 13: + } + 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]; - break; - - case 14: + } + 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]; - break; - - case 15: + } + else { c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_F_s[0] : f_string_ascii_f_s[0]; - break; - - default: - c = 0; - break; + } } - if (c && !fputc(c, output)) { + if (!fputc(c, output)) { return F_status_set_error(F_output); } } // for @@ -342,7 +324,7 @@ extern "C" { } } else { - const int used = digits + (data.flag & f_conversion_data_flag_sign_always & f_conversion_data_flag_sign_pad ? 1 : 0); + const int used = digits + (data.flag & (f_conversion_data_flag_sign_always | f_conversion_data_flag_sign_pad) ? 1 : 0); if (data.width > used) { if (data.flag & f_conversion_data_flag_zeros_leading) { @@ -387,79 +369,60 @@ extern "C" { current -= work * power; power /= data.base; - switch (number) { - case 0: + if (work < 8) { + if (work == 0) { c = f_string_ascii_0_s[0]; - break; - - case 1: + } + else if (work == 1) { c = f_string_ascii_1_s[0]; - break; - - case 2: + } + else if (work == 2) { c = f_string_ascii_2_s[0]; - break; - - case 3: + } + else if (work == 3) { c = f_string_ascii_3_s[0]; - break; - - case 4: + } + else if (work == 4) { c = f_string_ascii_4_s[0]; - break; - - case 5: + } + else if (work == 5) { c = f_string_ascii_5_s[0]; - break; - - case 6: + } + else if (work == 6) { c = f_string_ascii_6_s[0]; - break; - - case 7: + } + else { c = f_string_ascii_7_s[0]; - break; - - case 8: + } + } + else { + if (work == 8) { c = f_string_ascii_8_s[0]; - break; - - case 9: - c = f_string_ascii_9_s[0]; - break; - - case 10: + } + 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]; - break; - - case 101: + } + 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]; - break; - - case 12: + } + 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]; - break; - - case 13: + } + 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]; - break; - - case 14: - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_E_s[0] : f_string_ascii_E_s[0]; - break; - - case 15: - c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_F_s[0] : f_string_ascii_f_s[0]; - break; - - default: - c = 0; - break; + } + 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]; + } + else { + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_f_s[0] : f_string_ascii_f_s[0]; + } } - if (c) { - destination->string[destination->used++] = c; - } + destination->string[destination->used++] = c; } // for } #endif // !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) diff --git a/level_0/f_print/c/print.c b/level_0/f_print/c/print.c index 9564c1a..46e19ae 100644 --- a/level_0/f_print/c/print.c +++ b/level_0/f_print/c/print.c @@ -19,6 +19,27 @@ extern "C" { } #endif // _di_f_print_ +#ifndef _di_f_print_character_ + f_status_t f_print_character(const char character, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (fputc_unlocked(character, output)) { + return F_none; + } + + 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); + } +#endif // _di_f_print_character_ + #ifndef _di_f_print_character_safely_ f_status_t f_print_character_safely(const char character, FILE *output) { #ifndef _di_level_0_parameter_checking_ @@ -471,13 +492,61 @@ extern "C" { f_array_length_t start = 0; f_array_length_t total = 0; + uint8_t width = 0; + for (register f_array_length_t i = 0; string[i]; ) { - if (string[i] > 0x1f && string[i] != 0x7f || string[i] == 0x09) { - ++total; - ++i; + width = macro_f_utf_character_t_width_is(string[i]); + + if (width) { + if (width > 1) { + if (string[i + 1]) { + if (width > 2) { + if (string[i + 2]) { + if (width > 3) { + if (string[i + 3]) { + status = f_utf_is_control(string + i, 4); + } + else { + status = F_utf; + } + } + else { + status = f_utf_is_control(string + i, 3); + } + } + else { + status = F_utf; + } + } + else { + status = f_utf_is_control(string + i, 2); + } + } + else { + status = F_utf; + } + } + else { + status = f_utf_is_control(string + i, 1); + } + + if (status == F_false && total + width < f_print_write_max) { + total += width; + i += width; - continue; + continue; + } + } + else { + if ((string[i] > 0x1f && string[i] != 0x7f) && total < f_print_write_max) { + ++total; + ++i; + + continue; + } + + status = F_none; } if (total) { @@ -491,13 +560,35 @@ extern "C" { return F_status_set_error(F_output); } + + total = 0; + } + + if (status == F_true || F_status_set_fine(status) == F_utf) { + if (fwrite_unlocked(f_print_sequence_unknown_s, 1, 3, output) != -1) { + return F_none; + } + + i += width; } + else if (status == F_false) { + if (fwrite_unlocked(string + start, 1, width, 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); - for (; string[i] && (string[i] < 32 && string[i] != 0x09 || string[i] == 0x7f); ++i) { + return F_status_set_error(F_output); + } - status = private_f_print_character_safely(string[i], output); + i += width; + } + else { + status = private_f_print_character_safely(string[i++], output); if (F_status_is_error(status)) return status; - } // for + } start = i; } // for diff --git a/level_0/f_print/c/print.h b/level_0/f_print/c/print.h index 3a3fd2c..3e6160e 100644 --- a/level_0/f_print/c/print.h +++ b/level_0/f_print/c/print.h @@ -65,6 +65,26 @@ extern "C" { #endif // _di_f_print_ /** + * Given a single 1-byte character, print the character. + * + * @param character + * The character to verify as safe or not and then print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + */ +#ifndef _di_f_print_character_ + extern f_status_t f_print_character(const char character, FILE *output); +#endif // _di_f_print_character_ + +/** * Given a single 1-byte character, print the character or a replacement if the character is not considered safe. * * Control characters are converted to the Unicode control character symbols, including NULL. @@ -94,7 +114,8 @@ extern "C" { * Get a safe representation of the character if the character is considered unsafe. * * Control characters are converted to the Unicode control character symbols, including NULL. - * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * UTF-8 sequences with a width of 1 are converted to the unknown character '�'. + * For all other UTF-8 sequences, 0 is returned because it cannot be processed via a single 8-byte character. * * The returned string will either be NULL (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. @@ -105,7 +126,7 @@ extern "C" { * The character to verify as safe or not and then print. * * @return - * NULL is returned if the character is already replaced. + * NULL is returned if the character is already safe or if the character has a UTF-8 width of 2 or greater. * A non-NULL string is returned if the character needs safe replacement. * The non-NULL strings returned are NULL terminated. * The non-NULL strings returned are the 3-byte characters used as placeholder symbols. diff --git a/level_0/f_print/c/private-print.c b/level_0/f_print/c/private-print.c index d9d1b33..027092e 100644 --- a/level_0/f_print/c/private-print.c +++ b/level_0/f_print/c/private-print.c @@ -28,6 +28,7 @@ extern "C" { } i += total; + total = 0; } start = i; @@ -65,44 +66,52 @@ extern "C" { #if !defined(_di_f_print_character_safely_) || !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_) || !defined(_di_f_print_safely_terminated_) || !defined(_di_f_print_except_safely_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_dynamic_partial_safely_) || !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_character_safely(const char character, FILE *output) { - if (character > 0x1f && character != 0x7f) { - if (fputc_unlocked(character, output)) { + if (character == 0x7f) { + if (fwrite_unlocked(f_print_sequence_delete_s, 1, 3, output) != -1) { return F_none; } - - 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 (fwrite_unlocked(character == 0x7f ? f_print_sequence_delete_s : f_print_sequence_set_control_s[character], 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); - - return F_status_set_error(F_output); + else if (macro_f_utf_character_t_width_is(character) == 1) { + if (fwrite_unlocked(f_print_sequence_unknown_s, 1, 3, output) != -1) { + return F_none; + } + } + else if (macro_f_utf_character_t_width_is(character) > 1 || character > 0x1f) { + if (fwrite_unlocked(&character, 1, 1, output) != -1) { + return F_none; + } + } + else { + if (fwrite_unlocked(f_print_sequence_set_control_s[character], 1, 3, output) != -1) { + return F_none; + } } - return F_none; + 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); } #endif // !defined(_di_f_print_character_safely_) || !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_) || !defined(_di_f_print_safely_terminated_) || !defined(_di_f_print_except_safely_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_dynamic_partial_safely_) || !defined(_di_f_print_except_in_safely_) || !defined(_di_f_print_except_in_dynamic_safely_) || !defined(_di_f_print_except_in_dynamic_partial_safely_) #if !defined(_di_f_print_character_safely_get_) || !defined(_di_f_print_dynamic_to_safely_) || !defined(_di_f_print_dynamic_partial_to_safely_) || !defined(_di_f_print_to_except_dynamic_safely_) || !defined(_di_f_print_to_except_dynamic_partial_safely_) || !defined(_di_f_print_to_except_safely_) || !defined(_di_f_print_to_safely_) f_string_t private_f_print_character_safely_get(const char character) { - if (character > 0x1f && character != 0x7f) { + if (character == 0x7f) { + return (f_string_t) f_print_sequence_delete_s; + } + else if (macro_f_utf_character_t_width_is(character) == 1) { + return (f_string_t) f_print_sequence_unknown_s; + } + else if (macro_f_utf_character_t_width_is(character) > 1 || character > 0x1f) { return 0; } - return character == 0x7f ? f_print_sequence_delete_s : (f_string_t) f_print_sequence_set_control_s[character]; + return (f_string_t) f_print_sequence_set_control_s[character]; } #endif // !defined(_di_f_print_character_safely_get_) || !defined(_di_f_print_dynamic_to_safely_) || !defined(_di_f_print_dynamic_partial_to_safely_) || !defined(_di_f_print_to_except_dynamic_safely_) || !defined(_di_f_print_to_except_dynamic_partial_safely_) || !defined(_di_f_print_to_except_safely_) || !defined(_di_f_print_to_safely_) @@ -129,6 +138,7 @@ extern "C" { } i += total; + total = 0; } start = i; @@ -182,13 +192,31 @@ extern "C" { f_array_length_t start = 0; f_array_length_t total = 0; + uint8_t width = 0; + for (register f_array_length_t i = 0; i < length; ) { - if ((string[i] > 0x1f && string[i] != 0x7f) && total < f_print_write_max) { - ++total; - ++i; + width = macro_f_utf_character_t_width_is(string[i]); - continue; + if (width) { + status = f_utf_is_control(string + i, i + width > length ? length - i : width); + + if (status == F_false && total + width < f_print_write_max) { + total += width; + i += width; + + continue; + } + } + else { + if ((string[i] > 0x1f && string[i] != 0x7f) && total < f_print_write_max) { + ++total; + ++i; + + continue; + } + + status = F_none; } if (total) { @@ -202,13 +230,35 @@ extern "C" { return F_status_set_error(F_output); } + + total = 0; } - for (; i < length && (string[i] < 32 || string[i] == 0x7f); ++i) { + if (status == F_true || F_status_set_fine(status) == F_utf) { + if (fwrite_unlocked(f_print_sequence_unknown_s, 1, 3, output) != -1) { + return F_none; + } + + i += width; + } + else if (status == F_false) { + if (fwrite_unlocked(string + i, 1, width, 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); + } - status = private_f_print_character_safely(string[i], output); + i += width; + } + else { + status = private_f_print_character_safely(string[i++], output); if (F_status_is_error(status)) return status; - } // for + } start = i; } // for @@ -697,10 +747,11 @@ extern "C" { return F_status_set_error(F_output); } + + total = 0; } start = ++i; - total = 0; } // while if (total) { @@ -764,6 +815,8 @@ extern "C" { return F_status_set_error(F_output); } + + total = 0; } if (s) { @@ -780,7 +833,6 @@ extern "C" { } start = ++i; - total = 0; } else { status = f_utf_is_valid(string + i, length - i); @@ -800,7 +852,6 @@ extern "C" { i += macro_f_utf_byte_width(string[i]); start = i; - total = 0; continue; } @@ -820,7 +871,6 @@ extern "C" { i = length; start = length; - total = 0; continue; } @@ -1022,6 +1072,8 @@ extern "C" { return F_status_set_error(F_output); } + + total = 0; } if (s) { @@ -1038,7 +1090,6 @@ extern "C" { } start = ++i; - total = 0; } else { status = f_utf_is_valid(string + i, stop - i); @@ -1058,7 +1109,6 @@ extern "C" { i += macro_f_utf_byte_width(string[i]); start = i; - total = 0; continue; } @@ -1078,7 +1128,6 @@ extern "C" { i = stop; start = stop; - total = 0; continue; } diff --git a/level_0/f_print/c/private-print.h b/level_0/f_print/c/private-print.h index cc9a7da..e9c4aa8 100644 --- a/level_0/f_print/c/private-print.h +++ b/level_0/f_print/c/private-print.h @@ -98,7 +98,7 @@ extern "C" { * The character to verify as safe or not. * * @return - * NULL is returned if the character is already replaced. + * NULL is returned if the character is already safe or if the character has a UTF-8 width of 2 or greater. * A non-NULL string is returned if the character needs safe replacement. * The non-NULL strings returned are NULL terminated. * The non-NULL strings returned are the 3-byte characters used as placeholder symbols. diff --git a/level_1/fl_conversion/c/conversion.c b/level_1/fl_conversion/c/conversion.c index 13aa6da..763ebad 100644 --- a/level_1/fl_conversion/c/conversion.c +++ b/level_1/fl_conversion/c/conversion.c @@ -43,7 +43,7 @@ extern "C" { converted += digit; } } - else if (digit != 0) { + else if (digit) { digits = 1; if (negative) { @@ -54,7 +54,7 @@ extern "C" { } } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for @@ -93,12 +93,12 @@ extern "C" { converted <<= 1; converted += digit; } - else if (digit != 0) { + else if (digit) { digits = 1; converted = digit; } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for @@ -152,7 +152,7 @@ extern "C" { converted += digit; } } - else if (digit != 0) { + else if (digit) { digits = 1; if (negative) { @@ -163,7 +163,7 @@ extern "C" { } } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for @@ -205,12 +205,12 @@ extern "C" { converted *= 10; converted += digit; } - else if (digit != 0) { + else if (digit) { digits = 1; converted = digit; } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for @@ -264,7 +264,7 @@ extern "C" { converted += digit; } } - else if (digit != 0) { + else if (digit) { digits = 1; if (negative) { @@ -275,7 +275,7 @@ extern "C" { } } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for @@ -317,12 +317,12 @@ extern "C" { converted *= 12; converted += digit; } - else if (digit != 0) { + else if (digit) { digits = 1; converted = digit; } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for @@ -376,7 +376,7 @@ extern "C" { converted += digit; } } - else if (digit != 0) { + else if (digit) { digits = 1; if (negative) { @@ -387,7 +387,7 @@ extern "C" { } } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for @@ -429,12 +429,12 @@ extern "C" { converted <<= 4; converted += digit; } - else if (digit != 0) { + else if (digit) { digits = 1; converted = digit; } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for @@ -488,7 +488,7 @@ extern "C" { converted += digit; } } - else if (digit != 0) { + else if (digit) { digits = 1; if (negative) { @@ -499,7 +499,7 @@ extern "C" { } } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for @@ -541,12 +541,12 @@ extern "C" { converted <<= 3; converted += digit; } - else if (digit != 0) { + else if (digit) { digits = 1; converted = digit; } } - else if (string[i] != 0) { + else if (string[i]) { return F_status_set_error(F_number); } } // for diff --git a/level_1/fl_print/c/print.c b/level_1/fl_print/c/print.c index 1936c27..923aa38 100644 --- a/level_1/fl_print/c/print.c +++ b/level_1/fl_print/c/print.c @@ -5,6 +5,92 @@ extern "C" { #endif +#ifndef _di_fl_print_color_ + f_status_t fl_print_color(const f_string_static_t buffer, const f_color_set_t set, FILE *output) { + + if (!buffer.used) { + return F_data_not; + } + + f_status_t status = F_none; + + if (set.before) { + status = f_print_terminated(set.before->string, output); + if (F_status_is_error(status)) return status; + } + + status = f_print(buffer.string, buffer.used, output); + + if (set.after) { + + // attempt to always print the closing color, even on error. + if (F_status_is_error(status)) { + f_print_terminated(set.after->string, output); + } + else { + status = f_print_terminated(set.after->string, output); + if (F_status_is_error(status)) return status; + } + } + + return status; + } +#endif // _di_fl_print_color_ + +#ifndef _di_fl_print_color_after_ + f_status_t fl_print_color_after(const f_color_set_t set, FILE *output) { + + if (set.after) { + return f_print_terminated(set.after->string, output); + } + + return F_data_not; + } +#endif // _di_fl_print_color_after_ + +#ifndef _di_fl_print_color_before_ + f_status_t fl_print_color_before(const f_color_set_t set, FILE *output) { + + if (set.before) { + return f_print_terminated(set.before->string, output); + } + + return F_data_not; + } +#endif // _di_fl_print_color_before_ + +#ifndef _di_fl_print_color_terminated_ + f_status_t fl_print_color_terminated(const f_string_t string, const f_color_set_t set, FILE *output) { + + if (!*string) { + return F_data_not; + } + + f_status_t status = F_none; + + if (set.before) { + status = f_print_terminated(set.before->string, output); + if (F_status_is_error(status)) return status; + } + + status = f_print_terminated(string, output); + + if (set.after) { + + // attempt to always print the closing color, even on error. + if (F_status_is_error(status)) { + f_print_terminated(set.after->string, output); + } + else { + status = f_print_terminated(set.after->string, output); + if (F_status_is_error(status)) return status; + } + } + + return status; + } +#endif // _di_fl_print_color_terminated_ + #ifndef _di_fl_print_string_ f_status_t fl_print_string(const f_string_t string, FILE *output, ...) { #ifndef _di_level_1_parameter_checking_ diff --git a/level_1/fl_print/c/print.h b/level_1/fl_print/c/print.h index 0c96108..906243c 100644 --- a/level_1/fl_print/c/print.h +++ b/level_1/fl_print/c/print.h @@ -32,6 +32,108 @@ extern "C" { #endif /** + * Print the string with the given color set printed before and after as appropriate to the file stream. + * + * No before/after colors are printed when the string is determined to be empty. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to print. + * @param set + * The color set to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_data_not if nothing is printed. + * + * Success from: f_print(). + * + * Errors (with error bit) from: f_print() + * Errors (with error bit) from: f_print_terminated(). + * + * @see f_print() + * @see f_print_terminated() + */ +#ifndef _di_fl_print_color_ + extern f_status_t fl_print_color(const f_string_static_t buffer, const f_color_set_t set, FILE *output); +#endif // _di_fl_print_color_ + +/** + * Print the "after" part of a color set to the given file stream. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param set + * The color set to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_data_not if nothing is printed (such as when color code is NULL). + * + * Success from: f_print_terminated(). + * + * Errors (with error bit) from: f_print_terminated(). + * + * @see f_print_terminated() + */ +#ifndef _di_fl_print_color_after_ + extern f_status_t fl_print_color_after(const f_color_set_t set, FILE *output); +#endif // _di_fl_print_color_after_ + +/** + * Print the "after" part of a color set to the given file stream. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param set + * The color set to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_data_not if nothing is printed (such as when color code is NULL). + * + * Success from: f_print_terminated(). + * + * Errors (with error bit) from: f_print_terminated(). + * + * @see f_print_terminated() + */ +#ifndef _di_fl_print_color_before_ + extern f_status_t fl_print_color_before(const f_color_set_t set, FILE *output); +#endif // _di_fl_print_color_before_ + +/** + * Print the NULL-terminated string with the given color set printed before and after as appropriate to the file stream. + * + * No before/after colors are printed when the string is determined to be empty. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to print. + * @param set + * The color set to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_data_not if nothing is printed. + * + * Success from: f_print_terminated(). + * + * Errors (with error bit) from: f_print_terminated(). + * + * @see f_print_terminated() + */ +#ifndef _di_fl_print_color_terminated_ + extern f_status_t fl_print_color_terminated(const f_string_t string, const f_color_set_t set, FILE *output); +#endif // _di_fl_print_color_terminated_ + +/** * A formatted print function similar to (but not the same as) the c-library fprintf() function. * * @todo add the complex documentation. diff --git a/level_1/fl_print/c/private-print.c b/level_1/fl_print/c/private-print.c index 46ca516..3279f9e 100644 --- a/level_1/fl_print/c/private-print.c +++ b/level_1/fl_print/c/private-print.c @@ -27,7 +27,7 @@ extern "C" { for (; *string; string += 1) { - if (*string < 0x2d) { + if (*string < 0x2c) { if (*string == f_string_ascii_space_s[0]) { flag |= f_print_format_flag_sign_pad; @@ -80,7 +80,7 @@ extern "C" { return string; } } - else if (*string < 0x49) { + else if (*string < 0x41) { if (*string == f_string_ascii_minus_s[0]) { flag |= f_print_format_flag_align_left; @@ -143,20 +143,25 @@ extern "C" { continue; } - else if (*string == f_string_ascii_C_s[0]) { - char value[1] = { (char) va_arg(*ap, int) }; - - *status = f_print_safely(value, 1, output); + else if (*string == f_string_ascii_sign_at_s[0]) { + base = 8; - return string; + continue; } else { *status = F_status_set_error(F_valid_not); return string; } } - else if (*string < 0x5b) { - if (*string == f_string_ascii_I_s[0]) { + else if (*string < 0x56) { + if (*string == f_string_ascii_C_s[0]) { + char value[1] = { (char) va_arg(*ap, int) }; + + *status = f_print_safely(value, 1, output); + + return string; + } + else if (*string == f_string_ascii_I_s[0]) { type = f_print_format_type_signed_32; flag |= f_print_format_flag_uppercase; @@ -287,18 +292,18 @@ extern "C" { type = f_print_format_type_unsigned_number; string += 1; } - else if (*string == f_string_ascii_Z_s[0]) { - type = f_print_format_type_size; - flag |= f_print_format_flag_uppercase; - } } else { *status = F_status_set_error(F_valid_not); return string; } } - else if (*string < 0x63) { - if (*string == f_string_ascii_bracket_open_s[0]) { + else if (*string < 0x60) { + if (*string == f_string_ascii_Z_s[0]) { + type = f_print_format_type_size; + flag |= f_print_format_flag_uppercase; + } + else if (*string == f_string_ascii_bracket_open_s[0]) { const f_color_set_t value = va_arg(*ap, f_color_set_t); if (value.before) { @@ -326,11 +331,6 @@ extern "C" { continue; } - else if (*string == f_string_ascii_sign_at_s[0]) { - base = 8; - - continue; - } else { *status = F_status_set_error(F_valid_not); return string; @@ -1578,6 +1578,7 @@ extern "C" { return F_status_set_error(F_utf_not); } + // @todo: change logic to use single fwrite() based on byte width rather than multiple fputc... if (!fputc_unlocked(string[i], output)) { return F_status_set_error(F_output); } diff --git a/level_2/fll_print/c/print.c b/level_2/fll_print/c/print.c index 79971b3..0314831 100644 --- a/level_2/fll_print/c/print.c +++ b/level_2/fll_print/c/print.c @@ -30,6 +30,132 @@ extern "C" { } #endif // _di_fll_print_character_safely_ +#ifndef _di_fll_print_color_ + f_status_t fll_print_color(const f_string_static_t buffer, const f_color_set_t set, FILE *output) { + + if (!buffer.used) { + return F_data_not; + } + + f_status_t status = F_none; + + flockfile(output); + + if (set.before) { + status = f_print_terminated(set.before->string, output); + + if (F_status_is_error(status)) { + funlockfile(output); + + return status; + } + } + + status = f_print(buffer.string, buffer.used, output); + + if (set.after) { + + // attempt to always print the closing color, even on error. + if (F_status_is_error(status)) { + f_print_terminated(set.after->string, output); + } + else { + status = f_print_terminated(set.after->string, output); + + if (F_status_is_error(status)) { + funlockfile(output); + + return status; + } + } + } + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_color_ + +#ifndef _di_fll_print_color_after_ + f_status_t fll_print_color_after(const f_color_set_t set, FILE *output) { + + if (set.after) { + flockfile(output); + + const f_status_t status = f_print_terminated(set.after->string, output); + + funlockfile(output); + + return status; + } + + return F_data_not; + } +#endif // _di_fll_print_color_after_ + +#ifndef _di_fll_print_color_before_ + f_status_t fll_print_color_before(const f_color_set_t set, FILE *output) { + + if (set.before) { + flockfile(output); + + const f_status_t status = f_print_terminated(set.before->string, output); + + funlockfile(output); + + return status; + } + + return F_data_not; + } +#endif // _di_fll_print_color_before_ + +#ifndef _di_fll_print_color_terminated_ + f_status_t fll_print_color_terminated(const f_string_t string, const f_color_set_t set, FILE *output) { + + if (!*string) { + return F_data_not; + } + + f_status_t status = F_none; + + flockfile(output); + + if (set.before) { + status = f_print_terminated(set.before->string, output); + + if (F_status_is_error(status)) { + funlockfile(output); + + return status; + } + } + + status = f_print_terminated(set.before->string, output); + + if (set.after) { + + // attempt to always print the closing color, even on error. + if (F_status_is_error(status)) { + f_print_terminated(set.after->string, output); + } + else { + status = f_print_terminated(set.after->string, output); + + if (F_status_is_error(status)) { + funlockfile(output); + + return status; + } + } + } + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_color_terminated_ + #ifndef _di_fll_print_dynamic_ f_status_t fll_print_dynamic(const f_string_static_t buffer, FILE *output) { diff --git a/level_2/fll_print/c/print.h b/level_2/fll_print/c/print.h index aa6a3f4..30938e3 100644 --- a/level_2/fll_print/c/print.h +++ b/level_2/fll_print/c/print.h @@ -76,6 +76,108 @@ extern "C" { #endif // _di_fll_print_character_safely_ /** + * This is a variation of fl_print_color() that uses locking. + * + * @param buffer + * The string to print. + * @param set + * The color set to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_data_not if nothing is printed. + * + * Success from: f_print(). + * + * Errors (with error bit) from: f_print() + * Errors (with error bit) from: f_print_terminated(). + * + * @see f_print() + * @see f_print_terminated() + * @see fl_print_color() + */ +#ifndef _di_fll_print_color_ + extern f_status_t fll_print_color(const f_string_static_t buffer, const f_color_set_t set, FILE *output); +#endif // _di_fll_print_color_ + +/** + * This is a variation of fl_print_color_after() that uses locking. + * + * @param set + * The color set. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_data_not if nothing is printed (such as when color code is NULL). + * F_parameter (with error bit) if a parameter is invalid. + * + * Success from: f_print_terminated(). + * + * Errors (with error bit) from: f_print_terminated(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_terminated() + * @see fl_print_color_after() + */ +#ifndef _di_fll_print_color_after_ + extern f_status_t fll_print_color_after(const f_color_set_t set, FILE *output); +#endif // _di_fll_print_color_after_ + +/** + * This is a variation of fl_print_color_before() that uses locking. + * + * @param set + * The color set. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_data_not if nothing is printed (such as when color code is NULL). + * F_parameter (with error bit) if a parameter is invalid. + * + * Success from: f_print_terminated(). + * + * Errors (with error bit) from: f_print_terminated(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_terminated() + * @see fl_print_color_before() + */ +#ifndef _di_fll_print_color_before_ + extern f_status_t fll_print_color_before(const f_color_set_t set, FILE *output); +#endif // _di_fll_print_color_before_ + +/** + * This is a variation of fl_print_color_terminated() that uses locking. + * + * @param string + * The string to print. + * @param set + * The color set to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_data_not if nothing is printed. + * + * Success from: f_print_terminated(). + * + * Errors (with error bit) from: f_print_terminated(). + * + * @see f_print_terminated() + * @see fl_print_color_terminated() + */ +#ifndef _di_fll_print_color_terminated_ + extern f_status_t fll_print_color_terminated(const f_string_t string, const f_color_set_t set, FILE *output); +#endif // _di_fll_print_color_terminated_ + +/** * This is a variation of f_print_dynamic() that uses locking. * * @param buffer diff --git a/level_3/byte_dump/c/private-byte_dump.c b/level_3/byte_dump/c/private-byte_dump.c index 0204106..6ee4866 100644 --- a/level_3/byte_dump/c/private-byte_dump.c +++ b/level_3/byte_dump/c/private-byte_dump.c @@ -32,7 +32,7 @@ extern "C" { f_array_length_t character_current = 0; // The row starts based on the first byte starting point and how many columns of bytes are displayed per row. - if (main.first > 0) { + if (main.first) { cell.row = main.first / main.width; offset = main.first % main.width; @@ -77,9 +77,7 @@ extern "C" { memset(&invalid, 0, sizeof(uint8_t) * main.width); } - character_current = characters.used; - ++characters.used; - + character_current = characters.used++; invalid[character_current] = 0; } @@ -186,7 +184,7 @@ extern "C" { flockfile(main.output.stream); // Print placeholders to fill out the remaining line and then optionally print the text block. - if (cell.column > 0 && cell.column < main.width) { + if (cell.column && cell.column < main.width) { previous.bytes = 0; previous.invalid = 0; @@ -216,32 +214,32 @@ extern "C" { if (cell.column < main.width) { if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { if (!(cell.column % 4)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_hexidecimal) { if (!(cell.column % 8)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_duodecimal) { if (!(cell.column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_octal) { if (!(cell.column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_binary) { if (!(cell.column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_decimal) { if (!(cell.column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } } @@ -251,11 +249,11 @@ extern "C" { byte_dump_print_text(main, characters, invalid, &previous, &offset); } else { - f_print_terminated(f_string_eol_s, main.output.stream); + f_print_character(f_string_eol_s[0], main.output.stream); } } - f_print_terminated(f_string_eol_s, main.output.stream); + f_print_character(f_string_eol_s[0], main.output.stream); funlockfile(main.output.stream); @@ -265,7 +263,7 @@ extern "C" { if (found_invalid_utf) { flockfile(main.error.to.stream); - fl_print_string("%[Invalid UTF-8 codes were detected for file '%]", main.error.to.stream, main.context.set.error, main.context.set.error); + fl_print_color_terminated("Invalid UTF-8 codes were detected for file '", main.context.set.error, main.error.to.stream); fl_print_string("%[%S%]", main.error.to.stream, main.context.set.notable, file_name ? file_name : "-", main.context.set.notable); fl_print_string("%['.%]%c%c", main.error.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0], f_string_eol_s[0]); @@ -276,7 +274,7 @@ extern "C" { // @todo: determine what the error is and display it. flockfile(main.error.to.stream); - fl_print_string("%[%Sread() failed for '%]", main.error.to.stream, main.context.set.error, fll_error_print_error, main.context.set.error); + fl_print_string("%[%sread() failed for '%]", main.error.to.stream, main.context.set.error, fll_error_print_error, main.context.set.error); fl_print_string("%[%S%]", main.error.to.stream, main.context.set.notable, file_name ? file_name : "-", main.context.set.notable); fl_print_string("%['.%]%c%c", main.error.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0], f_string_eol_s[0]); @@ -347,32 +345,32 @@ extern "C" { if (cell->column < main.width) { if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { if (!(cell->column % 4)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_hexidecimal) { if (!(cell->column % 8)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_duodecimal) { if (!(cell->column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_octal) { if (!(cell->column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_binary) { if (!(cell->column % 4)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_decimal) { if (!(cell->column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } } @@ -381,6 +379,7 @@ extern "C" { } if (cell->column < main.width) { + // @fixme: when unicode is enabled but invalid, the mode and its respective length now matters. This needs to be included in the width calculations. if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found && !invalid[character_current]) { if (byte_current == 1) { uint32_t unicode = 0; @@ -444,10 +443,10 @@ extern "C" { } if (invalid[character_current]) { - fl_print_string(" %[%02&uii%]", main.output.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); + fl_print_string(" %[%03&uii%]", main.output.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); } else { - fl_print_string(" %02&uii", main.output.stream, (uint8_t) byte); + fl_print_string(" %03&uii", main.output.stream, (uint8_t) byte); } } else if (main.mode == byte_dump_mode_octal) { @@ -476,10 +475,10 @@ extern "C" { } if (invalid[character_current]) { - fl_print_string(" %[%03uii%]", main.output.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); + fl_print_string(" %[%3uii%]", main.output.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); } else { - fl_print_string(" %03uii", main.output.stream, (uint8_t) byte); + fl_print_string(" %3uii", main.output.stream, (uint8_t) byte); } } } @@ -500,7 +499,7 @@ extern "C" { byte_dump_print_text(main, characters, invalid, previous, offset); } else { - f_print_terminated(f_string_eol_s, main.output.stream); + f_print_character(f_string_eol_s[0], main.output.stream); } cell->column = 0; @@ -518,32 +517,32 @@ extern "C" { else { if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { if (!(cell->column % 4)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_hexidecimal) { if (!(cell->column % 8)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_duodecimal) { if (!(cell->column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_octal) { if (!(cell->column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_binary) { if (!(cell->column % 4)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (main.mode == byte_dump_mode_decimal) { if (!(cell->column % 6)) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } } @@ -556,17 +555,21 @@ extern "C" { void byte_dump_print_text(const byte_dump_main_t main, const f_utf_string_static_t characters, const char invalid[], byte_dump_previous_t *previous, uint8_t *offset) { uint8_t j = 0; - uint8_t output = 0; + uint8_t c = 0; uint8_t width_utf = 0; bool printed = F_false; - fl_print_string(" %[%s%] ", main.output.stream, main.context.set.notable, byte_dump_character_wall, main.context.set.notable); + char byte[5] = { 0, 0, 0, 0, 0 }; + + f_print_terminated(" ", main.output.stream); + fl_print_color_terminated(byte_dump_character_wall, main.context.set.notable, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); - if (*offset > 0) { + if (*offset) { if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - while (*offset > 0 && j < main.width) { + while (*offset && j < main.width) { - f_print_terminated(f_string_ascii_period_s, main.output.stream); + f_print_character(f_string_ascii_period_s[0], main.output.stream); --(*offset); ++j; } // while @@ -574,13 +577,18 @@ extern "C" { else { const char *placeholder = f_string_space_s; - if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { - placeholder = byte_dump_character_placeholder; - } + while (*offset && j < main.width) { + + f_print_terminated(" ", main.output.stream); - while (*offset > 0 && j < main.width) { + if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.warning, main.output.stream); + } + else { + fl_print_color_terminated(f_string_space_s, main.context.set.warning, main.output.stream); + } - fl_print_string(" %[%s%] ", main.output.stream, main.context.set.warning, placeholder, main.context.set.warning); + f_print_character(f_string_space_s[0], main.output.stream); --(*offset); ++j; } // while @@ -595,29 +603,29 @@ extern "C" { bytes_overflow = previous->bytes - 1 - main.width; } - if (previous->bytes > 0) { + if (previous->bytes) { if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { for (; j < previous->bytes && j < main.width; ++j) { if (previous->invalid) { - fl_print_string("%[%s%]", main.output.stream, main.context.set.error, byte_dump_character_placeholder, main.context.set.error); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.error, main.output.stream); } else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_terminated(f_string_ascii_period_s, main.output.stream); + f_print_character(f_string_ascii_period_s[0], main.output.stream); } else { - fl_print_string("%[%s%]", main.output.stream, main.context.set.warning, byte_dump_character_placeholder, main.context.set.warning); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.warning, main.output.stream); } } // for } else { for (; j < previous->bytes && j < main.width; ++j) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } // for } } - if (bytes_overflow > 0) { + if (bytes_overflow) { previous->bytes = bytes_overflow; } else { @@ -628,217 +636,161 @@ extern "C" { for (uint8_t i = 0; i < characters.used && j < main.width; ++i, ++j) { - output = macro_f_utf_character_t_to_char_1(characters.string[i]); - width_utf = macro_f_utf_byte_width_is(output); + c = macro_f_utf_character_t_to_char_1(characters.string[i]); + width_utf = macro_f_utf_byte_width_is(c); if (invalid[i]) { - fl_print_string("%[%s%]", main.output.stream, main.context.set.error, byte_dump_character_incomplete, main.context.set.error); + fl_print_color_terminated(byte_dump_character_incomplete, main.context.set.error, main.output.stream); } - else if (output >= 0 && output <= 32 || output == 127) { + else if (f_utf_character_is_control(characters.string[i]) == F_true) { if (main.presentation == byte_dump_presentation_normal) { - fl_print_string("%[%[", main.output.stream, main.context.set.notable, main.context.set.warning); + fl_print_color_before(main.context.set.notable, main.output.stream); + fl_print_color_before(main.context.set.warning, main.output.stream); - if (!output) { - f_print_terminated(byte_dump_sequence_null, main.output.stream); - } - else if (output == 1) { - f_print_terminated(byte_dump_sequence_start_of_header, main.output.stream); - } - else if (output == 2) { - f_print_terminated(byte_dump_sequence_start_of_text, main.output.stream); - } - else if (output == 3) { - f_print_terminated(byte_dump_sequence_end_of_text, main.output.stream); - } - else if (output == 4) { - f_print_terminated(byte_dump_sequence_end_of_transmission, main.output.stream); - } - else if (output == 5) { - f_print_terminated(byte_dump_sequence_end_of_enquiry, main.output.stream); - } - else if (output == 6) { - f_print_terminated(byte_dump_sequence_acknowledge, main.output.stream); - } - else if (output == 7) { - f_print_terminated(byte_dump_sequence_bell, main.output.stream); - } - else if (output == 8) { - f_print_terminated(byte_dump_sequence_backspace, main.output.stream); - } - else if (output == 9) { - f_print_terminated(byte_dump_sequence_tab, main.output.stream); - } - else if (output == 10) { - f_print_terminated(byte_dump_sequence_new_line, main.output.stream); - } - else if (output == 11) { - f_print_terminated(byte_dump_sequence_tab_vertical, main.output.stream); - } - else if (output == 12) { - f_print_terminated(byte_dump_sequence_form_feed, main.output.stream); - } - else if (output == 13) { - f_print_terminated(byte_dump_sequence_carriage_return, main.output.stream); - } - else if (output == 14) { - f_print_terminated(byte_dump_sequence_shift_out, main.output.stream); - } - else if (output == 15) { - f_print_terminated(byte_dump_sequence_shift_in, main.output.stream); - } - else if (output == 16) { - f_print_terminated(byte_dump_sequence_data_link_escape, main.output.stream); - } - else if (output == 17) { - f_print_terminated(byte_dump_sequence_device_control_1, main.output.stream); - } - else if (output == 18) { - f_print_terminated(byte_dump_sequence_device_control_2, main.output.stream); - } - else if (output == 19) { - f_print_terminated(byte_dump_sequence_device_control_3, main.output.stream); - } - else if (output == 20) { - f_print_terminated(byte_dump_sequence_device_control_4, main.output.stream); - } - else if (output == 21) { - f_print_terminated(byte_dump_sequence_acknowledge_negative, main.output.stream); - } - else if (output == 22) { - f_print_terminated(byte_dump_sequence_synchronous_idle, main.output.stream); - } - else if (output == 23) { - f_print_terminated(byte_dump_sequence_end_of_transmission_block, main.output.stream); - } - else if (output == 24) { - f_print_terminated(byte_dump_sequence_cancel, main.output.stream); - } - else if (output == 25) { - f_print_terminated(byte_dump_sequence_end_of_medium, main.output.stream); - } - else if (output == 26) { - f_print_terminated(byte_dump_sequence_substitute, main.output.stream); - } - else if (output == 27) { - f_print_terminated(byte_dump_sequence_escape, main.output.stream); - } - else if (output == 28) { - f_print_terminated(byte_dump_sequence_file_separator, main.output.stream); - } - else if (output == 29) { - f_print_terminated(byte_dump_sequence_group_separator, main.output.stream); - } - else if (output == 30) { - f_print_terminated(byte_dump_sequence_record_separator, main.output.stream); - } - else if (output == 31) { - f_print_terminated(byte_dump_sequence_unit_separator, main.output.stream); - } - else if (output == 32) { - f_print_terminated(byte_dump_sequence_space, main.output.stream); + if (width_utf) { + byte[0] = c; + + if (width_utf > 1) { + byte[1] = macro_f_utf_character_t_to_char_2(characters.string[i]); + + if (width_utf > 2) { + byte[2] = macro_f_utf_character_t_to_char_3(characters.string[i]); + + if (width_utf > 3) { + byte[3] = macro_f_utf_character_t_to_char_4(characters.string[i]); + } + else { + byte[3] = 0; + } + } + else { + byte[2] = 0; + } + } + else { + byte[1] = 0; + } + + f_print_safely(byte, width_utf ? width_utf : 1, main.output.stream); } - else if (output == 127) { - f_print_terminated(byte_dump_sequence_delete, main.output.stream); + else { + f_print_character_safely(c, main.output.stream); } - fl_print_string("%]%]", main.output.stream, main.context.set.warning, main.context.set.notable); + fl_print_color_after(main.context.set.warning, main.output.stream); + fl_print_color_after(main.context.set.notable, main.output.stream); } else if (main.presentation == byte_dump_presentation_simple) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); + + if (width_utf > 1) { + f_print_character(f_string_space_s[0], main.output.stream); + + if (width_utf > 2) { + f_print_character(f_string_space_s[0], main.output.stream); + + if (width_utf > 3) { + f_print_character(f_string_space_s[0], main.output.stream); + } + } + } } else if (main.presentation == byte_dump_presentation_classic) { - f_print_terminated(f_string_ascii_period_s, main.output.stream); + f_print_character(f_string_ascii_period_s[0], main.output.stream); + + if (width_utf > 1) { + f_print_character(f_string_ascii_period_s[0], main.output.stream); + + if (width_utf > 2) { + f_print_character(f_string_ascii_period_s[0], main.output.stream); + + if (width_utf > 3) { + f_print_character(f_string_ascii_period_s[0], main.output.stream); + } + } + } } } else if (f_utf_character_is_whitespace(characters.string[i]) == F_true) { if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_terminated(f_string_ascii_period_s, main.output.stream); + f_print_character(f_string_ascii_period_s[0], main.output.stream); } else { - fl_print_string("%[%[%s%]%]", main.output.stream, main.context.set.notable, main.context.set.warning, byte_dump_sequence_space, main.context.set.warning, main.context.set.notable); + fl_print_color_before(main.context.set.notable, main.output.stream); + fl_print_color_terminated(byte_dump_sequence_space, main.context.set.warning, main.output.stream); + fl_print_color_after(main.context.set.notable, main.output.stream); } } else if (f_utf_character_is_zero_width(characters.string[i]) == F_true) { if (main.presentation == byte_dump_presentation_classic) { - f_print_terminated(f_string_ascii_period_s, main.output.stream); + f_print_character(f_string_ascii_period_s[0], main.output.stream); } else if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { - fl_print_string("%[%[%s%]%]", main.output.stream, main.context.set.notable, main.context.set.warning, byte_dump_character_placeholder, main.context.set.warning, main.context.set.notable); - } - else { - f_print_terminated(f_string_space_s, main.output.stream); - } - } - else if (f_utf_character_is_control(characters.string[i]) == F_true) { - - // print a space (or '.') for control characters. - if (main.presentation == byte_dump_presentation_classic) { - fl_print_string("%[%s%]", main.output.stream, main.context.set.warning, f_string_ascii_period_s, main.context.set.warning); + fl_print_color_before(main.context.set.notable, main.output.stream); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.warning, main.output.stream); + fl_print_color_after(main.context.set.notable, main.output.stream); } else { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else if (width_utf == 2 && characters.string[i] == 0xd89d0000) { // U+061C - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 3 && characters.string[i] >= 0xefbfb000 && characters.string[i] <= 0xefbfbc00) { // Use space to represent Specials codes. // 0xefbfbd00 is excluded because it is printable (and is the "Replacement Character" code). - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 3 && characters.string[i] >= 0xe290a700 && characters.string[i] <= 0xe290bf00) { // Use space to represent Control Pictues codes that are not currently defined but are reserved. - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 3 && characters.string[i] >= 0xee808000 && characters.string[i] <= 0xefa3bf00) { // Use space to represent Private Use Area codes. - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 4 && characters.string[i] >= 0xf09c80a0 && characters.string[i] <= 0xf09c80bd) { // Use space to represent Vaiation Selectors Supplement codes. - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 4 && characters.string[i] >= 0xf3b08080 && characters.string[i] <= 0xf3bfbfbf) { // Use space to represent Supplemental Private Use Area-A codes. - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 4 && characters.string[i] >= 0xf4808080 && characters.string[i] <= 0xf48fbfbf) { // Use space to represent Supplemental Private Use Area-B codes. - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 1) { // print invalid placeholder for invalid UTF-8 widths. if (invalid[i]) { - fl_print_string("%[%s%]", main.output.stream, main.context.set.error, byte_dump_character_incomplete, main.context.set.error); + fl_print_color_terminated(byte_dump_character_incomplete, main.context.set.error, main.output.stream); } else { - fl_print_string("%[%s%]", main.output.stream, main.context.set.warning, byte_dump_character_incomplete, main.context.set.warning); + fl_print_color_terminated(byte_dump_character_incomplete, main.context.set.warning, main.output.stream); } } - else if (width_utf > 0) { - fl_print_string("%c", main.output.stream, (uint8_t) output); + else if (width_utf) { + f_print_character(c, main.output.stream); if (width_utf > 1) { - output = macro_f_utf_character_t_to_char_2(characters.string[i]); - fl_print_string("%c", main.output.stream, (uint8_t) output); + f_print_character(macro_f_utf_character_t_to_char_2(characters.string[i]), main.output.stream); if (width_utf > 2) { - output = macro_f_utf_character_t_to_char_3(characters.string[i]); - fl_print_string("%c", main.output.stream, (uint8_t) output); + f_print_character(macro_f_utf_character_t_to_char_3(characters.string[i]), main.output.stream); if (width_utf > 3) { - output = macro_f_utf_character_t_to_char_4(characters.string[i]); - fl_print_string("%c", main.output.stream, (uint8_t) output); + f_print_character(macro_f_utf_character_t_to_char_4(characters.string[i]), main.output.stream); } } } @@ -848,58 +800,58 @@ extern "C" { if (width_utf == 2 && characters.string[i] >= 0xdea60000 && characters.string[i] <= 0xdeb00000) { // Thana combining codes: U+07A6 to U+07B0. - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 2 && characters.string[i] >= 0xcc800000 && characters.string[i] <= 0xcdaf0000) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 3 && characters.string[i] >= 0xe1aab000 && characters.string[i] <= 0xe1abbf00) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 3 && characters.string[i] >= 0xe1b78000 && characters.string[i] <= 0xe1b7bf00) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 3 && characters.string[i] >= 0xe2839000 && characters.string[i] <= 0xe283bf00) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 2 && characters.string[i] >= 0xd8900000 && characters.string[i] <= 0xd89a0000) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 2 && characters.string[i] >= 0xd98b0000 && characters.string[i] <= 0xd99f0000) { // Arabic, U+064B to U+065F. - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 2 && characters.string[i] >= 0xdb960000 && characters.string[i] <= 0xdb9c0000) { // Arabic, U+06D6 to U+06DC. - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } else if (width_utf == 2 && characters.string[i] >= 0xd6910000 && characters.string[i] <= 0xd6bd0000) { // Hebrew, U+0591 to U+05BD. - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } } else { - fl_print_string("%c", main.output.stream, (uint8_t) output); + f_print_character(c, main.output.stream); } // When using UTF-8 characters, the character columns will not line up, so print placeholders to simulate the bytes that are not printed, if necessary for alignment. if (width_utf > 1 && j + 1 < main.width) { if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { if (invalid[i]) { - fl_print_string("%[%s%]", main.output.stream, main.context.set.error, byte_dump_character_placeholder, main.context.set.error); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.error, main.output.stream); } else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_terminated(f_string_ascii_period_s, main.output.stream); + f_print_character(f_string_ascii_period_s[0], main.output.stream); } else { - fl_print_string("%[%s%]", main.output.stream, main.context.set.warning, byte_dump_character_placeholder, main.context.set.warning); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.warning, main.output.stream); } } else { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } ++j; @@ -907,17 +859,17 @@ extern "C" { if (width_utf > 2 && j + 1 < main.width) { if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { if (invalid[i]) { - fl_print_string("%[%s%]", main.output.stream, main.context.set.error, byte_dump_character_placeholder, main.context.set.error); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.error, main.output.stream); } else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_terminated(f_string_ascii_period_s, main.output.stream); + f_print_character(f_string_ascii_period_s[0], main.output.stream); } else { - fl_print_string("%[%s%]", main.output.stream, main.context.set.warning, byte_dump_character_placeholder, main.context.set.warning); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.warning, main.output.stream); } } else { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } ++j; @@ -925,17 +877,17 @@ extern "C" { if (width_utf > 3 && j + 1 < main.width) { if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { if (invalid[i]) { - fl_print_string("%[%s%]", main.output.stream, main.context.set.error, byte_dump_character_placeholder, main.context.set.error); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.error, main.output.stream); } else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_terminated(f_string_ascii_period_s, main.output.stream); + f_print_character(f_string_ascii_period_s[0], main.output.stream); } else { - fl_print_string("%[%s%]", main.output.stream, main.context.set.warning, byte_dump_character_placeholder, main.context.set.warning); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.warning, main.output.stream); } } else { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } ++j; @@ -949,24 +901,25 @@ extern "C" { for (; j < main.width; ++j) { if (invalid[j]) { - fl_print_string("%[%s%]", main.output.stream, main.context.set.error, byte_dump_character_placeholder, main.context.set.error); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.error, main.output.stream); } else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_terminated(f_string_ascii_period_s, main.output.stream); + f_print_character(f_string_ascii_period_s[0], main.output.stream); } else { - fl_print_string("%[%s%]", main.output.stream, main.context.set.warning, byte_dump_character_placeholder, main.context.set.warning); + fl_print_color_terminated(byte_dump_character_placeholder, main.context.set.warning, main.output.stream); } } // for } else { for (; j < main.width; ++j) { - f_print_terminated(f_string_space_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); } // for } - fl_print_string(" %[|%]", main.output.stream, main.context.set.notable, main.context.set.notable); - f_print_terminated(f_string_eol_s, main.output.stream); + f_print_character(f_string_space_s[0], main.output.stream); + fl_print_color_terminated(byte_dump_character_wall, main.context.set.notable, main.output.stream); + f_print_character(f_string_eol_s[0], main.output.stream); } #endif // _di_byte_dump_file_ -- 1.8.3.1