diff --git a/libc/config/config.json b/libc/config/config.json index c38d424229218..d738aade74427 100644 --- a/libc/config/config.json +++ b/libc/config/config.json @@ -41,6 +41,10 @@ "LIBC_CONF_PRINTF_DISABLE_STRERROR": { "value": false, "doc": "Disable handling of %m to print strerror in printf and friends." + }, + "LIBC_CONF_PRINTF_RUNTIME_DISPATCH": { + "value": true, + "doc": "Use dynamic dispatch for the output mechanism to reduce code size." } }, "scanf": { diff --git a/libc/config/gpu/amdgpu/config.json b/libc/config/gpu/amdgpu/config.json index d99f48ecbede1..30ae10e2cfd61 100644 --- a/libc/config/gpu/amdgpu/config.json +++ b/libc/config/gpu/amdgpu/config.json @@ -19,6 +19,9 @@ }, "LIBC_CONF_PRINTF_DISABLE_STRERROR": { "value": true + }, + "LIBC_CONF_PRINTF_RUNTIME_DISPATCH": { + "value": false } }, "scanf": { diff --git a/libc/config/gpu/nvptx/config.json b/libc/config/gpu/nvptx/config.json index d99f48ecbede1..30ae10e2cfd61 100644 --- a/libc/config/gpu/nvptx/config.json +++ b/libc/config/gpu/nvptx/config.json @@ -19,6 +19,9 @@ }, "LIBC_CONF_PRINTF_DISABLE_STRERROR": { "value": true + }, + "LIBC_CONF_PRINTF_RUNTIME_DISPATCH": { + "value": false } }, "scanf": { diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst index 940a07754c458..dee9a63101eb9 100644 --- a/libc/docs/configure.rst +++ b/libc/docs/configure.rst @@ -45,6 +45,7 @@ to learn about the defaults for your platform and target. - ``LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_DYADIC_FLOAT``: Use dyadic float for faster and smaller but less accurate printf doubles. - ``LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_FLOAT320``: Use an alternative printf float implementation based on 320-bit floats - ``LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE``: Use large table for better printf long double performance. + - ``LIBC_CONF_PRINTF_RUNTIME_DISPATCH``: Use dynamic dispatch for the output mechanism to reduce code size. * **"pthread" options** - ``LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT``: Default number of spins before blocking if a mutex is in contention (default to 100). - ``LIBC_CONF_RWLOCK_DEFAULT_SPIN_COUNT``: Default number of spins before blocking if a rwlock is in contention (default to 100). diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt index ea58067c7070a..c22f9858f3b1e 100644 --- a/libc/src/stdio/printf_core/CMakeLists.txt +++ b/libc/src/stdio/printf_core/CMakeLists.txt @@ -25,6 +25,9 @@ endif() if(LIBC_CONF_PRINTF_DISABLE_STRERROR) list(APPEND printf_config_copts "-DLIBC_COPT_PRINTF_DISABLE_STRERROR") endif() +if(LIBC_CONF_PRINTF_RUNTIME_DISPATCH) + list(APPEND printf_config_copts "-DLIBC_COPT_PRINTF_RUNTIME_DISPATCH") +endif() if(printf_config_copts) list(PREPEND printf_config_copts "COMPILE_OPTIONS") endif() @@ -62,10 +65,8 @@ add_header_library( libc.src.__support.common ) -add_object_library( +add_header_library( writer - SRCS - writer.cpp HDRS writer.h DEPENDS @@ -76,10 +77,8 @@ add_object_library( libc.src.string.memory_utils.inline_memset ) -add_object_library( +add_header_library( converter - SRCS - converter.cpp HDRS converter.h converter_atlas.h @@ -113,10 +112,8 @@ add_object_library( libc.src.__support.StringUtil.error_to_string ) -add_object_library( +add_header_library( printf_main - SRCS - printf_main.cpp HDRS printf_main.h DEPENDS diff --git a/libc/src/stdio/printf_core/char_converter.h b/libc/src/stdio/printf_core/char_converter.h index 2596cba813c2e..fd2eb2553887a 100644 --- a/libc/src/stdio/printf_core/char_converter.h +++ b/libc/src/stdio/printf_core/char_converter.h @@ -17,7 +17,9 @@ namespace LIBC_NAMESPACE_DECL { namespace printf_core { -LIBC_INLINE int convert_char(Writer *writer, const FormatSection &to_conv) { +template +LIBC_INLINE int convert_char(Writer *writer, + const FormatSection &to_conv) { char c = static_cast(to_conv.conv_val_raw); constexpr int STRING_LEN = 1; diff --git a/libc/src/stdio/printf_core/converter.cpp b/libc/src/stdio/printf_core/converter.cpp deleted file mode 100644 index b1c66451f53f0..0000000000000 --- a/libc/src/stdio/printf_core/converter.cpp +++ /dev/null @@ -1,105 +0,0 @@ -//===-- Format specifier converter implmentation for printf -----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "src/stdio/printf_core/converter.h" - -#include "src/__support/macros/config.h" -#include "src/stdio/printf_core/core_structs.h" -#include "src/stdio/printf_core/printf_config.h" -#include "src/stdio/printf_core/strerror_converter.h" -#include "src/stdio/printf_core/writer.h" - -// This option allows for replacing all of the conversion functions with custom -// replacements. This allows conversions to be replaced at compile time. -#ifndef LIBC_COPT_PRINTF_CONV_ATLAS -#include "src/stdio/printf_core/converter_atlas.h" -#else -#include LIBC_COPT_PRINTF_CONV_ATLAS -#endif - -#include - -namespace LIBC_NAMESPACE_DECL { -namespace printf_core { - -int convert(Writer *writer, const FormatSection &to_conv) { - if (!to_conv.has_conv) - return writer->write(to_conv.raw_string); - -#if !defined(LIBC_COPT_PRINTF_DISABLE_FLOAT) && \ - defined(LIBC_COPT_PRINTF_HEX_LONG_DOUBLE) - if (to_conv.length_modifier == LengthModifier::L) { - switch (to_conv.conv_name) { - case 'f': - case 'F': - case 'e': - case 'E': - case 'g': - case 'G': - return convert_float_hex_exp(writer, to_conv); - default: - break; - } - } -#endif // LIBC_COPT_PRINTF_DISABLE_FLOAT - - switch (to_conv.conv_name) { - case '%': - return writer->write("%"); - case 'c': - return convert_char(writer, to_conv); - case 's': - return convert_string(writer, to_conv); - case 'd': - case 'i': - case 'u': - case 'o': - case 'x': - case 'X': - case 'b': - case 'B': - return convert_int(writer, to_conv); -#ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT - case 'f': - case 'F': - return convert_float_decimal(writer, to_conv); - case 'e': - case 'E': - return convert_float_dec_exp(writer, to_conv); - case 'a': - case 'A': - return convert_float_hex_exp(writer, to_conv); - case 'g': - case 'G': - return convert_float_dec_auto(writer, to_conv); -#endif // LIBC_COPT_PRINTF_DISABLE_FLOAT -#ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT - case 'r': - case 'R': - case 'k': - case 'K': - return convert_fixed(writer, to_conv); -#endif // LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT -#ifndef LIBC_COPT_PRINTF_DISABLE_STRERROR - case 'm': - return convert_strerror(writer, to_conv); -#endif // LIBC_COPT_PRINTF_DISABLE_STRERROR -#ifndef LIBC_COPT_PRINTF_DISABLE_WRITE_INT - case 'n': - return convert_write_int(writer, to_conv); -#endif // LIBC_COPT_PRINTF_DISABLE_WRITE_INT - case 'p': - return convert_pointer(writer, to_conv); - default: - return writer->write(to_conv.raw_string); - } - return -1; -} - -} // namespace printf_core -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/printf_core/converter.h b/libc/src/stdio/printf_core/converter.h index 2b3f06d0aa7a3..f26ed727f05f4 100644 --- a/libc/src/stdio/printf_core/converter.h +++ b/libc/src/stdio/printf_core/converter.h @@ -11,8 +11,18 @@ #include "src/__support/macros/config.h" #include "src/stdio/printf_core/core_structs.h" +#include "src/stdio/printf_core/printf_config.h" +#include "src/stdio/printf_core/strerror_converter.h" #include "src/stdio/printf_core/writer.h" +// This option allows for replacing all of the conversion functions with custom +// replacements. This allows conversions to be replaced at compile time. +#ifndef LIBC_COPT_PRINTF_CONV_ATLAS +#include "src/stdio/printf_core/converter_atlas.h" +#else +#include LIBC_COPT_PRINTF_CONV_ATLAS +#endif + #include namespace LIBC_NAMESPACE_DECL { @@ -21,7 +31,80 @@ namespace printf_core { // convert will call a conversion function to convert the FormatSection into // its string representation, and then that will write the result to the // writer. -int convert(Writer *writer, const FormatSection &to_conv); +template +int convert(Writer *writer, const FormatSection &to_conv) { + if (!to_conv.has_conv) + return writer->write(to_conv.raw_string); + +#if !defined(LIBC_COPT_PRINTF_DISABLE_FLOAT) && \ + defined(LIBC_COPT_PRINTF_HEX_LONG_DOUBLE) + if (to_conv.length_modifier == LengthModifier::L) { + switch (to_conv.conv_name) { + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + return convert_float_hex_exp(writer, to_conv); + default: + break; + } + } +#endif // LIBC_COPT_PRINTF_DISABLE_FLOAT + + switch (to_conv.conv_name) { + case '%': + return writer->write("%"); + case 'c': + return convert_char(writer, to_conv); + case 's': + return convert_string(writer, to_conv); + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + case 'b': + case 'B': + return convert_int(writer, to_conv); +#ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT + case 'f': + case 'F': + return convert_float_decimal(writer, to_conv); + case 'e': + case 'E': + return convert_float_dec_exp(writer, to_conv); + case 'a': + case 'A': + return convert_float_hex_exp(writer, to_conv); + case 'g': + case 'G': + return convert_float_dec_auto(writer, to_conv); +#endif // LIBC_COPT_PRINTF_DISABLE_FLOAT +#ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT + case 'r': + case 'R': + case 'k': + case 'K': + return convert_fixed(writer, to_conv); +#endif // LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT +#ifndef LIBC_COPT_PRINTF_DISABLE_STRERROR + case 'm': + return convert_strerror(writer, to_conv); +#endif // LIBC_COPT_PRINTF_DISABLE_STRERROR +#ifndef LIBC_COPT_PRINTF_DISABLE_WRITE_INT + case 'n': + return convert_write_int(writer, to_conv); +#endif // LIBC_COPT_PRINTF_DISABLE_WRITE_INT + case 'p': + return convert_pointer(writer, to_conv); + default: + return writer->write(to_conv.raw_string); + } + return -1; +} } // namespace printf_core } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/printf_core/fixed_converter.h b/libc/src/stdio/printf_core/fixed_converter.h index ba0a62d9fcb87..e8a3314967562 100644 --- a/libc/src/stdio/printf_core/fixed_converter.h +++ b/libc/src/stdio/printf_core/fixed_converter.h @@ -63,7 +63,9 @@ LIBC_INLINE constexpr uint32_t const_ten_exp(uint32_t exponent) { } \ } while (false) -LIBC_INLINE int convert_fixed(Writer *writer, const FormatSection &to_conv) { +template +LIBC_INLINE int convert_fixed(Writer *writer, + const FormatSection &to_conv) { // Long accum should be the largest type, so we can store all the smaller // numbers in things sized for it. using LARep = fixed_point::FXRep; diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h index d93457fcafd7f..ee5549825a6f2 100644 --- a/libc/src/stdio/printf_core/float_dec_converter.h +++ b/libc/src/stdio/printf_core/float_dec_converter.h @@ -93,7 +93,7 @@ zero_after_digits(int32_t base_2_exp, int32_t digits_after_point, T mantissa, return has_trailing_zeros; } -class PaddingWriter { +template class PaddingWriter { bool left_justified = false; bool leading_zeroes = false; char sign_char = 0; @@ -107,7 +107,8 @@ class PaddingWriter { sign_char(init_sign_char), min_width(to_conv.min_width > 0 ? to_conv.min_width : 0) {} - LIBC_INLINE int write_left_padding(Writer *writer, size_t total_digits) { + LIBC_INLINE int write_left_padding(Writer *writer, + size_t total_digits) { // The pattern is (spaces) (sign) (zeroes), but only one of spaces and // zeroes can be written, and only if the padding amount is positive. int padding_amount = @@ -130,7 +131,8 @@ class PaddingWriter { return 0; } - LIBC_INLINE int write_right_padding(Writer *writer, size_t total_digits) { + LIBC_INLINE int write_right_padding(Writer *writer, + size_t total_digits) { // If and only if the conversion is left justified, there may be trailing // spaces. int padding_amount = @@ -155,7 +157,7 @@ class PaddingWriter { This FloatWriter class does the buffering and counting, and writes to the output when necessary. */ -class FloatWriter { +template class FloatWriter { char block_buffer[BLOCK_SIZE]; // The buffer that holds a block. size_t buffered_digits = 0; // The number of digits held in the buffer. bool has_written = false; // True once any digits have been output. @@ -164,8 +166,9 @@ class FloatWriter { size_t digits_before_decimal = 0; // The # of digits to write before the '.' size_t total_digits_written = 0; // The # of digits that have been output. bool has_decimal_point; // True if the number has a decimal point. - Writer *writer; // Writes to the final output. - PaddingWriter padding_writer; // Handles prefixes/padding, uses total_digits. + Writer *writer; // Writes to the final output. + PaddingWriter + padding_writer; // Handles prefixes/padding, uses total_digits. LIBC_INLINE int flush_buffer(bool round_up_max_blocks = false) { const char MAX_BLOCK_DIGIT = (round_up_max_blocks ? '0' : '9'); @@ -245,8 +248,9 @@ class FloatWriter { static_assert(fputil::FPBits::EXP_LEN < (sizeof(int) * 8)); public: - LIBC_INLINE FloatWriter(Writer *init_writer, bool init_has_decimal_point, - const PaddingWriter &init_padding_writer) + LIBC_INLINE FloatWriter(Writer *init_writer, + bool init_has_decimal_point, + const PaddingWriter &init_padding_writer) : has_decimal_point(init_has_decimal_point), writer(init_writer), padding_writer(init_padding_writer) {} @@ -466,12 +470,24 @@ class FloatWriter { } }; +// Class-template auto deduction helpers, add more if needed. +FloatWriter(Writer, bool, + const PaddingWriter) + -> FloatWriter; +FloatWriter(Writer, bool, + const PaddingWriter) + -> FloatWriter; +FloatWriter(Writer, bool, + const PaddingWriter) + -> FloatWriter; + // This implementation is based on the Ryu Printf algorithm by Ulf Adams: // Ulf Adams. 2019. RyĆ« revisited: printf floating point conversion. // Proc. ACM Program. Lang. 3, OOPSLA, Article 169 (October 2019), 23 pages. // https://doi.org/10.1145/3360595 -template , int> = 0> -LIBC_INLINE int convert_float_decimal_typed(Writer *writer, +template , int> = 0> +LIBC_INLINE int convert_float_decimal_typed(Writer *writer, const FormatSection &to_conv, fputil::FPBits float_bits) { // signed because later we use -FRACTION_LEN @@ -498,7 +514,7 @@ LIBC_INLINE int convert_float_decimal_typed(Writer *writer, // ignored. bool nonzero = false; - PaddingWriter padding_writer(to_conv, sign_char); + PaddingWriter padding_writer(to_conv, sign_char); FloatWriter float_writer(writer, has_decimal_point, padding_writer); FloatToString float_converter(float_bits.get_val()); @@ -579,8 +595,9 @@ LIBC_INLINE int convert_float_decimal_typed(Writer *writer, return WRITE_OK; } -template , int> = 0> -LIBC_INLINE int convert_float_dec_exp_typed(Writer *writer, +template , int> = 0> +LIBC_INLINE int convert_float_dec_exp_typed(Writer *writer, const FormatSection &to_conv, fputil::FPBits float_bits) { // signed because later we use -FRACTION_LEN @@ -603,7 +620,7 @@ LIBC_INLINE int convert_float_dec_exp_typed(Writer *writer, bool has_decimal_point = (precision > 0) || ((to_conv.flags & FormatFlags::ALTERNATE_FORM) != 0); - PaddingWriter padding_writer(to_conv, sign_char); + PaddingWriter padding_writer(to_conv, sign_char); FloatWriter float_writer(writer, has_decimal_point, padding_writer); FloatToString float_converter(float_bits.get_val()); @@ -740,8 +757,9 @@ LIBC_INLINE int convert_float_dec_exp_typed(Writer *writer, return WRITE_OK; } -template , int> = 0> -LIBC_INLINE int convert_float_dec_auto_typed(Writer *writer, +template , int> = 0> +LIBC_INLINE int convert_float_dec_auto_typed(Writer *writer, const FormatSection &to_conv, fputil::FPBits float_bits) { // signed because later we use -FRACTION_LEN @@ -1107,7 +1125,9 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer *writer, } // TODO: unify the float converters to remove the duplicated checks for inf/nan. -LIBC_INLINE int convert_float_decimal(Writer *writer, + +template +LIBC_INLINE int convert_float_decimal(Writer *writer, const FormatSection &to_conv) { if (to_conv.length_modifier == LengthModifier::L) { fputil::FPBits::StorageType float_raw = to_conv.conv_val_raw; @@ -1128,7 +1148,8 @@ LIBC_INLINE int convert_float_decimal(Writer *writer, return convert_inf_nan(writer, to_conv); } -LIBC_INLINE int convert_float_dec_exp(Writer *writer, +template +LIBC_INLINE int convert_float_dec_exp(Writer *writer, const FormatSection &to_conv) { if (to_conv.length_modifier == LengthModifier::L) { fputil::FPBits::StorageType float_raw = to_conv.conv_val_raw; @@ -1149,7 +1170,8 @@ LIBC_INLINE int convert_float_dec_exp(Writer *writer, return convert_inf_nan(writer, to_conv); } -LIBC_INLINE int convert_float_dec_auto(Writer *writer, +template +LIBC_INLINE int convert_float_dec_auto(Writer *writer, const FormatSection &to_conv) { if (to_conv.length_modifier == LengthModifier::L) { fputil::FPBits::StorageType float_raw = to_conv.conv_val_raw; diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h index b264b5cf20728..16592e7bac932 100644 --- a/libc/src/stdio/printf_core/float_hex_converter.h +++ b/libc/src/stdio/printf_core/float_hex_converter.h @@ -25,7 +25,8 @@ namespace LIBC_NAMESPACE_DECL { namespace printf_core { -LIBC_INLINE int convert_float_hex_exp(Writer *writer, +template +LIBC_INLINE int convert_float_hex_exp(Writer *writer, const FormatSection &to_conv) { using LDBits = fputil::FPBits; using StorageType = LDBits::StorageType; diff --git a/libc/src/stdio/printf_core/float_inf_nan_converter.h b/libc/src/stdio/printf_core/float_inf_nan_converter.h index 3e41612e21c9f..ce31d7ae55499 100644 --- a/libc/src/stdio/printf_core/float_inf_nan_converter.h +++ b/libc/src/stdio/printf_core/float_inf_nan_converter.h @@ -24,7 +24,9 @@ namespace printf_core { using StorageType = fputil::FPBits::StorageType; -LIBC_INLINE int convert_inf_nan(Writer *writer, const FormatSection &to_conv) { +template +LIBC_INLINE int convert_inf_nan(Writer *writer, + const FormatSection &to_conv) { // All of the letters will be defined relative to variable a, which will be // the appropriate case based on the case of the conversion. bool is_negative; diff --git a/libc/src/stdio/printf_core/int_converter.h b/libc/src/stdio/printf_core/int_converter.h index d0af229f89be5..11234c32ce997 100644 --- a/libc/src/stdio/printf_core/int_converter.h +++ b/libc/src/stdio/printf_core/int_converter.h @@ -61,7 +61,9 @@ num_to_strview(uintmax_t num, cpp::span bufref, char conv_name) { } // namespace details -LIBC_INLINE int convert_int(Writer *writer, const FormatSection &to_conv) { +template +LIBC_INLINE int convert_int(Writer *writer, + const FormatSection &to_conv) { static constexpr size_t BITS_IN_BYTE = 8; static constexpr size_t BITS_IN_NUM = sizeof(uintmax_t) * BITS_IN_BYTE; diff --git a/libc/src/stdio/printf_core/printf_main.cpp b/libc/src/stdio/printf_core/printf_main.cpp deleted file mode 100644 index bd4a5a168bd23..0000000000000 --- a/libc/src/stdio/printf_core/printf_main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===-- Starting point for printf -------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "src/stdio/printf_core/printf_main.h" - -#include "src/__support/arg_list.h" -#include "src/__support/macros/config.h" -#include "src/stdio/printf_core/converter.h" -#include "src/stdio/printf_core/core_structs.h" -#include "src/stdio/printf_core/parser.h" -#include "src/stdio/printf_core/writer.h" - -#include - -namespace LIBC_NAMESPACE_DECL { -namespace printf_core { - -int printf_main(Writer *writer, const char *__restrict str, - internal::ArgList &args) { - Parser parser(str, args); - int result = 0; - for (FormatSection cur_section = parser.get_next_section(); - !cur_section.raw_string.empty(); - cur_section = parser.get_next_section()) { - if (cur_section.has_conv) - result = convert(writer, cur_section); - else - result = writer->write(cur_section.raw_string); - - if (result < 0) - return result; - } - - return writer->get_chars_written(); -} - -} // namespace printf_core -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/printf_core/printf_main.h b/libc/src/stdio/printf_core/printf_main.h index 3e73bf36e0e30..57f29858d5298 100644 --- a/libc/src/stdio/printf_core/printf_main.h +++ b/libc/src/stdio/printf_core/printf_main.h @@ -11,6 +11,9 @@ #include "src/__support/arg_list.h" #include "src/__support/macros/config.h" +#include "src/stdio/printf_core/converter.h" +#include "src/stdio/printf_core/core_structs.h" +#include "src/stdio/printf_core/parser.h" #include "src/stdio/printf_core/writer.h" #include @@ -18,8 +21,25 @@ namespace LIBC_NAMESPACE_DECL { namespace printf_core { -int printf_main(Writer *writer, const char *__restrict str, - internal::ArgList &args); +template +int printf_main(Writer *writer, const char *__restrict str, + internal::ArgList &args) { + Parser parser(str, args); + int result = 0; + for (FormatSection cur_section = parser.get_next_section(); + !cur_section.raw_string.empty(); + cur_section = parser.get_next_section()) { + if (cur_section.has_conv) + result = convert(writer, cur_section); + else + result = writer->write(cur_section.raw_string); + + if (result < 0) + return result; + } + + return writer->get_chars_written(); +} } // namespace printf_core } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/printf_core/ptr_converter.h b/libc/src/stdio/printf_core/ptr_converter.h index bf84718dfe6a8..c2a74e3043e6f 100644 --- a/libc/src/stdio/printf_core/ptr_converter.h +++ b/libc/src/stdio/printf_core/ptr_converter.h @@ -18,7 +18,9 @@ namespace LIBC_NAMESPACE_DECL { namespace printf_core { -LIBC_INLINE int convert_pointer(Writer *writer, const FormatSection &to_conv) { +template +LIBC_INLINE int convert_pointer(Writer *writer, + const FormatSection &to_conv) { FormatSection new_conv = to_conv; if (to_conv.conv_val_ptr == nullptr) { diff --git a/libc/src/stdio/printf_core/strerror_converter.h b/libc/src/stdio/printf_core/strerror_converter.h index 2902fd37c31ae..2cd6df0c01d45 100644 --- a/libc/src/stdio/printf_core/strerror_converter.h +++ b/libc/src/stdio/printf_core/strerror_converter.h @@ -19,7 +19,9 @@ namespace LIBC_NAMESPACE_DECL { namespace printf_core { -LIBC_INLINE int convert_strerror(Writer *writer, const FormatSection &to_conv) { +template +LIBC_INLINE int convert_strerror(Writer *writer, + const FormatSection &to_conv) { FormatSection new_conv = to_conv; const int error_num = static_cast(to_conv.conv_val_raw); diff --git a/libc/src/stdio/printf_core/string_converter.h b/libc/src/stdio/printf_core/string_converter.h index 1f36d51124107..74c9f598210f7 100644 --- a/libc/src/stdio/printf_core/string_converter.h +++ b/libc/src/stdio/printf_core/string_converter.h @@ -20,7 +20,9 @@ namespace LIBC_NAMESPACE_DECL { namespace printf_core { -LIBC_INLINE int convert_string(Writer *writer, const FormatSection &to_conv) { +template +LIBC_INLINE int convert_string(Writer *writer, + const FormatSection &to_conv) { size_t string_len = 0; const char *str_ptr = reinterpret_cast(to_conv.conv_val_ptr); diff --git a/libc/src/stdio/printf_core/vasprintf_internal.h b/libc/src/stdio/printf_core/vasprintf_internal.h index 0e446f856e438..9d46617da7751 100644 --- a/libc/src/stdio/printf_core/vasprintf_internal.h +++ b/libc/src/stdio/printf_core/vasprintf_internal.h @@ -19,8 +19,9 @@ namespace LIBC_NAMESPACE_DECL { namespace printf_core { LIBC_INLINE int resize_overflow_hook(cpp::string_view new_str, void *target) { - printf_core::WriteBuffer *wb = - reinterpret_cast(target); + WriteBuffer::value> *wb = + reinterpret_cast< + WriteBuffer::value> *>(target); size_t new_size = new_str.size() + wb->buff_cur; const bool isBuffOnStack = (wb->buff == wb->init_buff); char *new_buff = static_cast( @@ -45,9 +46,9 @@ constexpr size_t DEFAULT_BUFFER_SIZE = 200; LIBC_INLINE int vasprintf_internal(char **ret, const char *__restrict format, internal::ArgList args) { char init_buff_on_stack[DEFAULT_BUFFER_SIZE]; - printf_core::WriteBuffer wb(init_buff_on_stack, DEFAULT_BUFFER_SIZE, - resize_overflow_hook); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer::value> wb( + init_buff_on_stack, DEFAULT_BUFFER_SIZE, resize_overflow_hook); + printf_core::Writer writer(wb); auto ret_val = printf_core::printf_main(&writer, format, args); if (ret_val < 0) { diff --git a/libc/src/stdio/printf_core/vfprintf_internal.h b/libc/src/stdio/printf_core/vfprintf_internal.h index 3becfee71dd27..630de9d9d43dd 100644 --- a/libc/src/stdio/printf_core/vfprintf_internal.h +++ b/libc/src/stdio/printf_core/vfprintf_internal.h @@ -72,9 +72,9 @@ LIBC_INLINE int vfprintf_internal(::FILE *__restrict stream, internal::ArgList &args) { constexpr size_t BUFF_SIZE = 1024; char buffer[BUFF_SIZE]; - printf_core::WriteBuffer wb(buffer, BUFF_SIZE, &file_write_hook, - reinterpret_cast(stream)); - Writer writer(&wb); + printf_core::WriteBuffer::value> wb( + buffer, BUFF_SIZE, &file_write_hook, reinterpret_cast(stream)); + Writer writer(wb); internal::flockfile(stream); int retval = printf_main(&writer, format, args); int flushval = wb.overflow_write(""); diff --git a/libc/src/stdio/printf_core/write_int_converter.h b/libc/src/stdio/printf_core/write_int_converter.h index a47cb41cb3287..efcff278bd284 100644 --- a/libc/src/stdio/printf_core/write_int_converter.h +++ b/libc/src/stdio/printf_core/write_int_converter.h @@ -19,7 +19,8 @@ namespace LIBC_NAMESPACE_DECL { namespace printf_core { -LIBC_INLINE int convert_write_int(Writer *writer, +template +LIBC_INLINE int convert_write_int(Writer *writer, const FormatSection &to_conv) { #ifndef LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS diff --git a/libc/src/stdio/printf_core/writer.cpp b/libc/src/stdio/printf_core/writer.cpp deleted file mode 100644 index d1cf85df1c8f8..0000000000000 --- a/libc/src/stdio/printf_core/writer.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===-- Writer definition for printf ----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "writer.h" -#include "src/__support/CPP/string_view.h" -#include "src/__support/macros/config.h" -#include "src/stdio/printf_core/core_structs.h" -#include "src/string/memory_utils/inline_memset.h" -#include - -namespace LIBC_NAMESPACE_DECL { -namespace printf_core { - -int Writer::pad(char new_char, size_t length) { - // First, fill as much of the buffer as possible with the padding char. - size_t written = 0; - const size_t buff_space = wb->buff_len - wb->buff_cur; - // ASSERT: length > buff_space - if (buff_space > 0) { - inline_memset(wb->buff + wb->buff_cur, new_char, buff_space); - wb->buff_cur += buff_space; - written = buff_space; - } - - // Next, overflow write the rest of length using the mini_buff. - constexpr size_t MINI_BUFF_SIZE = 64; - char mini_buff[MINI_BUFF_SIZE]; - inline_memset(mini_buff, new_char, MINI_BUFF_SIZE); - cpp::string_view mb_string_view(mini_buff, MINI_BUFF_SIZE); - while (written + MINI_BUFF_SIZE < length) { - int result = wb->overflow_write(mb_string_view); - if (result != WRITE_OK) - return result; - written += MINI_BUFF_SIZE; - } - cpp::string_view mb_substr = mb_string_view.substr(0, length - written); - return wb->overflow_write(mb_substr); -} - -} // namespace printf_core -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/printf_core/writer.h b/libc/src/stdio/printf_core/writer.h index 28c9a28270875..1d4734a51b9b8 100644 --- a/libc/src/stdio/printf_core/writer.h +++ b/libc/src/stdio/printf_core/writer.h @@ -21,12 +21,24 @@ namespace LIBC_NAMESPACE_DECL { namespace printf_core { -struct WriteBuffer { - enum class WriteMode { - FILL_BUFF_AND_DROP_OVERFLOW, - FLUSH_TO_STREAM, - RESIZE_AND_FILL_BUFF, - }; +enum class WriteMode { + FILL_BUFF_AND_DROP_OVERFLOW, + FLUSH_TO_STREAM, + RESIZE_AND_FILL_BUFF, + RUNTIME_DISPATCH, +}; + +// Helper to omit the template argument if we are using runtime dispatch and +// avoid multiple copies of the converter functions. +template struct Mode { +#ifdef LIBC_COPT_PRINTF_RUNTIME_DISPATCH + static constexpr WriteMode value = WriteMode::RUNTIME_DISPATCH; +#else + static constexpr WriteMode value = write_mode; +#endif +}; + +template struct WriteBuffer { using StreamWriter = int (*)(cpp::string_view, void *); char *buff; const char *init_buff; // for checking when resize. @@ -35,23 +47,26 @@ struct WriteBuffer { // The stream writer will be called when the buffer is full. It will be passed // string_views to write to the stream. - StreamWriter stream_writer; + const StreamWriter stream_writer; void *output_target; - WriteMode write_mode; - LIBC_INLINE WriteBuffer(char *Buff, size_t Buff_len, StreamWriter hook, + // The current writing mode in case the user wants runtime dispatch of the + // stream writer with function pointers. + [[maybe_unused]] WriteMode write_mode_; + + LIBC_INLINE WriteBuffer(char *buff, size_t buff_len, StreamWriter hook, void *target) - : buff(Buff), init_buff(Buff), buff_len(Buff_len), stream_writer(hook), - output_target(target), write_mode(WriteMode::FLUSH_TO_STREAM) {} + : buff(buff), init_buff(buff), buff_len(buff_len), stream_writer(hook), + output_target(target), write_mode_(WriteMode::FLUSH_TO_STREAM) {} - LIBC_INLINE WriteBuffer(char *Buff, size_t Buff_len) - : buff(Buff), init_buff(Buff), buff_len(Buff_len), stream_writer(nullptr), + LIBC_INLINE WriteBuffer(char *buff, size_t buff_len) + : buff(buff), init_buff(buff), buff_len(buff_len), stream_writer(nullptr), output_target(nullptr), - write_mode(WriteMode::FILL_BUFF_AND_DROP_OVERFLOW) {} + write_mode_(WriteMode::FILL_BUFF_AND_DROP_OVERFLOW) {} - LIBC_INLINE WriteBuffer(char *Buff, size_t Buff_len, StreamWriter hook) - : buff(Buff), init_buff(Buff), buff_len(Buff_len), stream_writer(hook), - output_target(this), write_mode(WriteMode::RESIZE_AND_FILL_BUFF) {} + LIBC_INLINE WriteBuffer(char *buff, size_t buff_len, StreamWriter hook) + : buff(buff), init_buff(buff), buff_len(buff_len), stream_writer(hook), + output_target(this), write_mode_(WriteMode::RESIZE_AND_FILL_BUFF) {} LIBC_INLINE int flush_to_stream(cpp::string_view new_str) { if (buff_cur > 0) { @@ -92,40 +107,68 @@ struct WriteBuffer { // this with an empty string will flush the buffer if relevant. LIBC_INLINE int overflow_write(cpp::string_view new_str) { - switch (write_mode) { - case WriteMode::FILL_BUFF_AND_DROP_OVERFLOW: + if constexpr (write_mode == WriteMode::RUNTIME_DISPATCH) { + if (write_mode_ == WriteMode::FILL_BUFF_AND_DROP_OVERFLOW) + return fill_remaining_to_buff(new_str); + else if (write_mode_ == WriteMode::FLUSH_TO_STREAM) + return flush_to_stream(new_str); + else if (write_mode_ == WriteMode::RESIZE_AND_FILL_BUFF) + return resize_and_write(new_str); + } else if constexpr (write_mode == WriteMode::FILL_BUFF_AND_DROP_OVERFLOW) { return fill_remaining_to_buff(new_str); - case WriteMode::FLUSH_TO_STREAM: + } else if constexpr (write_mode == WriteMode::FLUSH_TO_STREAM) { return flush_to_stream(new_str); - case WriteMode::RESIZE_AND_FILL_BUFF: + } else if constexpr (write_mode == WriteMode::RESIZE_AND_FILL_BUFF) { return resize_and_write(new_str); } __builtin_unreachable(); } }; -class Writer final { - WriteBuffer *wb; +template class Writer final { + WriteBuffer &wb; int chars_written = 0; - // This is a separate, non-inlined function so that the inlined part of the - // write function is shorter. - int pad(char new_char, size_t length); + LIBC_INLINE int pad(char new_char, size_t length) { + // First, fill as much of the buffer as possible with the padding char. + size_t written = 0; + const size_t buff_space = wb.buff_len - wb.buff_cur; + // ASSERT: length > buff_space + if (buff_space > 0) { + inline_memset(wb.buff + wb.buff_cur, new_char, buff_space); + wb.buff_cur += buff_space; + written = buff_space; + } + + // Next, overflow write the rest of length using the mini_buff. + constexpr size_t MINI_BUFF_SIZE = 64; + char mini_buff[MINI_BUFF_SIZE]; + inline_memset(mini_buff, new_char, MINI_BUFF_SIZE); + cpp::string_view mb_string_view(mini_buff, MINI_BUFF_SIZE); + while (written + MINI_BUFF_SIZE < length) { + int result = wb.overflow_write(mb_string_view); + if (result != WRITE_OK) + return result; + written += MINI_BUFF_SIZE; + } + cpp::string_view mb_substr = mb_string_view.substr(0, length - written); + return wb.overflow_write(mb_substr); + } public: - LIBC_INLINE Writer(WriteBuffer *WB) : wb(WB) {} + LIBC_INLINE Writer(WriteBuffer &wb) : wb(wb) {} // Takes a string, copies it into the buffer if there is space, else passes it // to the overflow mechanism to be handled separately. LIBC_INLINE int write(cpp::string_view new_string) { chars_written += static_cast(new_string.size()); - if (LIBC_LIKELY(wb->buff_cur + new_string.size() <= wb->buff_len)) { - inline_memcpy(wb->buff + wb->buff_cur, new_string.data(), + if (LIBC_LIKELY(wb.buff_cur + new_string.size() <= wb.buff_len)) { + inline_memcpy(wb.buff + wb.buff_cur, new_string.data(), new_string.size()); - wb->buff_cur += new_string.size(); + wb.buff_cur += new_string.size(); return WRITE_OK; } - return wb->overflow_write(new_string); + return wb.overflow_write(new_string); } // Takes a char and a length, memsets the next length characters of the buffer @@ -134,10 +177,10 @@ class Writer final { LIBC_INLINE int write(char new_char, size_t length) { chars_written += static_cast(length); - if (LIBC_LIKELY(wb->buff_cur + length <= wb->buff_len)) { - inline_memset(wb->buff + wb->buff_cur, - static_cast(new_char), length); - wb->buff_cur += length; + if (LIBC_LIKELY(wb.buff_cur + length <= wb.buff_len)) { + inline_memset(wb.buff + wb.buff_cur, static_cast(new_char), + length); + wb.buff_cur += length; return WRITE_OK; } return pad(new_char, length); @@ -147,18 +190,26 @@ class Writer final { // to the overflow mechanism to be handled separately. LIBC_INLINE int write(char new_char) { chars_written += 1; - if (LIBC_LIKELY(wb->buff_cur + 1 <= wb->buff_len)) { - wb->buff[wb->buff_cur] = new_char; - wb->buff_cur += 1; + if (LIBC_LIKELY(wb.buff_cur + 1 <= wb.buff_len)) { + wb.buff[wb.buff_cur] = new_char; + wb.buff_cur += 1; return WRITE_OK; } cpp::string_view char_string_view(&new_char, 1); - return wb->overflow_write(char_string_view); + return wb.overflow_write(char_string_view); } LIBC_INLINE int get_chars_written() { return chars_written; } }; +// Class-template auto deduction helpers. +Writer(WriteBuffer) + -> Writer; +Writer(WriteBuffer) + -> Writer; +Writer(WriteBuffer) + -> Writer; + } // namespace printf_core } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/snprintf.cpp b/libc/src/stdio/snprintf.cpp index 12ad3cd1f762b..c8940862f711f 100644 --- a/libc/src/stdio/snprintf.cpp +++ b/libc/src/stdio/snprintf.cpp @@ -27,8 +27,10 @@ LLVM_LIBC_FUNCTION(int, snprintf, // and pointer semantics, as well as handling // destruction automatically. va_end(vlist); - printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer::value> + wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); + printf_core::Writer writer(wb); int ret_val = printf_core::printf_main(&writer, format, args); if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer. diff --git a/libc/src/stdio/sprintf.cpp b/libc/src/stdio/sprintf.cpp index 1f59e6bae4723..7be97d3591aaf 100644 --- a/libc/src/stdio/sprintf.cpp +++ b/libc/src/stdio/sprintf.cpp @@ -28,8 +28,10 @@ LLVM_LIBC_FUNCTION(int, sprintf, // destruction automatically. va_end(vlist); - printf_core::WriteBuffer wb(buffer, cpp::numeric_limits::max()); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer< + printf_core::Mode::value> + wb(buffer, cpp::numeric_limits::max()); + printf_core::Writer writer(wb); int ret_val = printf_core::printf_main(&writer, format, args); wb.buff[wb.buff_cur] = '\0'; diff --git a/libc/src/stdio/vsnprintf.cpp b/libc/src/stdio/vsnprintf.cpp index a584c76833a2d..b07a2499a0dd3 100644 --- a/libc/src/stdio/vsnprintf.cpp +++ b/libc/src/stdio/vsnprintf.cpp @@ -24,8 +24,10 @@ LLVM_LIBC_FUNCTION(int, vsnprintf, internal::ArgList args(vlist); // This holder class allows for easier copying // and pointer semantics, as well as handling // destruction automatically. - printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer::value> + wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); + printf_core::Writer writer(wb); int ret_val = printf_core::printf_main(&writer, format, args); if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer. diff --git a/libc/src/stdio/vsprintf.cpp b/libc/src/stdio/vsprintf.cpp index b3978a09c671a..26d497be42125 100644 --- a/libc/src/stdio/vsprintf.cpp +++ b/libc/src/stdio/vsprintf.cpp @@ -25,8 +25,10 @@ LLVM_LIBC_FUNCTION(int, vsprintf, // and pointer semantics, as well as handling // destruction automatically. - printf_core::WriteBuffer wb(buffer, cpp::numeric_limits::max()); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer::value> + wb(buffer, cpp::numeric_limits::max()); + printf_core::Writer writer(wb); int ret_val = printf_core::printf_main(&writer, format, args); wb.buff[wb.buff_cur] = '\0'; diff --git a/libc/src/stdlib/str_from_util.h b/libc/src/stdlib/str_from_util.h index 7f54bdf71a018..61e6ba24b3817 100644 --- a/libc/src/stdlib/str_from_util.h +++ b/libc/src/stdlib/str_from_util.h @@ -104,8 +104,8 @@ printf_core::FormatSection parse_format_string(const char *__restrict format, return section; } -template -int strfromfloat_convert(printf_core::Writer *writer, +template +int strfromfloat_convert(printf_core::Writer *writer, const printf_core::FormatSection §ion) { if (!section.has_conv) return writer->write(section.raw_string); diff --git a/libc/src/stdlib/strfromd.cpp b/libc/src/stdlib/strfromd.cpp index 4c51e4c5c8a01..f51e6d4c7f1df 100644 --- a/libc/src/stdlib/strfromd.cpp +++ b/libc/src/stdlib/strfromd.cpp @@ -19,8 +19,10 @@ LLVM_LIBC_FUNCTION(int, strfromd, printf_core::FormatSection section = internal::parse_format_string(format, fp); - printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0)); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer::value> + wb(s, (n > 0 ? n - 1 : 0)); + printf_core::Writer writer(wb); int result = 0; if (section.has_conv) diff --git a/libc/src/stdlib/strfromf.cpp b/libc/src/stdlib/strfromf.cpp index ea98a69ee4d60..14dbfdb25bab6 100644 --- a/libc/src/stdlib/strfromf.cpp +++ b/libc/src/stdlib/strfromf.cpp @@ -19,8 +19,10 @@ LLVM_LIBC_FUNCTION(int, strfromf, printf_core::FormatSection section = internal::parse_format_string(format, fp); - printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0)); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer::value> + wb(s, (n > 0 ? n - 1 : 0)); + printf_core::Writer writer(wb); int result = 0; if (section.has_conv) diff --git a/libc/src/stdlib/strfroml.cpp b/libc/src/stdlib/strfroml.cpp index d5bee7609f69c..12f22a8a2fb65 100644 --- a/libc/src/stdlib/strfroml.cpp +++ b/libc/src/stdlib/strfroml.cpp @@ -24,8 +24,10 @@ LLVM_LIBC_FUNCTION(int, strfroml, // the length modifier has to be set to LenghtModifier::L section.length_modifier = printf_core::LengthModifier::L; - printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0)); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer::value> + wb(s, (n > 0 ? n - 1 : 0)); + printf_core::Writer writer(wb); int result = 0; if (section.has_conv) diff --git a/libc/src/time/strftime.cpp b/libc/src/time/strftime.cpp index c19e58fbadf71..f36091bc9736e 100644 --- a/libc/src/time/strftime.cpp +++ b/libc/src/time/strftime.cpp @@ -19,8 +19,10 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(size_t, strftime, (char *__restrict buffer, size_t buffsz, const char *__restrict format, const tm *timeptr)) { - printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer::value> + wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); + printf_core::Writer writer(wb); int ret = strftime_core::strftime_main(&writer, format, timeptr); if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer. wb.buff[wb.buff_cur] = '\0'; diff --git a/libc/src/time/strftime_core/CMakeLists.txt b/libc/src/time/strftime_core/CMakeLists.txt index a12a26b2aee0f..5e40e662ac791 100644 --- a/libc/src/time/strftime_core/CMakeLists.txt +++ b/libc/src/time/strftime_core/CMakeLists.txt @@ -18,10 +18,8 @@ add_header_library( libc.src.__support.str_to_integer ) -add_object_library( +add_header_library( converter - SRCS - converter.cpp HDRS converter.h num_converter.h @@ -36,10 +34,8 @@ add_object_library( libc.src.__support.integer_to_string ) -add_object_library( +add_header_library( strftime_main - SRCS - strftime_main.cpp HDRS strftime_main.h DEPENDS diff --git a/libc/src/time/strftime_core/composite_converter.h b/libc/src/time/strftime_core/composite_converter.h index 3530075cfe9a9..53cb7e536a0e5 100644 --- a/libc/src/time/strftime_core/composite_converter.h +++ b/libc/src/time/strftime_core/composite_converter.h @@ -42,7 +42,8 @@ get_specific_int_format(const tm *timeptr, const FormatSection &base_to_conv, return result; } -LIBC_INLINE int convert_date_us(printf_core::Writer *writer, +template +LIBC_INLINE int convert_date_us(printf_core::Writer *writer, const FormatSection &to_conv, const tm *timeptr) { // format is %m/%d/%y (month/day/year) @@ -66,7 +67,8 @@ LIBC_INLINE int convert_date_us(printf_core::Writer *writer, return WRITE_OK; } -LIBC_INLINE int convert_date_iso(printf_core::Writer *writer, +template +LIBC_INLINE int convert_date_iso(printf_core::Writer *writer, const FormatSection &to_conv, const tm *timeptr) { // format is "%Y-%m-%d" (year-month-day) @@ -90,7 +92,8 @@ LIBC_INLINE int convert_date_iso(printf_core::Writer *writer, return WRITE_OK; } -LIBC_INLINE int convert_time_am_pm(printf_core::Writer *writer, +template +LIBC_INLINE int convert_time_am_pm(printf_core::Writer *writer, const FormatSection &to_conv, const tm *timeptr) { // format is "%I:%M:%S %p" (hour:minute:second AM/PM) @@ -119,7 +122,8 @@ LIBC_INLINE int convert_time_am_pm(printf_core::Writer *writer, return WRITE_OK; } -LIBC_INLINE int convert_time_minute(printf_core::Writer *writer, +template +LIBC_INLINE int convert_time_minute(printf_core::Writer *writer, const FormatSection &to_conv, const tm *timeptr) { // format is "%H:%M" (hour:minute) @@ -139,7 +143,8 @@ LIBC_INLINE int convert_time_minute(printf_core::Writer *writer, return WRITE_OK; } -LIBC_INLINE int convert_time_second(printf_core::Writer *writer, +template +LIBC_INLINE int convert_time_second(printf_core::Writer *writer, const FormatSection &to_conv, const tm *timeptr) { // format is "%H:%M:%S" (hour:minute:second) @@ -163,7 +168,8 @@ LIBC_INLINE int convert_time_second(printf_core::Writer *writer, return WRITE_OK; } -LIBC_INLINE int convert_full_date_time(printf_core::Writer *writer, +template +LIBC_INLINE int convert_full_date_time(printf_core::Writer *writer, const FormatSection &to_conv, const tm *timeptr) { const time_utils::TMReader time_reader(timeptr); @@ -204,7 +210,8 @@ LIBC_INLINE int convert_full_date_time(printf_core::Writer *writer, return WRITE_OK; } -LIBC_INLINE int convert_composite(printf_core::Writer *writer, +template +LIBC_INLINE int convert_composite(printf_core::Writer *writer, const FormatSection &to_conv, const tm *timeptr) { switch (to_conv.conv_name) { diff --git a/libc/src/time/strftime_core/converter.cpp b/libc/src/time/strftime_core/converter.cpp deleted file mode 100644 index e9263af3d0e55..0000000000000 --- a/libc/src/time/strftime_core/converter.cpp +++ /dev/null @@ -1,96 +0,0 @@ -//===-- Format specifier converter implmentation for strftime -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See htto_conv.times://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "hdr/types/struct_tm.h" -#include "src/__support/macros/config.h" -#include "src/stdio/printf_core/writer.h" -#include "src/time/strftime_core/core_structs.h" - -#include "composite_converter.h" -#include "num_converter.h" -#include "str_converter.h" - -namespace LIBC_NAMESPACE_DECL { -namespace strftime_core { - -int convert(printf_core::Writer *writer, const FormatSection &to_conv, - const tm *timeptr) { - // TODO: Implement the locale support. - // Currently locale flags are ignored, as described by the posix standard for - // the default locale. - - if (!to_conv.has_conv) - return writer->write(to_conv.raw_string); - switch (to_conv.conv_name) { - // The cases are grouped by type, then alphabetized with lowercase before - // uppercase. - - // raw conversions - case '%': - return writer->write("%"); - case 'n': - return writer->write("\n"); - case 't': - return writer->write("\t"); - - // numeric conversions - case 'C': // Century [00-99] - case 'd': // Day of the month [01-31] - case 'e': // Day of the month [1-31] - case 'g': // last 2 digits of ISO year [00-99] - case 'G': // ISO year - case 'H': // 24-hour format [00-23] - case 'I': // 12-hour format [01-12] - case 'j': // Day of the year [001-366] - case 'm': // Month of the year [01-12] - case 'M': // Minute of the hour [00-59] - case 's': // Seconds since the epoch - case 'S': // Second of the minute [00-60] - case 'u': // ISO day of the week ([1-7] starting Monday) - case 'U': // Week of the year ([00-53] week 1 starts on first *Sunday*) - case 'V': // ISO week number ([01-53], 01 is first week majority in this year) - case 'w': // Day of week ([0-6] starting Sunday) - case 'W': // Week of the year ([00-53] week 1 starts on first *Monday*) - case 'y': // Year of the Century [00-99] - case 'Y': // Full year - return convert_int(writer, to_conv, timeptr); - - // string conversions - case 'a': // Abbreviated weekday name - case 'A': // Full weekday name - case 'b': // Abbreviated month name - case 'B': // Full month name - case 'h': // same as %b - case 'p': // AM/PM designation - return convert_str(writer, to_conv, timeptr); - - // composite conversions - case 'c': // locale specified date and time - case 'D': // %m/%d/%y (month/day/year) - case 'F': // %Y-%m-%d (year-month-day) - case 'r': // %I:%M:%S %p (hour:minute:second AM/PM) - case 'R': // %H:%M (hour:minute) - case 'T': // %H:%M:%S (hour:minute:second) - case 'x': // locale specified date - case 'X': // locale specified time - return convert_composite(writer, to_conv, timeptr); - - // timezone conversions - case 'z': // Timezone offset (+/-hhmm) (num conv) - case 'Z': // Timezone name (string conv) - // the standard says if no time zone is determinable, write no characters. - // Leave this here until time zones are implemented. - return 0; - default: - return writer->write(to_conv.raw_string); - } - return 0; -} - -} // namespace strftime_core -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/strftime_core/converter.h b/libc/src/time/strftime_core/converter.h index 154ee38d9f05a..ff0faf35bbd90 100644 --- a/libc/src/time/strftime_core/converter.h +++ b/libc/src/time/strftime_core/converter.h @@ -10,17 +10,94 @@ #define LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_CONVERTER_H #include "hdr/types/struct_tm.h" +#include "src/__support/macros/config.h" #include "src/stdio/printf_core/writer.h" #include "src/time/strftime_core/core_structs.h" +#include "composite_converter.h" +#include "num_converter.h" +#include "str_converter.h" + namespace LIBC_NAMESPACE_DECL { namespace strftime_core { // convert will call a conversion function to convert the FormatSection into // its string representation, and then that will write the result to the // writer. -int convert(printf_core::Writer *writer, const FormatSection &to_conv, - const tm *timeptr); +template +int convert(printf_core::Writer *writer, + const FormatSection &to_conv, const tm *timeptr) { + // TODO: Implement the locale support. + // Currently locale flags are ignored, as described by the posix standard for + // the default locale. + + if (!to_conv.has_conv) + return writer->write(to_conv.raw_string); + switch (to_conv.conv_name) { + // The cases are grouped by type, then alphabetized with lowercase before + // uppercase. + + // raw conversions + case '%': + return writer->write("%"); + case 'n': + return writer->write("\n"); + case 't': + return writer->write("\t"); + + // numeric conversions + case 'C': // Century [00-99] + case 'd': // Day of the month [01-31] + case 'e': // Day of the month [1-31] + case 'g': // last 2 digits of ISO year [00-99] + case 'G': // ISO year + case 'H': // 24-hour format [00-23] + case 'I': // 12-hour format [01-12] + case 'j': // Day of the year [001-366] + case 'm': // Month of the year [01-12] + case 'M': // Minute of the hour [00-59] + case 's': // Seconds since the epoch + case 'S': // Second of the minute [00-60] + case 'u': // ISO day of the week ([1-7] starting Monday) + case 'U': // Week of the year ([00-53] week 1 starts on first *Sunday*) + case 'V': // ISO week number ([01-53], 01 is first week majority in this year) + case 'w': // Day of week ([0-6] starting Sunday) + case 'W': // Week of the year ([00-53] week 1 starts on first *Monday*) + case 'y': // Year of the Century [00-99] + case 'Y': // Full year + return convert_int(writer, to_conv, timeptr); + + // string conversions + case 'a': // Abbreviated weekday name + case 'A': // Full weekday name + case 'b': // Abbreviated month name + case 'B': // Full month name + case 'h': // same as %b + case 'p': // AM/PM designation + return convert_str(writer, to_conv, timeptr); + + // composite conversions + case 'c': // locale specified date and time + case 'D': // %m/%d/%y (month/day/year) + case 'F': // %Y-%m-%d (year-month-day) + case 'r': // %I:%M:%S %p (hour:minute:second AM/PM) + case 'R': // %H:%M (hour:minute) + case 'T': // %H:%M:%S (hour:minute:second) + case 'x': // locale specified date + case 'X': // locale specified time + return convert_composite(writer, to_conv, timeptr); + + // timezone conversions + case 'z': // Timezone offset (+/-hhmm) (num conv) + case 'Z': // Timezone name (string conv) + // the standard says if no time zone is determinable, write no characters. + // Leave this here until time zones are implemented. + return 0; + default: + return writer->write(to_conv.raw_string); + } + return 0; +} } // namespace strftime_core } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/strftime_core/num_converter.h b/libc/src/time/strftime_core/num_converter.h index aef9ddbf791b2..7da9195aa4885 100644 --- a/libc/src/time/strftime_core/num_converter.h +++ b/libc/src/time/strftime_core/num_converter.h @@ -30,7 +30,8 @@ struct IntFormatSection { char padding_char = '0'; }; -LIBC_INLINE int write_padded_int(printf_core::Writer *writer, +template +LIBC_INLINE int write_padded_int(printf_core::Writer *writer, const IntFormatSection &num_info) { DecFmt d(num_info.num); @@ -187,7 +188,8 @@ LIBC_INLINE IntFormatSection get_int_format(const FormatSection &to_conv, return result; } -LIBC_INLINE int convert_int(printf_core::Writer *writer, +template +LIBC_INLINE int convert_int(printf_core::Writer *writer, const FormatSection &to_conv, const tm *timeptr) { return write_padded_int(writer, get_int_format(to_conv, timeptr)); diff --git a/libc/src/time/strftime_core/str_converter.h b/libc/src/time/strftime_core/str_converter.h index f0d5bf59102f3..13eccd3979ea6 100644 --- a/libc/src/time/strftime_core/str_converter.h +++ b/libc/src/time/strftime_core/str_converter.h @@ -27,7 +27,8 @@ unwrap_opt(cpp::optional str_opt) { return str_opt.has_value() ? *str_opt : OUT_OF_BOUNDS_STR; } -LIBC_INLINE int convert_str(printf_core::Writer *writer, +template +LIBC_INLINE int convert_str(printf_core::Writer *writer, const FormatSection &to_conv, const tm *timeptr) { cpp::string_view str; cpp::optional str_opt; diff --git a/libc/src/time/strftime_core/strftime_main.cpp b/libc/src/time/strftime_core/strftime_main.cpp deleted file mode 100644 index 00839e5a3f4da..0000000000000 --- a/libc/src/time/strftime_core/strftime_main.cpp +++ /dev/null @@ -1,40 +0,0 @@ -//===-- Starting point for strftime ---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "src/time/strftime_core/strftime_main.h" - -#include "hdr/types/struct_tm.h" -#include "src/stdio/printf_core/writer.h" -#include "src/time/strftime_core/converter.h" -#include "src/time/strftime_core/core_structs.h" -#include "src/time/strftime_core/parser.h" - -namespace LIBC_NAMESPACE_DECL { -namespace strftime_core { - -int strftime_main(printf_core::Writer *writer, const char *__restrict str, - const tm *timeptr) { - Parser parser(str); - int result = 0; - for (FormatSection cur_section = parser.get_next_section(); - !cur_section.raw_string.empty(); - cur_section = parser.get_next_section()) { - if (cur_section.has_conv) - result = convert(writer, cur_section, timeptr); - else - result = writer->write(cur_section.raw_string); - - if (result < 0) - return result; - } - - return writer->get_chars_written(); -} - -} // namespace strftime_core -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/strftime_core/strftime_main.h b/libc/src/time/strftime_core/strftime_main.h index ae706828df44c..c7e590627094a 100644 --- a/libc/src/time/strftime_core/strftime_main.h +++ b/libc/src/time/strftime_core/strftime_main.h @@ -12,12 +12,32 @@ #include "hdr/types/struct_tm.h" #include "src/__support/macros/config.h" #include "src/stdio/printf_core/writer.h" +#include "src/time/strftime_core/converter.h" +#include "src/time/strftime_core/core_structs.h" +#include "src/time/strftime_core/parser.h" namespace LIBC_NAMESPACE_DECL { namespace strftime_core { -int strftime_main(printf_core::Writer *writer, const char *__restrict str, - const tm *timeptr); +template +int strftime_main(printf_core::Writer *writer, + const char *__restrict str, const tm *timeptr) { + Parser parser(str); + int result = 0; + for (strftime_core::FormatSection cur_section = parser.get_next_section(); + !cur_section.raw_string.empty(); + cur_section = parser.get_next_section()) { + if (cur_section.has_conv) + result = convert(writer, cur_section, timeptr); + else + result = writer->write(cur_section.raw_string); + + if (result < 0) + return result; + } + + return writer->get_chars_written(); +} } // namespace strftime_core } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/strftime_l.cpp b/libc/src/time/strftime_l.cpp index e19c7c605cd4a..201b85da39ee2 100644 --- a/libc/src/time/strftime_l.cpp +++ b/libc/src/time/strftime_l.cpp @@ -22,8 +22,10 @@ LLVM_LIBC_FUNCTION(size_t, strftime_l, (char *__restrict buffer, size_t buffsz, const char *__restrict format, const tm *timeptr, locale_t)) { - printf_core::WriteBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); - printf_core::Writer writer(&wb); + printf_core::WriteBuffer::value> + wb(buffer, (buffsz > 0 ? buffsz - 1 : 0)); + printf_core::Writer writer(wb); int ret = strftime_core::strftime_main(&writer, format, timeptr); if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer. wb.buff[wb.buff_cur] = '\0'; diff --git a/libc/test/src/stdio/printf_core/converter_test.cpp b/libc/test/src/stdio/printf_core/converter_test.cpp index 9da749f3b8ad1..96a00ae598ec2 100644 --- a/libc/test/src/stdio/printf_core/converter_test.cpp +++ b/libc/test/src/stdio/printf_core/converter_test.cpp @@ -18,10 +18,14 @@ class LlvmLibcPrintfConverterTest : public LIBC_NAMESPACE::testing::Test { // void TearDown() override {} char str[60]; - LIBC_NAMESPACE::printf_core::WriteBuffer wb = - LIBC_NAMESPACE::printf_core::WriteBuffer(str, sizeof(str) - 1); - LIBC_NAMESPACE::printf_core::Writer writer = - LIBC_NAMESPACE::printf_core::Writer(&wb); + LIBC_NAMESPACE::printf_core::WriteBuffer< + LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> + wb = LIBC_NAMESPACE::printf_core::WriteBuffer< + LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>( + str, sizeof(str) - 1); + LIBC_NAMESPACE::printf_core::Writer< + LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> + writer = LIBC_NAMESPACE::printf_core::Writer(wb); }; TEST_F(LlvmLibcPrintfConverterTest, SimpleRawConversion) { diff --git a/libc/test/src/stdio/printf_core/writer_test.cpp b/libc/test/src/stdio/printf_core/writer_test.cpp index 4fe5ffb4aa989..8611caa2dfa58 100644 --- a/libc/test/src/stdio/printf_core/writer_test.cpp +++ b/libc/test/src/stdio/printf_core/writer_test.cpp @@ -15,19 +15,20 @@ using LIBC_NAMESPACE::cpp::string_view; using LIBC_NAMESPACE::printf_core::WriteBuffer; +using LIBC_NAMESPACE::printf_core::WriteMode; using LIBC_NAMESPACE::printf_core::Writer; TEST(LlvmLibcPrintfWriterTest, Constructor) { char str[10]; - WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + WriteBuffer wb(str, sizeof(str) - 1); + Writer writer(wb); (void)writer; } TEST(LlvmLibcPrintfWriterTest, Write) { char str[4] = {'D', 'E', 'F', 'G'}; - WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + WriteBuffer wb(str, sizeof(str) - 1); + Writer writer(wb); writer.write({"abc", 3}); EXPECT_EQ(str[3], 'G'); @@ -42,8 +43,8 @@ TEST(LlvmLibcPrintfWriterTest, Write) { TEST(LlvmLibcPrintfWriterTest, WriteMultipleTimes) { char str[10]; - WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + WriteBuffer wb(str, sizeof(str) - 1); + Writer writer(wb); writer.write({"abc", 3}); writer.write({"DEF", 3}); writer.write({"1234", 3}); @@ -56,8 +57,8 @@ TEST(LlvmLibcPrintfWriterTest, WriteMultipleTimes) { TEST(LlvmLibcPrintfWriterTest, WriteChars) { char str[4] = {'D', 'E', 'F', 'G'}; - WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + WriteBuffer wb(str, sizeof(str) - 1); + Writer writer(wb); writer.write('a', 3); EXPECT_EQ(str[3], 'G'); @@ -69,8 +70,8 @@ TEST(LlvmLibcPrintfWriterTest, WriteChars) { TEST(LlvmLibcPrintfWriterTest, WriteCharsMultipleTimes) { char str[10]; - WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + WriteBuffer wb(str, sizeof(str) - 1); + Writer writer(wb); writer.write('a', 3); writer.write('D', 3); writer.write('1', 3); @@ -83,8 +84,8 @@ TEST(LlvmLibcPrintfWriterTest, WriteCharsMultipleTimes) { TEST(LlvmLibcPrintfWriterTest, WriteManyChars) { char str[100]; - WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + WriteBuffer wb(str, sizeof(str) - 1); + Writer writer(wb); writer.write('Z', 99); wb.buff[wb.buff_cur] = '\0'; @@ -105,8 +106,8 @@ TEST(LlvmLibcPrintfWriterTest, WriteManyChars) { TEST(LlvmLibcPrintfWriterTest, MixedWrites) { char str[13]; - WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + WriteBuffer wb(str, sizeof(str) - 1); + Writer writer(wb); writer.write('a', 3); writer.write({"DEF", 3}); writer.write('1', 3); @@ -120,8 +121,8 @@ TEST(LlvmLibcPrintfWriterTest, MixedWrites) { TEST(LlvmLibcPrintfWriterTest, WriteWithMaxLength) { char str[11]; - WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + WriteBuffer wb(str, sizeof(str) - 1); + Writer writer(wb); writer.write({"abcDEF123456", 12}); wb.buff[wb.buff_cur] = '\0'; @@ -132,8 +133,8 @@ TEST(LlvmLibcPrintfWriterTest, WriteWithMaxLength) { TEST(LlvmLibcPrintfWriterTest, WriteCharsWithMaxLength) { char str[11]; - WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + WriteBuffer wb(str, sizeof(str) - 1); + Writer writer(wb); writer.write('1', 15); wb.buff[wb.buff_cur] = '\0'; @@ -144,9 +145,9 @@ TEST(LlvmLibcPrintfWriterTest, WriteCharsWithMaxLength) { TEST(LlvmLibcPrintfWriterTest, MixedWriteWithMaxLength) { char str[11]; - WriteBuffer wb(str, sizeof(str) - 1); + WriteBuffer wb(str, sizeof(str) - 1); - Writer writer(&wb); + Writer writer(wb); writer.write('a', 3); writer.write({"DEF", 3}); writer.write('1', 3); @@ -162,9 +163,9 @@ TEST(LlvmLibcPrintfWriterTest, StringWithMaxLengthOne) { char str[1]; // This is because the max length should be at most 1 less than the size of // the buffer it's writing to. - WriteBuffer wb(str, 0); + WriteBuffer wb(str, 0); - Writer writer(&wb); + Writer writer(wb); writer.write('a', 3); writer.write({"DEF", 3}); writer.write('1', 3); @@ -177,9 +178,9 @@ TEST(LlvmLibcPrintfWriterTest, StringWithMaxLengthOne) { } TEST(LlvmLibcPrintfWriterTest, NullStringWithZeroMaxLength) { - WriteBuffer wb(nullptr, 0); + WriteBuffer wb(nullptr, 0); - Writer writer(&wb); + Writer writer(wb); writer.write('a', 3); writer.write({"DEF", 3}); writer.write('1', 3); @@ -213,9 +214,10 @@ TEST(LlvmLibcPrintfWriterTest, WriteWithMaxLengthWithCallback) { OutBuff out_buff = {str, 0}; char wb_buff[8]; - WriteBuffer wb(wb_buff, sizeof(wb_buff), ©_to_out, - reinterpret_cast(&out_buff)); - Writer writer(&wb); + WriteBuffer wb( + wb_buff, sizeof(wb_buff), ©_to_out, + reinterpret_cast(&out_buff)); + Writer writer(wb); writer.write({"abcDEF123456", 12}); // Flush the buffer @@ -232,9 +234,10 @@ TEST(LlvmLibcPrintfWriterTest, WriteCharsWithMaxLengthWithCallback) { OutBuff out_buff = {str, 0}; char wb_buff[8]; - WriteBuffer wb(wb_buff, sizeof(wb_buff), ©_to_out, - reinterpret_cast(&out_buff)); - Writer writer(&wb); + WriteBuffer wb( + wb_buff, sizeof(wb_buff), ©_to_out, + reinterpret_cast(&out_buff)); + Writer writer(wb); writer.write('1', 15); // Flush the buffer @@ -251,9 +254,10 @@ TEST(LlvmLibcPrintfWriterTest, MixedWriteWithMaxLengthWithCallback) { OutBuff out_buff = {str, 0}; char wb_buff[8]; - WriteBuffer wb(wb_buff, sizeof(wb_buff), ©_to_out, - reinterpret_cast(&out_buff)); - Writer writer(&wb); + WriteBuffer wb( + wb_buff, sizeof(wb_buff), ©_to_out, + reinterpret_cast(&out_buff)); + Writer writer(wb); writer.write('a', 3); writer.write({"DEF", 3}); writer.write('1', 3); @@ -273,9 +277,10 @@ TEST(LlvmLibcPrintfWriterTest, ZeroLengthBufferWithCallback) { OutBuff out_buff = {str, 0}; char wb_buff[1]; - WriteBuffer wb(wb_buff, 0, ©_to_out, reinterpret_cast(&out_buff)); + WriteBuffer wb( + wb_buff, 0, ©_to_out, reinterpret_cast(&out_buff)); - Writer writer(&wb); + Writer writer(wb); writer.write('a', 3); writer.write({"DEF", 3}); writer.write('1', 3); @@ -294,9 +299,10 @@ TEST(LlvmLibcPrintfWriterTest, NullStringWithZeroMaxLengthWithCallback) { OutBuff out_buff = {str, 0}; - WriteBuffer wb(nullptr, 0, ©_to_out, reinterpret_cast(&out_buff)); + WriteBuffer wb( + nullptr, 0, ©_to_out, reinterpret_cast(&out_buff)); - Writer writer(&wb); + Writer writer(wb); writer.write('a', 3); writer.write({"DEF", 3}); writer.write('1', 3); diff --git a/libc/utils/gpu/server/CMakeLists.txt b/libc/utils/gpu/server/CMakeLists.txt index ae8a0d902f459..7ca101e42a0af 100644 --- a/libc/utils/gpu/server/CMakeLists.txt +++ b/libc/utils/gpu/server/CMakeLists.txt @@ -1,8 +1,4 @@ -add_library(llvmlibc_rpc_server STATIC - ${LIBC_SOURCE_DIR}/src/stdio/printf_core/writer.cpp - ${LIBC_SOURCE_DIR}/src/stdio/printf_core/converter.cpp - rpc_server.cpp -) +add_library(llvmlibc_rpc_server STATIC rpc_server.cpp) # Include the RPC implemenation from libc. target_include_directories(llvmlibc_rpc_server PRIVATE ${LIBC_SOURCE_DIR}) diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp index 1faee531fa20d..6dc81a5ff805d 100644 --- a/libc/utils/gpu/server/rpc_server.cpp +++ b/libc/utils/gpu/server/rpc_server.cpp @@ -96,8 +96,8 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) { if (!format[lane]) continue; - WriteBuffer wb(nullptr, 0); - Writer writer(&wb); + WriteBuffer wb(nullptr, 0); + Writer writer(wb); internal::DummyArgList printf_args; Parser &> parser( @@ -123,8 +123,8 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) { if (!format[lane]) continue; - WriteBuffer wb(nullptr, 0); - Writer writer(&wb); + WriteBuffer wb(nullptr, 0); + Writer writer(wb); internal::StructArgList printf_args(args[lane], args_sizes[lane]); Parser> parser( @@ -180,8 +180,9 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) { continue; char *buffer = temp_storage.alloc(buffer_size[lane]); - WriteBuffer wb(buffer, buffer_size[lane]); - Writer writer(&wb); + WriteBuffer wb(buffer, + buffer_size[lane]); + Writer writer(wb); internal::StructArgList printf_args(args[lane], args_sizes[lane]); Parser> parser(