From 99a156bf43559635f77953b1a266b9a14bde32f5 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 25 Jul 2021 22:02:20 -0500 Subject: [PATCH] Progress: Redesign printing, redesign conversions, and some cleanup. The print functions have been redesigned (work is incomplete as of this commit): - Use unlocked printing where possible for all low level functions (like f_print()). - Provide locked versions of all f_print* and fl_print* functions in newly added fll_print project. - Redesign output variable to be at the end to be consistent with FLL practices (with an exception). - Implement fprintf() alternative (very much incomplete, see below) and use a parameter structure to match fprintf() as an exception to the FLL practice mentioned above. - Add *_raw() and *_safely() functions (see notes below). The conversions are redesigned to better accommodate more flexibility as well as the newly added fprintf() alternatives (fl_print_string(), etc..). - Provide a structure for more fine tuned control over convert process. - Allow for literal designated of base 10 rather than making it solely the default base. - Use bitwise operations and range comparisons more rather than switches and if then blocks for conversions. There are some private headers being exposed to the installation (private headers should not be specified in the build_sources_headers build settings). This commit all started with the observation that filenames could be created using control codes. I tested using the backspace control code with the byte_dump program and found that it does perform backspace. I consider this a security issue as I consider this undefined behavior. To resolve this, I decided that I needed a "print safely" set of print functions. After some consideration, I decided that providing my own fprintf() alternative is the way to go and has several advantages. - Allow moving print locking to higher levels to avoid thread problems where multiple fprintf() like functions are called that should not be allowed for something else to print between them. - The unlocked print functions also allow for better performance under the assumption or expectation allows for better control of the programmer to properly utilize this. - Allow for having an unlocked fprintf() function. - Still allow for locked versions of all unlocked print functions. - Allow for passing FLL f_string_static_t, f_string_dynamic_t, and similar to the fprintf() alternative (which hopefully will make the code a lot cleaner and better maintainable). - Allow for custom print options to "print safely". - Allow for custom print options to "print rawly" (that is, allow printing NULL character and any control character as-is). Working on this led to doing a rewrite of the conversion functions (which is needed anyway). This also required major changes to the print functions and as per my completeness principle also requires a lot more functions to be implemented. All of this resulted in a huge set of changes. So big, that I am afraid of mistakes. No, I expect there to be mistakes. At this point, I spent enough time so I put the code in a state that compiles correctly and am saving as-is. There are several @todos present and there are also a large number of incomplete areas of code. Of particular note is the fprintf() compatibility. I tried to stay as close to the fprintf() syntax as possible but I found that it is better to deviate in certain areas. I do not plan on implementing the "type conversion" support. I do plan on implementing the float/double support, but do to the additional complexity and my priorities, this functionality is being held off for a much later time. I will get to documenting the fprintf() alternatives later on. The fprintf() alternatives are being called fl_print_string() and fll_print_string() (including variations with different suffixes). This is done to distinguish these between the normal f_print() and fll_print() type of functions. --- build/level_0/settings | 4 +- build/level_2/settings | 4 +- build/monolithic/settings | 4 +- build/scripts/bootstrap-example.sh | 2 +- level_0/f_capability/c/capability.h | 4 +- level_0/f_conversion/c/conversion-common.h | 52 + level_0/f_conversion/c/conversion.c | 348 +---- level_0/f_conversion/c/conversion.h | 81 +- level_0/f_conversion/c/private-conversion.c | 528 +++++++ level_0/f_conversion/c/private-conversion.h | 240 +++ level_0/f_conversion/data/build/settings | 2 +- level_0/f_fss/data/build/settings | 2 +- level_0/f_print/c/print-common.c | 49 + level_0/f_print/c/print-common.h | 216 +++ level_0/f_print/c/print.c | 663 +++++++- level_0/f_print/c/print.h | 1654 +++++++++++++++++--- level_0/f_print/c/private-print.c | 1188 ++++++++++++++- level_0/f_print/c/private-print.h | 469 +++++- level_0/f_print/data/build/dependencies | 1 + level_0/f_print/data/build/settings | 6 +- level_0/f_status/c/status.h | 2 + level_0/f_string/data/build/settings | 2 +- level_0/f_type_array/data/build/settings | 2 +- level_1/fl_print/c/print.c | 362 ++++- level_1/fl_print/c/print.h | 492 ++++-- level_1/fl_print/c/private-print.c | 2202 ++++++++++++++++++++++++--- level_1/fl_print/c/private-print.h | 417 ++++- level_1/fl_status/c/status.c | 6 + level_1/fl_status/c/status.h | 4 + level_2/fll_path/c/path.h | 3 - level_2/fll_print/c/print.c | 455 ++++++ level_2/fll_print/c/print.h | 967 ++++++++++++ level_2/fll_print/data/build/defines | 2 + level_2/fll_print/data/build/dependencies | 8 + level_2/fll_print/data/build/settings | 56 + level_2/fll_status/c/status.c | 12 + 36 files changed, 9448 insertions(+), 1061 deletions(-) create mode 100644 level_0/f_conversion/c/private-conversion.c create mode 100644 level_0/f_conversion/c/private-conversion.h create mode 100644 level_0/f_print/c/print-common.c create mode 100644 level_0/f_print/c/print-common.h create mode 100644 level_2/fll_print/c/print.c create mode 100644 level_2/fll_print/c/print.h create mode 100644 level_2/fll_print/data/build/defines create mode 100644 level_2/fll_print/data/build/dependencies create mode 100644 level_2/fll_print/data/build/settings diff --git a/build/level_0/settings b/build/level_0/settings index 9c92c43..a0d2dea 100644 --- a/build/level_0/settings +++ b/build/level_0/settings @@ -22,10 +22,10 @@ build_language c build_libraries -lc -lcap build_libraries-level build_libraries-level_threadless -build_sources_library account.c private-account.c capability.c color.c color-common.c console.c console-common.c control_group.c control_group-common.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c file-common.c private-file.c fss.c private-fss.c fss-common.c fss_named.c fss_nest.c fss_set.c iki.c iki-common.c private-iki.c limit.c memory.c memory_structure.c private-memory.c path.c path-common.c private-path.c pipe.c print.c private-print.c serialize.c serialize-common.c private-serialize.c signal.c socket.c string.c string-common.c private-string.c string_dynamic.c string_map.c string_quantity.c string_range.c string_triple.c type_array.c private-type_array.c utf.c utf-common.c private-utf.c utf_dynamic.c utf_map.c utf_triple.c +build_sources_library account.c private-account.c capability.c color.c color-common.c console.c console-common.c control_group.c control_group-common.c conversion.c private-conversion.c directory.c private-directory.c environment.c private-environment.c file.c file-common.c private-file.c fss.c private-fss.c fss-common.c fss_named.c fss_nest.c fss_set.c iki.c iki-common.c private-iki.c limit.c memory.c memory_structure.c private-memory.c path.c path-common.c private-path.c pipe.c print.c print-common.c private-print.c serialize.c serialize-common.c private-serialize.c signal.c socket.c string.c string-common.c private-string.c string_dynamic.c string_map.c string_quantity.c string_range.c string_triple.c type_array.c private-type_array.c utf.c utf-common.c private-utf.c utf_dynamic.c utf_map.c utf_triple.c build_sources_library-level thread.c private-thread.c build_sources_program -build_sources_headers account.h account-common.h capability.h capability-common.h color.h color-common.h console.h console-common.h control_group.h control_group-common.h conversion.h conversion-common.h directory.h directory_type.h directory-common.h environment.h environment-common.h execute.h execute-common.h file.h file-common.h fss.h private-fss.h fss-common.h fss_comment.h fss_delimit.h fss_named.h fss_nest.h fss_quote.h fss_set.h iki.h iki-common.h limit.h limit-common.h memory.h memory_structure.h memory-common.h path.h path-common.h pipe.h print.h serialize.h serialize-common.h signal.h signal-common.h socket.h socket-common.h status.h string.h string-common.h private-string.h string_dynamic.h string_map.h string_quantity.h string_range.h string_triple.h type.h type_array.h private-type_array.h type_array-common.h utf.h utf-common.h utf_dynamic.h utf_map.h utf_triple.h +build_sources_headers account.h account-common.h capability.h capability-common.h color.h color-common.h console.h console-common.h control_group.h control_group-common.h conversion.h conversion-common.h directory.h directory_type.h directory-common.h environment.h environment-common.h execute.h execute-common.h file.h file-common.h fss.h fss-common.h fss_comment.h fss_delimit.h fss_named.h fss_nest.h fss_quote.h fss_set.h iki.h iki-common.h limit.h limit-common.h memory.h memory_structure.h memory-common.h path.h path-common.h pipe.h print.h print-common.h serialize.h serialize-common.h signal.h signal-common.h socket.h socket-common.h status.h string.h string-common.h string_dynamic.h string_map.h string_quantity.h string_range.h string_triple.h type.h type_array.h type_array-common.h utf.h utf-common.h utf_dynamic.h utf_map.h utf_triple.h build_sources_headers-level thread.h thread-common.h build_sources_script build_sources_setting diff --git a/build/level_2/settings b/build/level_2/settings index 8d43433..9dca932 100644 --- a/build/level_2/settings +++ b/build/level_2/settings @@ -22,10 +22,10 @@ build_language c build_libraries -lc -lcap build_libraries-level -lfll_1 -lfll_0 build_libraries-level_threadless -lfll_1 -lfll_0 -build_sources_library control_group.c error.c error-common.c private-error.c execute.c private-execute.c file.c private-file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c fss_status.c iki.c private-iki.c path.c program.c status.c +build_sources_library control_group.c error.c error-common.c private-error.c execute.c private-execute.c file.c private-file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c fss_status.c iki.c private-iki.c path.c print.c program.c status.c build_sources_library-level build_sources_program -build_sources_headers control_group.h error.h error-common.h execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h path.h program.h status.h +build_sources_headers control_group.h error.h error-common.h execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h path.h print.h program.h status.h build_sources_headers-level build_sources_script build_sources_setting diff --git a/build/monolithic/settings b/build/monolithic/settings index 99effec..c73cedb 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -22,10 +22,10 @@ build_language c build_libraries -lc -lcap build_libraries-monolithic build_libraries-monolithic_threadless -build_sources_library level_0/account.c level_0/private-account.c level_0/capability.c level_0/color.c level_0/color-common.c level_0/console.c level_0/console-common.c level_0/control_group.c level_0/control_group-common.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/file-common.c level_0/private-file.c level_0/fss.c level_0/private-fss.c level_0/fss-common.c level_0/fss_named.c level_0/fss_nest.c level_0/fss_set.c level_0/iki.c level_0/iki-common.c level_0/private-iki.c level_0/limit.c level_0/memory.c level_0/memory_structure.c level_0/private-memory.c level_0/path.c level_0/path-common.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/serialize-common.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/string.c level_0/string-common.c level_0/private-string.c level_0/string_dynamic.c level_0/string_map.c level_0/string_quantity.c level_0/string_range.c level_0/string_triple.c level_0/type_array.c level_0/private-type_array.c level_0/utf.c level_0/utf-common.c level_0/private-utf.c level_0/utf_dynamic.c level_0/utf_map.c level_0/utf_triple.c level_1/console.c level_1/control_group.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_embedded_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/signal.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/control_group.c level_2/error.c level_2/error-common.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_embedded_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c +build_sources_library level_0/account.c level_0/private-account.c level_0/capability.c level_0/color.c level_0/color-common.c level_0/console.c level_0/console-common.c level_0/control_group.c level_0/control_group-common.c level_0/conversion.c level_0/private-conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/file-common.c level_0/private-file.c level_0/fss.c level_0/private-fss.c level_0/fss-common.c level_0/fss_named.c level_0/fss_nest.c level_0/fss_set.c level_0/iki.c level_0/iki-common.c level_0/private-iki.c level_0/limit.c level_0/memory.c level_0/memory_structure.c level_0/private-memory.c level_0/path.c level_0/path-common.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/print-common.c level_0/private-print.c level_0/serialize.c level_0/serialize-common.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/string.c level_0/string-common.c level_0/private-string.c level_0/string_dynamic.c level_0/string_map.c level_0/string_quantity.c level_0/string_range.c level_0/string_triple.c level_0/type_array.c level_0/private-type_array.c level_0/utf.c level_0/utf-common.c level_0/private-utf.c level_0/utf_dynamic.c level_0/utf_map.c level_0/utf_triple.c level_1/console.c level_1/control_group.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_embedded_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/signal.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/control_group.c level_2/error.c level_2/error-common.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_embedded_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/print.c level_2/program.c level_2/status.c build_sources_library-monolithic level_0/thread.c level_0/private-thread.c build_sources_program -build_sources_headers level_0/account.h level_0/account-common.h level_0/capability.h level_0/capability-common.h level_0/color.h level_0/color-common.h level_0/console.h level_0/console-common.h level_0/control_group.h level_0/control_group-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/execute.h level_0/execute-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/private-fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/limit.h level_0/limit-common.h level_0/memory.h level_0/memory_structure.h level_0/memory-common.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/string.h level_0/string-common.h level_0/private-string.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/string_triple.h level_0/type.h level_0/type_array.h level_0/private-type_array.h level_0/type_array-common.h level_0/utf.h level_0/utf-common.h level_0/utf_dynamic.h level_0/utf_map.h level_0/utf_triple.h level_1/console.h level_1/control_group.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/execute.h level_1/execute-common.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_embedded_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/signal.h level_1/signal-common.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/control_group.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_embedded_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h +build_sources_headers level_0/account.h level_0/account-common.h level_0/capability.h level_0/capability-common.h level_0/color.h level_0/color-common.h level_0/console.h level_0/console-common.h level_0/control_group.h level_0/control_group-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/execute.h level_0/execute-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/limit.h level_0/limit-common.h level_0/memory.h level_0/memory_structure.h level_0/memory-common.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/print-common.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/string_triple.h level_0/type.h level_0/type_array.h level_0/type_array-common.h level_0/utf.h level_0/utf-common.h level_0/utf_dynamic.h level_0/utf_map.h level_0/utf_triple.h level_1/console.h level_1/control_group.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/execute.h level_1/execute-common.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_embedded_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/signal.h level_1/signal-common.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/control_group.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_embedded_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/print.h level_2/program.h level_2/status.h build_sources_headers-monolithic level_0/thread.h level_0/thread-common.h build_sources_script build_sources_setting diff --git a/build/scripts/bootstrap-example.sh b/build/scripts/bootstrap-example.sh index 388a301..bd78d2a 100644 --- a/build/scripts/bootstrap-example.sh +++ b/build/scripts/bootstrap-example.sh @@ -56,7 +56,7 @@ if [[ $1 == "individual" ]] ; then bash build/scripts/package.sh $verbose $color build -i if [[ $? -eq 0 ]] ; then - for i in f_type f_status f_memory f_type_array f_string f_utf f_account f_capability f_color f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_path f_pipe f_print f_serialize f_signal f_socket f_thread fl_console fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_print fl_signal fl_status fl_string fl_utf fl_utf_file fll_control_group fll_error fll_execute fll_file fll_fss fll_iki fll_path fll_program fll_status ; do + for i in f_type f_status f_memory f_type_array f_string f_utf f_account f_capability f_color f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_path f_pipe f_print f_serialize f_signal f_socket f_thread fl_console fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_print fl_signal fl_status fl_string fl_utf fl_utf_file fll_control_group fll_error fll_execute fll_file fll_fss fll_iki fll_path fll_print fll_program fll_status ; do echo && echo "Processing $i." && cd package/individual/$i-$2/ && diff --git a/level_0/f_capability/c/capability.h b/level_0/f_capability/c/capability.h index 178deb3..5aa1f9c 100644 --- a/level_0/f_capability/c/capability.h +++ b/level_0/f_capability/c/capability.h @@ -924,7 +924,7 @@ extern "C" { * * F_failure (with error bit) on any other failure. * - * Errors (with error bit) from f_string_dynamic_resize(). + * Errors (with error bit) from: f_string_dynamic_resize(). * * @see cap_free() * @see cap_to_name() @@ -955,7 +955,7 @@ extern "C" { * * F_failure (with error bit) on any other failure. * - * Errors (with error bit) from f_string_dynamic_resize(). + * Errors (with error bit) from: f_string_dynamic_resize(). * * @see cap_free() * @see cap_to_text() diff --git a/level_0/f_conversion/c/conversion-common.h b/level_0/f_conversion/c/conversion-common.h index 7ecc648..407b451 100644 --- a/level_0/f_conversion/c/conversion-common.h +++ b/level_0/f_conversion/c/conversion-common.h @@ -74,6 +74,58 @@ extern "C" { #define f_conversion_digits_hexidecimal_signed 32 #endif // _en_f_type_number_128_t_ +/** + * Provide a structure for customizing conversion settings for a conversion function using this. + * + * base: The base unit the number is to be represented as, only the numbers 2 through 16 are supported as a base. + * flag: Store flags from f_conversion_data_flag_*. + * width: The number of digits representing a minimum width (a width of 0, should result in not printing a 0 when the number is 0). + */ +#ifndef _di_f_conversion_data_t_ + typedef struct { + uint8_t base; + uint8_t flag; + + int width; + } f_conversion_data_t; + + #define f_conversion_data_t_initialize { 10, 0, 1 } + + #define macro_f_conversion_data_t_initialize(base, flag, width) { base, flag, width } + + #define macro_f_conversion_data_t_clear(data) \ + data.base = 0; \ + data.flag = 0; \ + data.width = 0; +#endif // _di_f_conversion_data_t_ + +/** + * Define flags used by f_conversion_data_t. + * + * f_conversion_data_flag_*: + * - align_left: Use left-justification. + * - base_prepend: Prepend the base character, such as "0x", or "0X", defaulting to lowercase (this includes base 10) (does nothing for unsupported base units). + * - base_upper: Any alphabet characters in the number are made uppercase rather than lowercase and when *_base_prepend flag is used, use uppercase in the base prepend. + * - sign_always: Always show the signs ("+" or "-"). + * - sign_pad: If the sign is not to be shown, then add a space as a placeholder (ignored when *_sign_always is used). + * - zeros_leading: If the number has fewer digits that specified in the padding, then display leading zeros to fill the pad length. + * + * Supported base prepend base units: + * - base 2: 0b, 0B. + * - base 8: 0o, 0O. + * - base 10: 0t, 0T. + * - base 12: 0d, 0D. + * - base 16: 0x, 0X. + */ +#ifndef _di_f_conversion_data_flag_ + #define f_conversion_data_flag_align_left 0x1 + #define f_conversion_data_flag_base_prepend 0x2 + #define f_conversion_data_flag_base_upper 0x4 + #define f_conversion_data_flag_sign_always 0x8 + #define f_conversion_data_flag_sign_pad 0x10 + #define f_conversion_data_flag_zeros_leading 0x20 +#endif // _di_f_conversion_data_flag_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_conversion/c/conversion.c b/level_0/f_conversion/c/conversion.c index 96a03b5..4e9f2ce 100644 --- a/level_0/f_conversion/c/conversion.c +++ b/level_0/f_conversion/c/conversion.c @@ -1,4 +1,5 @@ #include "conversion.h" +#include "private-conversion.h" #ifdef __cplusplus extern "C" { @@ -82,6 +83,7 @@ extern "C" { switch (character) { case 0x30: *number = 0; break; case 0x31: *number = 1; break; + default: return F_status_set_error(F_number); } @@ -96,88 +98,57 @@ extern "C" { if (!number) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - switch (character) { - case 0x30: *number = 0; break; - case 0x31: *number = 1; break; - case 0x32: *number = 2; break; - case 0x33: *number = 3; break; - case 0x34: *number = 4; break; - case 0x35: *number = 5; break; - case 0x36: *number = 6; break; - case 0x37: *number = 7; break; - case 0x38: *number = 8; break; - case 0x39: *number = 9; break; - default: - return F_status_set_error(F_number); + if (character > 0x29 && character < 0x40) { + *number = 0x7 & character; + + return F_none; } - return F_none; + return F_status_set_error(F_number); } #endif // _di_f_conversion_character_to_decimal_ #ifndef _di_f_conversion_character_to_duodecimal_ - f_status_t f_conversion_character_to_duodecimal(const char character, f_number_unsigned_t *decimal) { + f_status_t f_conversion_character_to_duodecimal(const char character, f_number_unsigned_t *number) { #ifndef _di_level_0_parameter_checking_ - if (!decimal) return F_status_set_error(F_parameter); + if (!number) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - switch (character) { - case 0x30: *decimal = 0; break; - case 0x31: *decimal = 1; break; - case 0x32: *decimal = 2; break; - case 0x33: *decimal = 3; break; - case 0x34: *decimal = 4; break; - case 0x35: *decimal = 5; break; - case 0x36: *decimal = 6; break; - case 0x37: *decimal = 7; break; - case 0x38: *decimal = 8; break; - case 0x39: *decimal = 9; break; - case 0x41: *decimal = 10; break; - case 0x42: *decimal = 11; break; - case 0x61: *decimal = 10; break; - case 0x62: *decimal = 11; break; - default: - return F_status_set_error(F_number); + if (character > 0x29 && character < 0x40) { + *number = 0x7 & character; + + return F_none; } - return F_none; + if (character > 0x40 && character < 0x43 || character > 0x60 && character < 0x63) { + *number = 9 + (0x7 & character); + + return F_none; + } + + return F_status_set_error(F_number); } #endif // _di_f_conversion_character_to_duodecimal_ #ifndef _di_f_conversion_character_to_hexidecimal_ - f_status_t f_conversion_character_to_hexidecimal(const char character, f_number_unsigned_t *decimal) { + f_status_t f_conversion_character_to_hexidecimal(const char character, f_number_unsigned_t *number) { #ifndef _di_level_0_parameter_checking_ - if (!decimal) return F_status_set_error(F_parameter); + if (!number) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - switch (character) { - case 0x30: *decimal = 0; break; - case 0x31: *decimal = 1; break; - case 0x32: *decimal = 2; break; - case 0x33: *decimal = 3; break; - case 0x34: *decimal = 4; break; - case 0x35: *decimal = 5; break; - case 0x36: *decimal = 6; break; - case 0x37: *decimal = 7; break; - case 0x38: *decimal = 8; break; - case 0x39: *decimal = 9; break; - case 0x41: *decimal = 10; break; - case 0x42: *decimal = 11; break; - case 0x43: *decimal = 12; break; - case 0x44: *decimal = 13; break; - case 0x45: *decimal = 14; break; - case 0x46: *decimal = 15; break; - case 0x61: *decimal = 10; break; - case 0x62: *decimal = 11; break; - case 0x63: *decimal = 12; break; - case 0x64: *decimal = 13; break; - case 0x65: *decimal = 14; break; - case 0x66: *decimal = 15; break; - default: - return F_status_set_error(F_number); + if (character > 0x29 && character < 0x40) { + *number = 0x7 & character; + + return F_none; } - return F_none; + if (character > 0x40 && character < 0x47 || character > 0x60 && character < 0x67) { + *number = 9 + (0x7 & character); + + return F_none; + } + + return F_status_set_error(F_number); } #endif // _di_f_conversion_character_to_hexidecimal_ @@ -187,250 +158,67 @@ extern "C" { if (!number) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - switch (character) { - case 0x30: *number = 0; break; - case 0x31: *number = 1; break; - case 0x32: *number = 2; break; - case 0x33: *number = 3; break; - case 0x34: *number = 4; break; - case 0x35: *number = 5; break; - case 0x36: *number = 6; break; - case 0x37: *number = 7; break; - default: - return F_status_set_error(F_number); + if (character < 0x30 || character > 0x37) { + return F_status_set_error(F_number); } + *number = 0x7 & character; + return F_none; } #endif // _di_f_conversion_character_to_octal_ -#ifndef _di_f_conversion_number_signed_to_string_ - f_status_t f_conversion_number_signed_to_string(const f_number_signed_t number, const uint8_t base, f_string_dynamic_t *destination) { +#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_level_0_parameter_checking_ - if (!destination) return F_status_set_error(F_parameter); - if (base < 2 || base > 16) return F_status_set_error(F_parameter); + if (!output) return F_status_set_error(F_parameter); + if (data.base < 2 || data.base > 16) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - f_status_t status = F_none; - - if (!number) { - macro_f_string_dynamic_t_resize(status, (*destination), destination->used + 2); - if (F_status_is_error(status)) return status; - - destination->string[destination->used] = f_string_ascii_0_s[0]; - destination->string[destination->used + 1] = 0; - destination->used += 2; - - return F_none; - } - - bool negative = F_false; - f_number_unsigned_t current = number; - if (number < 0) { - current = 0 - number; - negative = F_true; + return private_f_conversion_digit_to_file((f_number_unsigned_t) (0 - number), data, 1, output); } - f_array_length_t total = 0; - - for (register f_number_signed_t work = current; work; ++total) { - work /= base; - } // for + 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_ - if (negative) { - macro_f_string_dynamic_t_resize(status, (*destination), destination->used + total + 2); - } - else { - macro_f_string_dynamic_t_resize(status, (*destination), destination->used + total + 1); - } +#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) { + #ifndef _di_level_0_parameter_checking_ + if (!destination) return F_status_set_error(F_parameter); + if (data.base < 2 || data.base > 16) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ - if (F_status_is_error(status)) { - return status; + if (number < 0) { + return private_f_conversion_digit_to_string((f_number_unsigned_t) (0 - number), data, 1, destination); } - f_number_unsigned_t work = 0; - f_number_unsigned_t power = 1; - - if (negative) { - destination->string[destination->used] = f_string_ascii_minus_s[0]; - ++destination->used; - } + return private_f_conversion_digit_to_string((f_number_unsigned_t) number, data, number ? 0 : 2, destination); + } +#endif // _di_f_conversion_number_signed_to_string_ - for (register uint8_t i = 1; i < total; ++i) { - power *= base; - } // for - - for (; power; --total) { - - work = current / power; - current -= work * power; - power /= base; - - switch (work) { - case 0: - destination->string[destination->used] = f_string_ascii_0_s[0]; - break; - case 1: - destination->string[destination->used] = f_string_ascii_1_s[0]; - break; - case 2: - destination->string[destination->used] = f_string_ascii_2_s[0]; - break; - case 3: - destination->string[destination->used] = f_string_ascii_3_s[0]; - break; - case 4: - destination->string[destination->used] = f_string_ascii_4_s[0]; - break; - case 5: - destination->string[destination->used] = f_string_ascii_5_s[0]; - break; - case 6: - destination->string[destination->used] = f_string_ascii_6_s[0]; - break; - case 7: - destination->string[destination->used] = f_string_ascii_7_s[0]; - break; - case 8: - destination->string[destination->used] = f_string_ascii_8_s[0]; - break; - case 9: - destination->string[destination->used] = f_string_ascii_9_s[0]; - break; - case 10: - destination->string[destination->used] = f_string_ascii_a_s[0]; - break; - case 11: - destination->string[destination->used] = f_string_ascii_b_s[0]; - break; - case 12: - destination->string[destination->used] = f_string_ascii_c_s[0]; - break; - case 13: - destination->string[destination->used] = f_string_ascii_d_s[0]; - break; - case 14: - destination->string[destination->used] = f_string_ascii_e_s[0]; - break; - case 15: - destination->string[destination->used] = f_string_ascii_f_s[0]; - break; - } - - ++destination->used; - } // for - - destination->string[destination->used] = 0; - ++destination->used; +#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_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); + #endif // _di_level_0_parameter_checking_ - return F_none; + return private_f_conversion_digit_to_file(number, data, number ? 0 : 2, output); } -#endif // _di_f_conversion_decimal_signed_to_string_ +#endif // _di_f_conversion_number_unsigned_to_file_ #ifndef _di_f_conversion_number_unsigned_to_string_ - f_status_t f_conversion_number_unsigned_to_string(const f_number_unsigned_t number, const uint8_t base, f_string_dynamic_t *destination) { + 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) { #ifndef _di_level_0_parameter_checking_ if (!destination) return F_status_set_error(F_parameter); - if (base < 2 || base > 16) return F_status_set_error(F_parameter); + if (data.base < 2 || data.base > 16) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - f_status_t status = F_none; - - if (!number) { - macro_f_string_dynamic_t_resize(status, (*destination), destination->used + 2); - if (F_status_is_error(status)) return status; - - destination->string[destination->used] = f_string_ascii_0_s[0]; - destination->string[destination->used + 1] = 0; - destination->used += 2; - - return F_none; - } - - f_array_length_t total = 0; - - for (register f_number_unsigned_t work = number; work; ++total) { - work /= base; - } // for - - macro_f_string_dynamic_t_resize(status, (*destination), destination->used + total + 1); - if (F_status_is_error(status)) return status; - - f_number_unsigned_t current = number; - f_number_unsigned_t work = 0; - f_number_unsigned_t power = 1; - - for (register uint8_t i = 1; i < total; ++i) { - power *= base; - } // for - - for (; power; --total) { - - work = current / power; - current -= work * power; - power /= base; - - switch (work) { - case 0: - destination->string[destination->used] = f_string_ascii_0_s[0]; - break; - case 1: - destination->string[destination->used] = f_string_ascii_1_s[0]; - break; - case 2: - destination->string[destination->used] = f_string_ascii_2_s[0]; - break; - case 3: - destination->string[destination->used] = f_string_ascii_3_s[0]; - break; - case 4: - destination->string[destination->used] = f_string_ascii_4_s[0]; - break; - case 5: - destination->string[destination->used] = f_string_ascii_5_s[0]; - break; - case 6: - destination->string[destination->used] = f_string_ascii_6_s[0]; - break; - case 7: - destination->string[destination->used] = f_string_ascii_7_s[0]; - break; - case 8: - destination->string[destination->used] = f_string_ascii_8_s[0]; - break; - case 9: - destination->string[destination->used] = f_string_ascii_9_s[0]; - break; - case 10: - destination->string[destination->used] = f_string_ascii_a_s[0]; - break; - case 11: - destination->string[destination->used] = f_string_ascii_b_s[0]; - break; - case 12: - destination->string[destination->used] = f_string_ascii_c_s[0]; - break; - case 13: - destination->string[destination->used] = f_string_ascii_d_s[0]; - break; - case 14: - destination->string[destination->used] = f_string_ascii_e_s[0]; - break; - case 15: - destination->string[destination->used] = f_string_ascii_f_s[0]; - break; - } - - ++destination->used; - } // for - - destination->string[destination->used] = 0; - ++destination->used; - - return F_none; + return private_f_conversion_digit_to_string(number, data, number ? 0 : 2, destination); } -#endif // _di_f_conversion_decimal_unsigned_to_string_ +#endif // _di_f_conversion_number_unsigned_to_string_ #ifdef __cplusplus } // extern "C" diff --git a/level_0/f_conversion/c/conversion.h b/level_0/f_conversion/c/conversion.h index a6d71d3..82519ce 100644 --- a/level_0/f_conversion/c/conversion.h +++ b/level_0/f_conversion/c/conversion.h @@ -12,6 +12,7 @@ // libc includes #include +#include #include // fll-0 includes @@ -196,14 +197,42 @@ extern "C" { /** * Convert a signed number into the decimal digit string that it represents. * + * The generated number is printed to the file stream. + * + * This only supports the following base units: 2 through 16. + * This only supports base prefixes for: 2, 8, 10, 12, and 16. + * + * @param number + * The number to convert. + * @param data + * The settings designating how to perform the conversion. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none if the number was converted to a string. + * + * F_output (with error bit) on fputc() error. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc() + */ +#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_ + +/** + * Convert a signed number into the decimal digit string that it represents. + * * The generated number is appended to the destination string. * * This only supports the following base units: 2 through 16. + * This only supports base prefixes for: 2, 8, 10, 12, and 16. * * @param number * The number to convert. - * @param base - * The base unit, usually 10. + * @param data + * The settings designating how to perform the conversion. * @param destination * The destination the converted string is saved into. * @@ -211,23 +240,56 @@ extern "C" { * F_none if the number was converted to a string. * * F_parameter (with error bit) if a parameter is invalid. - * F_memory_not (with error bit) on out of memory. + * + * Errors (with error bit) from: f_string_dynamic_resize() + * + * @see f_string_dynamic_resize() */ #ifndef _di_f_conversion_number_signed_to_string_ - extern f_status_t f_conversion_number_signed_to_string(const f_number_signed_t number, const uint8_t base, f_string_dynamic_t *destination); + extern 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); #endif // _di_f_conversion_number_signed_to_string_ /** * Convert an unsigned number into the decimal digit string that it represents. * + * The generated number is printed to the file stream. + * + * This only supports the following base units: 2 through 16. + * This only supports base prefixes for: 2, 8, 10, 12, and 16. + * + * @param number + * The number to convert. + * This number is unsigned to allow for unsigned integers to be used. + * To represent a negative number, assign the flag f_conversion_data_flag_is_negative to data.flags. + * @param data + * The settings designating how to perform the conversion. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none if the number was converted to a string. + * + * F_output (with error bit) on fputc() error. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc() + */ +#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_ + +/** + * Convert an unsigned number into the decimal digit string that it represents. + * * The generated number is appended to the destination string. * * This only supports the following base units: 2 through 16. + * This only supports base prefixes for: 2, 8, 10, 12, and 16. * * @param number * The number to convert. - * @param base - * The base unit, usually 10. + * @param data + * The settings designating how to perform the conversion. * @param destination * The destination the converted string is saved into. * @@ -235,10 +297,13 @@ extern "C" { * F_none if the number was converted to a string. * * F_parameter (with error bit) if a parameter is invalid. - * F_memory_not (with error bit) on out of memory. + * + * Errors (with error bit) from: f_string_dynamic_resize() + * + * @see f_string_dynamic_resize() */ #ifndef _di_f_conversion_number_unsigned_to_string_ - extern f_status_t f_conversion_number_unsigned_to_string(const f_number_unsigned_t number, const uint8_t base, f_string_dynamic_t *destination); + extern 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); #endif // _di_f_conversion_number_unsigned_to_string_ #ifdef __cplusplus diff --git a/level_0/f_conversion/c/private-conversion.c b/level_0/f_conversion/c/private-conversion.c new file mode 100644 index 0000000..025bdb4 --- /dev/null +++ b/level_0/f_conversion/c/private-conversion.c @@ -0,0 +1,528 @@ +#include "conversion.h" +#include "private-conversion.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#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) { + + int digits = 0; + + for (register f_number_unsigned_t remaining = number; remaining; ++digits) { + remaining /= data.base; + } // for + + if (data.flag & f_conversion_data_flag_base_prepend) { + const int used = digits + 2 + (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) { + if (F_status_is_error(private_f_conversion_digit_to_file_prefix(data, negative, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_pad(data, f_string_ascii_0_s[0], data.width - used, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_number(data, number, digits, output))) { + return F_status_set_error(F_output); + } + } + else { + if (F_status_is_error(private_f_conversion_digit_to_file_pad(data, f_string_ascii_space_s[0], data.width - used, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_prefix(data, negative, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_number(data, number, digits, output))) { + return F_status_set_error(F_output); + } + } + } + else if (number) { + if (F_status_is_error(private_f_conversion_digit_to_file_prefix(data, negative, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_number(data, number, digits, output))) { + return F_status_set_error(F_output); + } + } + else if (data.width) { + if (F_status_is_error(private_f_conversion_digit_to_file_prefix(data, negative, output))) { + return F_status_set_error(F_output); + } + + if (!fputc(f_string_ascii_0_s[0], output)) { + return F_status_set_error(F_output); + } + } + } + else { + 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) { + if (F_status_is_error(private_f_conversion_digit_to_file_prefix(data, negative, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_pad(data, f_string_ascii_0_s[0], data.width - used, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_number(data, number, digits, output))) { + return F_status_set_error(F_output); + } + } + else { + if (F_status_is_error(private_f_conversion_digit_to_file_pad(data, f_string_ascii_space_s[0], data.width - used, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_prefix(data, negative, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_number(data, number, digits, output))) { + return F_status_set_error(F_output); + } + } + } + else if (number) { + if (F_status_is_error(private_f_conversion_digit_to_file_prefix(data, negative, output))) { + return F_status_set_error(F_output); + } + + if (F_status_is_error(private_f_conversion_digit_to_file_number(data, number, digits, output))) { + return F_status_set_error(F_output); + } + } + else if (data.width) { + if (!fputc(f_string_ascii_0_s[0], output)) { + 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_) + +#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_number(const f_conversion_data_t data, f_number_unsigned_t number, int digits, FILE *output) { + + f_number_unsigned_t power = 1; + + for (register uint8_t i = 1; i < digits; ++i) { + power *= data.base; + } // for + + f_number_unsigned_t current = number; + f_number_unsigned_t work = 0; + + for (char c = 0; power; --power) { + + work = current / power; + current -= work * power; + power /= data.base; + + switch (number) { + case 0: + c = f_string_ascii_0_s[0]; + break; + + case 1: + c = f_string_ascii_1_s[0]; + break; + + case 2: + c = f_string_ascii_2_s[0]; + break; + + case 3: + c = f_string_ascii_3_s[0]; + break; + + case 4: + c = f_string_ascii_4_s[0]; + break; + + case 5: + c = f_string_ascii_5_s[0]; + break; + + case 6: + c = f_string_ascii_6_s[0]; + break; + + case 7: + c = f_string_ascii_7_s[0]; + break; + + case 8: + c = f_string_ascii_8_s[0]; + break; + + case 9: + c = f_string_ascii_9_s[0]; + break; + + case 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: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_B_s[0] : f_string_ascii_b_s[0]; + break; + + case 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: + 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; + } + + if (c && !fputc(c, output)) { + 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_) + +#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_pad(const f_conversion_data_t data, const char pad, int total, FILE *output) { + + for (; total; --total) { + + if (!fputc(pad, output)) { + 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_) + +#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_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)) { + 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)) { + 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)) { + 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)) { + return F_status_set_error(F_output); + } + + char c = 0; + + switch (data.base) { + case 2: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_B_s[0] : f_string_ascii_b_s[0]; + break; + + case 8: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_O_s[0] : f_string_ascii_o_s[0]; + break; + + case 10: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_T_s[0] : f_string_ascii_t_s[0]; + break; + + case 12: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_D_s[0] : f_string_ascii_d_s[0]; + break; + + case 16: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_X_s[0] : f_string_ascii_x_s[0]; + break; + + default: + break; + } + + if (c && !fputc(c, output)) { + 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_) + +#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) { + + int digits = 0; + + for (register f_number_unsigned_t remaining = number; remaining; ++digits) { + remaining /= data.base; + } // for + + // Ensure there is enough space for pad, adding the sign (1) and the prepend units (2). + { + long max = 3; + + if (digits > data.width) { + max += digits; + } + else { + max += data.width; + } + + if (destination->used + max > destination->size) { + const f_status_t status = f_string_dynamic_resize(destination->used + max, destination); + if (F_status_is_error(status)) return status; + } + } + + if (data.flag & f_conversion_data_flag_base_prepend) { + const int used = digits + 2 + (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) { + private_f_conversion_digit_to_string_prefix(data, negative, destination); + private_f_conversion_digit_to_string_pad(data, f_string_ascii_0_s[0], data.width - used, destination); + private_f_conversion_digit_to_string_number(data, number, digits, destination); + } + else { + private_f_conversion_digit_to_string_pad(data, f_string_ascii_space_s[0], data.width - used, destination); + private_f_conversion_digit_to_string_prefix(data, negative, destination); + private_f_conversion_digit_to_string_number(data, number, digits, destination); + } + } + else if (number) { + private_f_conversion_digit_to_string_prefix(data, negative, destination); + private_f_conversion_digit_to_string_number(data, number, digits, destination); + } + else if (data.width) { + private_f_conversion_digit_to_string_prefix(data, negative, destination); + + destination->string[destination->used++] = f_string_ascii_0_s[0]; + } + } + else { + 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) { + private_f_conversion_digit_to_string_prefix(data, negative, destination); + private_f_conversion_digit_to_string_pad(data, f_string_ascii_0_s[0], data.width - used, destination); + private_f_conversion_digit_to_string_number(data, number, digits, destination); + } + else { + private_f_conversion_digit_to_string_pad(data, f_string_ascii_space_s[0], data.width - used, destination); + private_f_conversion_digit_to_string_prefix(data, negative, destination); + private_f_conversion_digit_to_string_number(data, number, digits, destination); + } + } + else if (number) { + private_f_conversion_digit_to_string_prefix(data, negative, destination); + private_f_conversion_digit_to_string_number(data, number, digits, destination); + } + else if (data.width) { + destination->string[destination->used++] = f_string_ascii_0_s[0]; + } + } + + return F_none; + } +#endif // !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + +#if !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + void private_f_conversion_digit_to_string_number(const f_conversion_data_t data, f_number_unsigned_t number, int digits, f_string_dynamic_t *destination) { + + f_number_unsigned_t power = 1; + + for (register uint8_t i = 1; i < digits; ++i) { + power *= data.base; + } // for + + f_number_unsigned_t current = number; + f_number_unsigned_t work = 0; + + for (char c = 0; power; --power) { + + work = current / power; + current -= work * power; + power /= data.base; + + switch (number) { + case 0: + c = f_string_ascii_0_s[0]; + break; + + case 1: + c = f_string_ascii_1_s[0]; + break; + + case 2: + c = f_string_ascii_2_s[0]; + break; + + case 3: + c = f_string_ascii_3_s[0]; + break; + + case 4: + c = f_string_ascii_4_s[0]; + break; + + case 5: + c = f_string_ascii_5_s[0]; + break; + + case 6: + c = f_string_ascii_6_s[0]; + break; + + case 7: + c = f_string_ascii_7_s[0]; + break; + + case 8: + c = f_string_ascii_8_s[0]; + break; + + case 9: + c = f_string_ascii_9_s[0]; + break; + + case 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: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_B_s[0] : f_string_ascii_b_s[0]; + break; + + case 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: + 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; + } + + if (c) { + destination->string[destination->used++] = c; + } + } // for + } +#endif // !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + +#if !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + void private_f_conversion_digit_to_string_pad(const f_conversion_data_t data, const char pad, int total, f_string_dynamic_t *destination) { + + for (; total; --total) { + destination->string[destination->used++] = pad; + } // for + } +#endif // !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + +#if !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + void private_f_conversion_digit_to_string_prefix(const f_conversion_data_t data, const uint8_t negative, f_string_dynamic_t *destination) { + + if (negative) { + if (negative == 1) { + destination->string[destination->used++] = f_string_ascii_minus_s[0]; + } + } + else if (data.flag & f_conversion_data_flag_sign_always) { + destination->string[destination->used++] = f_string_ascii_plus_s[0]; + } + else if (data.flag & f_conversion_data_flag_sign_pad) { + destination->string[destination->used++] = f_string_ascii_space_s[0]; + } + + if (data.flag & f_conversion_data_flag_base_prepend) { + destination->string[destination->used++] = f_string_ascii_0_s[0]; + + char c = 0; + + switch (data.base) { + case 2: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_B_s[0] : f_string_ascii_b_s[0]; + break; + + case 8: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_O_s[0] : f_string_ascii_o_s[0]; + break; + + case 10: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_T_s[0] : f_string_ascii_t_s[0]; + break; + + case 12: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_D_s[0] : f_string_ascii_d_s[0]; + break; + + case 16: + c = data.flag & f_conversion_data_flag_base_upper ? f_string_ascii_X_s[0] : f_string_ascii_x_s[0]; + break; + + default: + break; + } + + if (c) { + destination->string[destination->used++] = c; + } + } + } +#endif // !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_conversion/c/private-conversion.h b/level_0/f_conversion/c/private-conversion.h new file mode 100644 index 0000000..cb3b43b --- /dev/null +++ b/level_0/f_conversion/c/private-conversion.h @@ -0,0 +1,240 @@ +/** + * FLL - Level 0 + * + * Project: Conversion + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * Provide means to convert one data type to another, such as a string to an integer. + */ +#ifndef _PRIVATE_F_conversion_h +#define _PRIVATE_F_conversion_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Helper function for performing the entire process of printing to the output file. + * + * @param number + * The number to convert. + * @param data + * The settings designating how to perform the conversion. + * @param negative + * Designate that this number is to be represented as a negative number (or is zero). + * + * Set this to 0 to represent a positive number. + * Set this to 1 to represent a negative number. + * Set this to 2 to represent the number 0; + * @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 to print to the output file. + * + * @see fputc() + * + * @see f_conversion_number_signed_to_file() + * @see f_conversion_number_unsigned_to_file() + * + * @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_) + 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_) + +/** + * Helper function for printing the number to the output file. + * + * @param data + * The settings designating how to perform the conversion. + * @param number + * The number to convert. + * This number is unsigned to allow for unsigned integers to be used. + * To represent a negative number, assign the flag f_conversion_data_flag_is_negative to data.flags. + * @param digits + * The number of digits the number is represented by (based on the base unit). + * @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 to print to the output file. + * + * @see fputc() + * + * @see f_conversion_number_signed_to_file() + * @see f_conversion_number_unsigned_to_file() + */ +#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) + 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_) + +/** + * Helper function for printing the padding to the output file. + * + * @param data + * The settings designating how to perform the conversion. + * @param pad + * The character to print as the padding character. + * Should be either f_string_ascii_space_s[0] or f_string_ascii_0_s[0]. + * @param total + * The total number of times to print the pad. + * @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 to print to the output file. + * + * @see fputc() + * + * @see f_conversion_number_signed_to_file() + * @see f_conversion_number_unsigned_to_file() + */ +#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) + 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_) + +/** + * Helper function for printing the prefix to the output file. + * + * @param data + * The settings designating how to perform the conversion. + * @param negative + * Designate that this number is to be represented as a negative number (or is zero). + * + * Set this to 0 to represent a positive number. + * Set this to 1 to represent a negative number. + * Set this to 2 to represent the number 0; + * @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 to print to the output file. + * + * @see fputc() + * + * @see f_conversion_number_signed_to_file() + * @see f_conversion_number_unsigned_to_file() + */ +#if !defined(_di_f_conversion_number_signed_to_file_) || !defined(_di_f_conversion_number_unsigned_to_file_) + 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_) + +/** + * Helper function for performing the entire process of printing to the output file. + * + * @param number + * The number to convert. + * @param data + * The settings designating how to perform the conversion. + * @param negative + * Designate that this number is to be represented as a negative number (or is zero). + * + * Set this to 0 to represent a positive number. + * Set this to 1 to represent a negative number. + * Set this to 2 to represent the number 0; + * @param output + * + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_string_dynamic_resize() + * + * @see f_conversion_number_signed_to_string() + * @see f_conversion_number_unsigned_to_string() + * + * @see private_f_conversion_digit_to_string_number() + * @see private_f_conversion_digit_to_string_pad() + * @see private_f_conversion_digit_to_string_prefix() + */ +#if !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + extern 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) f_attribute_visibility_internal; +#endif // !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + +/** + * Helper function for printing the number to the output file. + * + * @param data + * The settings designating how to perform the conversion. + * @param number + * The number to convert. + * This number is unsigned to allow for unsigned integers to be used. + * To represent a negative number, assign the flag f_conversion_data_flag_is_negative to data.flags. + * @param digits + * The number of digits the number is represented by (based on the base unit). + * @param output + * + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @see f_conversion_number_signed_to_string() + * @see f_conversion_number_unsigned_to_string() + */ +#if !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + extern void private_f_conversion_digit_to_string_number(const f_conversion_data_t data, f_number_unsigned_t number, int digits, f_string_dynamic_t *destination) f_attribute_visibility_internal; +#endif // !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + +/** + * Helper function for printing the padding to the output file. + * + * @param data + * The settings designating how to perform the conversion. + * @param pad + * The character to print as the padding character. + * Should be either f_string_ascii_space_s[0] or f_string_ascii_0_s[0]. + * @param total + * The total number of times to print the pad. + * @param output + * + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @see f_conversion_number_signed_to_string() + * @see f_conversion_number_unsigned_to_string() + */ +#if !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + extern void private_f_conversion_digit_to_string_pad(const f_conversion_data_t data, const char pad, int total, f_string_dynamic_t *destination) f_attribute_visibility_internal; +#endif // !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + +/** + * Helper function for printing the prefix to the output file. + * + * @param data + * The settings designating how to perform the conversion. + * @param negative + * Designate that this number is to be represented as a negative number (or is zero). + * + * Set this to 0 to represent a positive number. + * Set this to 1 to represent a negative number. + * Set this to 2 to represent the number 0; + * @param output + * + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @see f_conversion_number_signed_to_string() + * @see f_conversion_number_unsigned_to_string() + */ +#if !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + extern void private_f_conversion_digit_to_string_prefix(const f_conversion_data_t data, const uint8_t negative, f_string_dynamic_t *destination) f_attribute_visibility_internal; +#endif // !defined(_di_f_conversion_number_signed_to_string_) || !defined(_di_f_conversion_number_unsigned_to_string_) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_F_conversion_h diff --git a/level_0/f_conversion/data/build/settings b/level_0/f_conversion/data/build/settings index 524cf05..707959a 100644 --- a/level_0/f_conversion/data/build/settings +++ b/level_0/f_conversion/data/build/settings @@ -21,7 +21,7 @@ build_indexer ar build_language c build_libraries -lc build_libraries-individual -lf_memory -lf_string -lf_utf -build_sources_library conversion.c +build_sources_library conversion.c private-conversion.c build_sources_program build_sources_headers conversion.h conversion-common.h build_sources_script diff --git a/level_0/f_fss/data/build/settings b/level_0/f_fss/data/build/settings index 99bb9a8..f5a0649 100644 --- a/level_0/f_fss/data/build/settings +++ b/level_0/f_fss/data/build/settings @@ -23,7 +23,7 @@ build_libraries -lc build_libraries-individual -lf_memory -lf_string -lf_type_array -lf_utf build_sources_library fss.c private-fss.c fss-common.c fss_named.c fss_nest.c fss_set.c build_sources_program -build_sources_headers fss.h private-fss.h fss-common.h fss_comment.h fss_delimit.h fss_named.h fss_nest.h fss_quote.h fss_set.h +build_sources_headers fss.h fss-common.h fss_comment.h fss_delimit.h fss_named.h fss_nest.h fss_quote.h fss_set.h build_sources_script build_sources_setting build_script yes diff --git a/level_0/f_print/c/print-common.c b/level_0/f_print/c/print-common.c new file mode 100644 index 0000000..c80ec9a --- /dev/null +++ b/level_0/f_print/c/print-common.c @@ -0,0 +1,49 @@ +#include "print.h" +#include "private-print.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_f_print_sequences_ + const f_string_t f_print_sequence_acknowledge_s = f_print_sequence_acknowledge; + const f_string_t f_print_sequence_backspace_s = f_print_sequence_backspace; + const f_string_t f_print_sequence_bell_s = f_print_sequence_bell; + const f_string_t f_print_sequence_cancel_s = f_print_sequence_cancel; + const f_string_t f_print_sequence_carriage_return_s = f_print_sequence_carriage_return; + const f_string_t f_print_sequence_data_link_escape_s = f_print_sequence_data_link_escape; + const f_string_t f_print_sequence_delete_s = f_print_sequence_delete; + const f_string_t f_print_sequence_device_control_1_s = f_print_sequence_device_control_1; + const f_string_t f_print_sequence_device_control_2_s = f_print_sequence_device_control_2; + const f_string_t f_print_sequence_device_control_3_s = f_print_sequence_device_control_3; + const f_string_t f_print_sequence_device_control_4_s = f_print_sequence_device_control_4; + const f_string_t f_print_sequence_end_of_enquiry_s = f_print_sequence_end_of_enquiry; + const f_string_t f_print_sequence_end_of_medium_s = f_print_sequence_end_of_medium; + const f_string_t f_print_sequence_end_of_text_s = f_print_sequence_end_of_text; + const f_string_t f_print_sequence_end_of_transmission_s = f_print_sequence_end_of_transmission; + const f_string_t f_print_sequence_end_of_transmission_block_s = f_print_sequence_end_of_transmission_block; + const f_string_t f_print_sequence_escape_s = f_print_sequence_escape; + const f_string_t f_print_sequence_file_separator_s = f_print_sequence_file_separator; + const f_string_t f_print_sequence_form_feed_s = f_print_sequence_form_feed; + const f_string_t f_print_sequence_group_separator_s = f_print_sequence_group_separator; + const f_string_t f_print_sequence_line_feed_s = f_print_sequence_line_feed; + const f_string_t f_print_sequence_negative_acknowledge_s = f_print_sequence_negative_acknowledge; + const f_string_t f_print_sequence_new_line_s = f_print_sequence_new_line; + const f_string_t f_print_sequence_null_s = f_print_sequence_null; + const f_string_t f_print_sequence_record_separator_s = f_print_sequence_record_separator; + const f_string_t f_print_sequence_shift_in_s = f_print_sequence_shift_in; + const f_string_t f_print_sequence_shift_out_s = f_print_sequence_shift_out; + const f_string_t f_print_sequence_space_s = f_print_sequence_space; + const f_string_t f_print_sequence_start_of_header_s = f_print_sequence_start_of_header; + const f_string_t f_print_sequence_start_of_text_s = f_print_sequence_start_of_text; + const f_string_t f_print_sequence_substitute_s = f_print_sequence_substitute; + const f_string_t f_print_sequence_synchronous_idle_s = f_print_sequence_synchronous_idle; + const f_string_t f_print_sequence_tab_s = f_print_sequence_tab; + const f_string_t f_print_sequence_tab_vertical_s = f_print_sequence_tab_vertical; + const f_string_t f_print_sequence_unit_separator_s = f_print_sequence_unit_separator; + const f_string_t f_print_sequence_unknown_s = f_print_sequence_unknown; +#endif // _di_f_print_sequences_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_print/c/print-common.h b/level_0/f_print/c/print-common.h new file mode 100644 index 0000000..fb9fa78 --- /dev/null +++ b/level_0/f_print/c/print-common.h @@ -0,0 +1,216 @@ +/** + * FLL - Level 0 + * + * Project: Print + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * Defines common data to be used for/by project print. + * + * This is auto-included by print.h and should not need to be explicitly included. + */ +#ifndef _F_print_common_h +#define _F_print_common_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Defines the maximum length supported by write() for use in printing. + * + * This is documented in the man write(2) pages under Linux to being 0x7ffff000 regardless of 32-bit or 64-bit. + */ +#ifndef _di_f_print_write_max_ + #define f_print_write_max 0x7ffff000 +#endif // _di_f_print_write_max_ + +/** + * Common print sequences. + * + * These are sequences only used by the print function and do not represent all possible sequences. + * + * All characters here are longer than 1-byte. + * The ones used here are 3-bytes wide. + * + * The code currently expects these to be 3-bytes wide so changing this to any other width will require changing code that utilizes these. + */ +#ifndef _di_f_print_sequences_ + #define f_print_sequence_acknowledge "␆" + #define f_print_sequence_backspace "␈" + #define f_print_sequence_bell "␇" + #define f_print_sequence_cancel "␘" + #define f_print_sequence_carriage_return "␍" + #define f_print_sequence_data_link_escape "␐" + #define f_print_sequence_delete "␡" + #define f_print_sequence_device_control_1 "␑" + #define f_print_sequence_device_control_2 "␒" + #define f_print_sequence_device_control_3 "␓" + #define f_print_sequence_device_control_4 "␔" + #define f_print_sequence_end_of_enquiry "␅" + #define f_print_sequence_end_of_medium "␙" + #define f_print_sequence_end_of_text "␃" + #define f_print_sequence_end_of_transmission "␄" + #define f_print_sequence_end_of_transmission_block "␗" + #define f_print_sequence_escape "␛" + #define f_print_sequence_file_separator "␜" + #define f_print_sequence_form_feed "␌" + #define f_print_sequence_group_separator "␝" + #define f_print_sequence_line_feed "␊" + #define f_print_sequence_negative_acknowledge "␕" + #define f_print_sequence_new_line "␤" + #define f_print_sequence_null "␀" + #define f_print_sequence_record_separator "␞" + #define f_print_sequence_shift_in "␏" + #define f_print_sequence_shift_out "␎" + #define f_print_sequence_space "␠" + #define f_print_sequence_start_of_header "␁" + #define f_print_sequence_start_of_text "␂" + #define f_print_sequence_substitute "␚" + #define f_print_sequence_synchronous_idle "␖" + #define f_print_sequence_tab "␉" + #define f_print_sequence_tab_vertical "␋" + #define f_print_sequence_unit_separator "␟" + #define f_print_sequence_unknown "�" + + extern const f_string_t f_print_sequence_acknowledge_s; + extern const f_string_t f_print_sequence_backspace_s; + extern const f_string_t f_print_sequence_bell_s; + extern const f_string_t f_print_sequence_cancel_s; + extern const f_string_t f_print_sequence_carriage_return_s; + extern const f_string_t f_print_sequence_data_link_escape_s; + extern const f_string_t f_print_sequence_delete_s; + extern const f_string_t f_print_sequence_device_control_1_s; + extern const f_string_t f_print_sequence_device_control_2_s; + extern const f_string_t f_print_sequence_device_control_3_s; + extern const f_string_t f_print_sequence_device_control_4_s; + extern const f_string_t f_print_sequence_end_of_enquiry_s; + extern const f_string_t f_print_sequence_end_of_medium_s; + extern const f_string_t f_print_sequence_end_of_text_s; + extern const f_string_t f_print_sequence_end_of_transmission_s; + extern const f_string_t f_print_sequence_end_of_transmission_block_s; + extern const f_string_t f_print_sequence_escape_s; + extern const f_string_t f_print_sequence_file_separator_s; + extern const f_string_t f_print_sequence_form_feed_s; + extern const f_string_t f_print_sequence_group_separator_s; + extern const f_string_t f_print_sequence_line_feed_s; + extern const f_string_t f_print_sequence_negative_acknowledge_s; + extern const f_string_t f_print_sequence_new_line_s; + extern const f_string_t f_print_sequence_null_s; + extern const f_string_t f_print_sequence_record_separator_s; + extern const f_string_t f_print_sequence_shift_in_s; + extern const f_string_t f_print_sequence_shift_out_s; + extern const f_string_t f_print_sequence_space_s; + extern const f_string_t f_print_sequence_start_of_header_s; + extern const f_string_t f_print_sequence_start_of_text_s; + extern const f_string_t f_print_sequence_substitute_s; + extern const f_string_t f_print_sequence_synchronous_idle_s; + extern const f_string_t f_print_sequence_tab_s; + extern const f_string_t f_print_sequence_tab_vertical_s; + extern const f_string_t f_print_sequence_unit_separator_s; + extern const f_string_t f_print_sequence_unknown_s; +#endif // _di_f_print_sequences_ + +/** + * Provide basic format flags. + * + * f_print_format_flag_*: + * - align_left: "-", Use left-justification. + * - convert: "#", Use alternate form conversion (prefixing 0b/0B, 0o/0O, 0t/0T, 0d/0D, 0x/0X). + * - ignore_index: "(", Ignore characters in the given positions from a f_array_length_t (only applies to string arguments but not character arguments). + * - ignore_range: ")", Ignore characters in the given ranges from a f_string_range_t (only applies to string arguments but not character arguments). + * - precision: Designates that a precision is in use. + * - sign_always: "+", Always show the signs (+ or -). + * - sign_pad: " ", Add a space where a sign would be if the sign is not displayed. + * - trim: "=", Trim leading and trailing whitespaces (only applies to string arguments but not character arguments). + * - uppercase: Display any base units as uppercase. + * - width: Designates that a width is in use. + * - zeros_leading: "0", Use leading zeros. + * + * @see fprintf() + */ +#ifndef _di_f_print_format_flag_ + #define f_print_format_flag_align_left 0x1 + #define f_print_format_flag_convert 0x2 + #define f_print_format_flag_ignore_index 0x4 + #define f_print_format_flag_ignore_range 0x8 + #define f_print_format_flag_precision 0x10 + #define f_print_format_flag_sign_always 0x20 + #define f_print_format_flag_sign_pad 0x40 + #define f_print_format_flag_trim 0x80 + #define f_print_format_flag_uppercase 0x100 + #define f_print_format_flag_width 0x200 + #define f_print_format_flag_zeros_leading 0x400 +#endif // _di_f_print_format_flags_ + +/** + * Provide base format flags. + * + * f_print_format_base_*: + * - binary: "!", Display number in Binary notation. + * - octal: "@", Display number in Octal notation. + * - decimal: "^", Display number in Octal notation. + * - duodecimal: "&", Display number in Duodecimal notation. + * - hexidecimal: "_", Display number in Hexidecimal notation. + * + * @see fprintf() + */ + +/** + * Provide type format flags. + * + * The uppercase "I", "L", "LL", "UL", "ULL" designates setting the uppercase flag. + * + * f_print_format_type_*: + * - character: "c", type is a 1-byte unsigned character. + * - character_safe: "C", type is a 1-byte unsigned character, where control characters and other problems are handled. + * - long: "l", "L", type is a signed integer. + * - long_long: "ll", "LL", type is a signed integer. + * - number: "n", "N", type is an f_number_signed_t. + * - signed: "i", "I", type is a signed integer. + * - signed_16: "ii", "II", type is a signed int16_t. + * - signed_8: "iii", "III", type is a signed integer. + * - size: "z", "Z", type is a size_t. + * - string_safe: "S", type is a NULL terminated string, where control characters and other problems are handled. + * - string_static: "q", type is an f_string_static_t or f_string_dynamic_t and NULLs are ignored (not printed). + * - string_static_raw: "r", type is an f_string_static_t or f_string_dynamic_t and NULLs (and all other control characters) are printed. + * - string_static_safe: "Q", type is an f_string_static_t or f_string_dynamic_t and NULLs are printed, where control characters and other problems are handled. + * - unsigned: "u", "U", type is an unsigned integer. + * - unsigned_16: "ui", "UI", type is an uint16_t. + * - unsigned_8: "uii", "UII", type is an uint8_t. + * - unsigned_long: "ul", "UL", type is an unsigned long. + * - unsigned_long_long: "ull", "ULL", type is an unsigned long long. + * - unsigned_number: "un", "UN", type is an f_number_unsigned_t. + * + * @see fprintf() + */ +#ifndef _di_f_print_format_type_ + enum { + f_print_format_type_character = 1, + f_print_format_type_character_safe, + f_print_format_type_long, + f_print_format_type_long_long, + f_print_format_type_number, + f_print_format_type_signed, + f_print_format_type_signed_16, + f_print_format_type_signed_8, + f_print_format_type_size, + f_print_format_type_string, + f_print_format_type_string_safe, + f_print_format_type_string_static, + f_print_format_type_string_static_raw, + f_print_format_type_string_static_safe, + f_print_format_type_unsigned, + f_print_format_type_unsigned_16, + f_print_format_type_unsigned_8, + f_print_format_type_unsigned_long, + f_print_format_type_unsigned_long_long, + f_print_format_type_unsigned_number, + }; +#endif // _di_f_print_format_type_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _F_print_common_h diff --git a/level_0/f_print/c/print.c b/level_0/f_print/c/print.c index 021a59c..d29b926 100644 --- a/level_0/f_print/c/print.c +++ b/level_0/f_print/c/print.c @@ -6,7 +6,7 @@ extern "C" { #endif #ifndef _di_f_print_ - f_status_t f_print(FILE *output, const f_string_t string, const f_array_length_t length) { + f_status_t f_print(const f_string_t string, const f_array_length_t length, FILE *output) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -15,31 +15,75 @@ extern "C" { return F_data_not; } - return private_f_print(output, string, length); + return private_f_print(string, length, output); } #endif // _di_f_print_ +#ifndef _di_f_print_character_safely_ + f_status_t f_print_character_safely(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_ + + return private_f_print_character_safely(character, output); + } +#endif // _di_f_print_character_safely_ + +#ifndef _di_f_print_character_safely_get_ + f_string_t f_print_character_safely_get(const char character) { + return private_f_print_character_safely_get(character); + } +#endif // _di_f_print_character_safely_get_ + #ifndef _di_f_print_dynamic_ - f_status_t f_print_dynamic(FILE *output, const f_string_static_t buffer) { + f_status_t f_print_dynamic(const f_string_static_t buffer, FILE *output) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used) { + if (!buffer.string || !buffer.used) { return F_data_not; } - return private_f_print(output, buffer.string, buffer.used); + return private_f_print(buffer.string, buffer.used, output); } #endif // _di_f_print_dynamic_ +#ifndef _di_f_print_dynamic_raw_ + f_status_t f_print_dynamic_raw(const f_string_static_t buffer, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) { + return F_data_not; + } + + return private_f_print_raw(buffer.string, buffer.used, output); + } +#endif // _di_f_print_dynamic_raw_ + +#ifndef _di_f_print_dynamic_safely_ + f_status_t f_print_dynamic_safely(const f_string_static_t buffer, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) { + return F_data_not; + } + + return private_f_print_safely(buffer.string, buffer.used, output); + } +#endif // _di_f_print_dynamic_safely_ + #ifndef _di_f_print_dynamic_partial_ - f_status_t f_print_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range) { + f_status_t f_print_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, FILE *output) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { return F_data_not; } @@ -49,12 +93,52 @@ extern "C" { length = buffer.used - range.start; } - return private_f_print(output, buffer.string + range.start, length); + return private_f_print(buffer.string + range.start, length, output); } #endif // _di_f_print_dynamic_partial_ +#ifndef _di_f_print_dynamic_partial_raw_ + f_status_t f_print_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_raw(buffer.string + range.start, length, output); + } +#endif // _di_f_print_dynamic_partial_raw_ + +#ifndef _di_f_print_dynamic_partial_safely_ + f_status_t f_print_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_safely(buffer.string + range.start, length, output); + } +#endif // _di_f_print_dynamic_partial_safely_ + #ifndef _di_f_print_except_ - f_status_t f_print_except(FILE *output, const f_string_t string, const f_array_length_t length, const f_array_lengths_t except) { + 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) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -63,24 +147,76 @@ extern "C" { return F_data_not; } - return private_f_print_except(output, string, 0, length, except); + return private_f_print_except(string, 0, length, except, output); } #endif // _di_f_print_except_ +#ifndef _di_f_print_except_raw_ + 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) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || length == 0) { + return F_data_not; + } + + return private_f_print_except_raw(string, 0, length, except, output); + } +#endif // _di_f_print_except_raw_ + +#ifndef _di_f_print_except_safely_ + f_status_t f_print_except_safely(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || length == 0) { + return F_data_not; + } + + return private_f_print_except_safely(string, 0, length, except, output); + } +#endif // _di_f_print_except_safely_ + #ifndef _di_f_print_except_dynamic_ - f_status_t f_print_except_dynamic(FILE *output, const f_string_static_t buffer, const f_array_lengths_t except) { + f_status_t f_print_except_dynamic(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used) return F_data_not; + if (!buffer.string || !buffer.used) return F_data_not; - return private_f_print_except(output, buffer.string, 0, buffer.used, except); + return private_f_print_except(buffer.string, 0, buffer.used, except, output); } #endif // _di_f_print_except_dynamic_ +#ifndef _di_f_print_except_dynamic_raw_ + f_status_t f_print_except_dynamic_raw(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) return F_data_not; + + return private_f_print_except_raw(buffer.string, 0, buffer.used, except, output); + } +#endif // _di_f_print_except_dynamic_raw_ + +#ifndef _di_f_print_except_dynamic_safely_ + f_status_t f_print_except_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) return F_data_not; + + return private_f_print_except_safely(buffer.string, 0, buffer.used, except, output); + } +#endif // _di_f_print_except_dynamic_safely_ + #ifndef _di_f_print_except_in_ - f_status_t f_print_except_in(FILE *output, 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) { + 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) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -89,29 +225,81 @@ extern "C" { return F_data_not; } - return private_f_print_except_in(output, string, 0, length, except_at, except_in); + return private_f_print_except_in(string, 0, length, except_at, except_in, output); } #endif // _di_f_print_except_in_ +#ifndef _di_f_print_except_in_raw_ + 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) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || length == 0) { + return F_data_not; + } + + return private_f_print_except_in_raw(string, 0, length, except_at, except_in, output); + } +#endif // _di_f_print_except_in_raw_ + +#ifndef _di_f_print_except_in_safely_ + f_status_t f_print_except_in_safely(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) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || length == 0) { + return F_data_not; + } + + return private_f_print_except_in_safely(string, 0, length, except_at, except_in, output); + } +#endif // _di_f_print_except_in_safely_ + #ifndef _di_f_print_except_in_dynamic_ - f_status_t f_print_except_in_dynamic(FILE *output, const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in) { + 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) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used) return F_data_not; + if (!buffer.string || !buffer.used) return F_data_not; - return private_f_print_except_in(output, buffer.string, 0, buffer.used, except_at, except_in); + return private_f_print_except_in(buffer.string, 0, buffer.used, except_at, except_in, output); } #endif // _di_f_print_except_in_dynamic_ +#ifndef _di_f_print_except_in_dynamic_raw_ + 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) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) return F_data_not; + + return private_f_print_except_in_raw(buffer.string, 0, buffer.used, except_at, except_in, output); + } +#endif // _di_f_print_except_in_dynamic_raw_ + +#ifndef _di_f_print_except_in_dynamic_safely_ + f_status_t f_print_except_in_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) return F_data_not; + + return private_f_print_except_in_safely(buffer.string, 0, buffer.used, except_at, except_in, output); + } +#endif // _di_f_print_except_in_dynamic_safely_ + #ifndef _di_f_print_except_in_dynamic_partial_ - f_status_t f_print_except_in_dynamic_partial(FILE *output, 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) { + 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) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { return F_data_not; } @@ -121,17 +309,57 @@ extern "C" { length = buffer.used - range.start; } - return private_f_print_except_in(output, buffer.string, range.start, range.start + length, except_at, except_in); + return private_f_print_except_in(buffer.string, range.start, range.start + length, except_at, except_in, output); } #endif // _di_f_print_except_in_dynamic_partial_ +#ifndef _di_f_print_except_in_dynamic_partial_raw_ + 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) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_except_in_raw(buffer.string, range.start, range.start + length, except_at, except_in, output); + } +#endif // _di_f_print_except_in_dynamic_partial_raw_ + +#ifndef _di_f_print_except_in_dynamic_partial_safely_ + f_status_t f_print_except_in_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_except_in_safely(buffer.string, range.start, range.start + length, except_at, except_in, output); + } +#endif // _di_f_print_except_in_dynamic_partial_safely_ + #ifndef _di_f_print_except_dynamic_partial_ - f_status_t f_print_except_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except) { + 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) { #ifndef _di_level_0_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { return F_data_not; } @@ -141,12 +369,175 @@ extern "C" { length = buffer.used - range.start; } - return private_f_print_except(output, buffer.string, range.start, range.start + length, except); + return private_f_print_except(buffer.string, range.start, range.start + length, except, output); } #endif // _di_f_print_except_dynamic_partial_ +#ifndef _di_f_print_except_dynamic_partial_raw_ + 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) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_except_raw(buffer.string, range.start, range.start + length, except, output); + } +#endif // _di_f_print_except_dynamic_partial_raw_ + +#ifndef _di_f_print_except_dynamic_partial_safely_ + f_status_t f_print_except_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_except_safely(buffer.string, range.start, range.start + length, except, output); + } +#endif // _di_f_print_except_dynamic_partial_safely_ + +#ifndef _di_f_print_raw_ + f_status_t f_print_raw(const f_string_t string, const f_array_length_t length, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || !length) { + return F_data_not; + } + + return private_f_print_raw(string, length, output); + } +#endif // _di_f_print_raw_ + +#ifndef _di_f_print_raw_terminated_ + f_status_t f_print_raw_terminated(const f_string_t string, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string) { + return F_data_not; + } + + // The f_print_raw_terminated() and f_print_terminated() are functionality identical due to being NULL terminated. + return private_f_print_terminated(string, output); + } +#endif // _di_f_print_raw_terminated_ + +#ifndef _di_f_print_safely_ + f_status_t f_print_safely(const f_string_t string, const f_array_length_t length, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || !length) { + return F_data_not; + } + + return private_f_print_safely(string, length, output); + } +#endif // _di_f_print_safely_ + +#ifndef _di_f_print_safely_terminated_ + f_status_t f_print_safely_terminated(const f_string_t string, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string) { + return F_data_not; + } + + char *current = string; + + f_string_t s = 0; + + while (*current) { + + s = private_f_print_character_safely_get(*current); + + if (s) { + if (!fputc_unlocked(s[0], output)) { + return F_status_set_error(F_output); + } + + if (!fputc_unlocked(s[1], output)) { + return F_status_set_error(F_output); + } + + if (!fputc_unlocked(s[2], output)) { + return F_status_set_error(F_output); + } + + current = current + 1; + } + else { + // @todo: redo this as done in private_f_print_safely, but add a NULL check as well. + if (macro_f_utf_byte_width(current[0]) == 1) { + if (!fputc_unlocked(current[0], output)) { + return F_status_set_error(F_output); + } + } + else { + if (!fputc_unlocked(current[1], output)) { + return F_status_set_error(F_output); + } + + if (macro_f_utf_byte_width(current[0]) > 2) { + if (!fputc_unlocked(current[2], output)) { + return F_status_set_error(F_output); + } + + if (macro_f_utf_byte_width(current[0]) > 3) { + if (!fputc_unlocked(current[3], output)) { + return F_status_set_error(F_output); + } + } + } + } + + current = current + macro_f_utf_byte_width((*current)); + } + } // while + + return F_none; + } +#endif // _di_f_print_safely_terminated_ + +#ifndef _di_f_print_terminated_ + f_status_t f_print_terminated(const f_string_t string, FILE *output) { + #ifndef _di_level_0_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string) { + return F_data_not; + } + + return private_f_print_terminated(string, output); + } +#endif // _di_f_print_terminated_ + #ifndef _di_f_print_to_ - f_status_t f_print_to(const int id, const f_string_t string, const f_array_length_t length) { + f_status_t f_print_to(const f_string_t string, const f_array_length_t length, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -155,31 +546,87 @@ extern "C" { return F_data_not; } - return private_f_print_to(id, string, length); + return private_f_print_to(string, length, id); } #endif // _di_f_print_to_ +#ifndef _di_f_print_to_raw_ + f_status_t f_print_to_raw(const f_string_t string, const f_array_length_t length, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || length == 0) { + return F_data_not; + } + + return private_f_print_to_raw(string, length, id); + } +#endif // _di_f_print_to_raw_ + +#ifndef _di_f_print_to_safely_ + f_status_t f_print_to_safely(const f_string_t string, const f_array_length_t length, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || length == 0) { + return F_data_not; + } + + return private_f_print_to_safely(string, length, id); + } +#endif // _di_f_print_to_safely_ + #ifndef _di_f_print_to_dynamic_ - f_status_t f_print_to_dynamic(const int id, const f_string_static_t buffer) { + f_status_t f_print_to_dynamic(const f_string_static_t buffer, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used) { + if (!buffer.string || !buffer.used) { return F_data_not; } - return private_f_print_to(id, buffer.string, buffer.used); + return private_f_print_to(buffer.string, buffer.used, id); } #endif // _di_f_print_to_dynamic_ +#ifndef _di_f_print_to_dynamic_raw_ + f_status_t f_print_to_dynamic_raw(const f_string_static_t buffer, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) { + return F_data_not; + } + + return private_f_print_to_raw(buffer.string, buffer.used, id); + } +#endif // _di_f_print_to_dynamic_raw_ + +#ifndef _di_f_print_to_dynamic_safely_ + f_status_t f_print_to_dynamic_safely(const f_string_static_t buffer, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) { + return F_data_not; + } + + return private_f_print_to_safely(buffer.string, buffer.used, id); + } +#endif // _di_f_print_to_dynamic_safely_ + #ifndef _di_f_print_to_dynamic_partial_ - f_status_t f_print_to_dynamic_partial(const int id, const f_string_static_t buffer, const f_string_range_t range) { + f_status_t f_print_to_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { return F_data_not; } @@ -189,12 +636,52 @@ extern "C" { length = buffer.used - range.start; } - return private_f_print_to(id, buffer.string + range.start, length); + return private_f_print_to(buffer.string + range.start, length, id); } #endif // _di_f_print_to_dynamic_partial_ +#ifndef _di_f_print_to_dynamic_partial_raw_ + f_status_t f_print_to_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_to_raw(buffer.string + range.start, length, id); + } +#endif // _di_f_print_to_dynamic_partial_raw_ + +#ifndef _di_f_print_to_dynamic_partial_safely_ + f_status_t f_print_to_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_to_safely(buffer.string + range.start, length, id); + } +#endif // _di_f_print_to_dynamic_partial_safely_ + #ifndef _di_f_print_to_except_ - f_status_t f_print_to_except(const int id, const f_string_t string, const f_array_length_t length, const f_array_lengths_t except) { + f_status_t f_print_to_except(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -203,31 +690,87 @@ extern "C" { return F_data_not; } - return private_f_print_to_except(id, string, 0, length, except); + return private_f_print_to_except(string, 0, length, except, id); } #endif // _di_f_print_to_except_ +#ifndef _di_f_print_to_except_raw_ + f_status_t f_print_to_except_raw(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || length == 0) { + return F_data_not; + } + + return private_f_print_to_except_raw(string, 0, length, except, id); + } +#endif // _di_f_print_to_except_raw_ + +#ifndef _di_f_print_to_except_safely_ + f_status_t f_print_to_except_safely(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!string || length == 0) { + return F_data_not; + } + + return private_f_print_to_except_safely(string, 0, length, except, id); + } +#endif // _di_f_print_to_except_safely_ + #ifndef _di_f_print_to_except_dynamic_ - f_status_t f_print_to_except_dynamic(const int id, const f_string_static_t buffer, const f_array_lengths_t except) { + f_status_t f_print_to_except_dynamic(const f_string_static_t buffer, const f_array_lengths_t except, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used) { + if (!buffer.string || !buffer.used) { return F_data_not; } - return private_f_print_to_except(id, buffer.string, 0, buffer.used, except); + return private_f_print_to_except(buffer.string, 0, buffer.used, except, id); } #endif // _di_f_print_to_except_dynamic_ +#ifndef _di_f_print_to_except_dynamic_raw_ + f_status_t f_print_to_except_dynamic_raw(const f_string_static_t buffer, const f_array_lengths_t except, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) { + return F_data_not; + } + + return private_f_print_to_except_raw(buffer.string, 0, buffer.used, except, id); + } +#endif // _di_f_print_to_except_dynamic_raw_ + +#ifndef _di_f_print_to_except_dynamic_safely_ + f_status_t f_print_to_except_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used) { + return F_data_not; + } + + return private_f_print_to_except_safely(buffer.string, 0, buffer.used, except, id); + } +#endif // _di_f_print_to_except_dynamic_safely_ + #ifndef _di_f_print_to_except_dynamic_partial_ - f_status_t f_print_to_except_dynamic_partial(const int id, const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except) { + f_status_t f_print_to_except_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, const int id) { #ifndef _di_level_0_parameter_checking_ if (id == -1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (!buffer.used || range.start > range.stop || range.start >= buffer.used) { + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { return F_data_not; } @@ -237,10 +780,50 @@ extern "C" { length = buffer.used - range.start; } - return private_f_print_to_except(id, buffer.string, range.start, range.start + length, except); + return private_f_print_to_except(buffer.string, range.start, range.start + length, except, id); } #endif // _di_f_print_to_except_dynamic_partial_ +#ifndef _di_f_print_to_except_dynamic_partial_raw_ + f_status_t f_print_to_except_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_to_except_raw(buffer.string, range.start, range.start + length, except, id); + } +#endif // _di_f_print_to_except_dynamic_partial_raw_ + +#ifndef _di_f_print_to_except_dynamic_partial_safely_ + f_status_t f_print_to_except_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, const int id) { + #ifndef _di_level_0_parameter_checking_ + if (id == -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.string || !buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_f_print_to_except_safely(buffer.string, range.start, range.start + length, except, id); + } +#endif // _di_f_print_to_except_dynamic_partial_safely_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_print/c/print.h b/level_0/f_print/c/print.h index 9032a76..5b9d415 100644 --- a/level_0/f_print/c/print.h +++ b/level_0/f_print/c/print.h @@ -14,6 +14,8 @@ // libc includes #include +#include +#include #include #include #include @@ -24,6 +26,10 @@ #include #include #include +#include + +// fll-0 print includes +#include #ifdef __cplusplus extern "C" { @@ -36,12 +42,14 @@ extern "C" { * Will not print NULL. * Will print up to length 1-byte characters. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param string * The string to output. * @param length * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -50,23 +58,74 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see fputc_unlocked() */ #ifndef _di_f_print_ - extern f_status_t f_print(FILE *output, const f_string_t string, const f_array_length_t length); + extern f_status_t f_print(const f_string_t string, const f_array_length_t length, FILE *output); #endif // _di_f_print_ /** + * 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. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * This can result in the 1-byte character being substituted with a 3-byte character when printing. + * + * This should only be called for the first 1-byte character of a multibyte 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_safely_ + extern f_status_t f_print_character_safely(const char character, FILE *output); +#endif // _di_f_print_character_safely_ + +/** + * 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 '�'. + * + * The returned string will either be NULL (for characters that are already safe) or a string representing the replacement. + * + * This should only be called for the first 1-byte character of a multibyte character. + * + * @param character + * The character to verify as safe or not and then print. + * + * @return + * NULL is returned if the character is already replaced. + * 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. + */ +#ifndef _di_f_print_character_safely_get_ + extern f_string_t f_print_character_safely_get(const char character); +#endif // _di_f_print_character_safely_get_ + +/** * Similar to a c-library printf, except that this prints a given dynamic string. * * Will not stop at NULL. * Will not print NULL. * Will print up to the length of the buffer. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -75,247 +134,1456 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see fputc_unlocked() */ #ifndef _di_f_print_dynamic_ - extern f_status_t f_print_dynamic(FILE *output, const f_string_static_t buffer); + extern f_status_t f_print_dynamic(const f_string_static_t buffer, FILE *output); #endif // _di_f_print_dynamic_ /** - * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * Will not stop at NULL. + * Will print NULL. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + */ +#ifndef _di_f_print_dynamic_raw_ + extern f_status_t f_print_dynamic_raw(const f_string_static_t buffer, FILE *output); +#endif // _di_f_print_dynamic_raw_ + +/** + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_dynamic_safely_ + extern f_status_t f_print_dynamic_safely(const f_string_static_t buffer, FILE *output); +#endif // _di_f_print_dynamic_safely_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will not print NULL. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_dynamic_partial_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will print NULL. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_dynamic_partial_raw_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_dynamic_partial_safely_ + extern f_status_t f_print_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, FILE *output); +#endif // _di_f_print_dynamic_partial_safely_ + +/** + * Similar to a c-library printf, except that this will only print a specific range. + * + * Will not stop at NULL. + * Will not print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_ + +/** + * Similar to a c-library printf, except that this will only print a specific range. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_raw_ + +/** + * Similar to a c-library printf, except that this will only print a specific range. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will not print any 1-byte character at a location specified in except array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_except_safely_ + extern f_status_t f_print_except_safely(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output); +#endif // _di_f_print_except_safely_ + +/** + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * Will not stop at NULL. + * Will not print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to the length of the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_dynamic_ + +/** + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_dynamic_raw_ + +/** + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will not print any 1-byte character at a location specified in except array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_except_dynamic_safely_ + extern f_status_t f_print_except_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output); +#endif // _di_f_print_except_dynamic_safely_ + +/** + * Similar to a c-library printf, except that this will only print a specific range. + * + * Will not stop at NULL. + * Will not print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_in_ + +/** + * Similar to a c-library printf, except that this will only print a specific range. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_in_raw_ + +/** + * Similar to a c-library printf, except that this will only print a specific range. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_except_in_safely_ + extern f_status_t f_print_except_in_safely(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); +#endif // _di_f_print_except_in_safely_ + +/** + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * Will not stop at NULL. + * Will not print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to the length of the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_in_dynamic_ + +/** + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_in_dynamic_raw_ + +/** + * Similar to a c-library printf, except that this prints a given dynamic string. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to the length of the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_except_in_dynamic_safely_ + extern f_status_t f_print_except_in_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output); +#endif // _di_f_print_except_in_dynamic_safely_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will not print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_in_dynamic_partial_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_in_dynamic_partial_raw_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will not print NULL. + * Will not print any 1-byte character at a location specified in except_at array. + * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_dynamic_except_partial_safely_ + extern f_status_t f_print_except_in_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output); +#endif // _di_f_print_except_in_dynamic_partial_safely_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will not print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_dynamic_partial_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_dynamic_partial_raw_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will not print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_dynamic_partial_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except array. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_except_dynamic_partial_raw_ + +/** + * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will not print any 1-byte character at a location specified in except array. + * Will print up to the specified range within the buffer. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_dynamic_except_partial_safely_ + extern f_status_t f_print_except_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); +#endif // _di_f_print_except_dynamic_partial_safely_ + +/** + * Similar to a c-library printf, except that this will only print a specific range. + * + * Will not stop at NULL. + * Will print NULL. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_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); +#endif // _di_f_print_raw_ + +/** + * Similar to a c-library printf. + * + * Will stop at NULL. + * Will not print NULL. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + */ +#ifndef _di_f_print_raw_terminated_ + extern f_status_t f_print_raw_terminated(const f_string_t string, FILE *output); +#endif // _di_f_print_raw_terminated_ + +/** + * Similar to a c-library printf, except that this will only print a specific range. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_safely_ + extern f_status_t f_print_safely(const f_string_t string, const f_array_length_t length, FILE *output); +#endif // _di_f_print_safely_ + +/** + * Similar to a c-library printf. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will stop at NULL. + * Will not print NULL (even as a control character symbol). + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_utf_is_valid() + */ +#ifndef _di_f_print_safely_terminated_ + extern f_status_t f_print_safely_terminated(const f_string_t string, FILE *output); +#endif // _di_f_print_safely_terminated_ + +/** + * Similar to a c-library printf. + * + * Will stop at NULL. + * Will not print NULL. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + */ +#ifndef _di_f_print_terminated_ + extern f_status_t f_print_terminated(const f_string_t string, FILE *output); +#endif // _di_f_print_terminated_ + +/** + * Similar to a c-library dprintf, except that this will only print a specific range. + * + * Will not stop at NULL. + * Will not print NULL. + * Will print up to length 1-byte characters. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see write() + */ +#ifndef _di_f_print_to_ + extern f_status_t f_print_to(const f_string_t string, const f_array_length_t length, const int id); +#endif // _di_f_print_to_ + +/** + * Similar to a c-library dprintf, except that this will only print a specific range. + * + * Will not stop at NULL. + * Will print NULL. + * Will print up to length 1-byte characters. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see write() + */ +#ifndef _di_f_print_to_raw_ + extern f_status_t f_print_to_raw(const f_string_t string, const f_array_length_t length, const int id); +#endif // _di_f_print_to_raw_ + +/** + * Similar to a c-library dprintf, except that this will only print a specific range. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will print up to length 1-byte characters. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see write() + */ +#ifndef _di_f_print_to_safely_ + extern f_status_t f_print_to_safely(const f_string_t string, const f_array_length_t length, const int id); +#endif // _di_f_print_to_safely_ + +/** + * Similar to a c-library dprintf, except that this prints a given dynamic string. + * + * Will not stop at NULL. + * Will not print NULL. + * Will print up to the length of the buffer. + * + * @param buffer + * The string to output. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see write() + */ +#ifndef _di_f_print_to_dynamic_ + extern f_status_t f_print_to_dynamic(const f_string_static_t buffer, const int id); +#endif // _di_f_print_to_dynamic_ + +/** + * Similar to a c-library dprintf, except that this prints a given dynamic string. + * + * Will not stop at NULL. + * Will print NULL. + * Will print up to length 1-byte characters. + * + * @param buffer + * The string to output. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see write() + */ +#ifndef _di_f_print_to_dynamic_raw_ + extern f_status_t f_print_to_dynamic_raw(const f_string_static_t buffer, const int id); +#endif // _di_f_print_to_dynamic_raw_ + +/** + * Similar to a c-library dprintf, except that this prints a given dynamic string. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. + * + * Will not stop at NULL. + * Will print NULL (as a control character symbol). + * Will print up to length 1-byte characters. + * + * @param buffer + * The string to output. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see write() + */ +#ifndef _di_f_print_to_dynamic_safely_ + extern f_status_t f_print_to_dynamic_safely(const f_string_static_t buffer, const int id); +#endif // _di_f_print_to_dynamic_safely_ + +/** + * Similar to a c-library dprintf, except that this will only print a specific range in a given dynamic string. + * + * Will not stop at NULL. + * Will not print NULL. + * Will print up to the specified range within the buffer. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if there is nothing to print. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see write() + */ +#ifndef _di_f_print_to_dynamic_partial_ + extern f_status_t f_print_to_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const int id); +#endif // _di_f_print_to_dynamic_partial_ + +/** + * Similar to a c-library dprintf, except that this will only print a specific range in a given dynamic string. * * Will not stop at NULL. - * Will not print NULL. + * Will print NULL. * Will print up to the specified range within the buffer. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param buffer * The string to output. * @param range * The range within the provided string to print. + * @param id + * The file descriptor to output to. * * @return * F_none on success. * F_data_not if there is nothing to print. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see write() */ -#ifndef _di_f_print_dynamic_partial_ - extern f_status_t f_print_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range); -#endif // _di_f_print_dynamic_partial_ +#ifndef _di_f_print_to_dynamic_partial_raw_ + extern f_status_t f_print_to_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, const int id); +#endif // _di_f_print_to_dynamic_partial_raw_ /** - * Similar to a c-library printf, except that this will only print a specific range. + * Similar to a c-library dprintf, except that this will only print a specific range in a given dynamic string. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. * * Will not stop at NULL. - * Will not print NULL. - * Will not print any 1-byte character at a location specified in except array. + * Will print NULL (as a control character symbol). * Will print up to length 1-byte characters. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. - * @param string + * @param buffer * The string to output. - * @param length - * The total number of characters to print. - * @param except - * An array of locations within the given string to not print. - * The array of locations is required/assumed to be in linear order. + * @param range + * The range within the provided string to print. + * @param id + * The file descriptor to output to. * * @return * F_none on success. * F_data_not if there is nothing to print. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see write() */ -#ifndef _di_f_print_except_ - extern f_status_t f_print_except(FILE *output, const f_string_t string, const f_array_length_t length, const f_array_lengths_t except); -#endif // _di_f_print_except_ +#ifndef _di_f_print_to_dynamic_partial_safely_ + extern f_status_t f_print_to_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const int id); +#endif // _di_f_print_to_dynamic_partial_safely_ /** - * Similar to a c-library printf, except that this prints a given dynamic string. + * Similar to a c-library dprintf, except that this will only print a specific range. * * Will not stop at NULL. * Will not print NULL. * Will not print any 1-byte character at a location specified in except array. - * Will print up to the length of the buffer. + * Will print up to length 1-byte characters. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. - * @param buffer + * @param string * The string to output. + * @param length + * The total number of characters to print. * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. * * @return * F_none on success. * F_data_not if there is nothing to print. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see write() */ -#ifndef _di_f_print_except_dynamic_ - extern f_status_t f_print_except_dynamic(FILE *output, const f_string_static_t buffer, const f_array_lengths_t except); -#endif // _di_f_print_except_dynamic_ +#ifndef _di_f_print_to_except_ + extern f_status_t f_print_to_except(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_ /** - * Similar to a c-library printf, except that this will only print a specific range. + * Similar to a c-library dprintf, except that this will only print a specific range. * * Will not stop at NULL. - * Will not print NULL. - * Will not print any 1-byte character at a location specified in except_at array. - * Will not print any 1-byte character within the ranges specified in except_in array. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except array. * Will print up to length 1-byte characters. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param string * The string to output. * @param length * The total number of characters to print. - * @param except_at + * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. - * @param except_in - * An array of ranges within the string to not print. - * The array of ranges is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. * * @return * F_none on success. * F_data_not if there is nothing to print. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see write() */ -#ifndef _di_f_print_except_in_ - extern f_status_t f_print_except_in(FILE *output, 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); -#endif // _di_f_print_except_in_ +#ifndef _di_f_print_to_except_raw_ + extern f_status_t f_print_to_except_raw(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_raw_ /** - * Similar to a c-library printf, except that this prints a given dynamic string. - * - * Will not stop at NULL. - * Will not print NULL. - * Will not print any 1-byte character at a location specified in except_at array. - * Will not print any 1-byte character within the ranges specified in except_in array. - * Will print up to the length of the buffer. - * - * @param output - * The file to output to, including standard streams such as stdout and stderr. - * @param buffer - * The string to output. - * @param except_at - * An array of locations within the given string to not print. - * The array of locations is required/assumed to be in linear order. - * @param except_in - * An array of ranges within the string to not print. - * The array of ranges is required/assumed to be in linear order. - * - * @return - * F_none on success. - * F_data_not if there is nothing to print. - * - * F_output (with error bit) on failure. - * F_parameter (with error bit) if a parameter is invalid. + * Similar to a c-library dprintf, except that this will only print a specific range. * - * @see fputc() - */ -#ifndef _di_f_print_except_in_dynamic_ - extern f_status_t f_print_except_in_dynamic(FILE *output, const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in); -#endif // _di_f_print_except_in_dynamic_ - -/** - * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. * * Will not stop at NULL. - * Will not print NULL. - * Will not print any 1-byte character at a location specified in except_at array. - * Will not print any 1-byte character within the ranges specified in except_in array. - * Will print up to the specified range within the buffer. + * Will print NULL (as a control character symbol). + * Will not print any 1-byte character at a location specified in except array. + * Will print up to length 1-byte characters. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. - * @param buffer + * @param string * The string to output. - * @param range - * The range within the provided string to print. - * @param except_at + * @param length + * The total number of characters to print. + * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. - * @param except_in - * An array of ranges within the string to not print. - * The array of ranges is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. * * @return * F_none on success. * F_data_not if there is nothing to print. * - * F_output (with error bit) on failure. + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. * F_parameter (with error bit) if a parameter is invalid. * - * @see fputc() + * @see write() */ -#ifndef _di_f_print_dynamic_except_partial_ - extern f_status_t f_print_except_in_dynamic_partial(FILE *output, 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); -#endif // _di_f_print_except_in_dynamic_partial_ +#ifndef _di_f_print_to_except_safely_ + extern f_status_t f_print_to_except_safely(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_safely_ /** - * Similar to a c-library printf, except that this will only print a specific range in a given dynamic string. + * Similar to a c-library dprintf, except that this prints a given dynamic string. * * Will not stop at NULL. * Will not print NULL. * Will not print any 1-byte character at a location specified in except array. - * Will print up to the specified range within the buffer. + * Will print up to the length of the buffer. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param buffer * The string to output. - * @param range - * The range within the provided string to print. * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. - * - * @return - * F_none on success. - * F_data_not if there is nothing to print. - * - * F_output (with error bit) on failure. - * F_parameter (with error bit) if a parameter is invalid. - * - * @see fputc() - */ -#ifndef _di_f_print_dynamic_except_partial_ - extern f_status_t f_print_except_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except); -#endif // _di_f_print_except_dynamic_partial_ - - -/** - * Similar to a c-library dprintf, except that this will only print a specific range. - * - * Will not stop at NULL. - * Will not print NULL. - * Will print up to length 1-byte characters. - * * @param id * The file descriptor to output to. - * @param string - * The string to output. - * @param length - * The total number of characters to print. * * @return * F_none on success. @@ -332,21 +1600,25 @@ extern "C" { * * @see write() */ -#ifndef _di_f_print_to_ - extern f_status_t f_print_to(const int id, const f_string_t string, const f_array_length_t length); -#endif // _di_f_print_to_ +#ifndef _di_f_print_to_except_dynamic_ + extern f_status_t f_print_to_except_dynamic(const f_string_static_t buffer, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_dynamic_ /** * Similar to a c-library dprintf, except that this prints a given dynamic string. * * Will not stop at NULL. - * Will not print NULL. + * Will print NULL. + * Will not print any 1-byte character at a location specified in except array. * Will print up to the length of the buffer. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param buffer * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. * * @return * F_none on success. @@ -363,23 +1635,28 @@ extern "C" { * * @see write() */ -#ifndef _di_f_print_to_dynamic_ - extern f_status_t f_print_to_dynamic(const int id, const f_string_static_t buffer); -#endif // _di_f_print_to_dynamic_ +#ifndef _di_f_print_to_except_dynamic_raw_ + extern f_status_t f_print_to_except_dynamic_raw(const f_string_static_t buffer, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_dynamic_raw_ /** - * Similar to a c-library dprintf, except that this will only print a specific range in a given dynamic string. + * Similar to a c-library dprintf, except that this prints a given dynamic string. + * + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. * * Will not stop at NULL. - * Will not print NULL. - * Will print up to the specified range within the buffer. + * Will print NULL (as a control character symbol). + * Will not print any 1-byte character at a location specified in except array. + * Will print up to the length of the buffer. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param buffer * The string to output. - * @param range - * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. * * @return * F_none on success. @@ -396,29 +1673,27 @@ extern "C" { * * @see write() */ -#ifndef _di_f_print_to_dynamic_partial_ - extern f_status_t f_print_to_dynamic_partial(const int id, const f_string_static_t buffer, const f_string_range_t range); -#endif // _di_f_print_to_dynamic_partial_ +#ifndef _di_f_print_to_except_dynamic_safely_ + extern f_status_t f_print_to_except_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_dynamic_safely_ /** - * Similar to a c-library dprintf, except that this will only print a specific range. - * - * The string is printed as-is without interpretation. + * Similar to a c-library dprintf, except that this will only print a specific range in a given dynamic string. * * Will not stop at NULL. * Will not print NULL. * Will not print any 1-byte character at a location specified in except array. - * Will print up to length 1-byte characters. + * Will print up to the specified range within the buffer. * - * @param id - * The file descriptor to output to. - * @param string + * @param buffer * The string to output. - * @param length - * The total number of characters to print. + * @param range + * The range within the provided string to print. * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. * * @return * F_none on success. @@ -435,27 +1710,27 @@ extern "C" { * * @see write() */ -#ifndef _di_f_print_to_except_ - extern f_status_t f_print_to_except(const int id, const f_string_t string, const f_array_length_t length, const f_array_lengths_t except); -#endif // _di_f_print_to_except_ +#ifndef _di_f_print_to_except_dynamic_partial_ + extern f_status_t f_print_to_except_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_dynamic_partial_ /** - * Similar to a c-library dprintf, except that this prints a given dynamic string. - * - * The string is printed as-is without interpretation. + * Similar to a c-library dprintf, except that this will only print a specific range in a given dynamic string. * * Will not stop at NULL. - * Will not print NULL. + * Will print NULL. * Will not print any 1-byte character at a location specified in except array. - * Will print up to the length of the buffer. + * Will print up to the specified range within the buffer. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param buffer * The string to output. + * @param range + * The range within the provided string to print. * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. * * @return * F_none on success. @@ -472,22 +1747,23 @@ extern "C" { * * @see write() */ -#ifndef _di_f_print_to_except_dynamic_ - extern f_status_t f_print_to_except_dynamic(const int id, const f_string_static_t buffer, const f_array_lengths_t except); -#endif // _di_f_print_to_except_dynamic_ +#ifndef _di_f_print_to_except_dynamic_partial_raw_ + extern f_status_t f_print_to_except_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_dynamic_partial_raw_ /** * Similar to a c-library dprintf, except that this will only print a specific range in a given dynamic string. * - * The string is printed as-is without interpretation. + * Control characters are converted to the Unicode control character symbols, including NULL. + * UTF-8 sequences with invalid widths are converted to the unknown character '�'. * * Will not stop at NULL. - * Will not print NULL. + * Will print NULL (as a control character symbol). * Will not print any 1-byte character at a location specified in except array. * Will print up to the specified range within the buffer. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * @param id + * The file descriptor to output to. * @param buffer * The string to output. * @param range @@ -511,9 +1787,9 @@ extern "C" { * * @see write() */ -#ifndef _di_f_print_to_except_dynamic_partial_ - extern f_status_t f_print_to_except_dynamic_partial(const int id, const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except); -#endif // _di_f_print_to_except_dynamic_partial_ +#ifndef _di_f_print_to_except_dynamic_partial_safely_ + extern f_status_t f_print_to_except_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, const int id); +#endif // _di_f_print_to_except_dynamic_partial_safely_ #ifdef __cplusplus } // extern "C" diff --git a/level_0/f_print/c/private-print.c b/level_0/f_print/c/private-print.c index 90c8a93..d066463 100644 --- a/level_0/f_print/c/private-print.c +++ b/level_0/f_print/c/private-print.c @@ -6,12 +6,12 @@ extern "C" { #endif #if !defined(_di_f_print_) || !defined(_di_f_print_dynamic_) || !defined(_di_f_print_dynamic_partial_) - f_status_t private_f_print(FILE *output, const f_string_t string, const f_array_length_t length) { + f_status_t private_f_print(const f_string_t string, const f_array_length_t length, FILE *output) { - for (f_array_length_t i = 0; i < length; ++i) { + for (register f_array_length_t i = 0; i < length; ++i) { if (string[i]) { - if (!fputc(string[i], output)) { + if (!fputc_unlocked(string[i], output)) { return F_status_set_error(F_output); } } @@ -21,87 +21,1020 @@ extern "C" { } #endif // !defined(_di_f_print_) || !defined(_di_f_print_dynamic_) || !defined(_di_f_print_dynamic_partial_) +#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 > 32 && character != 127) { + if (!fputc_unlocked(character, output)) { + return F_status_set_error(F_output); + } + } + + f_string_t string = 0; + + if (character == 0) { + string = f_print_sequence_null_s; + } + else if (character == 1) { + string = f_print_sequence_start_of_header_s; + } + else if (character == 2) { + string = f_print_sequence_start_of_text_s; + } + else if (character == 3) { + string = f_print_sequence_end_of_text_s; + } + else if (character == 4) { + string = f_print_sequence_end_of_transmission_s; + } + else if (character == 5) { + string = f_print_sequence_end_of_enquiry_s; + } + else if (character == 6) { + string = f_print_sequence_acknowledge_s; + } + else if (character == 7) { + string = f_print_sequence_bell_s; + } + else if (character == 8) { + string = f_print_sequence_backspace_s; + } + else if (character == 9) { + string = f_print_sequence_tab_s; + } + else if (character == 10) { + string = f_print_sequence_new_line_s; + } + else if (character == 11) { + string = f_print_sequence_tab_vertical_s; + } + else if (character == 12) { + string = f_print_sequence_form_feed_s; + } + else if (character == 13) { + string = f_print_sequence_carriage_return_s; + } + else if (character == 14) { + string = f_print_sequence_shift_out_s; + } + else if (character == 15) { + string = f_print_sequence_shift_in_s; + } + else if (character == 16) { + string = f_print_sequence_data_link_escape_s; + } + else if (character == 17) { + string = f_print_sequence_device_control_1_s; + } + else if (character == 18) { + string = f_print_sequence_device_control_2_s; + } + else if (character == 19) { + string = f_print_sequence_device_control_3_s; + } + else if (character == 20) { + string = f_print_sequence_device_control_4_s; + } + else if (character == 21) { + string = f_print_sequence_negative_acknowledge_s; + } + else if (character == 22) { + string = f_print_sequence_synchronous_idle_s; + } + else if (character == 23) { + string = f_print_sequence_end_of_transmission_block_s; + } + else if (character == 24) { + string = f_print_sequence_cancel_s; + } + else if (character == 25) { + string = f_print_sequence_end_of_medium_s; + } + else if (character == 26) { + string = f_print_sequence_substitute_s; + } + else if (character == 27) { + string = f_print_sequence_escape_s; + } + else if (character == 28) { + string = f_print_sequence_file_separator_s; + } + else if (character == 29) { + string = f_print_sequence_group_separator_s; + } + else if (character == 30) { + string = f_print_sequence_record_separator_s; + } + else if (character == 31) { + string = f_print_sequence_unit_separator_s; + } + else if (character == 32) { + string = f_print_sequence_space_s; + } + else { + + // character == 127. + string = f_print_sequence_delete_s; + } + + if (!fputc_unlocked(character, output)) { + return F_status_set_error(F_output); + } + + if (!fputc_unlocked(character, output)) { + return F_status_set_error(F_output); + } + + if (!fputc_unlocked(character, output)) { + return F_status_set_error(F_output); + } + + return F_none; + } +#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 > 32 && character != 127) { + return 0; + } + + if (character == 0) { + return f_print_sequence_null_s; + } + + if (character == 1) { + return f_print_sequence_start_of_header_s; + } + + if (character == 2) { + return f_print_sequence_start_of_text_s; + } + + if (character == 3) { + return f_print_sequence_end_of_text_s; + } + + if (character == 4) { + return f_print_sequence_end_of_transmission_s; + } + + if (character == 5) { + return f_print_sequence_end_of_enquiry_s; + } + + if (character == 6) { + return f_print_sequence_acknowledge_s; + } + + if (character == 7) { + return f_print_sequence_bell_s; + } + + if (character == 8) { + return f_print_sequence_backspace_s; + } + + if (character == 9) { + return f_print_sequence_tab_s; + } + + if (character == 10) { + return f_print_sequence_new_line_s; + } + + if (character == 11) { + return f_print_sequence_tab_vertical_s; + } + + if (character == 12) { + return f_print_sequence_form_feed_s; + } + + if (character == 13) { + return f_print_sequence_carriage_return_s; + } + + if (character == 14) { + return f_print_sequence_shift_out_s; + } + + if (character == 15) { + return f_print_sequence_shift_in_s; + } + + if (character == 16) { + return f_print_sequence_data_link_escape_s; + } + + if (character == 17) { + return f_print_sequence_device_control_1_s; + } + + if (character == 18) { + return f_print_sequence_device_control_2_s; + } + + if (character == 19) { + return f_print_sequence_device_control_3_s; + } + + if (character == 20) { + return f_print_sequence_device_control_4_s; + } + + if (character == 21) { + return f_print_sequence_negative_acknowledge_s; + } + + if (character == 22) { + return f_print_sequence_synchronous_idle_s; + } + + if (character == 23) { + return f_print_sequence_end_of_transmission_block_s; + } + + if (character == 24) { + return f_print_sequence_cancel_s; + } + + if (character == 25) { + return f_print_sequence_end_of_medium_s; + } + + if (character == 26) { + return f_print_sequence_substitute_s; + } + + if (character == 27) { + return f_print_sequence_escape_s; + } + + if (character == 28) { + return f_print_sequence_file_separator_s; + } + + if (character == 29) { + return f_print_sequence_group_separator_s; + } + + if (character == 30) { + return f_print_sequence_record_separator_s; + } + + if (character == 31) { + return f_print_sequence_unit_separator_s; + } + + if (character == 32) { + return f_print_sequence_space_s; + } + + // character == 127. + return f_print_sequence_delete_s; + } +#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_) + +#if !defined(_di_f_print_raw_) || !defined(_di_f_print_raw_dynamic_) || !defined(_di_f_print_raw_dynamic_partial_) + f_status_t private_f_print_raw(const f_string_t string, const f_array_length_t length, FILE *output) { + + for (register f_array_length_t i = 0; i < length; ++i) { + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + } // for + + return F_none; + } +#endif // !defined(_di_f_print_raw_) || !defined(_di_f_print_raw_dynamic_) || !defined(_di_f_print_raw_dynamic_partial_) + +#if !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_) + f_status_t private_f_print_safely(const f_string_t string, const f_array_length_t length, FILE *output) { + + register f_array_length_t i = 0; + + f_status_t status = F_none; + f_string_t s = 0; + + while (i < length) { + + 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 (!fputc_unlocked(s[i + 2], output)) { + return F_status_set_error(F_output); + } + + ++i; + } + else { + status = f_utf_is_valid(string + i, length - 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i += macro_f_utf_byte_width(string[i]); + continue; + } + + if (i + macro_f_utf_byte_width(string[i]) >= length) { + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i = length; + 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 (macro_f_utf_byte_width(string[i]) > 3) { + if (!fputc_unlocked(string[i + 3], output)) { + return F_status_set_error(F_output); + } + } + } + } + + i += macro_f_utf_byte_width(string[i]); + } + } // while + + return F_none; + } +#endif // !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_) + #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(FILE *output, const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except) { + 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) { + + f_array_length_t i = offset; + f_array_length_t j = 0; + + for (; i < stop; ++i) { + + while (j < except.used && except.array[j] < i) { + ++j; + } // while + + if (j < except.used && except.array[j] == i) continue; + + if (string[i]) { + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + } + } // for + + return F_none; + } +#endif // !defined(_di_f_print_except_) || !defined(_di_f_print_except_dynamic_) || !defined(_di_f_print_except_dynamic_partial_) + +#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) { + + f_array_length_t i = offset; + f_array_length_t j = 0; + + for (; i < stop; ++i) { + + while (j < except.used && except.array[j] < i) { + ++j; + } // while + + if (j < except.used && except.array[j] == i) continue; + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + } // for + + return F_none; + } +#endif // !defined(_di_f_print_except_raw_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_partial_raw_) + +#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) { + + f_array_length_t i = offset; + f_array_length_t j = 0; + + f_status_t status = F_none; + f_string_t s = 0; + + while (i < stop) { + + while (j < except.used && except.array[j] < i) { + ++j; + } // while + + if (j < except.used && except.array[j] == i) { + ++i; + + continue; + } + + 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 (!fputc_unlocked(s[i + 2], output)) { + return F_status_set_error(F_output); + } + + ++i; + } + else { + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i += macro_f_utf_byte_width(string[i]); + continue; + } + + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i = stop; + 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 (macro_f_utf_byte_width(string[i]) > 3) { + if (!fputc_unlocked(string[i + 3], output)) { + return F_status_set_error(F_output); + } + } + } + } + + i += macro_f_utf_byte_width(string[i]); + } + } // while + + return F_none; + } +#endif // !defined(_di_f_print_except_safely_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_dynamic_partial_safely_) + +#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) { + + f_array_length_t i = offset; + f_array_length_t at = 0; + f_array_length_t in = 0; + + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + if (in < except_in.used) { + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + } + + if (string[i]) { + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + } + + ++i; + } // while + + return F_none; + } +#endif // !defined(_di_f_print_except_in_) || !defined(_di_f_print_except_in_dynamic_) || !defined(_di_f_print_except_in_dynamic_partial_) + +#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) { + + f_array_length_t i = offset; + f_array_length_t at = 0; + f_array_length_t in = 0; + + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + if (in < except_in.used) { + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + } + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + + ++i; + } // while + + return F_none; + } +#endif // !defined(_di_f_print_except_in_raw_) || !defined(_di_f_print_except_in_dynamic_raw_) || !defined(_di_f_print_except_in_dynamic_partial_raw_) + +#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) { + + f_array_length_t i = offset; + f_array_length_t at = 0; + f_array_length_t in = 0; + + f_status_t status = F_none; + f_string_t s = 0; + + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + if (in < except_in.used) { + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + } + + 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 (!fputc_unlocked(s[i + 2], output)) { + return F_status_set_error(F_output); + } + + ++i; + } + else { + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i += macro_f_utf_byte_width(string[i]); + continue; + } + + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i = stop; + 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 (macro_f_utf_byte_width(string[i]) > 3) { + if (!fputc_unlocked(string[i + 3], output)) { + return F_status_set_error(F_output); + } + } + } + } + + i += macro_f_utf_byte_width(string[i]); + } + } // while + + return F_none; + } +#endif // !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_terminated_) || !defined(_di_f_print_raw_terminated_) + f_status_t private_f_print_terminated(const f_string_t string, FILE *output) { + + for (char *current = string; *current; current = current + 1) { + + if (!fputc_unlocked(*current, output)) { + return F_status_set_error(F_output); + } + } // for + + return F_none; + } +#endif // !defined(_di_f_print_terminated_) || !defined(_di_f_print_raw_terminated_) + +#if !defined(_di_f_print_to_) || !defined(_di_f_print_dynamic_to_) || !defined(_di_f_print_dynamic_partial_to_) + f_status_t private_f_print_to(const f_string_t string, const f_array_length_t length, const int id) { + + f_array_length_t i = 0; + f_array_length_t start = 0; + f_array_length_t total = 0; + + while (i < length) { + + if (string[i] && total < f_print_write_max) { + ++total; + ++i; + + continue; + } + + if (total) { + if (write(id, string + start, total) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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 (string[i]) { + start = i++; + total = 1; + } + else { + start = ++i; + total = 0; + } + } // for + + if (total) { + if (write(id, string + start, total) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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); - f_array_length_t j = 0; + return F_status_set_error(F_output); + } + } + + return F_none; + } +#endif // !defined(_di_f_print_to_) || !defined(_di_f_print_dynamic_to_) || !defined(_di_f_print_dynamic_partial_to_) - for (f_array_length_t i = offset; i < stop; ++i) { +#if !defined(_di_f_print_to_raw_) || !defined(_di_f_print_dynamic_to_raw_) || !defined(_di_f_print_dynamic_partial_to_raw_) + f_status_t private_f_print_to_raw(const f_string_t string, const f_array_length_t length, const int id) { - while (j < except.used && except.array[j] < i) { - ++j; - } // while + f_array_length_t i = 0; + f_array_length_t start = 0; + f_array_length_t total = 0; - if (j < except.used && except.array[j] == i) continue; + while (i < length) { + + if (total < f_print_write_max) { + ++total; + ++i; + + continue; + } + + if (total) { + if (write(id, string + start, total) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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 (string[i]) { - if (!fputc(string[i], output)) { return F_status_set_error(F_output); } } - } // for + + start = ++i; + total = 0; + } // while + + if (total) { + if (write(id, string + start, total) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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_print_except_) || !defined(_di_f_print_except_dynamic_) || !defined(_di_f_print_except_dynamic_partial_) +#endif // !defined(_di_f_print_to_raw_) || !defined(_di_f_print_dynamic_to_raw_) || !defined(_di_f_print_dynamic_partial_to_raw_) -#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(FILE *output, 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) { +#if !defined(_di_f_print_dynamic_to_safely_) || !defined(_di_f_print_dynamic_partial_to_safely_) || !defined(_di_f_print_to_safely_) + f_status_t private_f_print_to_safely(const f_string_t string, const f_array_length_t length, const int id) { - f_array_length_t i = offset; - f_array_length_t at = 0; - f_array_length_t in = 0; + f_array_length_t i = 0; + f_array_length_t start = 0; + f_array_length_t total = 0; - while (i < stop) { + f_status_t status = F_none; + f_string_t s = 0; - while (at < except_at.used && except_at.array[at] < i) { - ++at; - } // while + while (i < length) { - if (at < except_at.used && except_at.array[at] == i) { - ++i; + s = private_f_print_character_safely_get(string[i]); - continue; + if (s) { + if (total < f_print_write_max) { + ++total; + ++i; + + continue; + } } + else { + if (total + macro_f_utf_byte_width(string[i]) < f_print_write_max) { + total += macro_f_utf_byte_width(string[i]); + i += macro_f_utf_byte_width(string[i]); - if (in < except_in.used) { - while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { - ++in; - } // while + continue; + } + } - if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { - i = except_in.array[in].stop + 1; + if (total) { + if (write(id, string + start, total) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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); - continue; + return F_status_set_error(F_output); } } - if (string[i]) { - if (!fputc(string[i], output)) { + if (s) { + if (write(id, s, 3) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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); } + + start = ++i; + total = 0; } + else { + status = f_utf_is_valid(string + i, length - i); - ++i; + if (F_status_is_error(status) || status == F_false) { + if (write(id, f_print_sequence_unknown_s, 3) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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); + } + + i += macro_f_utf_byte_width(string[i]); + start = i; + total = 0; + + continue; + } + + if (i + macro_f_utf_byte_width(string[i]) >= length) { + if (write(id, f_print_sequence_unknown_s, 3) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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); + } + + i = length; + start = length; + total = 0; + + continue; + } + + total = macro_f_utf_byte_width(string[i]); + start = i; + i += total; + } } // while + if (total) { + if (write(id, string + start, total) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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_print_except_in_) || !defined(_di_f_print_except_in_dynamic_) || !defined(_di_f_print_except_in_dynamic_partial_) +#endif // !defined(_di_f_print_dynamic_to_safely_) || !defined(_di_f_print_dynamic_partial_to_safely_) || !defined(_di_f_print_to_safely_) -#if !defined(_di_f_print_to_) || !defined(_di_f_print_dynamic_to_) || !defined(_di_f_print_dynamic_partial_to_) - f_status_t private_f_print_to(const int id, const f_string_t string, const f_array_length_t length) { +#if !defined(_di_f_print_to_except_) || !defined(_di_f_print_to_except_dynamic_) || !defined(_di_f_print_to_except_dynamic_partial_) + f_status_t private_f_print_to_except(const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except, const int id) { - f_array_length_t i = 0; - f_array_length_t start = 0; + f_array_length_t i = offset; + f_array_length_t j = 0; + f_array_length_t start = offset; f_array_length_t total = 0; - for (; i < length; ++i) { + while (i < stop) { - if (string[i]) { - ++total; + while (j < except.used && except.array[j] < i) { + ++j; + } // while - continue; + if (j >= except.used || except.array[j] != i) { + if (string[i] && total < f_print_write_max) { + ++total; + ++i; + + continue; + } } if (total) { @@ -118,9 +1051,15 @@ extern "C" { } } - start = i + 1; - total = 0; - } // for + if ((j >= except.used || except.array[j] != i) && string[i]) { + start = i++; + total = 1; + } + else { + start = ++i; + total = 0; + } + } // while if (total) { if (write(id, string + start, total) == -1) { @@ -138,25 +1077,26 @@ extern "C" { return F_none; } -#endif // !defined(_di_f_print_to_) || !defined(_di_f_print_dynamic_to_) || !defined(_di_f_print_dynamic_partial_to_) +#endif // !defined(_di_f_print_to_except_) || !defined(_di_f_print_to_except_dynamic_) || !defined(_di_f_print_to_except_dynamic_partial_) -#if !defined(_di_f_print_to_except_) || !defined(_di_f_print_to_except_dynamic_) || !defined(_di_f_print_to_except_dynamic_partial_) - f_status_t private_f_print_to_except(const int id, const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except) { +#if !defined(_di_f_print_to_except_raw_) || !defined(_di_f_print_to_except_dynamic_raw_) || !defined(_di_f_print_to_except_dynamic_partial_raw_) + f_status_t private_f_print_to_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, const int id) { f_array_length_t i = offset; f_array_length_t j = 0; f_array_length_t start = offset; f_array_length_t total = 0; - for (; i < stop; ++i) { + while (i < stop) { while (j < except.used && except.array[j] < i) { ++j; } // while if (j >= except.used || except.array[j] != i) { - if (string[i]) { + if (total < f_print_write_max) { ++total; + ++i; continue; } @@ -176,9 +1116,15 @@ extern "C" { } } - start = i + 1; - total = 0; - } // for + if (j >= except.used || except.array[j] != i) { + start = i++; + total = 1; + } + else { + start = ++i; + total = 0; + } + } // while if (total) { if (write(id, string + start, total) == -1) { @@ -196,7 +1142,135 @@ extern "C" { return F_none; } -#endif // !defined(_di_f_print_to_except_) || !defined(_di_f_print_to_except_dynamic_) || !defined(_di_f_print_to_except_dynamic_partial_) +#endif // !defined(_di_f_print_to_except_raw_) || !defined(_di_f_print_to_except_dynamic_raw_) || !defined(_di_f_print_to_except_dynamic_partial_raw_) + +#if !defined(_di_f_print_to_except_dynamic_safely_) || !defined(_di_f_print_to_except_dynamic_partial_safely_) || !defined(_di_f_print_to_except_safely_) + f_status_t private_f_print_to_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, const int id) { + + f_array_length_t i = offset; + f_array_length_t j = 0; + f_array_length_t start = offset; + f_array_length_t total = 0; + + f_status_t status = F_none; + f_string_t s = 0; + + while (i < stop) { + + while (j < except.used && except.array[j] < i) { + ++j; + } // while + + if (j < except.used && except.array[j] == i) { + ++i; + continue; + } + + s = private_f_print_character_safely_get(string[i]); + + if (!s && total < f_print_write_max) { + ++total; + ++i; + + continue; + } + + if (total) { + if (write(id, string + start, total) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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 (s) { + if (write(id, s, 3) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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); + } + + start = ++i; + total = 0; + } + else { + status = f_utf_is_valid(string + i, stop - i); + + if (F_status_is_error(status) || status == F_false) { + if (write(id, f_print_sequence_unknown_s, 3) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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); + } + + i += macro_f_utf_byte_width(string[i]); + start = i; + total = 0; + + continue; + } + + if (i + macro_f_utf_byte_width(string[i]) >= stop) { + if (write(id, f_print_sequence_unknown_s, 3) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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); + } + + i = stop; + start = stop; + total = 0; + + continue; + } + + total = macro_f_utf_byte_width(string[i]); + start = i; + i += total; + } + } // while + + if (total) { + if (write(id, string + start, total) == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == 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_print_to_except_dynamic_safely_) || !defined(_di_f_print_to_except_dynamic_partial_safely_) || !defined(_di_f_print_to_except_safely_) #ifdef __cplusplus } // extern "C" diff --git a/level_0/f_print/c/private-print.h b/level_0/f_print/c/private-print.h index 703d34c..b20edf6 100644 --- a/level_0/f_print/c/private-print.h +++ b/level_0/f_print/c/private-print.h @@ -20,12 +20,12 @@ extern "C" { * * Intended to be shared to each of the different implementation variations. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param string * The string to output. * @param length * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -34,21 +34,140 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see fputc_unlocked() + * * @see f_print() * @see f_print_dynamic() * @see f_print_dynamic_partial() */ #if !defined(_di_f_print_) || !defined(_di_f_print_dynamic_) || !defined(_di_f_print_dynamic_partial_) - extern f_status_t private_f_print(FILE *output, const f_string_t string, const f_array_length_t length) f_attribute_visibility_internal; + extern f_status_t private_f_print(const f_string_t string, const f_array_length_t length, FILE *output) f_attribute_visibility_internal; #endif // !defined(_di_f_print_) || !defined(_di_f_print_dynamic_) || !defined(_di_f_print_dynamic_partial_) /** - * Private implementation of f_print_except(). + * Private implementation of f_print_character_safely_print(). * * Intended to be shared to each of the different implementation variations. * + * @param character + * The character to verify as safe or not. * @param output - * The file to output to, including standard streams such as stdout and stderr. + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_print_character_safely() + * @see f_print_safely() + * @see f_print_safely_dynamic() + * @see f_print_safely_dynamic_partial() + * @see f_print_safely_terminated() + * @see f_print_except_safely() + * @see f_print_except_dynamic_safely() + * @see f_print_except_dynamic_partial_safely() + * @see f_print_except_in_safely() + * @see f_print_except_in_dynamic_safely() + * @see f_print_except_in_dynamic_partial_safely() + */ +#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_) + extern f_status_t private_f_print_character_safely(const char character, FILE *output) f_attribute_visibility_internal; +#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_) + +/** + * Private implementation of f_print_character_safely_get(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param character + * The character to verify as safe or not. + * + * @return + * NULL is returned if the character is already replaced. + * 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. + * + * @see f_print_character_safely_get() + * @see f_print_dynamic_to_safely() + * @see f_print_dynamic_partial_to_safely() + * @see f_print_to_except_dynamic_safely() + * @see f_print_to_except_dynamic_partial_safely() + * @see f_print_to_except_safely() + * @see f_print_to_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_) + extern f_string_t private_f_print_character_safely_get(const char character) f_attribute_visibility_internal; +#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_) +/** + * Private implementation of f_print_raw(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_print_raw() + * @see f_print_raw_dynamic() + * @see f_print_raw_dynamic_partial() + */ +#if !defined(_di_f_print_raw_) || !defined(_di_f_print_raw_dynamic_) || !defined(_di_f_print_raw_dynamic_partial_) + extern f_status_t private_f_print_raw(const f_string_t string, const f_array_length_t length, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_raw_) || !defined(_di_f_print_raw_dynamic_) || !defined(_di_f_print_raw_dynamic_partial_) + +/** + * Private implementation of f_print_safely(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_print_safely() + * @see f_print_safely_dynamic() + * @see f_print_safely_dynamic_partial() + * @see f_utf_is_valid() + */ +#if !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_) + extern f_status_t private_f_print_safely(const f_string_t string, const f_array_length_t length, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_safely_) || !defined(_di_f_print_safely_dynamic_) || !defined(_di_f_print_safely_dynamic_partial_) + +/** + * Private implementation of f_print_except(). + * + * Intended to be shared to each of the different implementation variations. + * * @param string * The string to output. * @param offset @@ -58,6 +177,8 @@ extern "C" { * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -66,21 +187,90 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see fputc_unlocked() + * * @see f_print_except() * @see f_print_except_dynamic() * @see f_print_except_dynamic_partial() */ #if !defined(_di_f_print_except_) || !defined(_di_f_print_except_dynamic_) || !defined(_di_f_print_except_dynamic_partial_) - extern f_status_t private_f_print_except(FILE *output, const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except) f_attribute_visibility_internal; + extern 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) f_attribute_visibility_internal; #endif // !defined(_di_f_print_except_) || !defined(_di_f_print_except_dynamic_) || !defined(_di_f_print_except_dynamic_partial_) /** - * Private implementation of f_print_except_in(). + * Private implementation of f_print_except_raw(). * * Intended to be shared to each of the different implementation variations. * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_print_except_raw() + * @see f_print_except_dynamic_raw() + * @see f_print_except_dynamic_partial_raw() + */ +#if !defined(_di_f_print_except_raw_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_partial_raw_) + extern 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) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_except_raw_) || !defined(_di_f_print_except_dynamic_raw_) || !defined(_di_f_print_except_dynamic_partial_raw_) + +/** + * Private implementation of f_print_except_safely(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. * @param output - * The file to output to, including standard streams such as stdout and stderr. + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_print_except_safely() + * @see f_print_except_dynamic_safely() + * @see f_print_except_dynamic_partial_safely() + * @see f_utf_is_valid() + */ +#if !defined(_di_f_print_except_safely_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_dynamic_partial_safely_) + extern 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) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_except_safely_) || !defined(_di_f_print_except_dynamic_safely_) || !defined(_di_f_print_except_dynamic_partial_safely_) + +/** + * Private implementation of f_print_except_in(). + * + * Intended to be shared to each of the different implementation variations. + * * @param string * The string to output. * @param offset @@ -93,6 +283,8 @@ extern "C" { * @param except_in * An array of ranges within the string to not print. * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -101,25 +293,128 @@ extern "C" { * F_output (with error bit) on failure. * F_parameter (with error bit) if a parameter is invalid. * + * @see fputc_unlocked() + * * @see f_print_except_in() * @see f_print_except_in_dynamic() * @see f_print_except_in_dynamic_partial() */ #if !defined(_di_f_print_except_in_) || !defined(_di_f_print_except_dynamic_in_) || !defined(_di_f_print_except_in_dynamic_partial_) - extern f_status_t private_f_print_except_in(FILE *output, const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except_at, f_string_ranges_t except_in) f_attribute_visibility_internal; + extern 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, f_string_ranges_t except_in, FILE *output) f_attribute_visibility_internal; #endif // !defined(_di_f_print_except_in_) || !defined(_di_f_print_except_dynamic_in_) || !defined(_di_f_print_except_in_dynamic_partial_) /** - * Private implementation of f_print_to(). + * Private implementation of f_print_except_in_raw(). * * Intended to be shared to each of the different implementation variations. * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. * @param output - * The file to output to, including standard streams such as stdout and stderr. + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_print_except_in_raw() + * @see f_print_except_in_dynamic_raw() + * @see f_print_except_in_dynamic_partial_raw() + */ +#if !defined(_di_f_print_except_in_raw_) || !defined(_di_f_print_except_dynamic_in_raw_) || !defined(_di_f_print_except_in_dynamic_partial_raw_) + extern 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, f_string_ranges_t except_in, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_except_in_raw_) || !defined(_di_f_print_except_dynamic_in_raw_) || !defined(_di_f_print_except_in_dynamic_partial_raw_) + +/** + * Private implementation of f_print_except_in_safely(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_print_except_in_safely() + * @see f_print_except_in_dynamic_safely() + * @see f_print_except_in_dynamic_partial_safely() + * @see f_utf_is_valid() + */ +#if !defined(_di_f_print_except_in_safely_) || !defined(_di_f_print_except_dynamic_in_safely_) || !defined(_di_f_print_except_in_dynamic_partial_safely_) + extern 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, f_string_ranges_t except_in, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_except_in_safely_) || !defined(_di_f_print_except_dynamic_in_safely_) || !defined(_di_f_print_except_in_dynamic_partial_safely_) + +/** + * Private implementation of f_print_terminated(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_output (with error bit) on failure. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fputc_unlocked() + * + * @see f_print_terminated() + * @see f_print_raw_terminated() + */ +#if !defined(_di_f_print_terminated_) || !defined(_di_f_print_raw_terminated_) + extern f_status_t private_f_print_terminated(const f_string_t string, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_terminated_) || !defined(_di_f_print_raw_terminated_) + +/** + * Private implementation of f_print_to(). + * + * Intended to be shared to each of the different implementation variations. + * * @param string * The string to output. * @param length * The total number of characters to print. + * @param id + * The file descriptor to output to. * * @return * F_none on success. @@ -139,16 +434,81 @@ extern "C" { * @see f_print_to_dynamic_partial() */ #if !defined(_di_f_print_to_) || !defined(_di_f_print_to_dynamic_) || !defined(_di_f_print_to_dynamic_partial_) - extern f_status_t private_f_print_to(const int id, const f_string_t string, const f_array_length_t length) f_attribute_visibility_internal; + extern f_status_t private_f_print_to(const f_string_t string, const f_array_length_t length, const int id) f_attribute_visibility_internal; #endif // !defined(_di_f_print_to_) || !defined(_di_f_print_to_dynamic_) || !defined(_di_f_print_to_dynamic_partial_) /** + * Private implementation of f_print_to_raw(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see f_print_to_raw() + * @see f_print_to_dynamic_raw() + * @see f_print_to_dynamic_partial_raw() + */ +#if !defined(_di_f_print_to_raw_) || !defined(_di_f_print_to_dynamic_raw_) || !defined(_di_f_print_to_dynamic_partial_raw_) + extern f_status_t private_f_print_to_raw(const f_string_t string, const f_array_length_t length, const int id) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_to_raw_) || !defined(_di_f_print_to_dynamic_raw_) || !defined(_di_f_print_to_dynamic_partial_raw_) + +/** + * Private implementation of f_print_to_safely(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see f_print_to_safely() + * @see f_print_to_dynamic_safely() + * @see f_print_to_dynamic_partial_safely() + * @see f_utf_is_valid() + */ +#if !defined(_di_f_print_to_safely_) || !defined(_di_f_print_to_dynamic_safely_) || !defined(_di_f_print_to_dynamic_partial_safely_) + extern f_status_t private_f_print_to_safely(const f_string_t string, const f_array_length_t length, const int id) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_to_safely_) || !defined(_di_f_print_to_dynamic_safely_) || !defined(_di_f_print_to_dynamic_partial_safely_) + +/** * Private implementation of f_print_to(). * * Intended to be shared to each of the different implementation variations. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param string * The string to output. * @param offset @@ -158,6 +518,8 @@ extern "C" { * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. * * @return * F_none on success. @@ -177,9 +539,86 @@ extern "C" { * @see f_print_to_except_dynamic_partial() */ #if !defined(_di_f_print_to_except_) || !defined(_di_f_print_to_except_dynamic_) || !defined(_di_f_print_to_except_dynamic_partial_) - extern f_status_t private_f_print_to_except(const int id, const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except) f_attribute_visibility_internal; + extern f_status_t private_f_print_to_except(const f_string_t string, const f_array_length_t offset, const f_array_length_t stop, const f_array_lengths_t except, const int id) f_attribute_visibility_internal; #endif // !defined(_di_f_print_to_except_) || !defined(_di_f_print_to_except_dynamic_) || !defined(_di_f_print_to_except_dynamic_partial_) +/** + * Private implementation of f_print_to_raw(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see f_print_to_except_raw() + * @see f_print_to_except_dynamic_raw() + * @see f_print_to_except_dynamic_partial_raw() + */ +#if !defined(_di_f_print_to_except_raw_) || !defined(_di_f_print_to_except_dynamic_raw_) || !defined(_di_f_print_to_except_dynamic_partial_raw_) + extern f_status_t private_f_print_to_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, const int id) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_to_except_raw_) || !defined(_di_f_print_to_except_dynamic_raw_) || !defined(_di_f_print_to_except_dynamic_partial_raw_) + +/** + * Private implementation of f_print_to_safely(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param id + * The file descriptor to output to. + * + * @return + * F_none on success. + * F_data_not if length is 0. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see f_print_to_except_safely() + * @see f_print_to_except_dynamic_safely() + * @see f_print_to_except_dynamic_partial_safely() + * @see f_utf_is_valid() + */ +#if !defined(_di_f_print_to_except_safely_) || !defined(_di_f_print_to_except_dynamic_safely_) || !defined(_di_f_print_to_except_dynamic_partial_safely_) + extern f_status_t private_f_print_to_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, const int id) f_attribute_visibility_internal; +#endif // !defined(_di_f_print_to_except_safely_) || !defined(_di_f_print_to_except_dynamic_safely_) || !defined(_di_f_print_to_except_dynamic_partial_safely_) + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_print/data/build/dependencies b/level_0/f_print/data/build/dependencies index d798245..deb9037 100644 --- a/level_0/f_print/data/build/dependencies +++ b/level_0/f_print/data/build/dependencies @@ -4,3 +4,4 @@ f_type f_status f_memory f_string +f_utf diff --git a/level_0/f_print/data/build/settings b/level_0/f_print/data/build/settings index a30f3cc..e257986 100644 --- a/level_0/f_print/data/build/settings +++ b/level_0/f_print/data/build/settings @@ -20,10 +20,10 @@ build_compiler gcc build_indexer ar build_language c build_libraries -lc -build_libraries-individual -lf_memory -lf_string -build_sources_library print.c private-print.c +build_libraries-individual -lf_memory -lf_string -lf_utf +build_sources_library print.c print-common.c private-print.c build_sources_program -build_sources_headers print.h +build_sources_headers print.h print-common.h build_sources_script build_sources_setting build_script yes diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index 5829c8f..1ed6585 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -149,6 +149,8 @@ extern "C" { F_absolute_not, F_address, F_address_not, + F_ascii, + F_ascii_not, F_block, F_block_not, F_bound, diff --git a/level_0/f_string/data/build/settings b/level_0/f_string/data/build/settings index b0e7510..274d90b 100644 --- a/level_0/f_string/data/build/settings +++ b/level_0/f_string/data/build/settings @@ -23,7 +23,7 @@ build_libraries -lc build_libraries-individual -lf_memory build_sources_library string.c string-common.c private-string.c string_dynamic.c string_map.c string_quantity.c string_range.c string_triple.c build_sources_program -build_sources_headers string.h string-common.h private-string.h string_dynamic.h string_map.h string_quantity.h string_range.h string_triple.h +build_sources_headers string.h string-common.h string_dynamic.h string_map.h string_quantity.h string_range.h string_triple.h build_sources_script build_sources_setting build_script yes diff --git a/level_0/f_type_array/data/build/settings b/level_0/f_type_array/data/build/settings index b66604b..acc5998 100644 --- a/level_0/f_type_array/data/build/settings +++ b/level_0/f_type_array/data/build/settings @@ -23,7 +23,7 @@ build_libraries -lc build_libraries-individual -lf_memory build_sources_library type_array.c private-type_array.c build_sources_program -build_sources_headers type_array.h private-type_array.h type_array-common.h +build_sources_headers type_array.h type_array-common.h build_sources_script build_sources_setting build_script yes diff --git a/level_1/fl_print/c/print.c b/level_1/fl_print/c/print.c index ca0e12e..94ad5e6 100644 --- a/level_1/fl_print/c/print.c +++ b/level_1/fl_print/c/print.c @@ -5,8 +5,262 @@ extern "C" { #endif +#ifndef _di_fl_print_string_ + f_status_t fl_print_string(FILE *output, const f_string_t string, ...) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + if (!string) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + f_status_t status = F_none; + + va_list ap; + + va_start(ap, string); + + for (char *current = string; *current; current = current + 1) { + + if (*current == f_string_ascii_percent_s[0]) { + current = current + 1; + + status = private_fl_print_string_convert(current, &ap, output); + if (F_status_is_error(status)) break; + + if (!*current) break; + } + else if (!fputc_unlocked(*current, output)) { + return F_status_set_error(F_output); + } + } // for + + va_end(ap); + + return status; + } +#endif // _di_fl_print_string_ + +#ifndef _di_fl_print_string_convert_ + f_status_t fl_print_string_convert(FILE *output, char *current, va_list *ap) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_print_string_convert(current, ap, output); + } +#endif // _di_fl_print_string_convert_ + +#ifndef _di_fl_print_string_va_ + f_status_t fl_print_string_va(FILE *output, const f_string_t string, va_list ap) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + if (!string) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + uint8_t width = 0; + uint8_t i = 0; + + char *current = string; + char replace = *current; + + while (*current) { + + width = macro_f_utf_byte_width_is(*current); + + if (width) { + if (width == 1) { + if (!fputc_unlocked(f_print_sequence_unknown_s[0], output)) { + return F_status_set_error(F_output); + } + } + else { + for (i = 0; i < width && current[i]; ++i) { + // do nothing. + } // for + + if (i < width) { + if (!fputc_unlocked(f_print_sequence_unknown_s[0], output)) { + return F_status_set_error(F_output); + } + + break; + } + + for (i = 0; i < width; ++i) { + + if (!fputc_unlocked(current[i], output)) { + return F_status_set_error(F_output); + } + } // for + + current = current + (width - 1); + } + } + else { + if (*current > 32 && *current != 127) { + replace = *current; + } + else if (replace == 1) { + replace = f_print_sequence_start_of_header_s[0]; + } + else if (replace == 2) { + replace = f_print_sequence_start_of_text_s[0]; + } + else if (replace == 3) { + replace = f_print_sequence_end_of_text_s[0]; + } + else if (replace == 4) { + replace = f_print_sequence_end_of_transmission_s[0]; + } + else if (replace == 5) { + replace = f_print_sequence_end_of_enquiry_s[0]; + } + else if (replace == 6) { + replace = f_print_sequence_acknowledge_s[0]; + } + else if (replace == 7) { + replace = f_print_sequence_bell_s[0]; + } + else if (replace == 8) { + replace = f_print_sequence_backspace_s[0]; + } + else if (replace == 9) { + replace = f_print_sequence_tab_s[0]; + } + else if (replace == 10) { + replace = f_print_sequence_new_line_s[0]; + } + else if (replace == 11) { + replace = f_print_sequence_tab_vertical_s[0]; + } + else if (replace == 12) { + replace = f_print_sequence_form_feed_s[0]; + } + else if (replace == 13) { + replace = f_print_sequence_carriage_return_s[0]; + } + else if (replace == 14) { + replace = f_print_sequence_shift_out_s[0]; + } + else if (replace == 15) { + replace = f_print_sequence_shift_in_s[0]; + } + else if (replace == 16) { + replace = f_print_sequence_data_link_escape_s[0]; + } + else if (replace == 17) { + replace = f_print_sequence_device_control_1_s[0]; + } + else if (replace == 18) { + replace = f_print_sequence_device_control_2_s[0]; + } + else if (replace == 19) { + replace = f_print_sequence_device_control_3_s[0]; + } + else if (replace == 20) { + replace = f_print_sequence_device_control_4_s[0]; + } + else if (replace == 21) { + replace = f_print_sequence_negative_acknowledge_s[0]; + } + else if (replace == 22) { + replace = f_print_sequence_synchronous_idle_s[0]; + } + else if (replace == 23) { + replace = f_print_sequence_end_of_transmission_block_s[0]; + } + else if (replace == 24) { + replace = f_print_sequence_cancel_s[0]; + } + else if (replace == 25) { + replace = f_print_sequence_end_of_medium_s[0]; + } + else if (replace == 26) { + replace = f_print_sequence_substitute_s[0]; + } + else if (replace == 27) { + replace = f_print_sequence_escape_s[0]; + } + else if (replace == 28) { + replace = f_print_sequence_file_separator_s[0]; + } + else if (replace == 29) { + replace = f_print_sequence_group_separator_s[0]; + } + else if (replace == 30) { + replace = f_print_sequence_record_separator_s[0]; + } + else if (replace == 31) { + replace = f_print_sequence_unit_separator_s[0]; + } + else if (replace == 32) { + replace = f_print_sequence_space_s[0]; + } + else if (replace == 127) { + replace = f_print_sequence_delete_s[0]; + } + + if (!fputc_unlocked(replace, output)) { + return F_status_set_error(F_output); + } + } + + current = current + 1; + } // while + + return F_none; + } +#endif // _di_fl_print_string_va_ + +#ifndef _di_fl_print_trim_ + f_status_t fl_print_trim(const f_string_t string, const f_array_length_t length, FILE *output) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + if (!string || !length) { + return F_data_not; + } + + return private_fl_print_trim(string, length, output); + } +#endif // _di_fl_print_trim_ + +#ifndef _di_fl_print_trim_dynamic_ + f_status_t fl_print_trim_dynamic(const f_string_static_t buffer, FILE *output) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + if (!buffer.used) { + return F_data_not; + } + + return private_fl_print_trim(buffer.string, buffer.used, output); + } +#endif // _di_fl_print_trim_dynamic_ + +#ifndef _di_fl_print_trim_dynamic_partial_ + f_status_t fl_print_trim_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, FILE *output) { + #ifndef _di_level_1_parameter_checking_ + if (!output) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + if (!buffer.used || range.start > range.stop || range.start >= buffer.used) { + return F_data_not; + } + + f_array_length_t length = (range.stop - range.start) + 1; + + if (length + range.start > buffer.used) { + length = buffer.used - range.start; + } + + return private_fl_print_trim(buffer.string + range.start, length, output); + } +#endif // _di_fl_print_trim_dynamic_partial_ + #ifndef _di_fl_print_trim_except_ - f_status_t fl_print_trim_except(FILE *output, const f_string_t string, const f_array_length_t length, const f_array_lengths_t except) { + f_status_t fl_print_trim_except(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -17,12 +271,12 @@ extern "C" { const f_string_ranges_t except_in = f_string_ranges_t_initialize; - return private_fl_print_trim_except_in(output, string, 0, length, except, except_in); + return private_fl_print_trim_except_in(string, 0, length, except, except_in, output); } #endif // _di_fl_print_trim_except_ #ifndef _di_fl_print_trim_except_dynamic_ - f_status_t fl_print_trim_except_dynamic(FILE *output, const f_string_static_t buffer, const f_array_lengths_t except) { + f_status_t fl_print_trim_except_dynamic(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -33,12 +287,12 @@ extern "C" { const f_string_ranges_t except_in = f_string_ranges_t_initialize; - return private_fl_print_trim_except_in(output, buffer.string, 0, buffer.used, except, except_in); + return private_fl_print_trim_except_in(buffer.string, 0, buffer.used, except, except_in, output); } #endif // _di_fl_print_trim_except_dynamic_ #ifndef _di_fl_print_trim_except_in_ - f_status_t fl_print_trim_except_in(FILE *output, 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) { + f_status_t fl_print_trim_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) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -47,12 +301,12 @@ extern "C" { return F_data_not; } - return private_fl_print_trim_except_in(output, string, 0, length, except_at, except_in); + return private_fl_print_trim_except_in(string, 0, length, except_at, except_in, output); } #endif // _di_fl_print_trim_except_in_ #ifndef _di_fl_print_trim_except_in_dynamic_ - f_status_t fl_print_trim_except_in_dynamic(FILE *output, const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in) { + f_status_t fl_print_trim_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) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -61,12 +315,12 @@ extern "C" { return F_data_not; } - return private_fl_print_trim_except_in(output, buffer.string, 0, buffer.used, except_at, except_in); + return private_fl_print_trim_except_in(buffer.string, 0, buffer.used, except_at, except_in, output); } #endif // _di_fl_print_trim_except_in_dynamic_ #ifndef _di_fl_print_trim_except_in_dynamic_partial_ - f_status_t fl_print_trim_except_in_dynamic_partial(FILE *output, 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) { + f_status_t fl_print_trim_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) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -81,12 +335,12 @@ extern "C" { length = buffer.used - range.start; } - return private_fl_print_trim_except_in(output, buffer.string, range.start, range.start + length, except_at, except_in); + return private_fl_print_trim_except_in(buffer.string, range.start, range.start + length, except_at, except_in, output); } #endif // _di_fl_print_trim_except_in_dynamic_partial_ #ifndef _di_fl_print_trim_except_dynamic_partial_ - f_status_t fl_print_trim_except_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except) { + f_status_t fl_print_trim_except_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -103,12 +357,12 @@ extern "C" { const f_string_ranges_t except_in = f_string_ranges_t_initialize; - return private_fl_print_trim_except_in(output, buffer.string, range.start, range.start + length, except, except_in); + return private_fl_print_trim_except_in(buffer.string, range.start, range.start + length, except, except_in, output); } #endif // _di_fl_print_trim_except_dynamic_partial_ #ifndef _di_fl_print_trim_except_utf_ - f_status_t fl_print_trim_except_utf(FILE *output, const f_utf_string_t string, const f_array_length_t length, const f_array_lengths_t except) { + f_status_t fl_print_trim_except_utf(const f_utf_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -119,12 +373,12 @@ extern "C" { const f_string_ranges_t except_in = f_string_ranges_t_initialize; - return private_fl_print_trim_except_in_utf(output, string, 0, length, except, except_in); + return private_fl_print_trim_except_in_utf(string, 0, length, except, except_in, output); } #endif // _di_fl_print_trim_except_utf_ #ifndef _di_fl_print_trim_except_utf_dynamic_ - f_status_t fl_print_trim_except_utf_dynamic(FILE *output, const f_utf_string_static_t buffer, const f_array_lengths_t except) { + f_status_t fl_print_trim_except_utf_dynamic(const f_utf_string_static_t buffer, const f_array_lengths_t except, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -135,12 +389,12 @@ extern "C" { const f_string_ranges_t except_in = f_string_ranges_t_initialize; - return private_fl_print_trim_except_in_utf(output, buffer.string, 0, buffer.used, except, except_in); + return private_fl_print_trim_except_in_utf(buffer.string, 0, buffer.used, except, except_in, output); } #endif // _di_fl_print_trim_except_utf_dynamic_ #ifndef _di_fl_print_trim_except_in_utf_ - f_status_t fl_print_trim_except_in_utf(FILE *output, const f_utf_string_t string, const f_array_length_t length, const f_array_lengths_t except_at, const f_string_ranges_t except_in) { + f_status_t fl_print_trim_except_in_utf(const f_utf_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) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -149,12 +403,12 @@ extern "C" { return F_data_not; } - return private_fl_print_trim_except_in_utf(output, string, 0, length, except_at, except_in); + return private_fl_print_trim_except_in_utf(string, 0, length, except_at, except_in, output); } #endif // _di_fl_print_trim_except_in_utf_ #ifndef _di_fl_print_trim_except_in_utf_dynamic_ - f_status_t fl_print_trim_except_in_utf_dynamic(FILE *output, const f_utf_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in) { + f_status_t fl_print_trim_except_in_utf_dynamic(const f_utf_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -163,12 +417,12 @@ extern "C" { return F_data_not; } - return private_fl_print_trim_except_in_utf(output, buffer.string, 0, buffer.used, except_at, except_in); + return private_fl_print_trim_except_in_utf(buffer.string, 0, buffer.used, except_at, except_in, output); } #endif // _di_fl_print_trim_except_in_utf_dynamic_ #ifndef _di_fl_print_trim_except_in_utf_dynamic_partial_ - f_status_t fl_print_trim_except_in_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except_at, const f_string_ranges_t except_in) { + f_status_t fl_print_trim_except_in_utf_dynamic_partial(const f_utf_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) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -183,12 +437,12 @@ extern "C" { length = buffer.used - range.start; } - return private_fl_print_trim_except_in_utf(output, buffer.string, range.start, range.start + length, except_at, except_in); + return private_fl_print_trim_except_in_utf(buffer.string, range.start, range.start + length, except_at, except_in, output); } #endif // _di_fl_print_trim_except_in_utf_dynamic_partial_ #ifndef _di_fl_print_trim_except_utf_dynamic_partial_ - f_status_t fl_print_trim_except_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except) { + f_status_t fl_print_trim_except_utf_dynamic_partial(const f_utf_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -205,60 +459,12 @@ extern "C" { const f_string_ranges_t except_in = f_string_ranges_t_initialize; - return private_fl_print_trim_except_in_utf(output, buffer.string, range.start, range.start + length, except, except_in); + return private_fl_print_trim_except_in_utf(buffer.string, range.start, range.start + length, except, except_in, output); } #endif // _di_fl_print_trim_except_utf_dynamic_partial_ -#ifndef _di_fl_print_trim_ - f_status_t fl_print_trim(FILE *output, const f_string_t string, const f_array_length_t length) { - #ifndef _di_level_1_parameter_checking_ - if (!output) return F_status_set_error(F_parameter); - #endif // _di_level_1_parameter_checking_ - - if (!string || !length) { - return F_data_not; - } - - return private_fl_print_trim(output, string, length); - } -#endif // _di_fl_print_trim_ - -#ifndef _di_fl_print_trim_dynamic_ - f_status_t fl_print_trim_dynamic(FILE *output, const f_string_static_t buffer) { - #ifndef _di_level_1_parameter_checking_ - if (!output) return F_status_set_error(F_parameter); - #endif // _di_level_1_parameter_checking_ - - if (!buffer.used) { - return F_data_not; - } - - return private_fl_print_trim(output, buffer.string, buffer.used); - } -#endif // _di_fl_print_trim_dynamic_ - -#ifndef _di_fl_print_trim_dynamic_partial_ - f_status_t fl_print_trim_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range) { - #ifndef _di_level_1_parameter_checking_ - if (!output) return F_status_set_error(F_parameter); - #endif // _di_level_1_parameter_checking_ - - if (!buffer.used || range.start > range.stop || range.start >= buffer.used) { - return F_data_not; - } - - f_array_length_t length = (range.stop - range.start) + 1; - - if (length + range.start > buffer.used) { - length = buffer.used - range.start; - } - - return private_fl_print_trim(output, buffer.string + range.start, length); - } -#endif // _di_fl_print_trim_dynamic_partial_ - #ifndef _di_fl_print_trim_utf_ - f_status_t fl_print_trim_utf(FILE *output, const f_utf_string_t string, const f_array_length_t length) { + f_status_t fl_print_trim_utf(const f_utf_string_t string, const f_array_length_t length, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -267,12 +473,12 @@ extern "C" { return F_data_not; } - return private_fl_print_trim_utf(output, string, length); + return private_fl_print_trim_utf(string, length, output); } #endif // _di_fl_print_trim_utf_ #ifndef _di_fl_print_trim_utf_dynamic_ - f_status_t fl_print_trim_utf_dynamic(FILE *output, const f_utf_string_static_t buffer) { + f_status_t fl_print_trim_utf_dynamic(const f_utf_string_static_t buffer, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -281,12 +487,12 @@ extern "C" { return F_data_not; } - return private_fl_print_trim_utf(output, buffer.string, buffer.used); + return private_fl_print_trim_utf(buffer.string, buffer.used, output); } #endif // _di_fl_print_trim_utf_dynamic_ #ifndef _di_fl_print_trim_utf_dynamic_partial_ - f_status_t fl_print_trim_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_string_range_t range) { + f_status_t fl_print_trim_utf_dynamic_partial(const f_utf_string_static_t buffer, const f_string_range_t range, FILE *output) { #ifndef _di_level_1_parameter_checking_ if (!output) return F_status_set_error(F_parameter); #endif // _di_level_1_parameter_checking_ @@ -301,7 +507,7 @@ extern "C" { length = buffer.used - range.start; } - return private_fl_print_trim_utf(output, buffer.string + range.start, length); + return private_fl_print_trim_utf(buffer.string + range.start, length, output); } #endif // _di_fl_print_trim_utf_dynamic_partial_ diff --git a/level_1/fl_print/c/print.h b/level_1/fl_print/c/print.h index da16d52..1c08801 100644 --- a/level_1/fl_print/c/print.h +++ b/level_1/fl_print/c/print.h @@ -22,22 +22,276 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { #endif /** + * A formatted print function similar to (but not the same as) the c-library fprintf() function. + * + * @todo add the complex documentation. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * This function violates this FLL projects' standard practice of having a parameter with '*' before const parameters. + * This is done as an exception case to achieve similar arguments structure with the fprintf() family of functions. + * + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * @param string + * The formatted string to process and output. + * This is a NULL terminated string. + * @param ... + * Additional arguments relating to the string. + * + * @return + * F_none on success. + * + * F_output (with error bit) on failure to print to the output file. + * F_valid_not (with error bit) on invalid syntax (such as terminating the string on a single '%'). + * + * Success from: f_print_dynamic(). + * Success from: f_print_dynamic_safely(). + * 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_print_dynamic(). + * Errors (with error bit) from: f_print_dynamic_safely(). + * Errors (with error bit) from: f_print_safely(). + * Errors (with error bit) from: f_print_terminated(). + * + * @see fputc_unlocked() + * @see va_start() + * @see va_end() + * + * @see f_conversion_number_signed_to_file() + * @see f_conversion_number_unsigned_to_file() + * @see f_print_dynamic() + * @see f_print_dynamic_safely() + * @see f_print_safely() + * @see f_print_terminated() + */ +#ifndef _di_fl_print_string_ + extern f_status_t fl_print_string(FILE *output, const f_string_t string, ...); +#endif // _di_fl_print_string_ + +/** + * Convert and print a single part of a formatted string represented by the '%'. + * + * This should be called after each first '%' is encountered. + * This should return only after a single '%' group is fully processed, end of current is reached, or an error occurs. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * This function violates this FLL projects' standard practice of having a parameter with '*' before const parameters. + * This is done as an exception case to achieve similar arguments structure with the fprintf() family of functions. + * + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * @param current + * The current character position within the string. + * @param ap + * The variable arguments list. + * + * @return + * F_none on success. + * + * F_output (with error bit) on failure to print to the output file. + * F_valid_not (with error bit) on invalid syntax (such as terminating the string on a single '%'). + * + * Success from: f_print_dynamic(). + * Success from: f_print_dynamic_safely(). + * 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_print_dynamic(). + * Errors (with error bit) from: f_print_dynamic_safely(). + * Errors (with error bit) from: f_print_safely(). + * Errors (with error bit) from: f_print_terminated(). + * + * @see fputc_unlocked() + * + * @see f_conversion_number_signed_to_file() + * @see f_conversion_number_unsigned_to_file() + * @see f_print_dynamic() + * @see f_print_dynamic_safely() + * @see f_print_safely() + * @see f_print_terminated() + */ +#ifndef _di_fl_print_string_convert_ + extern f_status_t fl_print_string_convert(FILE *output, char *current, va_list *ap); +#endif // _di_fl_print_string_convert_ + +/** + * A formatted print function similar to (but not the same as) the c-library vfprintf() function. + * + * @todo add the complex documentation. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * This function violates this FLL projects' standard practice of having a parameter with '*' before const parameters. + * This is done as an exception case to achieve similar arguments structure with the fprintf() family of functions. + * + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * @param string + * The formatted string to process and output. + * @param ap + * The variable list. + * The va_start(ap, string) and va_end(ap) is required to be called outside this function. + * + * @return + * F_none on success. + * + * F_output (with error bit) on failure to print to the output file. + * F_valid_not (with error bit) on invalid syntax (such as terminating the string on a single '%'). + * + * Success from: f_print_dynamic(). + * Success from: f_print_dynamic_safely(). + * 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_print_dynamic(). + * Errors (with error bit) from: f_print_dynamic_safely(). + * Errors (with error bit) from: f_print_safely(). + * Errors (with error bit) from: f_print_terminated(). + * + * @see fputc_unlocked() + * @see va_start() + * @see va_end() + * + * @see f_conversion_number_signed_to_file() + * @see f_conversion_number_unsigned_to_file() + * @see f_print_dynamic() + * @see f_print_dynamic_safely() + * @see f_print_safely() + * @see f_print_terminated() + */ +#ifndef _di_fl_print_string_va_ + extern f_status_t fl_print_string_va(FILE *output, const f_string_t string, va_list ap); +#endif // _di_fl_print_string_va_ + +/** * Print a string, stripping leading and trailing whitespace. * * Except for leading/trailing whitespace, the string is printed as-is without interpretation. * * Will not stop at \0. * Will not print \0. - * Will not print any 1-byte character at a location specified in except array. * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. * @param output - * The file to output to, including standard streams such as stdout and stderr. + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() + */ +#ifndef _di_fl_print_trim_ + extern f_status_t fl_print_trim(const f_string_t string, const f_array_length_t length, FILE *output); +#endif // _di_fl_print_trim_ + +/** + * Print a dynamic string, stripping leading and trailing whitespace. + * + * Except for leading/trailing whitespace, the string is printed as-is without interpretation. + * + * Will not stop at \0. + * Will not print \0. + * Will print the entire dynamic string, except for leading/trailing whitespace. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() + */ +#ifndef _di_fl_print_trim_dynamic_ + extern f_status_t fl_print_trim_dynamic(const f_string_static_t buffer, FILE *output); +#endif // _di_fl_print_trim_dynamic_ + +/** + * Print a partial dynamic string, stripping leading and trailing whitespace. + * + * Except for leading/trailing whitespace, the string is printed as-is without interpretation. + * + * Will not stop at \0. + * Will not print \0. + * Will print the only the buffer range specified by range, except for leading/trailing whitespace. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on error when printing to output. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() + */ +#ifndef _di_fl_print_trim_dynamic_partial_ + extern f_status_t fl_print_trim_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, FILE *output); +#endif // _di_fl_print_trim_dynamic_partial_ + +/** + * Print a string, stripping leading and trailing whitespace. + * + * Except for leading/trailing whitespace, the string is printed as-is without interpretation. + * + * Will not stop at \0. + * Will not print \0. + * Will not print any 1-byte character at a location specified in except array. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param string * The string to output. * @param length @@ -45,6 +299,8 @@ extern "C" { * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -56,9 +312,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_ - extern f_status_t fl_print_trim_except(FILE *output, const f_string_t string, const f_array_length_t length, const f_array_lengths_t except); + extern f_status_t fl_print_trim_except(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output); #endif // _di_fl_print_trim_except_ /** @@ -71,13 +329,15 @@ extern "C" { * Will print the entire dynamic string, except for leading/trailing whitespace. * Will not print any 1-byte character at a location specified in except array. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -89,9 +349,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_dynamic_ - extern f_status_t fl_print_trim_except_dynamic(FILE *output, const f_string_static_t buffer, const f_array_lengths_t except); + extern f_status_t fl_print_trim_except_dynamic(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output); #endif // _di_fl_print_trim_except_dynamic_ /** @@ -104,8 +366,8 @@ extern "C" { * Will not print any 1-byte character at a location specified in except_at array. * Will not print any 1-byte character within the ranges specified in except_in array. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param string * The string to output. * @param length @@ -116,6 +378,8 @@ extern "C" { * @param except_in * An array of ranges within the string to not print. * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -127,9 +391,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_in_ - extern f_status_t fl_print_trim_except_in(FILE *output, 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); + extern f_status_t fl_print_trim_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); #endif // _di_fl_print_trim_except_in_ /** @@ -143,8 +409,8 @@ extern "C" { * Will not print any 1-byte character at a location specified in except_at array. * Will not print any 1-byte character within the ranges specified in except_in array. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. * @param except_at @@ -153,6 +419,8 @@ extern "C" { * @param except_in * An array of ranges within the string to not print. * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -164,9 +432,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_in_dynamic_ - extern f_status_t fl_print_trim_except_in_dynamic(FILE *output, const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in); + extern f_status_t fl_print_trim_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); #endif // _di_fl_print_trim_except_in_dynamic_ /** @@ -180,8 +450,8 @@ extern "C" { * Will not print any 1-byte character within the ranges specified in except_in array. * Will print the only the buffer range specified by range, except for leading/trailing whitespace. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. * @param range @@ -192,6 +462,8 @@ extern "C" { * @param except_in * An array of ranges within the string to not print. * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -203,9 +475,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_in_dynamic_partial_ - extern f_status_t fl_print_trim_except_in_dynamic_partial(FILE *output, 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); + extern f_status_t fl_print_trim_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); #endif // _di_fl_print_trim_except_in_dynamic_partial_ /** @@ -218,8 +492,8 @@ extern "C" { * Will not print any 1-byte character at a location specified in except array. * Will print the only the buffer range specified by range, except for leading/trailing whitespace. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. * @param range @@ -227,6 +501,8 @@ extern "C" { * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -238,9 +514,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_dynamic_partial_ - extern f_status_t fl_print_trim_except_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except); + extern f_status_t fl_print_trim_except_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); #endif // _di_fl_print_trim_except_dynamic_partial_ /** @@ -252,8 +530,8 @@ extern "C" { * Will not print \0. * Will not print any 1 UTF character at a location specified in except array. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param string * The string to output. * @param length @@ -261,6 +539,8 @@ extern "C" { * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -272,9 +552,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_utf_ - extern f_status_t fl_print_trim_except_utf(FILE *output, const f_utf_string_t string, const f_array_length_t length, const f_array_lengths_t except); + extern f_status_t fl_print_trim_except_utf(const f_utf_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output); #endif // _di_fl_print_trim_except_utf_ /** @@ -287,13 +569,15 @@ extern "C" { * Will not print any 1 UTF character at a location specified in except array. * Will print the entire dynamic string, except for leading/trailing whitespace. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -305,9 +589,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_utf_dynamic_ - extern f_status_t fl_print_trim_except_utf_dynamic(FILE *output, const f_utf_string_static_t buffer, const f_array_lengths_t except); + extern f_status_t fl_print_trim_except_utf_dynamic(const f_utf_string_static_t buffer, const f_array_lengths_t except, FILE *output); #endif // _di_fl_print_trim_except_utf_dynamic_ /** @@ -320,8 +606,8 @@ extern "C" { * Will not print any 1 UTF character at a location specified in except_at array. * Will not print any 1 UTF character within the ranges specified in except_in array. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param string * The string to output. * @param length @@ -332,6 +618,8 @@ extern "C" { * @param except_in * An array of ranges within the string to not print. * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -343,9 +631,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_in_utf_ - extern f_status_t fl_print_trim_except_in_utf(FILE *output, const f_utf_string_t string, const f_array_length_t length, const f_array_lengths_t except_at, const f_string_ranges_t except_in); + extern f_status_t fl_print_trim_except_in_utf(const f_utf_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); #endif // _di_fl_print_trim_except_in_utf_ /** @@ -359,8 +649,8 @@ extern "C" { * Will not print any 1 UTF character within the ranges specified in except_in array. * Will print the entire dynamic string, except for leading/trailing whitespace. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. * @param except_at @@ -369,6 +659,8 @@ extern "C" { * @param except_in * An array of ranges within the string to not print. * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -380,9 +672,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_in_utf_dynamic_ - extern f_status_t fl_print_trim_except_in_utf_dynamic(FILE *output, const f_utf_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in); + extern f_status_t fl_print_trim_except_in_utf_dynamic(const f_utf_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output); #endif // _di_fl_print_trim_except_in_utf_dynamic_ /** @@ -396,8 +690,8 @@ extern "C" { * Will not print any 1 UTF character within the ranges specified in except_in array. * Will print the only the buffer range specified by range, except for leading/trailing whitespace. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. * @param range @@ -408,6 +702,8 @@ extern "C" { * @param except_in * An array of ranges within the string to not print. * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -419,9 +715,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_in_utf_dynamic_partial_ - extern f_status_t fl_print_trim_except_in_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except_at, const f_string_ranges_t except_in); + extern f_status_t fl_print_trim_except_in_utf_dynamic_partial(const f_utf_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); #endif // _di_fl_print_trim_except_in_utf_dynamic_partial_ /** @@ -434,8 +732,8 @@ extern "C" { * Will not print any 1 UTF character at a location specified in except array. * Will print the only the buffer range specified by range, except for leading/trailing whitespace. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. * @param range @@ -443,6 +741,8 @@ extern "C" { * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -454,9 +754,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_except_utf_dynamic_partial_ - extern f_status_t fl_print_trim_except_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except); + extern f_status_t fl_print_trim_except_utf_dynamic_partial(const f_utf_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); #endif // _di_fl_print_trim_except_utf_dynamic_partial_ /** @@ -467,102 +769,14 @@ extern "C" { * Will not stop at \0. * Will not print \0. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. - * @param string - * The string to output. - * @param length - * The total number of characters to print. - * - * @return - * F_none on success. - * F_data_not on success but there is nothing to print. - * - * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. - * F_output (with error bit) on error when printing to output. - * F_parameter (with error bit) if a parameter is invalid. - * F_utf (with error bit) if character is an invalid UTF-8 character. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. * - * Errors (with error bit) from: f_utf_is_whitespace(). - */ -#ifndef _di_fl_print_trim_ - extern f_status_t fl_print_trim(FILE *output, const f_string_t string, const f_array_length_t length); -#endif // _di_fl_print_trim_ - -/** - * Print a dynamic string, stripping leading and trailing whitespace. - * - * Except for leading/trailing whitespace, the string is printed as-is without interpretation. - * - * Will not stop at \0. - * Will not print \0. - * Will print the entire dynamic string, except for leading/trailing whitespace. - * - * @param output - * The file to output to, including standard streams such as stdout and stderr. - * @param buffer - * The string to output. - * - * @return - * F_none on success. - * F_data_not on success but there is nothing to print. - * - * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. - * F_output (with error bit) on error when printing to output. - * F_parameter (with error bit) if a parameter is invalid. - * F_utf (with error bit) if character is an invalid UTF-8 character. - * - * Errors (with error bit) from: f_utf_is_whitespace(). - */ -#ifndef _di_fl_print_trim_dynamic_ - extern f_status_t fl_print_trim_dynamic(FILE *output, const f_string_static_t buffer); -#endif // _di_fl_print_trim_dynamic_ - -/** - * Print a partial dynamic string, stripping leading and trailing whitespace. - * - * Except for leading/trailing whitespace, the string is printed as-is without interpretation. - * - * Will not stop at \0. - * Will not print \0. - * Will print the only the buffer range specified by range, except for leading/trailing whitespace. - * - * @param output - * The file to output to, including standard streams such as stdout and stderr. - * @param buffer - * The string to output. - * @param range - * The range within the provided string to print. - * - * @return - * F_none on success. - * F_data_not on success but there is nothing to print. - * - * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. - * F_output (with error bit) on error when printing to output. - * F_parameter (with error bit) if a parameter is invalid. - * F_utf (with error bit) if character is an invalid UTF-8 character. - * - * Errors (with error bit) from: f_utf_is_whitespace(). - */ -#ifndef _di_fl_print_trim_dynamic_partial_ - extern f_status_t fl_print_trim_dynamic_partial(FILE *output, const f_string_static_t buffer, const f_string_range_t range); -#endif // _di_fl_print_trim_dynamic_partial_ - -/** - * Print a string, stripping leading and trailing whitespace. - * - * Except for leading/trailing whitespace, the string is printed as-is without interpretation. - * - * Will not stop at \0. - * Will not print \0. - * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param string * The string to output. * @param length * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -574,9 +788,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_utf_ - extern f_status_t fl_print_trim_utf(FILE *output, const f_utf_string_t string, const f_array_length_t length); + extern f_status_t fl_print_trim_utf(const f_utf_string_t string, const f_array_length_t length, FILE *output); #endif // _di_fl_print_trim_utf_ /** @@ -588,10 +804,12 @@ extern "C" { * Will not print \0. * Will print the entire dynamic string, except for leading/trailing whitespace. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -603,9 +821,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_utf_dynamic_ - extern f_status_t fl_print_trim_utf_dynamic(FILE *output, const f_utf_string_static_t buffer); + extern f_status_t fl_print_trim_utf_dynamic(const f_utf_string_static_t buffer, FILE *output); #endif // _di_fl_print_trim_utf_dynamic_ /** @@ -617,12 +837,14 @@ extern "C" { * Will not print \0. * Will print the only the buffer range specified by range, except for leading/trailing whitespace. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * * @param buffer * The string to output. * @param range * The range within the provided string to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. @@ -634,9 +856,11 @@ extern "C" { * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() */ #ifndef _di_fl_print_trim_utf_dynamic_partial_ - extern f_status_t fl_print_trim_utf_dynamic_partial(FILE *output, const f_utf_string_static_t buffer, const f_string_range_t range); + extern f_status_t fl_print_trim_utf_dynamic_partial(const f_utf_string_static_t buffer, const f_string_range_t range, FILE *output); #endif // _di_fl_print_trim_utf_dynamic_partial_ #ifdef __cplusplus diff --git a/level_1/fl_print/c/private-print.c b/level_1/fl_print/c/private-print.c index a916c1d..2abfab2 100644 --- a/level_1/fl_print/c/private-print.c +++ b/level_1/fl_print/c/private-print.c @@ -5,9 +5,471 @@ extern "C" { #endif +#if !defined(_di_fl_print_string_convert_) || !defined(_di_fl_print_string_) + f_status_t private_fl_print_string_convert(char *current, va_list *ap, FILE *output) { + + // An unpaired '%' character must not be at the end of the string. + if (!*current) { + return F_status_set_error(F_valid_not); + } + + uint8_t base = 10; + uint16_t flag = 0; + uint8_t type = 0; + + unsigned int width = 1; + unsigned int precision = 1; + + for (; *current; current = current + 1) { + + if (*current == f_string_ascii_minus_s[0]) { + flag |= f_print_format_flag_align_left; + } + else if (*current == f_string_ascii_pound_s[0]) { + flag |= f_print_format_flag_convert; + } + else if (*current == f_string_ascii_parenthesis_open_s[0]) { + flag |= f_print_format_flag_ignore_index; // @todo + } + else if (*current == f_string_ascii_parenthesis_close_s[0]) { + flag |= f_print_format_flag_ignore_range; // @todo + } + else if (*current == f_string_ascii_plus_s[0]) { + flag |= f_print_format_flag_sign_always; + } + else if (*current == f_string_ascii_space_s[0]) { + flag |= f_print_format_flag_sign_pad; + } + else if (*current == f_string_ascii_equal_s[0]) { + flag |= f_print_format_flag_trim; + } + else if (*current == f_string_ascii_0_s[0] || *current == f_string_ascii_1_s[0] || *current == f_string_ascii_2_s[0] || *current == f_string_ascii_3_s[0] || *current == f_string_ascii_4_s[0] || *current == f_string_ascii_5_s[0] || *current == f_string_ascii_6_s[0] || *current == f_string_ascii_7_s[0] || *current == f_string_ascii_8_s[0] || *current == f_string_ascii_9_s[0]) { + + if (!(flag & f_print_format_flag_width)) { + if (*current == f_string_ascii_0_s[0]) { + flag |= f_print_format_flag_zeros_leading; + } + else { + flag |= f_print_format_flag_width; + + if (private_fl_print_convert_number(current, ap, &width)) { + break; + } + } + } + else { + return F_status_set_error(F_valid_not); + } + } + else if (*current == f_string_ascii_dollar_s[0]) { + // If followed immediately by a '$' this is ignored. + // Use '%$' to separate, such as '%l%$l' would allow for '0l' to be printed where '%ll' would interpret the 'l', resulting in a long long. + return F_none; + } + else if (*current == f_string_ascii_exclamation_s[0]) { + base = 2; + } + else if (*current == f_string_ascii_sign_at_s[0]) { + base = 8; + } + else if (*current == f_string_ascii_caret_s[0]) { + base = 10; + } + else if (*current == f_string_ascii_ampersand_s[0]) { + base = 12; + } + else if (*current == f_string_ascii_underscore_s[0]) { + base = 16; + } + else if (*current == f_string_ascii_period_s[0]) { + if (!*(current + 1)) { + return F_status_set_error(F_valid_not); + } + + if (private_fl_print_convert_number(current, ap, &precision)) { + break; + } + + continue; + } + else { + if (*current == f_string_ascii_c_s[0]) { + + // char. + const char value = (char) va_arg(*ap, int); + + if (!fputc_unlocked(value, output)) { + return F_status_set_error(F_output); + } + + return F_none; + } + else if (*current == f_string_ascii_C_s[0]) { + + // safe character. + char value[1] = { (char) va_arg(*ap, int) }; + + return f_print_safely(value, 1, output); + } + else if (*current == f_string_ascii_i_s[0]) { + type = f_print_format_type_signed; + + if (*(current + 1) == f_string_ascii_i_s[0]) { + if (*(current + 2) == f_string_ascii_i_s[0]) { + type = f_print_format_type_signed_8; + current = current + 2; + } + else { + type = f_print_format_type_signed_16; + current = current + 1; + } + } + } + else if (*current == f_string_ascii_I_s[0]) { + type = f_print_format_type_signed; + flag |= f_print_format_flag_uppercase; + + if (*(current + 1) == f_string_ascii_I_s[0]) { + if (*(current + 2) == f_string_ascii_I_s[0]) { + type = f_print_format_type_signed_8; + current = current + 2; + } + else { + type = f_print_format_type_signed_16; + current = current + 1; + } + } + } + else if (*current == f_string_ascii_l_s[0]) { + type = f_print_format_type_long; + + if (*(current + 1) == f_string_ascii_l_s[0]) { + type = f_print_format_type_long_long; + current = current + 1; + } + } + else if (*current == f_string_ascii_L_s[0]) { + type = f_print_format_type_long; + flag |= f_print_format_flag_uppercase; + + if (*(current + 1) == f_string_ascii_L_s[0]) { + type = f_print_format_type_long_long; + current = current + 1; + } + } + else if (*current == f_string_ascii_n_s[0]) { + type = f_print_format_type_number; + } + else if (*current == f_string_ascii_N_s[0]) { + type = f_print_format_type_number; + flag |= f_print_format_flag_uppercase; + } + else if (*current == f_string_ascii_q_s[0]) { + + // static/dynamic string. + const f_string_static_t value = va_arg(*ap, f_string_static_t); + + if (flag & f_print_format_flag_trim) { + return private_fl_print_trim(value.string, value.used, output); + } + + return f_print_dynamic(value, output); + } + else if (*current == f_string_ascii_Q_s[0]) { + + // safe static/dynamic string. + const f_string_static_t value = va_arg(*ap, f_string_static_t); + + if (flag & f_print_format_flag_trim) { + return private_fl_print_trim(value.string, value.used, output); + } + + return f_print_dynamic_safely(value, output); + } + else if (*current == f_string_ascii_r_s[0]) { + + // raw static/dynamic string. + const f_string_static_t value = va_arg(*ap, f_string_static_t); + + if (flag & f_print_format_flag_trim) { + return private_fl_print_trim(value.string, value.used, output); + } + + return f_print_dynamic_raw(value, output); + } + else if (*current == f_string_ascii_s_s[0]) { + + // NULL terminated string. + const f_string_t value = va_arg(*ap, f_string_t); + + if (flag & f_print_format_flag_trim) { + // @todo: implement a: private_fl_print_trim_teminated(). + //return private_fl_print_trim_teminated(value, output); + } + + return f_print_terminated(value, output); + } + else if (*current == f_string_ascii_S_s[0]) { + + // NULL terminated static/dynamic string. + const f_string_static_t value = va_arg(*ap, f_string_static_t); + + if (flag & f_print_format_flag_trim) { + return private_fl_print_trim(value.string, value.used, output); + } + + return f_print_dynamic(value, output); + } + else if (*current == f_string_ascii_u_s[0]) { + type = f_print_format_type_unsigned; + + if (*(current + 1)) { + if (*(current + 1) == f_string_ascii_i_s[0]) { + if (*(current + 2) == f_string_ascii_i_s[0]) { + type = f_print_format_type_unsigned_8; + current = current + 2; + } + else { + type = f_print_format_type_unsigned_16; + current = current + 1; + } + } + else if (*(current + 1) == f_string_ascii_n_s[0]) { + if (*(current + 2) == f_string_ascii_l_s[0]) { + type = f_print_format_type_unsigned_long_long; + current = current + 2; + } + else { + type = f_print_format_type_unsigned_long; + current = current + 1; + } + } + else if (*(current + 1) == f_string_ascii_n_s[0]) { + type = f_print_format_type_unsigned_number; + current = current + 1; + } + } + } + else if (*current == f_string_ascii_U_s[0]) { + type = f_print_format_type_unsigned; + flag |= f_print_format_flag_uppercase; + + if (*(current + 1)) { + if (*(current + 1) == f_string_ascii_I_s[0]) { + if (*(current + 2) == f_string_ascii_I_s[0]) { + type = f_print_format_type_unsigned_8; + current = current + 2; + } + else { + type = f_print_format_type_unsigned_16; + current = current + 1; + } + } + else if (*(current + 1) == f_string_ascii_N_s[0]) { + if (*(current + 2) == f_string_ascii_L_s[0]) { + type = f_print_format_type_unsigned_long_long; + current = current + 2; + } + else { + type = f_print_format_type_unsigned_long; + current = current + 1; + } + } + else if (*(current + 1) == f_string_ascii_N_s[0]) { + type = f_print_format_type_unsigned_number; + current = current + 1; + } + } + } + else if (*current == f_string_ascii_z_s[0]) { + type = f_print_format_type_size; + } + else if (*current == f_string_ascii_Z_s[0]) { + type = f_print_format_type_size; + flag |= f_print_format_flag_uppercase; + } + else { + return F_status_set_error(F_valid_not); + } + + f_conversion_data_t conversion_data = macro_f_conversion_data_t_initialize(base, 0, 1); + + if (flag & f_print_format_flag_align_left) { + conversion_data.flag |= f_conversion_data_flag_align_left; + } + + if (flag & f_print_format_flag_convert) { + conversion_data.flag |= f_conversion_data_flag_base_prepend; + } + + if (flag & f_print_format_flag_sign_always) { + conversion_data.flag |= f_conversion_data_flag_sign_always; + } + + if (flag & f_print_format_flag_sign_pad) { + conversion_data.flag |= f_conversion_data_flag_sign_pad; + } + + if (flag & f_print_format_flag_uppercase) { + conversion_data.flag |= f_conversion_data_flag_base_upper; + } + + if (flag & f_print_format_flag_zeros_leading) { + conversion_data.flag |= f_conversion_data_flag_zeros_leading; + } + + if (flag & f_print_format_flag_width) { + conversion_data.width = width; + } + else if (flag & f_print_format_flag_precision) { + conversion_data.width = precision; + } + + f_status_t status = F_none; + + if (type == f_print_format_type_long) { + status = f_conversion_number_signed_to_file((f_number_signed_t) va_arg(*ap, long), conversion_data, output); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_long_long) { + status = f_conversion_number_signed_to_file((f_number_signed_t) va_arg(*ap, long), conversion_data, output); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_number) { + status = f_conversion_number_signed_to_file((f_number_signed_t) va_arg(*ap, f_number_signed_t), conversion_data, output); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_signed) { + status = f_conversion_number_signed_to_file((f_number_signed_t) va_arg(*ap, int), conversion_data, output); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_signed_16) { + // @todo research this: 'short int' is promoted to 'int' when passed through '...'. + 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); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_signed_8) { + // @todo research this: 'signed char' is promoted to 'int' when passed through '...'. + 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); + if (F_status_is_error(status)) return status; + } + 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); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_unsigned) { + status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) va_arg(*ap, unsigned int), conversion_data, output); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_unsigned_16) { + // @todo research this: 'short unsigned int' is promoted to 'int' when passed through '...'. + const uint16_t value = (uint16_t) va_arg(*ap, int); + + status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) value, conversion_data, output); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_unsigned_8) { + // @todo research this: 'unsigned char' is promoted to 'int' when passed through '...'. + const uint8_t value = (uint8_t) va_arg(*ap, int); + + status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) value, conversion_data, output); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_unsigned_long) { + status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) va_arg(*ap, unsigned long), conversion_data, output); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_unsigned_long_long) { + status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) va_arg(*ap, unsigned long long), conversion_data, output); + if (F_status_is_error(status)) return status; + } + else if (type == f_print_format_type_unsigned_number) { + status = f_conversion_number_unsigned_to_file((f_number_unsigned_t) va_arg(*ap, f_number_unsigned_t), conversion_data, output); + if (F_status_is_error(status)) return status; + } + + return F_none; + } + } // for + + if (*current) { + return F_none; + } + + return F_status_set_error(F_valid_not); + } +#endif // !defined(_di_fl_print_string_convert_) || !defined(_di_fl_print_string_) + +#if !defined(_di_fl_print_string_convert_) || !defined(_di_fl_print_string_) + f_status_t private_fl_print_convert_number(char *current, va_list *ap, unsigned int *number) { + + *number = 0; + + for (current = current + 1; *current; current = current + 1) { + + if (*current == f_string_ascii_0_s[0]) { + *number *= 10; + } + else if (*current == f_string_ascii_1_s[0]) { + *number *= 10; + *number += 1; + } + else if (*current == f_string_ascii_2_s[0]) { + *number *= 10; + *number += 2; + } + else if (*current == f_string_ascii_3_s[0]) { + *number *= 10; + *number += 3; + } + else if (*current == f_string_ascii_4_s[0]) { + *number *= 10; + *number += 4; + } + else if (*current == f_string_ascii_5_s[0]) { + *number *= 10; + *number += 5; + } + else if (*current == f_string_ascii_6_s[0]) { + *number *= 10; + *number += 6; + } + else if (*current == f_string_ascii_7_s[0]) { + *number *= 10; + *number += 7; + } + else if (*current == f_string_ascii_8_s[0]) { + *number *= 10; + *number += 8; + } + else if (*current == f_string_ascii_9_s[0]) { + *number *= 10; + *number += 9; + } + else if (*current == f_string_ascii_asterisk_s[0]) { + *number = va_arg(*ap, unsigned int); + + break; + } + else { + break; + } + } // for + + if (!*current) return F_false; + + return F_true; + } +#endif // !defined(_di_fl_print_string_convert_) || !defined(_di_fl_print_string_) + #if !defined(_di_fl_print_trim_except_) || !defined(_di_fl_print_trim_except_dynamic_) || !defined(_di_fl_print_trim_except_dynamic_partial_) || !defined(_di_fl_print_trim_except_in_) || !defined(_di_fl_print_trim_except_in_dynamic_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_) - f_status_t private_fl_print_trim_except_in(FILE *output, const f_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in) { + f_status_t private_fl_print_trim_except_in(const f_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + // @todo resume converting this function. f_array_length_t i = start; f_array_length_t j = 0; f_array_length_t at = 0; @@ -16,11 +478,16 @@ extern "C" { f_array_length_t in2 = 0; f_status_t status = F_none; - uint8_t width_max = 0; // skip past leading whitespace. while (i < stop) { + if (!string[i]) { + ++i; + + continue; + } + while (at < except_at.used && except_at.array[at] < i) { ++at; } // while @@ -41,7 +508,1444 @@ extern "C" { continue; } - width_max = (stop - i) + 1; + status = f_utf_is_whitespace(string + i, (stop - i) + 1); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + + i += macro_f_utf_byte_width(string[i]); + } // while + + f_string_t s = 0; + + while (i < stop) { + + if (!string[i]) { + ++i; + + continue; + } + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + if (in < except_in.used) { + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + } + + status = f_utf_is_whitespace(string + i, (stop - i) + 1); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + macro_f_utf_byte_width(string[i]); + + while (j < stop) { + + if (!string[j]) { + ++j; + + continue; + } + + while (at2 < except_at.used && except_at.array[at2] < j) { + ++at2; + } // while + + if (at2 < except_at.used && except_at.array[at2] == j) { + ++j; + + continue; + } + + while (in2 < except_in.used && except_in.array[in2].start < j && except_in.array[in2].stop < j) { + ++in2; + } // while + + if (in2 < except_in.used && except_in.array[in2].start <= j && except_in.array[in2].stop >= j) { + j = except_in.array[in2].stop + 1; + + continue; + } + + status = f_utf_is_whitespace(string + j, (stop - j) + 1); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + } // while + + if (j == stop || status == F_true) break; + + // print all processed whitespace (note: control characters are not whitespace so no checks for this are needed). + while (i < j) { + + if (!string[i]) { + ++i; + + continue; + } + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i = stop; + status = F_none; + break; + } + + 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 (macro_f_utf_byte_width(string[i]) > 3) { + if (!fputc_unlocked(string[i + 3], output)) { + return F_status_set_error(F_output); + } + } + } + } + + i += macro_f_utf_byte_width(string[i]); + } // while + + if (i >= stop) break; + } + + status = f_utf_is_valid(string + i, stop - i); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i += macro_f_utf_byte_width(string[i]); + continue; + } + + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i = stop; + 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 (macro_f_utf_byte_width(string[i]) > 3) { + if (!fputc_unlocked(string[i + 3], output)) { + return F_status_set_error(F_output); + } + } + } + } + + i += macro_f_utf_byte_width(string[i]); + } // while + } +#endif // !defined(_di_fl_print_trim_except_) || !defined(_di_fl_print_trim_except_dynamic_) || !defined(_di_fl_print_trim_except_dynamic_partial_) || !defined(_di_fl_print_trim_except_in_) || !defined(_di_fl_print_trim_except_in_dynamic_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_) + +#if !defined(_di_fl_print_trim_except_raw_) || !defined(_di_fl_print_trim_except_dynamic_raw_) || !defined(_di_fl_print_trim_except_dynamic_partial_raw_) || !defined(_di_fl_print_trim_except_in_raw_) || !defined(_di_fl_print_trim_except_in_dynamic_raw_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_raw_) + f_status_t private_fl_print_trim_except_in_raw(const f_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + + f_array_length_t i = start; + f_array_length_t j = 0; + f_array_length_t at = 0; + f_array_length_t at2 = 0; + f_array_length_t in = 0; + f_array_length_t in2 = 0; + + f_status_t status = F_none; + uint8_t width_max = 0; + + // skip past leading whitespace. + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + + width_max = (stop - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + + i += macro_f_utf_byte_width(string[i]); + } // while + + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + + width_max = (stop - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + macro_f_utf_byte_width(string[i]); + + if (j == stop) { + return F_none; + } + + at2 = at; + + while (j < stop) { + + while (at2 < except_at.used && except_at.array[at2] < j) { + ++at2; + } // while + + if (at2 < except_at.used && except_at.array[at2] == j) { + ++j; + + continue; + } + + while (in2 < except_in.used && except_in.array[in2].start < j && except_in.array[in2].stop <= j) { + ++in2; + } // while + + if (in2 < except_in.used && except_in.array[in2].start <= j && except_in.array[in2].stop >= j) { + j = except_in.array[in2].stop + 1; + + continue; + } + + width_max = (stop - j) + 1; + status = f_utf_is_whitespace(string + j, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + while (i < j) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + + ++i; + } // while + + break; + } + + j += macro_f_utf_byte_width(string[j]); + } // while + + if (status == F_true) break; + } + + width_max = macro_f_utf_byte_width(string[i]); + + for (j = 0; j < width_max; ++j) { + + if (!fputc_unlocked(string[i + j], output)) { + return F_status_set_error(F_output); + } + } // for + + i += width_max; + } // while + + return F_none; + } +#endif // !defined(_di_fl_print_trim_except_raw_) || !defined(_di_fl_print_trim_except_dynamic_raw_) || !defined(_di_fl_print_trim_except_dynamic_partial_raw_) || !defined(_di_fl_print_trim_except_in_raw_) || !defined(_di_fl_print_trim_except_in_dynamic_raw_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_raw_) + +#if !defined(_di_fl_print_trim_except_safely_) || !defined(_di_fl_print_trim_except_dynamic_safely_) || !defined(_di_fl_print_trim_except_dynamic_partial_safely_) || !defined(_di_fl_print_trim_except_in_safely_) || !defined(_di_fl_print_trim_except_in_dynamic_safely_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_safely_) + f_status_t private_fl_print_trim_except_in_safely(const f_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + + f_array_length_t i = start; + f_array_length_t j = 0; + f_array_length_t at = 0; + f_array_length_t at2 = 0; + f_array_length_t in = 0; + f_array_length_t in2 = 0; + + f_status_t status = F_none; + + // skip past leading whitespace. + while (i < stop) { + + // Consider NULL whitespace for the purposes of trimming (@todo update documentation to describe this behavior). + if (!string[i]) { + ++i; + + continue; + } + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + + status = f_utf_is_whitespace(string + i, (stop - i) + 1); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + + i += macro_f_utf_byte_width(string[i]); + } // while + + f_string_t s = 0; + + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + if (in < except_in.used) { + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + } + + status = f_utf_is_whitespace(string + i, (stop - i) + 1); + + // invalid UTF-8 characters will be considered non-whitespace. + if (F_status_is_error(status)) { + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i += macro_f_utf_byte_width(string[i]); + continue; + } + + if (status == F_true) { // @todo: update to handle NULL as whitespace in this condition. + j = i + macro_f_utf_byte_width(string[i]); + + while (j < stop) { + + // Consider NULL whitespace for the purposes of trimming (@todo update documentation to describe this behavior). + if (!string[i]) { + ++j; + + continue; + } + + while (at2 < except_at.used && except_at.array[at2] < j) { + ++at2; + } // while + + if (at2 < except_at.used && except_at.array[at2] == j) { + ++j; + + continue; + } + + while (in2 < except_in.used && except_in.array[in2].start < j && except_in.array[in2].stop < j) { + ++in2; + } // while + + if (in2 < except_in.used && except_in.array[in2].start <= j && except_in.array[in2].stop >= j) { + j = except_in.array[in2].stop + 1; + + continue; + } + + status = f_utf_is_whitespace(string + j, (stop - j) + 1); + if (F_status_is_error(status)) break; + + if (status == F_false) break; + } // while + + if (j == stop || status == F_true) break; + + // print all processed whitespace (note: control characters are not whitespace so no checks for this are needed). + while (i < j) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i = stop; + status = F_none; + break; + } + + if (string[i]) { + 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 (macro_f_utf_byte_width(string[i]) > 3) { + if (!fputc_unlocked(string[i + 3], output)) { + return F_status_set_error(F_output); + } + } + } + } + + i += macro_f_utf_byte_width(string[i]); + } + else { + if (!fputc_unlocked(f_print_sequence_null_s[0], output)) { + return F_status_set_error(F_output); + } + + if (!fputc_unlocked(f_print_sequence_null_s[1], output)) { + return F_status_set_error(F_output); + } + + if (!fputc_unlocked(f_print_sequence_null_s[2], output)) { + return F_status_set_error(F_output); + } + + ++i; + } + } // while + + // at this point the invalid character found while looping with j shall be safely printed. + if (F_status_is_error(status)) { + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i += macro_f_utf_byte_width(string[i]); + continue; + } + + if (i >= stop) break; + } + + s = 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 (!fputc_unlocked(s[i + 2], output)) { + return F_status_set_error(F_output); + } + + ++i; + } + else { + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i += macro_f_utf_byte_width(string[i]); + continue; + } + + 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 (!fputc_unlocked(f_print_sequence_unknown_s[2], output)) { + return F_status_set_error(F_output); + } + + i = stop; + 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 (macro_f_utf_byte_width(string[i]) > 3) { + if (!fputc_unlocked(string[i + 3], output)) { + return F_status_set_error(F_output); + } + } + } + } + + i += macro_f_utf_byte_width(string[i]); + } + } // while + + return F_none; + } +#endif // !defined(_di_fl_print_trim_except_safely_) || !defined(_di_fl_print_trim_except_dynamic_safely_) || !defined(_di_fl_print_trim_except_dynamic_partial_safely_) || !defined(_di_fl_print_trim_except_in_safely_) || !defined(_di_fl_print_trim_except_in_dynamic_safely_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_safely_) + +#if !defined(_di_fl_print_trim_except_in_utf_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_) || !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) + f_status_t private_fl_print_trim_except_in_utf(const f_utf_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + + f_array_length_t i = start; + f_array_length_t j = 0; + f_array_length_t at = 0; + f_array_length_t at2 = 0; + f_array_length_t in = 0; + f_array_length_t in2 = 0; + + f_status_t status = F_none; + + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + + ++i; + } // while + + while (i < stop) { + + if (!string[i]) { + ++i; + + continue; + } + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + 1; + + if (j == stop) { + return F_none; + } + + at2 = at; + + while (j < stop) { + + while (at2 < except_at.used && except_at.array[at2] < j) { + ++at2; + } // while + + if (at2 < except_at.used && except_at.array[at2] == j) { + ++j; + + continue; + } + + while (in2 < except_in.used && except_in.array[in2].start < j && except_in.array[in2].stop <= j) { + ++in2; + } // while + + if (in2 < except_in.used && except_in.array[in2].start <= j && except_in.array[in2].stop >= j) { + j = except_in.array[in2].stop + 1; + + continue; + } + + status = f_utf_character_is_whitespace(string[j]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + while (i < j) { + + if (!string[i]) { + ++i; + + continue; + } + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + + ++i; + } // while + + break; + } + + ++j; + } // while + + if (status == F_true) break; + } + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + + ++i; + } // while + + return F_none; + } +#endif // !defined(_di_fl_print_trim_except_in_utf_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_) || !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) + +#if !defined(_di_fl_print_trim_except_in_utf_raw_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_raw_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_raw_) || !defined(_di_fl_print_trim_except_utf_raw_) || !defined(_di_fl_print_trim_except_utf_dynamic_raw_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_raw_) + f_status_t private_fl_print_trim_except_in_utf_raw(const f_utf_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + + f_array_length_t i = start; + f_array_length_t j = 0; + f_array_length_t at = 0; + f_array_length_t at2 = 0; + f_array_length_t in = 0; + f_array_length_t in2 = 0; + + f_status_t status = F_none; + + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + + ++i; + } // while + + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + 1; + + if (j == stop) { + return F_none; + } + + at2 = at; + + while (j < stop) { + + while (at2 < except_at.used && except_at.array[at2] < j) { + ++at2; + } // while + + if (at2 < except_at.used && except_at.array[at2] == j) { + ++j; + + continue; + } + + while (in2 < except_in.used && except_in.array[in2].start < j && except_in.array[in2].stop <= j) { + ++in2; + } // while + + if (in2 < except_in.used && except_in.array[in2].start <= j && except_in.array[in2].stop >= j) { + j = except_in.array[in2].stop + 1; + + continue; + } + + status = f_utf_character_is_whitespace(string[j]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + while (i < j) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + + ++i; + } // while + + break; + } + + ++j; + } // while + + if (status == F_true) break; + } + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + + ++i; + } // while + + return F_none; + } +#endif // !defined(_di_fl_print_trim_except_in_utf_raw_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_raw_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_raw_) || !defined(_di_fl_print_trim_except_utf_raw_) || !defined(_di_fl_print_trim_except_utf_dynamic_raw_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_raw_) + +#if !defined(_di_fl_print_trim_except_in_utf_safely_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_safely_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_safely_) || !defined(_di_fl_print_trim_except_utf_safely_) || !defined(_di_fl_print_trim_except_utf_dynamic_safely_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_safely_) + f_status_t private_fl_print_trim_except_in_utf_safely(const f_utf_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + + f_array_length_t i = start; + f_array_length_t j = 0; + f_array_length_t at = 0; + f_array_length_t at2 = 0; + f_array_length_t in = 0; + f_array_length_t in2 = 0; + + f_status_t status = F_none; + + while (i < stop) { + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { + ++in; + } // while + + if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { + i = except_in.array[in].stop + 1; + + continue; + } + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + + ++i; + } // while + + while (i < stop) { + + if (!string[i]) { // @todo each of these needs to be replaced with a get safe check. + ++i; + + continue; + } + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + status = f_utf_character_is_whitespace(string[i]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + 1; + + if (j == stop) { + return F_none; + } + + at2 = at; + + while (j < stop) { + + while (at2 < except_at.used && except_at.array[at2] < j) { + ++at2; + } // while + + if (at2 < except_at.used && except_at.array[at2] == j) { + ++j; + + continue; + } + + while (in2 < except_in.used && except_in.array[in2].start < j && except_in.array[in2].stop <= j) { + ++in2; + } // while + + if (in2 < except_in.used && except_in.array[in2].start <= j && except_in.array[in2].stop >= j) { + j = except_in.array[in2].stop + 1; + + continue; + } + + status = f_utf_character_is_whitespace(string[j]); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + while (i < j) { + + if (!string[i]) { + ++i; + + continue; + } + + while (at < except_at.used && except_at.array[at] < i) { + ++at; + } // while + + if (at < except_at.used && except_at.array[at] == i) { + ++i; + + continue; + } + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + + ++i; + } // while + + break; + } + + ++j; + } // while + + if (status == F_true) break; + } + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + + ++i; + } // while + + return F_none; + } +#endif // !defined(_di_fl_print_trim_except_in_utf_safely_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_safely_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_safely_) || !defined(_di_fl_print_trim_except_utf_safely_) || !defined(_di_fl_print_trim_except_utf_dynamic_safely_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_safely_) + +#if !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) + f_status_t private_fl_print_trim(const f_string_t string, const f_array_length_t length, FILE *output) { + + f_array_length_t i = 0; + f_array_length_t j = 0; + + f_status_t status = F_none; + uint8_t width_max = 0; + + for (; i < length; i += macro_f_utf_byte_width(string[i])) { + + width_max = (length - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + } // for + + for (; i < length; i += macro_f_utf_byte_width(string[i])) { + + if (!string[i]) continue; + + width_max = (length - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + macro_f_utf_byte_width(string[i]); + + if (j == length) { + return F_none; + } + + for (; j < length; j += macro_f_utf_byte_width(string[j])) { + + width_max = (length - j) + 1; + status = f_utf_is_whitespace(string + j, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + for (; i < j; ++i) { + + if (!string[i]) continue; + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + } // for + + break; + } + } // for + + if (status == F_true) break; + } + + width_max = macro_f_utf_byte_width(string[i]); + + for (j = 0; j < width_max; ++j) { + + if (!fputc_unlocked(string[i + j], output)) { + return F_status_set_error(F_output); + } + } // for + } // for + + return F_none; + } +#endif // !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) + +#if !defined(_di_fl_print_trim_raw_) || !defined(_di_fl_print_trim_dynamic_raw_) || !defined(_di_fl_print_trim_dynamic_partial_raw_) + f_status_t private_fl_print_trim_raw(const f_string_t string, const f_array_length_t length, FILE *output) { + + f_array_length_t i = 0; + f_array_length_t j = 0; + + f_status_t status = F_none; + uint8_t width_max = 0; + + for (; i < length; i += macro_f_utf_byte_width(string[i])) { + + width_max = (length - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_false) break; + } // for + + for (; i < length; i += macro_f_utf_byte_width(string[i])) { + + width_max = (length - i) + 1; + status = f_utf_is_whitespace(string + i, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + if (status == F_true) { + j = i + macro_f_utf_byte_width(string[i]); + + if (j == length) { + return F_none; + } + + for (; j < length; j += macro_f_utf_byte_width(string[j])) { + + width_max = (length - j) + 1; + status = f_utf_is_whitespace(string + j, width_max); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_maybe) { + return F_status_set_error(F_utf); + } + + return status; + } + + // all whitespaces found so far must be printed when a non-whitespace is found. + if (status == F_false) { + for (; i < j; ++i) { + + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } + } // for + + break; + } + } // for + + if (status == F_true) break; + } + + width_max = macro_f_utf_byte_width(string[i]); + + for (j = 0; j < width_max; ++j) { + + if (!fputc_unlocked(string[i + j], output)) { + return F_status_set_error(F_output); + } + } // for + } // for + + return F_none; + } +#endif // !defined(_di_fl_print_trim_raw_) || !defined(_di_fl_print_trim_dynamic_raw_) || !defined(_di_fl_print_trim_dynamic_partial_raw_) + +#if !defined(_di_fl_print_trim_safely_) || !defined(_di_fl_print_trim_dynamic_safely_) || !defined(_di_fl_print_trim_dynamic_partial_safely_) + f_status_t private_fl_print_trim_safely(const f_string_t string, const f_array_length_t length, FILE *output) { + + f_array_length_t i = 0; + f_array_length_t j = 0; + + f_status_t status = F_none; + uint8_t width_max = 0; + + for (; i < length; i += macro_f_utf_byte_width(string[i])) { + + width_max = (length - i) + 1; status = f_utf_is_whitespace(string + i, width_max); if (F_status_is_error(status)) { @@ -53,35 +1957,13 @@ extern "C" { } if (status == F_false) break; + } // for - i += macro_f_utf_byte_width(string[i]); - } // while - - while (i < stop) { - - if (!string[i]) continue; - - while (at < except_at.used && except_at.array[at] < i) { - ++at; - } // while - - if (at < except_at.used && except_at.array[at] == i) { - ++i; - - continue; - } - - while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { - ++in; - } // while - - if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { - i = except_in.array[in].stop + 1; + for (; i < length; i += macro_f_utf_byte_width(string[i])) { - continue; - } + if (!string[i]) continue; // @todo each of these needs to be replaced with a get safe check. - width_max = (stop - i) + 1; + width_max = (length - i) + 1; status = f_utf_is_whitespace(string + i, width_max); if (F_status_is_error(status)) { @@ -95,35 +1977,13 @@ extern "C" { if (status == F_true) { j = i + macro_f_utf_byte_width(string[i]); - if (j == stop) { + if (j == length) { return F_none; } - at2 = at; - - while (j < stop) { - - while (at2 < except_at.used && except_at.array[at2] < j) { - ++at2; - } // while - - if (at2 < except_at.used && except_at.array[at2] == j) { - ++j; - - continue; - } - - while (in2 < except_in.used && except_in.array[in2].start < j && except_in.array[in2].stop <= j) { - ++in2; - } // while - - if (in2 < except_in.used && except_in.array[in2].start <= j && except_in.array[in2].stop >= j) { - j = except_in.array[in2].stop + 1; - - continue; - } + for (; j < length; j += macro_f_utf_byte_width(string[j])) { - width_max = (stop - j) + 1; + width_max = (length - j) + 1; status = f_utf_is_whitespace(string + j, width_max); if (F_status_is_error(status)) { @@ -136,46 +1996,18 @@ extern "C" { // all whitespaces found so far must be printed when a non-whitespace is found. if (status == F_false) { - while (i < j) { - - if (!string[i]) { - ++i; - - continue; - } - - while (at < except_at.used && except_at.array[at] < i) { - ++at; - } // while - - if (at < except_at.used && except_at.array[at] == i) { - ++i; - - continue; - } - - while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { - ++in; - } // while - - if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { - i = except_in.array[in].stop + 1; + for (; i < j; ++i) { - continue; - } + if (!string[i]) continue; - if (!fputc(string[i], output)) { + if (!fputc_unlocked(string[i], output)) { return F_status_set_error(F_output); } - - ++i; - } // while + } // for break; } - - j += macro_f_utf_byte_width(string[j]); - } // while + } // for if (status == F_true) break; } @@ -184,51 +2016,25 @@ extern "C" { for (j = 0; j < width_max; ++j) { - if (!fputc(string[i + j], output)) { + if (!fputc_unlocked(string[i + j], output)) { return F_status_set_error(F_output); } } // for - - i += width_max; - } // while + } // for return F_none; } -#endif // !defined(_di_fl_print_trim_except_) || !defined(_di_fl_print_trim_except_dynamic_) || !defined(_di_fl_print_trim_except_dynamic_partial_) || !defined(_di_fl_print_trim_except_in_) || !defined(_di_fl_print_trim_except_in_dynamic_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_) +#endif // !defined(_di_fl_print_trim_safely_) || !defined(_di_fl_print_trim_dynamic_safely_) || !defined(_di_fl_print_trim_dynamic_partial_safely_) -#if !defined(_di_fl_print_trim_except_in_utf_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_) || !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) - f_status_t private_fl_print_trim_except_in_utf(FILE *output, const f_utf_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in) { +#if !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) + f_status_t private_fl_print_trim_utf(const f_utf_string_t string, const f_array_length_t length, FILE *output) { - f_array_length_t i = start; + f_array_length_t i = 0; f_array_length_t j = 0; - f_array_length_t at = 0; - f_array_length_t at2 = 0; - f_array_length_t in = 0; - f_array_length_t in2 = 0; f_status_t status = F_none; - while (i < stop) { - - while (at < except_at.used && except_at.array[at] < i) { - ++at; - } // while - - if (at < except_at.used && except_at.array[at] == i) { - ++i; - - continue; - } - - while (in < except_in.used && except_in.array[in].start < i && except_in.array[in].stop < i) { - ++in; - } // while - - if (in < except_in.used && except_in.array[in].start <= i && except_in.array[in].stop >= i) { - i = except_in.array[in].stop + 1; - - continue; - } + for (; i < length; ++i) { status = f_utf_character_is_whitespace(string[i]); @@ -241,27 +2047,11 @@ extern "C" { } if (status == F_false) break; + } // for - ++i; - } // while - - while (i < stop) { - - if (!string[i]) { - ++i; - - continue; - } - - while (at < except_at.used && except_at.array[at] < i) { - ++at; - } // while - - if (at < except_at.used && except_at.array[at] == i) { - ++i; + for (; i < length; ++i) { - continue; - } + if (!string[i]) continue; status = f_utf_character_is_whitespace(string[i]); @@ -276,33 +2066,11 @@ extern "C" { if (status == F_true) { j = i + 1; - if (j == stop) { + if (j == length) { return F_none; } - at2 = at; - - while (j < stop) { - - while (at2 < except_at.used && except_at.array[at2] < j) { - ++at2; - } // while - - if (at2 < except_at.used && except_at.array[at2] == j) { - ++j; - - continue; - } - - while (in2 < except_in.used && except_in.array[in2].start < j && except_in.array[in2].stop <= j) { - ++in2; - } // while - - if (in2 < except_in.used && except_in.array[in2].start <= j && except_in.array[in2].stop >= j) { - j = except_in.array[in2].stop + 1; - - continue; - } + for (; j < length; ++j) { status = f_utf_character_is_whitespace(string[j]); @@ -316,64 +2084,42 @@ extern "C" { // all whitespaces found so far must be printed when a non-whitespace is found. if (status == F_false) { - while (i < j) { - - if (!string[i]) { - ++i; - - continue; - } - - while (at < except_at.used && except_at.array[at] < i) { - ++at; - } // while - - if (at < except_at.used && except_at.array[at] == i) { - ++i; + for (; i < j; ++i) { - continue; - } + if (!string[i]) continue; - if (!fputc(string[i], output)) { + if (!fputc_unlocked(string[i], output)) { return F_status_set_error(F_output); } - - ++i; - } // while + } // for break; } - - ++j; - } // while + } // for if (status == F_true) break; } - if (!fputc(string[i], output)) { + if (!fputc_unlocked(string[i], output)) { return F_status_set_error(F_output); } - - ++i; - } // while + } // for return F_none; } -#endif // !defined(_di_fl_print_trim_except_in_utf_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_) || !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) +#endif // !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) -#if !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) - f_status_t private_fl_print_trim(FILE *output, const f_string_t string, const f_array_length_t length) { +#if !defined(_di_fl_print_trim_utf_raw_) || !defined(_di_fl_print_trim_utf_dynamic_raw_) || !defined(_di_fl_print_trim_utf_dynamic_partial_raw_) + f_status_t private_fl_print_trim_utf_raw(const f_utf_string_t string, const f_array_length_t length, FILE *output) { f_array_length_t i = 0; f_array_length_t j = 0; f_status_t status = F_none; - uint8_t width_max = 0; - for (; i < length; i += macro_f_utf_byte_width(string[i])) { + for (; i < length; ++i) { - width_max = (length - i) + 1; - status = f_utf_is_whitespace(string + i, width_max); + status = f_utf_character_is_whitespace(string[i]); if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_maybe) { @@ -386,12 +2132,9 @@ extern "C" { if (status == F_false) break; } // for - for (; i < length; i += macro_f_utf_byte_width(string[i])) { - - if (!string[i]) continue; + for (; i < length; ++i) { - width_max = (length - i) + 1; - status = f_utf_is_whitespace(string + i, width_max); + status = f_utf_character_is_whitespace(string[i]); if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_maybe) { @@ -402,16 +2145,15 @@ extern "C" { } if (status == F_true) { - j = i + macro_f_utf_byte_width(string[i]); + j = i + 1; if (j == length) { return F_none; } - for (; j < length; j += macro_f_utf_byte_width(string[j])) { + for (; j < length; ++j) { - width_max = (length - j) + 1; - status = f_utf_is_whitespace(string + j, width_max); + status = f_utf_character_is_whitespace(string[j]); if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_maybe) { @@ -425,9 +2167,7 @@ extern "C" { if (status == F_false) { for (; i < j; ++i) { - if (!string[i]) continue; - - if (!fputc(string[i], output)) { + if (!fputc_unlocked(string[i], output)) { return F_status_set_error(F_output); } } // for @@ -439,28 +2179,25 @@ extern "C" { if (status == F_true) break; } - width_max = macro_f_utf_byte_width(string[i]); - - for (j = 0; j < width_max; ++j) { - - if (!fputc(string[i + j], output)) { - return F_status_set_error(F_output); - } - } // for + if (!fputc_unlocked(string[i], output)) { + return F_status_set_error(F_output); + } } // for return F_none; } -#endif // !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) +#endif // !defined(_di_fl_print_trim_utf_raw_) || !defined(_di_fl_print_trim_utf_dynamic_raw_) || !defined(_di_fl_print_trim_utf_dynamic_partial_raw_) -#if !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) - f_status_t private_fl_print_trim_utf(FILE *output, const f_utf_string_t string, const f_array_length_t length) { +#if !defined(_di_fl_print_trim_utf_safely_) || !defined(_di_fl_print_trim_utf_dynamic_safely_) || !defined(_di_fl_print_trim_utf_dynamic_partial_safely_) + f_status_t private_fl_print_trim_utf_safely(const f_utf_string_t string, const f_array_length_t length, FILE *output) { f_array_length_t i = 0; f_array_length_t j = 0; f_status_t status = F_none; + f_string_t s = 0; + for (; i < length; ++i) { status = f_utf_character_is_whitespace(string[i]); @@ -478,8 +2215,6 @@ extern "C" { for (; i < length; ++i) { - if (!string[i]) continue; - status = f_utf_character_is_whitespace(string[i]); if (F_status_is_error(status)) { @@ -513,9 +2248,19 @@ extern "C" { if (status == F_false) { for (; i < j; ++i) { + + /* @todo + s = f_print_character_safely_get(string[i]); // @todo: in addition to this, the width of the character at string[i] needs to be taken into consideration. + + if (s) { + // + status = F_false; + } + */ + if (!string[i]) continue; - if (!fputc(string[i], output)) { + if (!fputc_unlocked(string[i], output)) { return F_status_set_error(F_output); } } // for @@ -527,14 +2272,21 @@ extern "C" { if (status == F_true) break; } - if (!fputc(string[i], output)) { + s = f_print_character_safely_get(string[i]); // @todo: in addition to this, the width of the character at string[i] needs to be taken into consideration. + + if (s) { + // + status = F_false; + } + + if (!fputc_unlocked(string[i], output)) { return F_status_set_error(F_output); } } // for return F_none; } -#endif // !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) +#endif // !defined(_di_fl_print_trim_utf_safely_) || !defined(_di_fl_print_trim_utf_dynamic_safely_) || !defined(_di_fl_print_trim_utf_dynamic_partial_safely_) #ifdef __cplusplus } // extern "C" diff --git a/level_1/fl_print/c/private-print.h b/level_1/fl_print/c/private-print.h index 4b144e6..38645b3 100644 --- a/level_1/fl_print/c/private-print.h +++ b/level_1/fl_print/c/private-print.h @@ -16,12 +16,85 @@ extern "C" { #endif /** + * Helper function for converting one substitution in a string. + * + * This should be called after each first '%' is encountered. + * This should return only after a single '%' group is fully processed, end of current is reached, or an error occurs. + * + * @param current + * The current character position within the string. + * @param ap + * The variable arguments list. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on failure to print to the output file. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * F_valid_not (with error bit) on invalid syntax (such as terminating the string on a single '%'). + * + * Success from: f_print_dynamic(). + * Success from: f_print_dynamic_raw(). + * Success from: f_print_dynamic_safely(). + * 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_print_dynamic(). + * Errors (with error bit) from: f_print_dynamic_raw(). + * Errors (with error bit) from: f_print_dynamic_safely(). + * Errors (with error bit) from: f_print_safely(). + * Errors (with error bit) from: f_print_terminated(). + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() + * + * @see f_conversion_number_signed_to_file() + * @see f_conversion_number_unsigned_to_file() + * @see f_print_dynamic() + * @see f_print_dynamic_raw() + * @see f_print_dynamic_safely() + * @see f_print_safely() + * @see f_print_terminated() + * + * @see private_fl_print_convert_number() + */ +#if !defined(_di_fl_print_string_convert_) || !defined(_di_fl_print_string_) + extern f_status_t private_fl_print_string_convert(char *current, va_list *ap, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_string_convert_) || !defined(_di_fl_print_string_) + +/** + * Helper function for processing the number in a convert string. + * + * This should be called to convert numbers after a '%', such as the field with or precision. + * + * @param current + * The current character position within the string. + * @param ap + * The variable arguments list. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_true on success and end of current is found. + * F_false on success without reaching the end of current. + * + * @see va_arg() + */ +#if !defined(_di_fl_print_string_convert_) || !defined(_di_fl_print_string_) + extern f_status_t private_fl_print_convert_number(char *current, va_list *ap, unsigned int *number) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_string_convert_) || !defined(_di_fl_print_string_) + +/** * Private implementation of fl_print_trim_except(). * * Intended to be shared to each of the different implementation variations. * - * @param output - * The file to output to, including standard streams such as stdout and stderr. * @param string * The string to output. * @param offset @@ -34,18 +107,22 @@ extern "C" { * @param except_in * An array of ranges within the string to not print. * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. * F_data_not on success but there is nothing to print. * * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. - * F_output (with error bit) on error when printing to output. + * F_output (with error bit) on failure to print to the output file. * F_parameter (with error bit) if a parameter is invalid. * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_is_whitespace(). * + * @see fputc_unlocked() + * * @see fl_print_trim_except() * @see fl_print_trim_except_dynamic() * @see fl_print_trim_except_dynamic_partial() @@ -54,16 +131,102 @@ extern "C" { * @see fl_print_trim_except_in_dynamic_partial() */ #if !defined(_di_fl_print_trim_except_) || !defined(_di_fl_print_trim_except_dynamic_) || !defined(_di_fl_print_trim_except_dynamic_partial_) || !defined(_di_fl_print_trim_except_in_) || !defined(_di_fl_print_trim_except_in_dynamic_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_) - extern f_status_t private_fl_print_trim_except_in(FILE *output, const f_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in) f_attribute_visibility_internal; + extern f_status_t private_fl_print_trim_except_in(const f_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) f_attribute_visibility_internal; #endif // !defined(_di_fl_print_trim_except_) || !defined(_di_fl_print_trim_except_dynamic_) || !defined(_di_fl_print_trim_except_dynamic_partial_) || !defined(_di_fl_print_trim_except_in_) || !defined(_di_fl_print_trim_except_in_dynamic_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_) /** - * Private implementation of fl_print_trim_except_utf(). + * Private implementation of fl_print_trim_except_raw(). * * Intended to be shared to each of the different implementation variations. * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. * @param output - * The file to output to, including standard streams such as stdout and stderr. + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on failure to print to the output file. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() + * + * @see fl_print_trim_except_raw() + * @see fl_print_trim_except_dynamic_raw() + * @see fl_print_trim_except_dynamic_partial_raw() + * @see fl_print_trim_except_in_raw() + * @see fl_print_trim_except_in_dynamic_raw() + * @see fl_print_trim_except_in_dynamic_partial_raw() + */ +#if !defined(_di_fl_print_trim_except_raw_) || !defined(_di_fl_print_trim_except_dynamic_raw_) || !defined(_di_fl_print_trim_except_dynamic_partial_raw_) || !defined(_di_fl_print_trim_except_in_raw_) || !defined(_di_fl_print_trim_except_in_dynamic_raw_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_raw_) + extern f_status_t private_fl_print_trim_except_in_raw(const f_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_except_raw_) || !defined(_di_fl_print_trim_except_dynamic_raw_) || !defined(_di_fl_print_trim_except_dynamic_partial_raw_) || !defined(_di_fl_print_trim_except_in_raw_) || !defined(_di_fl_print_trim_except_in_dynamic_raw_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_raw_) + +/** + * Private implementation of fl_print_trim_except_safely(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on failure to print to the output file. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() + * + * @see fl_print_trim_except_safely() + * @see fl_print_trim_except_dynamic_safely() + * @see fl_print_trim_except_dynamic_partial_safely() + * @see fl_print_trim_except_in_safely() + * @see fl_print_trim_except_in_dynamic_safely() + * @see fl_print_trim_except_in_dynamic_partial_safely() + */ +#if !defined(_di_fl_print_trim_except_safely_) || !defined(_di_fl_print_trim_except_dynamic_safely_) || !defined(_di_fl_print_trim_except_dynamic_partial_safely_) || !defined(_di_fl_print_trim_except_in_safely_) || !defined(_di_fl_print_trim_except_in_dynamic_safely_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_safely_) + extern f_status_t private_fl_print_trim_except_in_safely(const f_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_except_safely_) || !defined(_di_fl_print_trim_except_dynamic_safely_) || !defined(_di_fl_print_trim_except_dynamic_partial_safely_) || !defined(_di_fl_print_trim_except_in_safely_) || !defined(_di_fl_print_trim_except_in_dynamic_safely_) || !defined(_di_fl_print_trim_except_in_dynamic_partial_safely_) + +/** + * Private implementation of fl_print_trim_except_utf(). + * + * Intended to be shared to each of the different implementation variations. + * * @param string * The string to output. * @param offset @@ -73,18 +236,22 @@ extern "C" { * @param except * An array of locations within the given string to not print. * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. * F_data_not on success but there is nothing to print. * * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. - * F_output (with error bit) on error when printing to output. + * F_output (with error bit) on failure to print to the output file. * F_parameter (with error bit) if a parameter is invalid. * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). * + * @see fputc_unlocked() + * * @see fl_print_trim_except_in_utf() * @see fl_print_trim_except_in_utf_dynamic() * @see fl_print_trim_except_in_utf_dynamic_partial() @@ -93,71 +260,289 @@ extern "C" { * @see fl_print_trim_except_utf_dynamic_partial() */ #if !defined(_di_fl_print_trim_except_in_utf_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_) || !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) - extern f_status_t private_fl_print_trim_except_in_utf(FILE *output, const f_utf_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in) f_attribute_visibility_internal; + extern f_status_t private_fl_print_trim_except_in_utf(const f_utf_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) f_attribute_visibility_internal; #endif // !defined(_di_fl_print_trim_except_in_utf_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_) || !defined(_di_fl_print_trim_except_utf_) || !defined(_di_fl_print_trim_except_utf_dynamic_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_) /** - * Private implementation of fl_print_trim(). + * Private implementation of fl_print_trim_except_utf_raw(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on failure to print to the output file. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() + * + * @see fl_print_trim_except_in_utf_raw() + * @see fl_print_trim_except_in_utf_dynamic_raw() + * @see fl_print_trim_except_in_utf_dynamic_partial_raw() + * @see fl_print_trim_except_utf_raw() + * @see fl_print_trim_except_utf_dynamic_raw() + * @see fl_print_trim_except_utf_dynamic_partial_raw() + */ +#if !defined(_di_fl_print_trim_except_in_utf_raw_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_raw_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_raw_) || !defined(_di_fl_print_trim_except_utf_raw_) || !defined(_di_fl_print_trim_except_utf_dynamic_raw_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_raw_) + extern f_status_t private_fl_print_trim_except_in_utf_raw(const f_utf_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_except_in_utf_raw_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_raw_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_raw_) || !defined(_di_fl_print_trim_except_utf_raw_) || !defined(_di_fl_print_trim_except_utf_dynamic_raw_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_raw_) + +/** + * Private implementation of fl_print_trim_except_utf_safely(). * * Intended to be shared to each of the different implementation variations. * + * @param string + * The string to output. + * @param offset + * The inclusive start point to start printing. + * @param stop + * The exclusive stop point to stop printing. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. * @param output - * The file to output to, including standard streams such as stdout and stderr. + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on failure to print to the output file. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() + * + * @see fl_print_trim_except_in_utf_safely() + * @see fl_print_trim_except_in_utf_dynamic_safely() + * @see fl_print_trim_except_in_utf_dynamic_partial_safely() + * @see fl_print_trim_except_utf_safely() + * @see fl_print_trim_except_utf_dynamic_safely() + * @see fl_print_trim_except_utf_dynamic_partial_safely() + */ +#if !defined(_di_fl_print_trim_except_in_utf_safely_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_safely_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_safely_) || !defined(_di_fl_print_trim_except_utf_safely_) || !defined(_di_fl_print_trim_except_utf_dynamic_safely_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_safely_) + extern f_status_t private_fl_print_trim_except_in_utf_safely(const f_utf_string_t string, const f_array_length_t start, const f_array_length_t stop, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_except_in_utf_safely_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_safely_) || !defined(_di_fl_print_trim_except_in_utf_dynamic_partial_safely_) || !defined(_di_fl_print_trim_except_utf_safely_) || !defined(_di_fl_print_trim_except_utf_dynamic_safely_) || !defined(_di_fl_print_trim_except_utf_dynamic_partial_safely_) + +/** + * Private implementation of fl_print_trim(). + * + * Intended to be shared to each of the different implementation variations. + * * @param string * The string to output. * @param length * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. * F_data_not on success but there is nothing to print. * * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. - * F_output (with error bit) on error when printing to output. + * F_output (with error bit) on failure to print to the output file. * F_parameter (with error bit) if a parameter is invalid. * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_is_whitespace(). * + * @see fputc_unlocked() + * * @see fl_print_trim() * @see fl_print_trim_dynamic() * @see fl_print_trim_dynamic_partial() */ #if !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) - extern f_status_t private_fl_print_trim(FILE *output, const f_string_t string, const f_array_length_t length) f_attribute_visibility_internal; + extern f_status_t private_fl_print_trim(const f_string_t string, const f_array_length_t length, FILE *output) f_attribute_visibility_internal; #endif // !defined(_di_fl_print_trim_) || !defined(_di_fl_print_trim_dynamic_) || !defined(_di_fl_print_trim_dynamic_partial_) /** - * Private implementation of fl_print_trim_utf(). + * Private implementation of fl_print_trim_raw(). * * Intended to be shared to each of the different implementation variations. * + * @param string + * The string to output. + * @param length + * The total number of characters to print. * @param output - * The file to output to, including standard streams such as stdout and stderr. + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on failure to print to the output file. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() + * + * @see fl_print_trim_raw() + * @see fl_print_trim_dynamic_raw() + * @see fl_print_trim_dynamic_partial_raw() + */ +#if !defined(_di_fl_print_trim_raw_) || !defined(_di_fl_print_trim_dynamic_raw_) || !defined(_di_fl_print_trim_dynamic_partial_raw_) + extern f_status_t private_fl_print_trim_raw(const f_string_t string, const f_array_length_t length, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_raw_) || !defined(_di_fl_print_trim_dynamic_raw_) || !defined(_di_fl_print_trim_dynamic_partial_raw_) + +/** + * Private implementation of fl_print_trim_safely(). + * + * Intended to be shared to each of the different implementation variations. + * * @param string * The string to output. * @param length * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. * * @return * F_none on success. * F_data_not on success but there is nothing to print. * * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. - * F_output (with error bit) on error when printing to output. + * F_output (with error bit) on failure to print to the output file. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_is_whitespace(). + * + * @see fputc_unlocked() + * + * @see fl_print_trim_safely() + * @see fl_print_trim_dynamic_safely() + * @see fl_print_trim_dynamic_partial_safely() + */ +#if !defined(_di_fl_print_trim_safely_) || !defined(_di_fl_print_trim_dynamic_safely_) || !defined(_di_fl_print_trim_dynamic_partial_safely_) + extern f_status_t private_fl_print_trim_safely(const f_string_t string, const f_array_length_t length, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_safely_) || !defined(_di_fl_print_trim_dynamic_safely_) || !defined(_di_fl_print_trim_dynamic_partial_safely_) + +/** + * Private implementation of fl_print_trim_utf(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on failure to print to the output file. * F_parameter (with error bit) if a parameter is invalid. * F_utf (with error bit) if character is an invalid UTF-8 character. * * Errors (with error bit) from: f_utf_character_is_whitespace(). * + * @see fputc_unlocked() + * * @see fl_print_trim_utf() * @see fl_print_trim_utf_dynamic() * @see fl_print_trim_utf_dynamic_partial() */ #if !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) - extern f_status_t private_fl_print_trim_utf(FILE *output, const f_utf_string_t string, const f_array_length_t length) f_attribute_visibility_internal; + extern f_status_t private_fl_print_trim_utf(const f_utf_string_t string, const f_array_length_t length, FILE *output) f_attribute_visibility_internal; #endif // !defined(_di_fl_print_trim_utf_) || !defined(_di_fl_print_trim_utf_dynamic_) || !defined(_di_fl_print_trim_utf_dynamic_partial_) +/** + * Private implementation of fl_print_trim_utf_raw(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on failure to print to the output file. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() + * + * @see fl_print_trim_utf_raw() + * @see fl_print_trim_utf_dynamic_raw() + * @see fl_print_trim_utf_dynamic_partial_raw() + */ +#if !defined(_di_fl_print_trim_utf_raw_) || !defined(_di_fl_print_trim_utf_dynamic_raw_) || !defined(_di_fl_print_trim_utf_dynamic_partial_raw_) + extern f_status_t private_fl_print_trim_utf_raw(const f_utf_string_t string, const f_array_length_t length, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_utf_raw_) || !defined(_di_fl_print_trim_utf_dynamic_raw_) || !defined(_di_fl_print_trim_utf_dynamic_partial_raw_) + +/** + * Private implementation of fl_print_trim_utf_safely(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to print. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_output (with error bit) on failure to print to the output file. + * F_parameter (with error bit) if a parameter is invalid. + * F_utf (with error bit) if character is an invalid UTF-8 character. + * + * Errors (with error bit) from: f_utf_character_is_whitespace(). + * + * @see fputc_unlocked() + * + * @see fl_print_trim_utf_safely() + * @see fl_print_trim_utf_dynamic_safely() + * @see fl_print_trim_utf_dynamic_partial_safely() + */ +#if !defined(_di_fl_print_trim_utf_safely_) || !defined(_di_fl_print_trim_utf_dynamic_safely_) || !defined(_di_fl_print_trim_utf_dynamic_partial_safely_) + extern f_status_t private_fl_print_trim_utf_safely(const f_utf_string_t string, const f_array_length_t length, FILE *output) f_attribute_visibility_internal; +#endif // !defined(_di_fl_print_trim_utf_safely_) || !defined(_di_fl_print_trim_utf_dynamic_safely_) || !defined(_di_fl_print_trim_utf_dynamic_partial_safely_) + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_1/fl_status/c/status.c b/level_1/fl_status/c/status.c index 3d20608..dd97bdc 100644 --- a/level_1/fl_status/c/status.c +++ b/level_1/fl_status/c/status.c @@ -231,6 +231,12 @@ extern "C" { case F_address_not: *string = FL_status_string_address_not; break; + case F_ascii: + *string = FL_status_string_ascii; + break; + case F_ascii_not: + *string = FL_status_string_ascii_not; + break; case F_block: *string = FL_status_string_block; break; diff --git a/level_1/fl_status/c/status.h b/level_1/fl_status/c/status.h index 3297181..6823fcf 100644 --- a/level_1/fl_status/c/status.h +++ b/level_1/fl_status/c/status.h @@ -169,6 +169,8 @@ extern "C" { #define FL_status_string_absolute_not "F_absolute_not" #define FL_status_string_address "F_address" #define FL_status_string_address_not "F_address_not" + #define FL_status_string_ascii "F_ascii" + #define FL_status_string_ascii_not "F_ascii_not" #define FL_status_string_block "F_block" #define FL_status_string_block_not "F_block_not" #define FL_status_string_bound "F_bound" @@ -346,6 +348,8 @@ extern "C" { #define FL_status_string_absolute_not_length 14 #define FL_status_string_address_length 9 #define FL_status_string_address_not_length 13 + #define FL_status_string_ascii_length 7 + #define FL_status_string_ascii_not_length 11 #define FL_status_string_block_length 7 #define FL_status_string_block_not_length 11 #define FL_status_string_bound_length 7 diff --git a/level_2/fll_path/c/path.h b/level_2/fll_path/c/path.h index b1920b8..476db37 100644 --- a/level_2/fll_path/c/path.h +++ b/level_2/fll_path/c/path.h @@ -20,9 +20,6 @@ #include #include -// fll-1 includes -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/level_2/fll_print/c/print.c b/level_2/fll_print/c/print.c new file mode 100644 index 0000000..bab5909 --- /dev/null +++ b/level_2/fll_print/c/print.c @@ -0,0 +1,455 @@ +#include "print.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fll_print_ + f_status_t fll_print(const f_string_t string, const f_array_length_t length, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print(string, length, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_ + +#ifndef _di_fll_print_character_safely_ + f_status_t fll_print_character_safely(const char character, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_character_safely(character, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_character_safely_ + +#ifndef _di_fll_print_dynamic_ + f_status_t fll_print_dynamic(const f_string_static_t buffer, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_dynamic(buffer, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_dynamic_ + +#ifndef _di_fll_print_dynamic_raw_ + f_status_t fll_print_dynamic_raw(const f_string_static_t buffer, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_dynamic_raw(buffer, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_dynamic_raw_ + +#ifndef _di_fll_print_dynamic_safely_ + f_status_t fll_print_dynamic_safely(const f_string_static_t buffer, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_dynamic_safely(buffer, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_dynamic_safely_ + +#ifndef _di_fll_print_dynamic_partial_ + f_status_t fll_print_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_dynamic_partial(buffer, range, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_dynamic_partial_ + +#ifndef _di_fll_print_dynamic_partial_raw_ + f_status_t fll_print_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_dynamic_partial_raw(buffer, range, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_dynamic_partial_raw_ + +#ifndef _di_fll_print_dynamic_partial_safely_ + f_status_t fll_print_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_dynamic_partial_safely(buffer, range, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_dynamic_partial_safely_ + +#ifndef _di_fll_print_except_ + f_status_t fll_print_except(const f_string_t buffer, const f_array_length_t length, const f_array_lengths_t except, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except(buffer, length, except, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_ + +#ifndef _di_fll_print_except_raw_ + f_status_t fll_print_except_raw(const f_string_t buffer, const f_array_length_t length, const f_array_lengths_t except, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except_raw(buffer, length, except, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_raw_ + +#ifndef _di_fll_print_except_safely_ + f_status_t fll_print_except_safely(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except_safely(string, length, except, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_safely_ + +#ifndef _di_fll_print_except_dynamic_ + f_status_t fll_print_except_dynamic(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except_dynamic(buffer, except, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_dynamic_ + +#ifndef _di_fll_print_except_dynamic_raw_ + f_status_t fll_print_except_dynamic_raw(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except_dynamic_raw(buffer, except, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_dynamic_raw_ + +#ifndef _di_fll_print_except_dynamic_safely_ + f_status_t fll_print_except_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except_dynamic_safely(buffer, except, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_dynamic_safely_ + +#ifndef _di_fll_print_except_in_ + f_status_t fll_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) { + + flockfile(output); + + const f_status_t status = f_print_except_in(string, length, except_at, except_in, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_in_ + +#ifndef _di_fll_print_except_in_raw_ + f_status_t fll_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) { + + flockfile(output); + + const f_status_t status = f_print_except_in_raw(string, length, except_at, except_in, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_in_raw_ + +#ifndef _di_fll_print_except_in_safely_ + f_status_t fll_print_except_in_safely(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) { + + flockfile(output); + + const f_status_t status = f_print_except_in_safely(string, length, except_at, except_in, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_in_safely_ + +#ifndef _di_fll_print_except_in_dynamic_ + f_status_t fll_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) { + + flockfile(output); + + const f_status_t status = f_print_except_in_dynamic(buffer, except_at, except_in, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_in_dynamic_ + +#ifndef _di_fll_print_except_in_dynamic_raw_ + f_status_t fll_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) { + + flockfile(output); + + const f_status_t status = f_print_except_in_dynamic_raw(buffer, except_at, except_in, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_in_dynamic_raw_ + +#ifndef _di_fll_print_except_in_dynamic_safely_ + f_status_t fll_print_except_in_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except_in_dynamic_safely(buffer, except_at, except_in, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_in_dynamic_safely_ + +#ifndef _di_fll_print_except_in_dynamic_partial_ + f_status_t fll_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) { + + flockfile(output); + + const f_status_t status = f_print_except_in_dynamic_partial(buffer, range, except_at, except_in, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_in_dynamic_partial_ + +#ifndef _di_fll_print_except_in_dynamic_partial_raw_ + f_status_t fll_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) { + + flockfile(output); + + const f_status_t status = f_print_except_in_dynamic_partial_raw(buffer, range, except_at, except_in, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_in_dynamic_partial_raw_ + +#ifndef _di_fll_print_except_in_dynamic_partial_safely_ + f_status_t fll_print_except_in_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except_in_dynamic_partial_safely(buffer, range, except_at, except_in, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_in_dynamic_partial_safely_ + +#ifndef _di_fll_print_except_dynamic_partial_ + f_status_t fll_print_except_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except_dynamic_partial(buffer, range, except, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_dynamic_partial_ + +#ifndef _di_fll_print_except_dynamic_partial_raw_ + f_status_t fll_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) { + + flockfile(output); + + const f_status_t status = f_print_except_dynamic_partial_raw(buffer, range, except, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_dynamic_partial_raw_ + +#ifndef _di_fll_print_except_dynamic_partial_safely_ + f_status_t fll_print_except_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_except_dynamic_partial_safely(buffer, range, except, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_except_dynamic_partial_safely_ + +#ifndef _di_fll_print_raw_ + f_status_t fll_print_raw(const f_string_t string, const f_array_length_t length, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_raw(string, length, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_raw_ + +#ifndef _di_fll_print_raw_terminated_ + f_status_t fll_print_raw_terminated(const f_string_t string, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_raw_terminated(string, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_raw_terminated_ + +#ifndef _di_fll_print_safely_ + f_status_t fll_print_safely(const f_string_t string, const f_array_length_t length, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_safely(string, length, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_safely_ + +#ifndef _di_fll_print_safely_terminated_ + f_status_t fll_print_safely_terminated(const f_string_t string, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_safely_terminated(string, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_safely_terminated_ + +#ifndef _di_fll_print_string_ + f_status_t fll_print_string(FILE *output, const f_string_t string, ...) { + + flockfile(output); + + va_list ap; + + va_start(ap, string); + + const f_status_t status = fl_print_string_va(output, string, ap); + + va_end(ap); + + funlockfile(output); + } +#endif // _di_fll_print_string_ + +#ifndef _di_fll_print_string_convert_ + f_status_t fll_print_string_convert(FILE *output, char *current, va_list *ap) { + + flockfile(output); + + const f_status_t status = fl_print_string_convert(output, current, ap); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_string_convert_ + +#ifndef _di_fll_print_string_va_ + f_status_t fll_print_string_va(FILE *output, const f_string_t string, va_list ap) { + + flockfile(output); + + const f_status_t status = fl_print_string_va(output, string, ap); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_string_va_ + +#ifndef _di_fll_print_terminated_ + f_status_t fll_print_terminated(const f_string_t string, FILE *output) { + + flockfile(output); + + const f_status_t status = f_print_terminated(string, output); + + funlockfile(output); + + return status; + } +#endif // _di_fll_print_terminated_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_2/fll_print/c/print.h b/level_2/fll_print/c/print.h new file mode 100644 index 0000000..bc33f4c --- /dev/null +++ b/level_2/fll_print/c/print.h @@ -0,0 +1,967 @@ +/** + * FLL - Level 2 + * + * Project: Print + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * Provides print-related functionality. + */ +#ifndef _FLL_print_h +#define _FLL_print_h + +// libc includes +#include + +// fll-0 includes +#include +#include +#include +#include +#include +#include +#include + +// fll-1 includes +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This is a variation of f_print() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print(). + * + * Errors (with error bit) from: f_print(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print() + */ +#ifndef _di_fll_print_ + extern f_status_t fll_print(const f_string_t string, const f_array_length_t length, FILE *output); +#endif // _di_fll_print_ + +/** + * This is a variation of f_print_character_safely() that uses locking. + * + * @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 + * Success from: f_print_character_safely(). + * + * Errors (with error bit) from: f_print_character_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_character_safely() + */ +#ifndef _di_fll_print_character_safely_ + extern f_status_t fll_print_character_safely(const char character, FILE *output); +#endif // _di_fll_print_character_safely_ + +/** + * This is a variation of f_print_dynamic() that uses locking. + * + * @param buffer + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_dynamic(). + * + * Errors (with error bit) from: f_print_dynamic(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_dynamic() + */ +#ifndef _di_fll_print_dynamic_ + extern f_status_t fll_print_dynamic(const f_string_static_t buffer, FILE *output); +#endif // _di_fll_print_dynamic_ + +/** + * This is a variation of f_print_dynamic_raw() that uses locking. + * + * @param buffer + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_dynamic_raw(). + * + * Errors (with error bit) from: f_print_dynamic_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_dynamic_raw() + */ +#ifndef _di_fll_print_dynamic_raw_ + extern f_status_t fll_print_dynamic_raw(const f_string_static_t buffer, FILE *output); +#endif // _di_fll_print_dynamic_raw_ + +/** + * This is a variation of f_print_dynamic_safely() that uses locking. + * + * @param buffer + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_dynamic_safely(). + * + * Errors (with error bit) from: f_print_dynamic_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_dynamic_safely() + */ +#ifndef _di_fll_print_dynamic_safely_ + extern f_status_t fll_print_dynamic_safely(const f_string_static_t buffer, FILE *output); +#endif // _di_fll_print_dynamic_safely_ + +/** + * This is a variation of f_print_dynamic_partial() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_dynamic_partial(). + * + * Errors (with error bit) from: f_print_dynamic_partial(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_dynamic_partial() + */ +#ifndef _di_fll_print_dynamic_partial_ + extern f_status_t fll_print_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, FILE *output); +#endif // _di_fll_print_dynamic_partial_ + +/** + * This is a variation of f_print_dynamic_partial_raw() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_dynamic_partial_raw(). + * + * Errors (with error bit) from: f_print_dynamic_partial_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_dynamic_partial_raw() + */ +#ifndef _di_fll_print_dynamic_partial_raw_ + extern f_status_t fll_print_dynamic_partial_raw(const f_string_static_t buffer, const f_string_range_t range, FILE *output); +#endif // _di_fll_print_dynamic_partial_raw_ + +/** + * This is a variation of f_print_dynamic_partial_safely() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_dynamic_partial_safely(). + * + * Errors (with error bit) from: f_print_dynamic_partial_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_dynamic_partial_safely() + */ +#ifndef _di_fll_print_dynamic_partial_safely_ + extern f_status_t fll_print_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, FILE *output); +#endif // _di_fll_print_dynamic_partial_safely_ + +/** + * This is a variation of f_print_except() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except(). + * + * Errors (with error bit) from: f_print_except(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except() + */ +#ifndef _di_fll_print_except_ + extern f_status_t fll_print_except(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output); +#endif // _di_fll_print_except_ + +/** + * This is a variation of f_print_except_raw() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_raw(). + * + * Errors (with error bit) from: f_print_except_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_raw() + */ +#ifndef _di_fll_print_except_raw_ + extern f_status_t fll_print_except_raw(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output); +#endif // _di_fll_print_except_raw_ + +/** + * This is a variation of f_print_except_safely() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_safely(). + * + * Errors (with error bit) from: f_print_except_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_safely() + */ +#ifndef _di_fll_print_except_safely_ + extern f_status_t fll_print_except_safely(const f_string_t string, const f_array_length_t length, const f_array_lengths_t except, FILE *output); +#endif // _di_fll_print_except_safely_ + +/** + * This is a variation of f_print_except_dynamic() that uses locking. + * + * @param buffer + * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_dynamic(). + * + * Errors (with error bit) from: f_print_except_dynamic(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_dynamic() + */ +#ifndef _di_fll_print_except_dynamic_ + extern f_status_t fll_print_except_dynamic(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output); +#endif // _di_fll_print_except_dynamic_ + +/** + * This is a variation of f_print_except_dynamic_raw() that uses locking. + * + * @param buffer + * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_dynamic_raw(). + * + * Errors (with error bit) from: f_print_except_dynamic_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_dynamic_raw() + */ +#ifndef _di_fll_print_except_dynamic_raw_ + extern f_status_t fll_print_except_dynamic_raw(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output); +#endif // _di_fll_print_except_dynamic_raw_ + +/** + * This is a variation of f_print_except_dynamic_safely() that uses locking. + * + * @param buffer + * The string to output. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_dynamic_safely(). + * + * Errors (with error bit) from: f_print_except_dynamic_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_dynamic_safely() + */ +#ifndef _di_fll_print_except_dynamic_safely_ + extern f_status_t fll_print_except_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except, FILE *output); +#endif // _di_fll_print_except_dynamic_safely_ + +/** + * This is a variation of f_print_except_in() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_in(). + * + * Errors (with error bit) from: f_print_except_in(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_in() + */ +#ifndef _di_fll_print_except_in_ + extern f_status_t fll_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); +#endif // _di_fll_print_except_in_ + +/** + * This is a variation of f_print_except_in_raw() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_in_raw(). + * + * Errors (with error bit) from: f_print_except_in_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_in_raw() + */ +#ifndef _di_fll_print_except_in_raw_ + extern f_status_t fll_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); +#endif // _di_fll_print_except_in_raw_ + +/** + * This is a variation of f_print_except_in_safely() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_in_safely(). + * + * Errors (with error bit) from: f_print_except_in_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_in_safely() + */ +#ifndef _di_fll_print_except_in_safely_ + extern f_status_t fll_print_except_in_safely(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); +#endif // _di_fll_print_except_in_safely_ + +/** + * This is a variation of f_print_except_in_dynamic() that uses locking. + * + * @param buffer + * The string to output. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_in_dynamic(). + * + * Errors (with error bit) from: f_print_except_in_dynamic(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_in_dynamic() + */ +#ifndef _di_fll_print_except_in_dynamic_ + extern f_status_t fll_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); +#endif // _di_fll_print_except_in_dynamic_ + +/** + * This is a variation of f_print_except_in_dynamic_raw() that uses locking. + * + * @param buffer + * The string to output. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_in_dynamic_raw(). + * + * Errors (with error bit) from: f_print_except_in_dynamic_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_in_dynamic_raw() + */ +#ifndef _di_fll_print_except_in_dynamic_raw_ + extern f_status_t fll_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); +#endif // _di_fll_print_except_in_dynamic_raw_ + +/** + * This is a variation of f_print_except_in_dynamic_safely() that uses locking. + * + * @param buffer + * The string to output. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_in_dynamic_safely(). + * + * Errors (with error bit) from: f_print_except_in_dynamic_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_in_dynamic_safely() + */ +#ifndef _di_fll_print_except_in_dynamic_safely_ + extern f_status_t fll_print_except_in_dynamic_safely(const f_string_static_t buffer, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output); +#endif // _di_fll_print_except_in_dynamic_safely_ + +/** + * This is a variation of f_print_except_in_dynamic_partial() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_in_dynamic_partial(). + * + * Errors (with error bit) from: f_print_except_in_dynamic_partial(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_in_dynamic_partial() + */ +#ifndef _di_fll_print_dynamic_except_partial_ + extern f_status_t fll_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); +#endif // _di_fll_print_except_in_dynamic_partial_ + +/** + * This is a variation of f_print_except_in_dynamic_partial_raw() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_in_dynamic_partial_raw(). + * + * Errors (with error bit) from: f_print_except_in_dynamic_partial_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_in_dynamic_partial_raw() + */ +#ifndef _di_fll_print_dynamic_except_partial_raw_ + extern f_status_t fll_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); +#endif // _di_fll_print_except_in_dynamic_partial_raw_ + +/** + * This is a variation of f_print_except_in_dynamic_partial_safely() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except_at + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param except_in + * An array of ranges within the string to not print. + * The array of ranges is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_in_dynamic_partial_safely(). + * + * Errors (with error bit) from: f_print_except_in_dynamic_partial_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_in_dynamic_partial_safely() + */ +#ifndef _di_fll_print_dynamic_except_partial_safely_ + extern f_status_t fll_print_except_in_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except_at, const f_string_ranges_t except_in, FILE *output); +#endif // _di_fll_print_except_in_dynamic_partial_safely_ + +/** + * This is a variation of f_print_except_dynamic_partial() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_dynamic_partial(). + * + * Errors (with error bit) from: f_print_except_dynamic_partial(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_dynamic_partial() + */ +#ifndef _di_fll_print_dynamic_except_partial_ + extern f_status_t fll_print_except_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); +#endif // _di_fll_print_except_dynamic_partial_ + +/** + * This is a variation of f_print_except_dynamic_partial_raw() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_dynamic_partial_raw(). + * + * Errors (with error bit) from: f_print_except_dynamic_partial_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_dynamic_partial_raw() + */ +#ifndef _di_fll_print_dynamic_except_partial_raw_ + extern f_status_t fll_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); +#endif // _di_fll_print_except_dynamic_partial_raw_ + +/** + * This is a variation of f_print_except_dynamic_partial() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_dynamic_partial(). + * + * Errors (with error bit) from: f_print_except_dynamic_partial(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_dynamic_partial() + */ +#ifndef _di_fll_print_dynamic_except_partial_ + extern f_status_t fll_print_except_dynamic_partial(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); +#endif // _di_fll_print_except_dynamic_partial_ + +/** + * This is a variation of f_print_except_dynamic_partial_raw() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_dynamic_partial_raw(). + * + * Errors (with error bit) from: f_print_except_dynamic_partial_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_dynamic_partial_raw() + */ +#ifndef _di_fll_print_dynamic_except_partial_raw_ + extern f_status_t fll_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); +#endif // _di_fll_print_except_dynamic_partial_raw_ + +/** + * This is a variation of f_print_except_dynamic_partial_safely() that uses locking. + * + * @param buffer + * The string to output. + * @param range + * The range within the provided string to print. + * @param except + * An array of locations within the given string to not print. + * The array of locations is required/assumed to be in linear order. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_except_dynamic_partial_safely(). + * + * Errors (with error bit) from: f_print_except_dynamic_partial_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_except_dynamic_partial_safely() + */ +#ifndef _di_fll_print_dynamic_except_partial_safely_ + extern f_status_t fll_print_except_dynamic_partial_safely(const f_string_static_t buffer, const f_string_range_t range, const f_array_lengths_t except, FILE *output); +#endif // _di_fll_print_except_dynamic_partial_safely_ + +/** + * This is a variation of f_print_raw() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_raw(). + * + * Errors (with error bit) from: f_print_raw(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_raw() + */ +#ifndef _di_fll_print_raw_ + extern f_status_t fll_print_raw(const f_string_t string, const f_array_length_t length, FILE *output); +#endif // _di_fll_print_raw_ + +/** + * This is a variation of f_print_raw_terminated() that uses locking. + * + * @param string + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_raw_terminated(). + * + * Errors (with error bit) from: f_print_raw_terminated(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_raw_terminated() + */ +#ifndef _di_fll_print_raw_terminated_ + extern f_status_t fll_print_raw_terminated(const f_string_t string, FILE *output); +#endif // _di_fll_print_raw_terminated_ + +/** + * This is a variation of f_print_safely() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_safely(). + * + * Errors (with error bit) from: f_print_safely(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_safely() + */ +#ifndef _di_fll_print_safely_ + extern f_status_t fll_print_safely(const f_string_t string, const f_array_length_t length, FILE *output); +#endif // _di_fll_print_safely_ + +/** + * This is a variation of f_print_safely_terminated() that uses locking. + * + * @param string + * The string to output. + * @param length + * The total number of characters to print. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_safely_terminated(). + * + * Errors (with error bit) from: f_print_safely_terminated(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_safely_terminated() + */ +#ifndef _di_fll_print_safely_terminated_ + extern f_status_t fll_print_safely_terminated(const f_string_t string, FILE *output); +#endif // _di_fll_print_safely_terminated_ + +/** + * This is a variation of fl_print_string() that uses locking. + * + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * @param string + * The formatted string to process and output. + * This is a NULL terminated string. + * @param ... + * Additional arguments relating to the string. + * + * @return + * Success from: fl_print_string(). + * + * Errors (with error bit) from: fl_print_string(). + * + * @see flockfile() + * @see funlockfile() + * @see va_start() + * @see va_end() + * + * @see fl_print_string() + */ +#ifndef _di_fll_print_string_ + extern f_status_t fll_print_string(FILE *output, const f_string_t string, ...); +#endif // _di_fll_print_string_ + +/** + * This is a variation of fl_print_string_convert() that uses locking. + * + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * @param current + * The current character position within the string. + * @param ap + * The variable arguments list. + * + * @return + * Success from: fl_print_string_convert(). + * + * Errors (with error bit) from: fl_print_string_convert(). + * + * @see flockfile() + * @see funlockfile() + * + * @see fl_print_string_convert() + */ +#ifndef _di_fll_print_string_convert_ + extern f_status_t fll_print_string_convert(FILE *output, char *current, va_list *ap); +#endif // _di_fll_print_string_convert_ + +/** + * This is a variation of fl_print_string_va() that uses locking. + * + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * @param string + * The formatted string to process and output. + * @param ap + * The variable list. + * The va_start(ap, string) and va_end(ap) is required to be called outside this function. + * + * @return + * Success from: fl_print_string_va(). + * + * Errors (with error bit) from: fl_print_string_va(). + * + * @see flockfile() + * @see funlockfile() + * + * @see fl_print_string_va() + */ +#ifndef _di_fll_print_string_va_ + extern f_status_t fll_print_string_va(FILE *output, const f_string_t string, va_list ap); +#endif // _di_fll_print_string_va_ + +/** + * This is a variation of f_print_terminated() that uses locking. + * + * @param string + * The string to output. + * @param output + * The file stream to output to, including standard streams such as stdout and stderr. + * + * @return + * Success from: f_print_terminated(). + * + * Errors (with error bit) from: f_print_terminated(). + * + * @see flockfile() + * @see funlockfile() + * + * @see f_print_terminated() + */ +#ifndef _di_fll_print_terminated_ + extern f_status_t fll_print_terminated(const f_string_t string, FILE *output); +#endif // _di_fll_print_terminated_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _FLL_path_h diff --git a/level_2/fll_print/data/build/defines b/level_2/fll_print/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_2/fll_print/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_2/fll_print/data/build/dependencies b/level_2/fll_print/data/build/dependencies new file mode 100644 index 0000000..9488792 --- /dev/null +++ b/level_2/fll_print/data/build/dependencies @@ -0,0 +1,8 @@ +# fss-0000 + +f_type +f_status +f_memory +f_string +f_print +fl_print diff --git a/level_2/fll_print/data/build/settings b/level_2/fll_print/data/build/settings new file mode 100644 index 0000000..a44d01b --- /dev/null +++ b/level_2/fll_print/data/build/settings @@ -0,0 +1,56 @@ +# fss-0001 + +project_name fll_print + +version_major 0 +version_minor 5 +version_micro 5 +version_file minor +version_target micro + +environment + +process_pre +process_post + +modes individual +modes_default individual + +build_compiler gcc +build_indexer ar +build_language c +build_libraries -lc +build_libraries-individual -lfl_print -lf_conversion -lf_memory -lf_print -lf_string -lf_utf +build_sources_library print.c +build_sources_program +build_sources_headers print.h +build_sources_script +build_sources_setting +build_script yes +build_shared yes +build_static no + +path_headers fll/level_2 +path_headers_preserve no +path_library_script script +path_library_shared shared +path_library_static static +path_program_script script +path_program_shared shared +path_program_static static +path_sources +path_standard yes + +search_exclusive yes +search_shared yes +search_static yes + +defines_all +defines_static +defines_shared + +flags_all -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-logical-op-parentheses -Wno-parentheses +flags_shared +flags_static +flags_library -fPIC +flags_program -fPIE diff --git a/level_2/fll_status/c/status.c b/level_2/fll_status/c/status.c index 62f8a31..0a1e1b5 100644 --- a/level_2/fll_status/c/status.c +++ b/level_2/fll_status/c/status.c @@ -457,6 +457,18 @@ extern "C" { return F_none; } + if (fl_string_compare(string, FL_status_string_ascii, length, FL_status_string_ascii_length) == F_equal_to) { + *code = F_ascii; + + return F_none; + } + + if (fl_string_compare(string, FL_status_string_ascii_not, length, FL_status_string_ascii_not_length) == F_equal_to) { + *code = F_ascii_not; + + return F_none; + } + if (fl_string_compare(string, FL_status_string_block, length, FL_status_string_block_length) == F_equal_to) { *code = F_block; -- 1.8.3.1