diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt --- a/libc/src/stdio/printf_core/CMakeLists.txt +++ b/libc/src/stdio/printf_core/CMakeLists.txt @@ -3,6 +3,9 @@ core_structs HDRS core_structs.h + DEPENDS + libc.src.__support.CPP.string_view + libc.src.__support.FPUtil.fputil ) add_object_library( @@ -17,7 +20,7 @@ libc.src.__support.ctype_utils libc.src.__support.str_to_integer libc.src.__support.CPP.bit - libc.src.string.memory_utils.memset_implementation + libc.src.__support.CPP.string_view ) add_object_library( @@ -27,7 +30,9 @@ HDRS string_writer.h DEPENDS + libc.src.__support.CPP.string_view libc.src.string.memory_utils.memcpy_implementation + libc.src.string.memory_utils.memset_implementation .core_structs ) @@ -37,8 +42,6 @@ writer.cpp HDRS writer.h - DEPENDS - libc.src.string.memory_utils.memset_implementation ) add_object_library( @@ -95,6 +98,8 @@ file_writer.h DEPENDS libc.src.__support.File.file + libc.src.__support.CPP.string_view + libc.src.string.memory_utils.memset_implementation .core_structs ) diff --git a/libc/src/stdio/printf_core/char_converter.h b/libc/src/stdio/printf_core/char_converter.h --- a/libc/src/stdio/printf_core/char_converter.h +++ b/libc/src/stdio/printf_core/char_converter.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CHAR_CONVERTER_H #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CHAR_CONVERTER_H +#include "src/__support/CPP/string_view.h" #include "src/stdio/printf_core/converter_utils.h" #include "src/stdio/printf_core/core_structs.h" #include "src/stdio/printf_core/writer.h" @@ -19,18 +20,25 @@ int inline convert_char(Writer *writer, const FormatSection &to_conv) { char c = to_conv.conv_val_raw; - if (to_conv.min_width > 1) { - if ((to_conv.flags & FormatFlags::LEFT_JUSTIFIED) == - FormatFlags::LEFT_JUSTIFIED) { - RET_IF_RESULT_NEGATIVE(writer->write(&c, 1)); - RET_IF_RESULT_NEGATIVE(writer->write_chars(' ', to_conv.min_width - 1)); - } else { - RET_IF_RESULT_NEGATIVE(writer->write_chars(' ', to_conv.min_width - 1)); - RET_IF_RESULT_NEGATIVE(writer->write(&c, 1)); - } - } else { - RET_IF_RESULT_NEGATIVE(writer->write(&c, 1)); + constexpr int string_len = 1; + + size_t padding_spaces = + to_conv.min_width > string_len ? to_conv.min_width - string_len : 0; + + // If the padding is on the left side, write the spaces first. + if (padding_spaces > 0 && + (to_conv.flags & FormatFlags::LEFT_JUSTIFIED) == 0) { + RET_IF_RESULT_NEGATIVE(writer->write(' ', to_conv.min_width - string_len)); + } + + RET_IF_RESULT_NEGATIVE(writer->write(c)); + + // If the padding is on the right side, write the spaces last. + if (padding_spaces > 0 && + (to_conv.flags & FormatFlags::LEFT_JUSTIFIED) != 0) { + RET_IF_RESULT_NEGATIVE(writer->write(' ', to_conv.min_width - string_len)); } + return WRITE_OK; } diff --git a/libc/src/stdio/printf_core/converter.cpp b/libc/src/stdio/printf_core/converter.cpp --- a/libc/src/stdio/printf_core/converter.cpp +++ b/libc/src/stdio/printf_core/converter.cpp @@ -26,11 +26,11 @@ int convert(Writer *writer, const FormatSection &to_conv) { if (!to_conv.has_conv) - return writer->write(to_conv.raw_string, to_conv.raw_len); + return writer->write(to_conv.raw_string); switch (to_conv.conv_name) { case '%': - return writer->write("%", 1); + return writer->write("%"); case 'c': return convert_char(writer, to_conv); case 's': @@ -63,7 +63,7 @@ case 'p': return convert_pointer(writer, to_conv); default: - return writer->write(to_conv.raw_string, to_conv.raw_len); + return writer->write(to_conv.raw_string); } return -1; } diff --git a/libc/src/stdio/printf_core/core_structs.h b/libc/src/stdio/printf_core/core_structs.h --- a/libc/src/stdio/printf_core/core_structs.h +++ b/libc/src/stdio/printf_core/core_structs.h @@ -37,8 +37,7 @@ struct FormatSection { bool has_conv; - const char *__restrict raw_string; - size_t raw_len; + cpp::string_view raw_string; // Format Specifier Values FormatFlags flags = FormatFlags(0); @@ -58,8 +57,7 @@ if (has_conv != other.has_conv) return false; - if (cpp::string_view(raw_string, raw_len) != - cpp::string_view(other.raw_string, other.raw_len)) + if (raw_string != other.raw_string) return false; if (has_conv) { diff --git a/libc/src/stdio/printf_core/file_writer.h b/libc/src/stdio/printf_core/file_writer.h --- a/libc/src/stdio/printf_core/file_writer.h +++ b/libc/src/stdio/printf_core/file_writer.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FILE_WRITER_H #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FILE_WRITER_H +#include "src/__support/CPP/string_view.h" #include "src/__support/File/file.h" #include @@ -29,12 +30,13 @@ ~FileWriter() { file->unlock(); } int write(const char *__restrict to_write, size_t len); -}; -// write_to_file treats raw_pointer as a File and calls its write -// function. -int write_to_file(void *raw_pointer, const char *__restrict to_write, - size_t len); + // These write functions take a FileWriter as a void* in raw_pointer, and + // call the appropriate write function on it. + static int write_str(void *raw_pointer, cpp::string_view new_string); + static int write_chars(void *raw_pointer, char new_char, size_t len); + static int write_char(void *raw_pointer, char new_char); +}; } // namespace printf_core } // namespace __llvm_libc diff --git a/libc/src/stdio/printf_core/file_writer.cpp b/libc/src/stdio/printf_core/file_writer.cpp --- a/libc/src/stdio/printf_core/file_writer.cpp +++ b/libc/src/stdio/printf_core/file_writer.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/stdio/printf_core/file_writer.h" +#include "src/__support/CPP/string_view.h" #include "src/__support/File/file.h" #include "src/stdio/printf_core/core_structs.h" #include @@ -23,10 +24,29 @@ return written; } -int write_to_file(void *raw_pointer, const char *__restrict to_write, - size_t len) { +int FileWriter::write_str(void *raw_pointer, cpp::string_view new_string) { FileWriter *file_writer = reinterpret_cast(raw_pointer); - return file_writer->write(to_write, len); + return file_writer->write(new_string.data(), new_string.size()); +} + +int FileWriter::write_chars(void *raw_pointer, char new_char, size_t len) { + FileWriter *file_writer = reinterpret_cast(raw_pointer); + constexpr size_t BUFF_SIZE = 8; + char buff[BUFF_SIZE] = {new_char}; + int result; + while (len > BUFF_SIZE) { + result = file_writer->write(buff, BUFF_SIZE); + if (result < 0) + return result; + len -= BUFF_SIZE; + } + return file_writer->write(buff, len); +} + +// TODO(michaelrj): Move this to putc_unlocked once that is available. +int FileWriter::write_char(void *raw_pointer, char new_char) { + FileWriter *file_writer = reinterpret_cast(raw_pointer); + return file_writer->write(&new_char, 1); } } // namespace printf_core diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h --- a/libc/src/stdio/printf_core/float_hex_converter.h +++ b/libc/src/stdio/printf_core/float_hex_converter.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_HEX_CONVERTER_H #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_HEX_CONVERTER_H +#include "src/__support/CPP/string_view.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/stdio/printf_core/converter_utils.h" @@ -193,6 +194,7 @@ char prefix[PREFIX_LEN]; prefix[0] = '0'; prefix[1] = a + ('x' - 'a'); + const cpp::string_view prefix_str(prefix, PREFIX_LEN); // If the precision is greater than the actual result, pad with 0s if (to_conv.precision > static_cast(mant_digits - 1)) @@ -201,7 +203,7 @@ bool has_hexadecimal_point = (mant_digits > 1) || ((to_conv.flags & FormatFlags::ALTERNATE_FORM) == FormatFlags::ALTERNATE_FORM); - constexpr char HEXADECIMAL_POINT = '.'; + constexpr cpp::string_view HEXADECIMAL_POINT("."); // This is for the letter 'p' before the exponent. const char exp_seperator = a + ('p' - 'a'); @@ -218,42 +220,42 @@ // The pattern is (sign), 0x, digit, (.), (other digits), (zeroes), p, // exponent, (spaces) if (sign_char > 0) - RET_IF_RESULT_NEGATIVE(writer->write(&sign_char, 1)); - RET_IF_RESULT_NEGATIVE(writer->write(prefix, PREFIX_LEN)); - RET_IF_RESULT_NEGATIVE(writer->write(mant_buffer, 1)); + RET_IF_RESULT_NEGATIVE(writer->write(sign_char)); + RET_IF_RESULT_NEGATIVE(writer->write(prefix_str)); + RET_IF_RESULT_NEGATIVE(writer->write(mant_buffer[0])); if (has_hexadecimal_point) - RET_IF_RESULT_NEGATIVE(writer->write(&HEXADECIMAL_POINT, 1)); + RET_IF_RESULT_NEGATIVE(writer->write(HEXADECIMAL_POINT)); if (mant_digits > 1) - RET_IF_RESULT_NEGATIVE(writer->write(mant_buffer + 1, mant_digits - 1)); + RET_IF_RESULT_NEGATIVE(writer->write({mant_buffer + 1, mant_digits - 1})); if (trailing_zeroes > 0) - RET_IF_RESULT_NEGATIVE(writer->write_chars('0', trailing_zeroes)); - RET_IF_RESULT_NEGATIVE(writer->write(&exp_seperator, EXP_SEPERATOR_LEN)); + RET_IF_RESULT_NEGATIVE(writer->write('0', trailing_zeroes)); + RET_IF_RESULT_NEGATIVE(writer->write(exp_seperator)); RET_IF_RESULT_NEGATIVE( - writer->write(exp_buffer + exp_cur, EXP_LEN - exp_cur)); + writer->write({exp_buffer + exp_cur, EXP_LEN - exp_cur})); if (padding > 0) - RET_IF_RESULT_NEGATIVE(writer->write_chars(' ', padding)); + RET_IF_RESULT_NEGATIVE(writer->write(' ', padding)); } else { // The pattern is (spaces), (sign), 0x, (zeroes), digit, (.), (other // digits), (zeroes), p, exponent if ((padding > 0) && ((to_conv.flags & FormatFlags::LEADING_ZEROES) != FormatFlags::LEADING_ZEROES)) - RET_IF_RESULT_NEGATIVE(writer->write_chars(' ', padding)); + RET_IF_RESULT_NEGATIVE(writer->write(' ', padding)); if (sign_char > 0) - RET_IF_RESULT_NEGATIVE(writer->write(&sign_char, 1)); - RET_IF_RESULT_NEGATIVE(writer->write(prefix, PREFIX_LEN)); + RET_IF_RESULT_NEGATIVE(writer->write(sign_char)); + RET_IF_RESULT_NEGATIVE(writer->write(prefix_str)); if ((padding > 0) && ((to_conv.flags & FormatFlags::LEADING_ZEROES) == FormatFlags::LEADING_ZEROES)) - RET_IF_RESULT_NEGATIVE(writer->write_chars('0', padding)); - RET_IF_RESULT_NEGATIVE(writer->write(mant_buffer, 1)); + RET_IF_RESULT_NEGATIVE(writer->write('0', padding)); + RET_IF_RESULT_NEGATIVE(writer->write(mant_buffer[0])); if (has_hexadecimal_point) - RET_IF_RESULT_NEGATIVE(writer->write(&HEXADECIMAL_POINT, 1)); + RET_IF_RESULT_NEGATIVE(writer->write(HEXADECIMAL_POINT)); if (mant_digits > 1) - RET_IF_RESULT_NEGATIVE(writer->write(mant_buffer + 1, mant_digits - 1)); + RET_IF_RESULT_NEGATIVE(writer->write({mant_buffer + 1, mant_digits - 1})); if (trailing_zeroes > 0) - RET_IF_RESULT_NEGATIVE(writer->write_chars('0', trailing_zeroes)); - RET_IF_RESULT_NEGATIVE(writer->write(&exp_seperator, EXP_SEPERATOR_LEN)); + RET_IF_RESULT_NEGATIVE(writer->write('0', trailing_zeroes)); + RET_IF_RESULT_NEGATIVE(writer->write(exp_seperator)); RET_IF_RESULT_NEGATIVE( - writer->write(exp_buffer + exp_cur, EXP_LEN - exp_cur)); + writer->write({exp_buffer + exp_cur, EXP_LEN - exp_cur})); } return WRITE_OK; } diff --git a/libc/src/stdio/printf_core/float_inf_nan_converter.h b/libc/src/stdio/printf_core/float_inf_nan_converter.h --- a/libc/src/stdio/printf_core/float_inf_nan_converter.h +++ b/libc/src/stdio/printf_core/float_inf_nan_converter.h @@ -59,19 +59,19 @@ if (padding > 0 && ((to_conv.flags & FormatFlags::LEFT_JUSTIFIED) != FormatFlags::LEFT_JUSTIFIED)) - RET_IF_RESULT_NEGATIVE(writer->write_chars(' ', padding)); + RET_IF_RESULT_NEGATIVE(writer->write(' ', padding)); if (sign_char) - RET_IF_RESULT_NEGATIVE(writer->write(&sign_char, 1)); + RET_IF_RESULT_NEGATIVE(writer->write(sign_char)); if (mantissa == 0) { // inf - RET_IF_RESULT_NEGATIVE(writer->write((a == 'a' ? "inf" : "INF"), 3)); + RET_IF_RESULT_NEGATIVE(writer->write(a == 'a' ? "inf" : "INF")); } else { // nan - RET_IF_RESULT_NEGATIVE(writer->write((a == 'a' ? "nan" : "NAN"), 3)); + RET_IF_RESULT_NEGATIVE(writer->write(a == 'a' ? "nan" : "NAN")); } if (padding > 0 && ((to_conv.flags & FormatFlags::LEFT_JUSTIFIED) == FormatFlags::LEFT_JUSTIFIED)) - RET_IF_RESULT_NEGATIVE(writer->write_chars(' ', padding)); + RET_IF_RESULT_NEGATIVE(writer->write(' ', padding)); return WRITE_OK; } diff --git a/libc/src/stdio/printf_core/int_converter.h b/libc/src/stdio/printf_core/int_converter.h --- a/libc/src/stdio/printf_core/int_converter.h +++ b/libc/src/stdio/printf_core/int_converter.h @@ -27,8 +27,9 @@ constexpr char inline to_lower(char a) { return a | 32; } constexpr bool inline is_lower(char a) { return (a & 32) > 0; } -cpp::optional inline num_to_strview( - uintmax_t num, cpp::span bufref, char conv_name) { +cpp::optional inline num_to_strview(uintmax_t num, + cpp::span bufref, + char conv_name) { if (to_lower(conv_name) == 'x') { return IntegerToString::hex(num, bufref, is_lower(conv_name)); } else if (conv_name == 'o') { @@ -88,7 +89,7 @@ // prefix is "0x" for hexadecimal, or the sign character for signed // conversions. Since hexadecimal is unsigned these will never conflict. - int prefix_len; + size_t prefix_len; char prefix[2]; if ((to_lower(to_conv.conv_name) == 'x') && ((flags & FormatFlags::ALTERNATE_FORM) != 0)) { @@ -141,23 +142,23 @@ if ((flags & FormatFlags::LEFT_JUSTIFIED) == FormatFlags::LEFT_JUSTIFIED) { // If left justified it goes prefix zeroes digits spaces if (prefix_len != 0) - RET_IF_RESULT_NEGATIVE(writer->write(prefix, prefix_len)); + RET_IF_RESULT_NEGATIVE(writer->write({prefix, prefix_len})); if (zeroes > 0) - RET_IF_RESULT_NEGATIVE(writer->write_chars('0', zeroes)); + RET_IF_RESULT_NEGATIVE(writer->write('0', zeroes)); if (digits_written > 0) - RET_IF_RESULT_NEGATIVE(writer->write(str->data(), digits_written)); + RET_IF_RESULT_NEGATIVE(writer->write(*str)); if (spaces > 0) - RET_IF_RESULT_NEGATIVE(writer->write_chars(' ', spaces)); + RET_IF_RESULT_NEGATIVE(writer->write(' ', spaces)); } else { // Else it goes spaces prefix zeroes digits if (spaces > 0) - RET_IF_RESULT_NEGATIVE(writer->write_chars(' ', spaces)); + RET_IF_RESULT_NEGATIVE(writer->write(' ', spaces)); if (prefix_len != 0) - RET_IF_RESULT_NEGATIVE(writer->write(prefix, prefix_len)); + RET_IF_RESULT_NEGATIVE(writer->write({prefix, prefix_len})); if (zeroes > 0) - RET_IF_RESULT_NEGATIVE(writer->write_chars('0', zeroes)); + RET_IF_RESULT_NEGATIVE(writer->write('0', zeroes)); if (digits_written > 0) - RET_IF_RESULT_NEGATIVE(writer->write(str->data(), digits_written)); + RET_IF_RESULT_NEGATIVE(writer->write(*str)); } return WRITE_OK; } diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h --- a/libc/src/stdio/printf_core/parser.h +++ b/libc/src/stdio/printf_core/parser.h @@ -11,7 +11,6 @@ #include "src/__support/arg_list.h" #include "src/stdio/printf_core/core_structs.h" -#include "src/string/memory_utils/memset_implementations.h" #include @@ -49,7 +48,7 @@ // TypeDesc objects, which store the size as well as minimal type information. // This is necessary because some systems separate the floating point and // integer values in va_args. - TypeDesc desc_arr[DESC_ARR_LEN]; + TypeDesc desc_arr[DESC_ARR_LEN] = {{0, Integer}};; // TODO: Look into object stores for optimization. @@ -58,10 +57,7 @@ public: #ifndef LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE Parser(const char *__restrict new_str, internal::ArgList &args) - : str(new_str), args_cur(args), args_start(args) { - inline_memset(reinterpret_cast(desc_arr), 0, - DESC_ARR_LEN * sizeof(TypeDesc)); - } + : str(new_str), args_cur(args), args_start(args) {} #else Parser(const char *__restrict new_str, internal::ArgList &args) : str(new_str), args_cur(args) {} diff --git a/libc/src/stdio/printf_core/parser.cpp b/libc/src/stdio/printf_core/parser.cpp --- a/libc/src/stdio/printf_core/parser.cpp +++ b/libc/src/stdio/printf_core/parser.cpp @@ -13,6 +13,7 @@ #include "src/__support/arg_list.h" #include "src/__support/CPP/bit.h" +#include "src/__support/CPP/string_view.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/ctype_utils.h" #include "src/__support/str_to_integer.h" @@ -28,7 +29,6 @@ FormatSection Parser::get_next_section() { FormatSection section; - section.raw_string = str + cur_pos; size_t starting_pos = cur_pos; if (str[cur_pos] == '%') { // format section @@ -158,7 +158,7 @@ while (str[cur_pos] != '%' && str[cur_pos] != '\0') ++cur_pos; } - section.raw_len = cur_pos - starting_pos; + section.raw_string = {str + starting_pos, cur_pos - starting_pos}; return section; } diff --git a/libc/src/stdio/printf_core/printf_main.cpp b/libc/src/stdio/printf_core/printf_main.cpp --- a/libc/src/stdio/printf_core/printf_main.cpp +++ b/libc/src/stdio/printf_core/printf_main.cpp @@ -24,11 +24,12 @@ Parser parser(str, args); int result = 0; for (FormatSection cur_section = parser.get_next_section(); - cur_section.raw_len > 0; 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, cur_section.raw_len); + result = writer->write(cur_section.raw_string); if (result < 0) return result; diff --git a/libc/src/stdio/printf_core/ptr_converter.h b/libc/src/stdio/printf_core/ptr_converter.h --- a/libc/src/stdio/printf_core/ptr_converter.h +++ b/libc/src/stdio/printf_core/ptr_converter.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_PTR_CONVERTER_H #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_PTR_CONVERTER_H +#include "src/__support/CPP/string_view.h" #include "src/stdio/printf_core/converter_utils.h" #include "src/stdio/printf_core/core_structs.h" #include "src/stdio/printf_core/int_converter.h" @@ -19,9 +20,7 @@ int inline convert_pointer(Writer *writer, const FormatSection &to_conv) { if (to_conv.conv_val_ptr == (void *)(nullptr)) { - const char ZERO_STR[] = "(nullptr)"; - // subtract 1 from sizeof to remove the null byte at the end. - RET_IF_RESULT_NEGATIVE(writer->write(ZERO_STR, sizeof(ZERO_STR) - 1)); + RET_IF_RESULT_NEGATIVE(writer->write("(nullptr)")); } else { FormatSection hex_conv; hex_conv.has_conv = true; diff --git a/libc/src/stdio/printf_core/string_converter.h b/libc/src/stdio/printf_core/string_converter.h --- a/libc/src/stdio/printf_core/string_converter.h +++ b/libc/src/stdio/printf_core/string_converter.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_STRING_CONVERTER_H #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_STRING_CONVERTER_H +#include "src/__support/CPP/string_view.h" #include "src/stdio/printf_core/converter_utils.h" #include "src/stdio/printf_core/core_structs.h" #include "src/stdio/printf_core/writer.h" @@ -19,33 +20,34 @@ namespace printf_core { int inline convert_string(Writer *writer, const FormatSection &to_conv) { - int string_len = 0; + size_t string_len = 0; for (char *cur_str = reinterpret_cast(to_conv.conv_val_ptr); cur_str[string_len]; ++string_len) { ; } - if (to_conv.precision >= 0 && to_conv.precision < string_len) + if (to_conv.precision >= 0 && + static_cast(to_conv.precision) < string_len) string_len = to_conv.precision; - if (to_conv.min_width > string_len) { - if ((to_conv.flags & FormatFlags::LEFT_JUSTIFIED) == - FormatFlags::LEFT_JUSTIFIED) { - RET_IF_RESULT_NEGATIVE(writer->write( - reinterpret_cast(to_conv.conv_val_ptr), string_len)); - RET_IF_RESULT_NEGATIVE( - writer->write_chars(' ', to_conv.min_width - string_len)); - - } else { - RET_IF_RESULT_NEGATIVE( - writer->write_chars(' ', to_conv.min_width - string_len)); - RET_IF_RESULT_NEGATIVE(writer->write( - reinterpret_cast(to_conv.conv_val_ptr), string_len)); - } - } else { - RET_IF_RESULT_NEGATIVE(writer->write( - reinterpret_cast(to_conv.conv_val_ptr), string_len)); + size_t padding_spaces = to_conv.min_width > static_cast(string_len) + ? to_conv.min_width - string_len + : 0; + + // If the padding is on the left side, write the spaces first. + if (padding_spaces > 0 && + (to_conv.flags & FormatFlags::LEFT_JUSTIFIED) == 0) { + RET_IF_RESULT_NEGATIVE(writer->write(' ', to_conv.min_width - string_len)); + } + + RET_IF_RESULT_NEGATIVE(writer->write( + {reinterpret_cast(to_conv.conv_val_ptr), string_len})); + + // If the padding is on the right side, write the spaces last. + if (padding_spaces > 0 && + (to_conv.flags & FormatFlags::LEFT_JUSTIFIED) != 0) { + RET_IF_RESULT_NEGATIVE(writer->write(' ', to_conv.min_width - string_len)); } return WRITE_OK; } diff --git a/libc/src/stdio/printf_core/string_writer.h b/libc/src/stdio/printf_core/string_writer.h --- a/libc/src/stdio/printf_core/string_writer.h +++ b/libc/src/stdio/printf_core/string_writer.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_STRING_WRITER_H #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_STRING_WRITER_H +#include "src/__support/CPP/string_view.h" #include "src/string/memory_utils/memcpy_implementations.h" #include @@ -26,18 +27,21 @@ StringWriter(char *__restrict buffer, size_t max_len = ~size_t(0)) : cur_buffer(buffer), available_capacity(max_len) {} - void write(const char *__restrict to_write, size_t len); + void write(cpp::string_view new_string); + void write(char new_char, size_t len); + void write(char new_char); // Terminate should only be called if the original max length passed to // snprintf was greater than 0. It writes a null byte to the end of the // cur_buffer, regardless of available_capacity. void terminate() { *cur_buffer = '\0'; } -}; -// write_to_string treats raw_pointer as a StringWriter and calls its write -// function. -int write_to_string(void *raw_pointer, const char *__restrict to_write, - size_t len); + // These write functions take a StringWriter as a void* in raw_pointer, and + // call the appropriate write function on it. + static int write_str(void *raw_pointer, cpp::string_view new_string); + static int write_chars(void *raw_pointer, char new_char, size_t len); + static int write_char(void *raw_pointer, char new_char); +}; } // namespace printf_core } // namespace __llvm_libc diff --git a/libc/src/stdio/printf_core/string_writer.cpp b/libc/src/stdio/printf_core/string_writer.cpp --- a/libc/src/stdio/printf_core/string_writer.cpp +++ b/libc/src/stdio/printf_core/string_writer.cpp @@ -7,28 +7,62 @@ //===----------------------------------------------------------------------===// #include "src/stdio/printf_core/string_writer.h" +#include "src/__support/CPP/string_view.h" #include "src/stdio/printf_core/core_structs.h" #include "src/string/memory_utils/memcpy_implementations.h" +#include "src/string/memory_utils/memset_implementations.h" #include namespace __llvm_libc { namespace printf_core { -void StringWriter::write(const char *__restrict to_write, size_t len) { +void StringWriter::write(cpp::string_view new_string) { + size_t len = new_string.size(); if (len > available_capacity) len = available_capacity; if (len > 0) { - inline_memcpy(cur_buffer, to_write, len); + inline_memcpy(cur_buffer, new_string.data(), len); cur_buffer += len; available_capacity -= len; } } -int write_to_string(void *raw_pointer, const char *__restrict to_write, - size_t len) { +void StringWriter::write(char new_char, size_t len) { + if (len > available_capacity) + len = available_capacity; + + if (len > 0) { + inline_memset(cur_buffer, new_char, len); + cur_buffer += len; + available_capacity -= len; + } +} + +void StringWriter::write(char new_char) { + if (1 > available_capacity) + return; + + cur_buffer[0] = new_char; + ++cur_buffer; + available_capacity -= 1; +} + +int StringWriter::write_str(void *raw_pointer, cpp::string_view new_string) { + StringWriter *string_writer = reinterpret_cast(raw_pointer); + string_writer->write(new_string); + return WRITE_OK; +} + +int StringWriter::write_chars(void *raw_pointer, char new_char, size_t len) { + StringWriter *string_writer = reinterpret_cast(raw_pointer); + string_writer->write(new_char, len); + return WRITE_OK; +} + +int StringWriter::write_char(void *raw_pointer, char new_char) { StringWriter *string_writer = reinterpret_cast(raw_pointer); - string_writer->write(to_write, len); + string_writer->write(new_char); return WRITE_OK; } diff --git a/libc/src/stdio/printf_core/vfprintf_internal.cpp b/libc/src/stdio/printf_core/vfprintf_internal.cpp --- a/libc/src/stdio/printf_core/vfprintf_internal.cpp +++ b/libc/src/stdio/printf_core/vfprintf_internal.cpp @@ -22,7 +22,9 @@ internal::ArgList &args) { FileWriter file_writer(stream); printf_core::Writer writer(reinterpret_cast(&file_writer), - printf_core::write_to_file); + printf_core::FileWriter::write_str, + printf_core::FileWriter::write_chars, + printf_core::FileWriter::write_char); return printf_core::printf_main(&writer, format, args); } diff --git a/libc/src/stdio/printf_core/writer.h b/libc/src/stdio/printf_core/writer.h --- a/libc/src/stdio/printf_core/writer.h +++ b/libc/src/stdio/printf_core/writer.h @@ -9,12 +9,15 @@ #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_WRITER_H #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_WRITER_H +#include "src/__support/CPP/string_view.h" #include namespace __llvm_libc { namespace printf_core { -using WriteFunc = int (*)(void *, const char *__restrict, size_t); +using WriteStrFunc = int (*)(void *, cpp::string_view); +using WriteCharsFunc = int (*)(void *, char, size_t); +using WriteCharFunc = int (*)(void *, char); class Writer final { // output is a pointer to the string or file that the writer is meant to write @@ -25,23 +28,31 @@ // length, will copy the number of bytes equal to the length from the char* // onto the end of output. It should return a positive number or zero on // success, or a negative number on failure. - WriteFunc raw_write; + WriteStrFunc str_write; + WriteCharsFunc chars_write; + WriteCharFunc char_write; int chars_written = 0; public: - Writer(void *init_output, WriteFunc init_raw_write) - : output(init_output), raw_write(init_raw_write) {} - - // write will copy length bytes from new_string into output using - // raw_write. It increments chars_written by length always. It returns the - // result of raw_write. - int write(const char *new_string, size_t length); - - // write_chars will copy length copies of new_char into output using the write - // function and a statically sized buffer. This is primarily used for padding. - // If write returns a negative value, this will return early with that value. - int write_chars(char new_char, size_t length); + Writer(void *init_output, WriteStrFunc init_str_write, + WriteCharsFunc init_chars_write, WriteCharFunc init_char_write) + : output(init_output), str_write(init_str_write), + chars_write(init_chars_write), char_write(init_char_write) {} + + // write will copy new_string into output using str_write. It increments + // chars_written by the length of new_string. It returns the result of + // str_write. + int write(cpp::string_view new_string); + + // this version of write will copy length copies of new_char into output using + // chars_write. This is primarily used for padding. It returns the result of + // chars_write. + int write(char new_char, size_t len); + + // this version of write will copy just new_char into output. This is often + // used for negative signs. It returns the result of chars_write. + int write(char new_char); int get_chars_written() { return chars_written; } }; diff --git a/libc/src/stdio/printf_core/writer.cpp b/libc/src/stdio/printf_core/writer.cpp --- a/libc/src/stdio/printf_core/writer.cpp +++ b/libc/src/stdio/printf_core/writer.cpp @@ -7,29 +7,25 @@ //===----------------------------------------------------------------------===// #include "writer.h" -#include "src/string/memory_utils/memset_implementations.h" +#include "src/__support/CPP/string_view.h" #include namespace __llvm_libc { namespace printf_core { -int Writer::write(const char *new_string, size_t length) { +int Writer::write(cpp::string_view new_string) { + chars_written += new_string.size(); + return str_write(output, new_string); +} + +int Writer::write(char new_char, size_t length) { chars_written += length; - return raw_write(output, new_string, length); + return chars_write(output, new_char, length); } -int Writer::write_chars(char new_char, size_t length) { - constexpr size_t BUFF_SIZE = 8; - char buff[BUFF_SIZE]; - int result; - inline_memset(buff, new_char, BUFF_SIZE); - while (length > BUFF_SIZE) { - result = write(buff, BUFF_SIZE); - if (result < 0) - return result; - length -= BUFF_SIZE; - } - return write(buff, length); +int Writer::write(char new_char) { + chars_written += 1; + return char_write(output, new_char); } } // namespace printf_core diff --git a/libc/src/stdio/snprintf.cpp b/libc/src/stdio/snprintf.cpp --- a/libc/src/stdio/snprintf.cpp +++ b/libc/src/stdio/snprintf.cpp @@ -29,7 +29,9 @@ va_end(vlist); printf_core::StringWriter str_writer(buffer, (buffsz > 0 ? buffsz - 1 : 0)); printf_core::Writer writer(reinterpret_cast(&str_writer), - printf_core::write_to_string); + printf_core::StringWriter::write_str, + printf_core::StringWriter::write_chars, + printf_core::StringWriter::write_char); 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 --- a/libc/src/stdio/sprintf.cpp +++ b/libc/src/stdio/sprintf.cpp @@ -28,7 +28,9 @@ va_end(vlist); printf_core::StringWriter str_writer(buffer); printf_core::Writer writer(reinterpret_cast(&str_writer), - printf_core::write_to_string); + printf_core::StringWriter::write_str, + printf_core::StringWriter::write_chars, + printf_core::StringWriter::write_char); int ret_val = printf_core::printf_main(&writer, format, args); str_writer.terminate(); diff --git a/libc/test/src/stdio/printf_core/CMakeLists.txt b/libc/test/src/stdio/printf_core/CMakeLists.txt --- a/libc/test/src/stdio/printf_core/CMakeLists.txt +++ b/libc/test/src/stdio/printf_core/CMakeLists.txt @@ -9,6 +9,7 @@ DEPENDS libc.src.stdio.printf_core.parser libc.src.stdio.printf_core.core_structs + libc.src.__support.CPP.string_view libc.src.__support.arg_list ) @@ -21,6 +22,7 @@ DEPENDS libc.src.stdio.printf_core.writer libc.src.stdio.printf_core.string_writer + libc.src.__support.CPP.string_view ) add_libc_unittest( diff --git a/libc/test/src/stdio/printf_core/converter_test.cpp b/libc/test/src/stdio/printf_core/converter_test.cpp --- a/libc/test/src/stdio/printf_core/converter_test.cpp +++ b/libc/test/src/stdio/printf_core/converter_test.cpp @@ -23,14 +23,15 @@ __llvm_libc::printf_core::StringWriter(str); __llvm_libc::printf_core::Writer writer = __llvm_libc::printf_core::Writer( reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); + __llvm_libc::printf_core::StringWriter::write_str, + __llvm_libc::printf_core::StringWriter::write_chars, + __llvm_libc::printf_core::StringWriter::write_char); }; TEST_F(LlvmLibcPrintfConverterTest, SimpleRawConversion) { __llvm_libc::printf_core::FormatSection raw_section; raw_section.has_conv = false; raw_section.raw_string = "abc"; - raw_section.raw_len = 3; __llvm_libc::printf_core::convert(&writer, raw_section); @@ -196,17 +197,10 @@ ASSERT_EQ(writer.get_chars_written(), 5); } -TEST(LlvmLibcPrintfConverterTest, HexConversion) { - char str[20]; - __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - +TEST_F(LlvmLibcPrintfConverterTest, HexConversion) { __llvm_libc::printf_core::FormatSection section; section.has_conv = true; section.raw_string = "%#018x"; - section.raw_len = 6; section.conv_name = 'x'; section.flags = static_cast<__llvm_libc::printf_core::FormatFlags>( __llvm_libc::printf_core::FormatFlags::ALTERNATE_FORM | @@ -220,17 +214,11 @@ ASSERT_EQ(writer.get_chars_written(), 18); } -TEST(LlvmLibcPrintfConverterTest, PointerConversion) { - char str[20]; - __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); +TEST_F(LlvmLibcPrintfConverterTest, PointerConversion) { __llvm_libc::printf_core::FormatSection section; section.has_conv = true; section.raw_string = "%p"; - section.raw_len = 2; section.conv_name = 'p'; section.conv_val_ptr = (void *)(0x123456ab); __llvm_libc::printf_core::convert(&writer, section); @@ -240,17 +228,11 @@ ASSERT_EQ(writer.get_chars_written(), 10); } -TEST(LlvmLibcPrintfConverterTest, OctConversion) { - char str[20]; - __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); +TEST_F(LlvmLibcPrintfConverterTest, OctConversion) { __llvm_libc::printf_core::FormatSection section; section.has_conv = true; section.raw_string = "%o"; - section.raw_len = 2; section.conv_name = 'o'; section.conv_val_raw = 01234; __llvm_libc::printf_core::convert(&writer, section); diff --git a/libc/test/src/stdio/printf_core/parser_test.cpp b/libc/test/src/stdio/printf_core/parser_test.cpp --- a/libc/test/src/stdio/printf_core/parser_test.cpp +++ b/libc/test/src/stdio/printf_core/parser_test.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/__support/CPP/bit.h" +#include "src/__support/CPP/string_view.h" #include "src/__support/arg_list.h" #include "src/stdio/printf_core/parser.h" @@ -15,6 +16,8 @@ #include "utils/UnitTest/PrintfMatcher.h" #include "utils/UnitTest/Test.h" +using __llvm_libc::cpp::string_view; + void init(const char *__restrict str, ...) { va_list vlist; va_start(vlist, str); @@ -33,7 +36,8 @@ __llvm_libc::printf_core::Parser parser(str, v); - for (auto cur_section = parser.get_next_section(); cur_section.raw_len > 0; + for (auto cur_section = parser.get_next_section(); + !cur_section.raw_string.empty(); cur_section = parser.get_next_section()) { *format_arr = cur_section; ++format_arr; @@ -49,8 +53,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = false; - expected.raw_len = 4; - expected.raw_string = str; + + expected.raw_string = {str, 4}; ASSERT_FORMAT_EQ(expected, format_arr[0]); // TODO: add checks that the format_arr after the last one has length 0 @@ -63,21 +67,21 @@ __llvm_libc::printf_core::FormatSection expected0, expected1, expected2; expected0.has_conv = false; - expected0.raw_len = 5; - expected0.raw_string = str; + + expected0.raw_string = {str, 5}; ASSERT_FORMAT_EQ(expected0, format_arr[0]); expected1.has_conv = true; - expected1.raw_len = 2; - expected1.raw_string = str + 5; + + expected1.raw_string = {str + 5, 2}; expected1.conv_name = '%'; ASSERT_FORMAT_EQ(expected1, format_arr[1]); expected2.has_conv = false; - expected2.raw_len = 5; - expected2.raw_string = str + 7; + + expected2.raw_string = {str + 7, 5}; ASSERT_FORMAT_EQ(expected2, format_arr[2]); } @@ -90,8 +94,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 2; - expected.raw_string = str; + + expected.raw_string = {str, 2}; expected.conv_val_raw = arg1; expected.conv_name = 'd'; @@ -106,8 +110,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 7; - expected.raw_string = str; + + expected.raw_string = {str, 7}; expected.flags = static_cast<__llvm_libc::printf_core::FormatFlags>( __llvm_libc::printf_core::FormatFlags::FORCE_SIGN | __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED | @@ -128,8 +132,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 4; - expected.raw_string = str; + + expected.raw_string = {str, 4}; expected.min_width = 12; expected.conv_val_raw = arg1; expected.conv_name = 'd'; @@ -145,8 +149,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 5; - expected.raw_string = str; + + expected.raw_string = {str, 5}; expected.precision = 34; expected.conv_val_raw = arg1; expected.conv_name = 'd'; @@ -162,8 +166,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 3; - expected.raw_string = str; + + expected.raw_string = {str, 3}; expected.precision = 0; expected.conv_val_raw = arg1; expected.conv_name = 'd'; @@ -179,8 +183,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 3; - expected.raw_string = str; + + expected.raw_string = {str, 3}; expected.length_modifier = __llvm_libc::printf_core::LengthModifier::h; expected.conv_val_raw = arg1; expected.conv_name = 'd'; @@ -196,8 +200,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 4; - expected.raw_string = str; + + expected.raw_string = {str, 4}; expected.length_modifier = __llvm_libc::printf_core::LengthModifier::ll; expected.conv_val_raw = arg1; expected.conv_name = 'd'; @@ -213,8 +217,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 11; - expected.raw_string = str; + + expected.raw_string = {str, 11}; expected.flags = static_cast<__llvm_libc::printf_core::FormatFlags>( __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED | __llvm_libc::printf_core::FormatFlags::LEADING_ZEROES | @@ -238,24 +242,24 @@ __llvm_libc::printf_core::FormatSection expected0, expected1, expected2; expected0.has_conv = true; - expected0.raw_len = 2; - expected0.raw_string = str; + + expected0.raw_string = {str, 2}; expected0.conv_val_raw = arg1; expected0.conv_name = 'd'; ASSERT_FORMAT_EQ(expected0, format_arr[0]); expected1.has_conv = true; - expected1.raw_len = 2; - expected1.raw_string = str + 2; + + expected1.raw_string = {str + 2, 2}; expected1.conv_val_raw = __llvm_libc::cpp::bit_cast(arg2); expected1.conv_name = 'f'; ASSERT_FORMAT_EQ(expected1, format_arr[1]); expected2.has_conv = true; - expected2.raw_len = 2; - expected2.raw_string = str + 4; + + expected2.raw_string = {str + 4, 2}; expected2.conv_val_ptr = const_cast(arg3); expected2.conv_name = 's'; @@ -272,8 +276,8 @@ __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 4; - expected.raw_string = str; + + expected.raw_string = {str, 4}; expected.conv_val_raw = arg1; expected.conv_name = 'd'; @@ -290,24 +294,24 @@ __llvm_libc::printf_core::FormatSection expected0, expected1, expected2; expected0.has_conv = true; - expected0.raw_len = 4; - expected0.raw_string = str; + + expected0.raw_string = {str, 4}; expected0.conv_val_raw = arg1; expected0.conv_name = 'd'; ASSERT_FORMAT_EQ(expected0, format_arr[0]); expected1.has_conv = true; - expected1.raw_len = 4; - expected1.raw_string = str + 4; + + expected1.raw_string = {str + 4, 4}; expected1.conv_val_raw = __llvm_libc::cpp::bit_cast(arg2); expected1.conv_name = 'f'; ASSERT_FORMAT_EQ(expected1, format_arr[1]); expected2.has_conv = true; - expected2.raw_len = 4; - expected2.raw_string = str + 8; + + expected2.raw_string = {str + 8, 4}; expected2.conv_val_ptr = const_cast(arg3); expected2.conv_name = 's'; @@ -324,24 +328,24 @@ __llvm_libc::printf_core::FormatSection expected0, expected1, expected2; expected0.has_conv = true; - expected0.raw_len = 4; - expected0.raw_string = str; + + expected0.raw_string = {str, 4}; expected0.conv_val_raw = arg1; expected0.conv_name = 'd'; ASSERT_FORMAT_EQ(expected0, format_arr[0]); expected1.has_conv = true; - expected1.raw_len = 4; - expected1.raw_string = str + 4; + + expected1.raw_string = {str + 4, 4}; expected1.conv_val_raw = __llvm_libc::cpp::bit_cast(arg2); expected1.conv_name = 'f'; ASSERT_FORMAT_EQ(expected1, format_arr[1]); expected2.has_conv = true; - expected2.raw_len = 4; - expected2.raw_string = str + 8; + + expected2.raw_string = {str + 8, 4}; expected2.conv_val_ptr = const_cast(arg3); expected2.conv_name = 's'; @@ -358,8 +362,9 @@ for (size_t i = 0; i < 10; ++i) { __llvm_libc::printf_core::FormatSection expected; expected.has_conv = true; - expected.raw_len = 4 + (i >= 9 ? 1 : 0); - expected.raw_string = str + (4 * i); + + expected.raw_string = {str + (4 * i), + static_cast(4 + (i >= 9 ? 1 : 0))}; expected.conv_val_raw = i + 1; expected.conv_name = 'd'; EXPECT_FORMAT_EQ(expected, format_arr[i]); @@ -380,14 +385,14 @@ expected9; expected0.has_conv = false; - expected0.raw_len = 12; - expected0.raw_string = str; + + expected0.raw_string = {str, 12}; EXPECT_FORMAT_EQ(expected0, format_arr[0]); expected1.has_conv = true; - expected1.raw_len = 6; - expected1.raw_string = str + 12; + + expected1.raw_string = {str + 12, 6}; expected1.length_modifier = __llvm_libc::printf_core::LengthModifier::ll; expected1.conv_val_raw = arg3; expected1.conv_name = 'u'; @@ -395,27 +400,27 @@ EXPECT_FORMAT_EQ(expected1, format_arr[1]); expected2.has_conv = false; - expected2.raw_len = 1; - expected2.raw_string = str + 18; + + expected2.raw_string = {str + 18, 1}; EXPECT_FORMAT_EQ(expected2, format_arr[2]); expected3.has_conv = true; - expected3.raw_len = 2; - expected3.raw_string = str + 19; + + expected3.raw_string = {str + 19, 2}; expected3.conv_name = '%'; EXPECT_FORMAT_EQ(expected3, format_arr[3]); expected4.has_conv = false; - expected4.raw_len = 1; - expected4.raw_string = str + 21; + + expected4.raw_string = {str + 21, 1}; EXPECT_FORMAT_EQ(expected4, format_arr[4]); expected5.has_conv = true; - expected5.raw_len = 8; - expected5.raw_string = str + 22; + + expected5.raw_string = {str + 22, 8}; expected5.flags = __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX; expected5.min_width = arg4; expected5.conv_val_raw = __llvm_libc::cpp::bit_cast(arg2); @@ -424,14 +429,14 @@ EXPECT_FORMAT_EQ(expected5, format_arr[5]); expected6.has_conv = false; - expected6.raw_len = 1; - expected6.raw_string = str + 30; + + expected6.raw_string = {str + 30, 1}; EXPECT_FORMAT_EQ(expected6, format_arr[6]); expected7.has_conv = true; - expected7.raw_len = 9; - expected7.raw_string = str + 31; + + expected7.raw_string = {str + 31, 9}; expected7.flags = __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX; expected7.precision = arg4; expected7.conv_val_raw = __llvm_libc::cpp::bit_cast(arg2); @@ -440,14 +445,14 @@ EXPECT_FORMAT_EQ(expected7, format_arr[7]); expected8.has_conv = false; - expected8.raw_len = 1; - expected8.raw_string = str + 40; + + expected8.raw_string = {str + 40, 1}; EXPECT_FORMAT_EQ(expected8, format_arr[8]); expected9.has_conv = true; - expected9.raw_len = 7; - expected9.raw_string = str + 41; + + expected9.raw_string = {str + 41, 7}; expected9.min_width = 1; expected9.precision = 1; expected9.conv_val_raw = arg1; diff --git a/libc/test/src/stdio/printf_core/string_writer_test.cpp b/libc/test/src/stdio/printf_core/string_writer_test.cpp --- a/libc/test/src/stdio/printf_core/string_writer_test.cpp +++ b/libc/test/src/stdio/printf_core/string_writer_test.cpp @@ -6,26 +6,34 @@ // //===----------------------------------------------------------------------===// +#include "src/__support/CPP/string_view.h" #include "src/stdio/printf_core/string_writer.h" #include "src/stdio/printf_core/writer.h" #include "utils/UnitTest/Test.h" +using __llvm_libc::cpp::string_view; + +__llvm_libc::printf_core::Writer get_writer(void *str_writer) { + return __llvm_libc::printf_core::Writer( + str_writer, __llvm_libc::printf_core::StringWriter::write_str, + __llvm_libc::printf_core::StringWriter::write_chars, + __llvm_libc::printf_core::StringWriter::write_char); +} + TEST(LlvmLibcPrintfStringWriterTest, Constructor) { char str[10]; __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); } TEST(LlvmLibcPrintfStringWriterTest, Write) { char str[4] = {'D', 'E', 'F', 'G'}; __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - writer.write("abc", 3); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); + writer.write({"abc", 3}); EXPECT_EQ(str[3], 'G'); // This null terminates the string. The writer has no indication when the @@ -42,12 +50,11 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteMultipleTimes) { char str[10]; __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - writer.write("abc", 3); - writer.write("DEF", 3); - writer.write("1234", 3); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); + writer.write({"abc", 3}); + writer.write({"DEF", 3}); + writer.write({"1234", 3}); str_writer.terminate(); @@ -58,10 +65,9 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteChars) { char str[4] = {'D', 'E', 'F', 'G'}; __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - writer.write_chars('a', 3); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); + writer.write('a', 3); EXPECT_EQ(str[3], 'G'); str_writer.terminate(); @@ -73,12 +79,11 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteCharsMultipleTimes) { char str[10]; __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - writer.write_chars('a', 3); - writer.write_chars('D', 3); - writer.write_chars('1', 3); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); + writer.write('a', 3); + writer.write('D', 3); + writer.write('1', 3); str_writer.terminate(); @@ -89,10 +94,9 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteManyChars) { char str[100]; __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - writer.write_chars('Z', 99); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); + writer.write('Z', 99); str_writer.terminate(); @@ -113,13 +117,12 @@ TEST(LlvmLibcPrintfStringWriterTest, MixedWrites) { char str[13]; __llvm_libc::printf_core::StringWriter str_writer(str); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - writer.write_chars('a', 3); - writer.write("DEF", 3); - writer.write_chars('1', 3); - writer.write("456", 3); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); + writer.write('a', 3); + writer.write({"DEF", 3}); + writer.write('1', 3); + writer.write({"456", 3}); str_writer.terminate(); @@ -130,10 +133,9 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteWithMaxLength) { char str[11]; __llvm_libc::printf_core::StringWriter str_writer(str, 10); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - writer.write("abcDEF123456", 12); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); + writer.write({"abcDEF123456", 12}); str_writer.terminate(); @@ -144,11 +146,10 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteCharsWithMaxLength) { char str[11]; __llvm_libc::printf_core::StringWriter str_writer(str, 10); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); - writer.write_chars('1', 15); + writer.write('1', 15); str_writer.terminate(); @@ -159,13 +160,12 @@ TEST(LlvmLibcPrintfStringWriterTest, MixedWriteWithMaxLength) { char str[11]; __llvm_libc::printf_core::StringWriter str_writer(str, 10); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - writer.write_chars('a', 3); - writer.write("DEF", 3); - writer.write_chars('1', 3); - writer.write("456", 3); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); + writer.write('a', 3); + writer.write({"DEF", 3}); + writer.write('1', 3); + writer.write({"456", 3}); str_writer.terminate(); @@ -176,15 +176,14 @@ TEST(LlvmLibcPrintfStringWriterTest, StringWithMaxLengthOne) { char str[1]; __llvm_libc::printf_core::StringWriter str_writer(str, 0); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); // This is because the max length should be at most 1 less than the size of // the buffer it's writing to. - writer.write_chars('a', 3); - writer.write("DEF", 3); - writer.write_chars('1', 3); - writer.write("456", 3); + writer.write('a', 3); + writer.write({"DEF", 3}); + writer.write('1', 3); + writer.write({"456", 3}); str_writer.terminate(); @@ -194,13 +193,12 @@ TEST(LlvmLibcPrintfStringWriterTest, NullStringWithZeroMaxLength) { __llvm_libc::printf_core::StringWriter str_writer(nullptr, 0); - __llvm_libc::printf_core::Writer writer( - reinterpret_cast(&str_writer), - __llvm_libc::printf_core::write_to_string); - writer.write_chars('a', 3); - writer.write("DEF", 3); - writer.write_chars('1', 3); - writer.write("456", 3); + __llvm_libc::printf_core::Writer writer = + get_writer(reinterpret_cast(&str_writer)); + writer.write('a', 3); + writer.write({"DEF", 3}); + writer.write('1', 3); + writer.write({"456", 3}); ASSERT_EQ(writer.get_chars_written(), 12); } diff --git a/libc/utils/UnitTest/CMakeLists.txt b/libc/utils/UnitTest/CMakeLists.txt --- a/libc/utils/UnitTest/CMakeLists.txt +++ b/libc/utils/UnitTest/CMakeLists.txt @@ -64,7 +64,7 @@ add_dependencies( LibcPrintfHelpers LibcUnitTest - libc.src.__support.CPP.uint128 + libc.src.__support.FPUtil.fputil #FPBits libc.src.stdio.printf_core.core_structs libc.utils.UnitTest.string_utils ) diff --git a/libc/utils/UnitTest/PrintfMatcher.cpp b/libc/utils/UnitTest/PrintfMatcher.cpp --- a/libc/utils/UnitTest/PrintfMatcher.cpp +++ b/libc/utils/UnitTest/PrintfMatcher.cpp @@ -8,7 +8,7 @@ #include "PrintfMatcher.h" -#include "src/__support/CPP/UInt128.h" +#include "src/__support/FPUtil/FPBits.h" #include "src/stdio/printf_core/core_structs.h" #include "utils/UnitTest/StringUtils.h" @@ -37,8 +37,8 @@ break void display(testutils::StreamWrapper &stream, FormatSection form) { - stream << "Raw String (len " << form.raw_len << "): \""; - for (size_t i = 0; i < form.raw_len; ++i) { + stream << "Raw String (len " << form.raw_string.size() << "): \""; + for (size_t i = 0; i < form.raw_string.size(); ++i) { stream << form.raw_string[i]; } stream << "\""; @@ -72,7 +72,10 @@ reinterpret_cast(form.conv_val_ptr)) << "\n"; else if (form.conv_name != '%') - stream << "\tvalue: " << int_to_hex(form.conv_val_raw) << "\n"; + stream << "\tvalue: " + << int_to_hex::UIntType>( + form.conv_val_raw) + << "\n"; } } } // anonymous namespace