[libc-commits] [libc] 096463d - [libc] move printf to use StringViews

Michael Jones via libc-commits libc-commits at lists.llvm.org
Wed Aug 24 10:28:41 PDT 2022


Author: Michael Jones
Date: 2022-08-24T10:28:31-07:00
New Revision: 096463d08eaa053c000700c3d4648f0c93cb7af6

URL: https://github.com/llvm/llvm-project/commit/096463d08eaa053c000700c3d4648f0c93cb7af6
DIFF: https://github.com/llvm/llvm-project/commit/096463d08eaa053c000700c3d4648f0c93cb7af6.diff

LOG: [libc] move printf to use StringViews

The FormatSection and the writer functions both previously took a char*
and a length to represent a string. Now they use the StringView class to
represent that more succinctly. This change also required fixing
everywhere these were used, so it touches a lot of files.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D131994

Added: 
    

Modified: 
    libc/src/stdio/printf_core/CMakeLists.txt
    libc/src/stdio/printf_core/char_converter.h
    libc/src/stdio/printf_core/converter.cpp
    libc/src/stdio/printf_core/core_structs.h
    libc/src/stdio/printf_core/file_writer.cpp
    libc/src/stdio/printf_core/file_writer.h
    libc/src/stdio/printf_core/float_hex_converter.h
    libc/src/stdio/printf_core/float_inf_nan_converter.h
    libc/src/stdio/printf_core/int_converter.h
    libc/src/stdio/printf_core/parser.cpp
    libc/src/stdio/printf_core/parser.h
    libc/src/stdio/printf_core/printf_main.cpp
    libc/src/stdio/printf_core/ptr_converter.h
    libc/src/stdio/printf_core/string_converter.h
    libc/src/stdio/printf_core/string_writer.cpp
    libc/src/stdio/printf_core/string_writer.h
    libc/src/stdio/printf_core/vfprintf_internal.cpp
    libc/src/stdio/printf_core/writer.cpp
    libc/src/stdio/printf_core/writer.h
    libc/src/stdio/snprintf.cpp
    libc/src/stdio/sprintf.cpp
    libc/test/src/stdio/printf_core/CMakeLists.txt
    libc/test/src/stdio/printf_core/converter_test.cpp
    libc/test/src/stdio/printf_core/parser_test.cpp
    libc/test/src/stdio/printf_core/string_writer_test.cpp
    libc/utils/UnitTest/CMakeLists.txt
    libc/utils/UnitTest/PrintfMatcher.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index edf77fe0018ba..4ab4d61a41bc1 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -3,6 +3,9 @@ add_header_library(
   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 @@ add_object_library(
     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 @@ add_object_library(
   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 @@ add_object_library(
     writer.cpp
   HDRS
     writer.h
-  DEPENDS
-    libc.src.string.memory_utils.memset_implementation
 )
 
 add_object_library(
@@ -95,6 +98,8 @@ add_object_library(
     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
index b32a39c419ff4..cd4724fd7695b 100644
--- 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 @@ namespace printf_core {
 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
index 663d5bb54d6a0..597e75553bfb0 100644
--- a/libc/src/stdio/printf_core/converter.cpp
+++ b/libc/src/stdio/printf_core/converter.cpp
@@ -26,11 +26,11 @@ namespace printf_core {
 
 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 @@ int convert(Writer *writer, const FormatSection &to_conv) {
   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
index 25e530337eec4..fb8c8bbd9e1f2 100644
--- a/libc/src/stdio/printf_core/core_structs.h
+++ b/libc/src/stdio/printf_core/core_structs.h
@@ -37,8 +37,7 @@ enum FormatFlags : uint8_t {
 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 @@ struct FormatSection {
     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.cpp b/libc/src/stdio/printf_core/file_writer.cpp
index 888c5ecbb60ff..7e0dd1b678e7b 100644
--- 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 <stddef.h>
@@ -23,10 +24,29 @@ int FileWriter::write(const char *__restrict to_write, size_t len) {
   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<FileWriter *>(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<FileWriter *>(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<FileWriter *>(raw_pointer);
+  return file_writer->write(&new_char, 1);
 }
 
 } // namespace printf_core

diff  --git a/libc/src/stdio/printf_core/file_writer.h b/libc/src/stdio/printf_core/file_writer.h
index 9e4eb331687f2..6ba1428a160e2 100644
--- 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 <stddef.h>
@@ -29,12 +30,13 @@ class FileWriter {
   ~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/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h
index 0844f4cb0e809..9cc3b14b5ae4a 100644
--- 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 @@ int inline convert_float_hex_exp(Writer *writer, const FormatSection &to_conv) {
   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<int>(mant_digits - 1))
@@ -201,7 +203,7 @@ int inline convert_float_hex_exp(Writer *writer, const FormatSection &to_conv) {
   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 @@ int inline convert_float_hex_exp(Writer *writer, const FormatSection &to_conv) {
     // 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
index 640612e1b6d4d..35c5f44ba8125 100644
--- 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 @@ int inline convert_inf_nan(Writer *writer, const FormatSection &to_conv) {
 
   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
index 219605e672ccf..4479ec6e88e42 100644
--- a/libc/src/stdio/printf_core/int_converter.h
+++ b/libc/src/stdio/printf_core/int_converter.h
@@ -27,8 +27,9 @@ namespace printf_core {
 constexpr char inline to_lower(char a) { return a | 32; }
 constexpr bool inline is_lower(char a) { return (a & 32) > 0; }
 
-cpp::optional<cpp::string_view> inline num_to_strview(
-    uintmax_t num, cpp::span<char> bufref, char conv_name) {
+cpp::optional<cpp::string_view> inline num_to_strview(uintmax_t num,
+                                                      cpp::span<char> 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 @@ int inline convert_int(Writer *writer, const FormatSection &to_conv) {
 
   // 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 @@ int inline convert_int(Writer *writer, const FormatSection &to_conv) {
   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.cpp b/libc/src/stdio/printf_core/parser.cpp
index d2f0b89b0f1ba..38d2e1e69cf92 100644
--- 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 @@ namespace printf_core {
 
 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 @@ FormatSection Parser::get_next_section() {
     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/parser.h b/libc/src/stdio/printf_core/parser.h
index 25dd0f65e8171..3d47f6af39bf4 100644
--- 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 <stddef.h>
 
@@ -49,7 +48,7 @@ class Parser {
   // 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 @@ class Parser {
 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<char *>(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/printf_main.cpp b/libc/src/stdio/printf_core/printf_main.cpp
index fb46da46e074d..b7684cdf1e74f 100644
--- a/libc/src/stdio/printf_core/printf_main.cpp
+++ b/libc/src/stdio/printf_core/printf_main.cpp
@@ -24,11 +24,12 @@ int printf_main(Writer *writer, const char *__restrict str,
   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
index 17c05924bcc66..a2738447c0dc4 100644
--- 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 @@ namespace printf_core {
 
 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
index eaf9b9987620c..e10ecd6f9f55d 100644
--- 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 __llvm_libc {
 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<char *>(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<size_t>(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<const char *>(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<const char *>(to_conv.conv_val_ptr), string_len));
-    }
-  } else {
-    RET_IF_RESULT_NEGATIVE(writer->write(
-        reinterpret_cast<const char *>(to_conv.conv_val_ptr), string_len));
+  size_t padding_spaces = to_conv.min_width > static_cast<int>(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<const char *>(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.cpp b/libc/src/stdio/printf_core/string_writer.cpp
index 1e95ec805dcd4..a80df32d40a02 100644
--- 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 <stddef.h>
 
 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<StringWriter *>(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<StringWriter *>(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<StringWriter *>(raw_pointer);
-  string_writer->write(to_write, len);
+  string_writer->write(new_char);
   return WRITE_OK;
 }
 

diff  --git a/libc/src/stdio/printf_core/string_writer.h b/libc/src/stdio/printf_core/string_writer.h
index bcf040b9b16f5..9d2578904c734 100644
--- 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 <stddef.h>
 
@@ -26,18 +27,21 @@ class StringWriter {
   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/vfprintf_internal.cpp b/libc/src/stdio/printf_core/vfprintf_internal.cpp
index 479bf1acc6260..b25d545e54a11 100644
--- a/libc/src/stdio/printf_core/vfprintf_internal.cpp
+++ b/libc/src/stdio/printf_core/vfprintf_internal.cpp
@@ -22,7 +22,9 @@ int vfprintf_internal(::FILE *__restrict stream, const char *__restrict format,
                       internal::ArgList &args) {
   FileWriter file_writer(stream);
   printf_core::Writer writer(reinterpret_cast<void *>(&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.cpp b/libc/src/stdio/printf_core/writer.cpp
index fe48414837189..825697103492c 100644
--- 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 <stddef.h>
 
 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/printf_core/writer.h b/libc/src/stdio/printf_core/writer.h
index c8a9f7d7e8786..b5c36bf38e814 100644
--- 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 <stddef.h>
 
 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 @@ class Writer final {
   // 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/snprintf.cpp b/libc/src/stdio/snprintf.cpp
index ecc5fc94e6e8c..571a547ed8f2d 100644
--- a/libc/src/stdio/snprintf.cpp
+++ b/libc/src/stdio/snprintf.cpp
@@ -29,7 +29,9 @@ LLVM_LIBC_FUNCTION(int, snprintf,
   va_end(vlist);
   printf_core::StringWriter str_writer(buffer, (buffsz > 0 ? buffsz - 1 : 0));
   printf_core::Writer writer(reinterpret_cast<void *>(&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
index 442dbdfb14d11..a97b83e805d1e 100644
--- a/libc/src/stdio/sprintf.cpp
+++ b/libc/src/stdio/sprintf.cpp
@@ -28,7 +28,9 @@ LLVM_LIBC_FUNCTION(int, sprintf,
   va_end(vlist);
   printf_core::StringWriter str_writer(buffer);
   printf_core::Writer writer(reinterpret_cast<void *>(&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
index 3b38f2ccdb1a7..7636eec138d38 100644
--- a/libc/test/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/test/src/stdio/printf_core/CMakeLists.txt
@@ -9,6 +9,7 @@ add_libc_unittest(
   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 @@ add_libc_unittest(
   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
index 62a7356ec787c..ac79d67d75dfb 100644
--- a/libc/test/src/stdio/printf_core/converter_test.cpp
+++ b/libc/test/src/stdio/printf_core/converter_test.cpp
@@ -23,14 +23,15 @@ class LlvmLibcPrintfConverterTest : public __llvm_libc::testing::Test {
       __llvm_libc::printf_core::StringWriter(str);
   __llvm_libc::printf_core::Writer writer = __llvm_libc::printf_core::Writer(
       reinterpret_cast<void *>(&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 @@ TEST_F(LlvmLibcPrintfConverterTest, IntConversionSimple) {
   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<void *>(&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 @@ TEST(LlvmLibcPrintfConverterTest, HexConversion) {
   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<void *>(&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 @@ TEST(LlvmLibcPrintfConverterTest, PointerConversion) {
   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<void *>(&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
index d2f32b795ffbd..643c32bd69c91 100644
--- 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 @@ void evaluate(__llvm_libc::printf_core::FormatSection *format_arr,
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalRaw) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalSimple) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArg) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithFlags) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithWidth) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithPrecision) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithTrivialPrecision) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithShortLengthModifier) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithLongLengthModifier) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithAllOptions) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, EvalThreeArgs) {
 
   __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<uint64_t>(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<char *>(arg3);
   expected2.conv_name = 's';
 
@@ -272,8 +276,8 @@ TEST(LlvmLibcPrintfParserTest, IndexModeOneArg) {
 
   __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 @@ TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsSequential) {
 
   __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<uint64_t>(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<char *>(arg3);
   expected2.conv_name = 's';
 
@@ -324,24 +328,24 @@ TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsReverse) {
 
   __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<uint64_t>(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<char *>(arg3);
   expected2.conv_name = 's';
 
@@ -358,8 +362,9 @@ TEST(LlvmLibcPrintfParserTest, IndexModeTenArgsRandom) {
   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<size_t>(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 @@ TEST(LlvmLibcPrintfParserTest, IndexModeComplexParsing) {
       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 @@ TEST(LlvmLibcPrintfParserTest, IndexModeComplexParsing) {
   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<uint64_t>(arg2);
@@ -424,14 +429,14 @@ TEST(LlvmLibcPrintfParserTest, IndexModeComplexParsing) {
   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<uint64_t>(arg2);
@@ -440,14 +445,14 @@ TEST(LlvmLibcPrintfParserTest, IndexModeComplexParsing) {
   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
index 12a6e93705b9f..b7ad69524b54c 100644
--- 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<void *>(&str_writer),
-      __llvm_libc::printf_core::write_to_string);
+  __llvm_libc::printf_core::Writer writer =
+      get_writer(reinterpret_cast<void *>(&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<void *>(&str_writer),
-      __llvm_libc::printf_core::write_to_string);
-  writer.write("abc", 3);
+  __llvm_libc::printf_core::Writer writer =
+      get_writer(reinterpret_cast<void *>(&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, Write) {
 TEST(LlvmLibcPrintfStringWriterTest, WriteMultipleTimes) {
   char str[10];
   __llvm_libc::printf_core::StringWriter str_writer(str);
-  __llvm_libc::printf_core::Writer writer(
-      reinterpret_cast<void *>(&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<void *>(&str_writer));
+  writer.write({"abc", 3});
+  writer.write({"DEF", 3});
+  writer.write({"1234", 3});
 
   str_writer.terminate();
 
@@ -58,10 +65,9 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteMultipleTimes) {
 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<void *>(&str_writer),
-      __llvm_libc::printf_core::write_to_string);
-  writer.write_chars('a', 3);
+  __llvm_libc::printf_core::Writer writer =
+      get_writer(reinterpret_cast<void *>(&str_writer));
+  writer.write('a', 3);
 
   EXPECT_EQ(str[3], 'G');
   str_writer.terminate();
@@ -73,12 +79,11 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteChars) {
 TEST(LlvmLibcPrintfStringWriterTest, WriteCharsMultipleTimes) {
   char str[10];
   __llvm_libc::printf_core::StringWriter str_writer(str);
-  __llvm_libc::printf_core::Writer writer(
-      reinterpret_cast<void *>(&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<void *>(&str_writer));
+  writer.write('a', 3);
+  writer.write('D', 3);
+  writer.write('1', 3);
 
   str_writer.terminate();
 
@@ -89,10 +94,9 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteCharsMultipleTimes) {
 TEST(LlvmLibcPrintfStringWriterTest, WriteManyChars) {
   char str[100];
   __llvm_libc::printf_core::StringWriter str_writer(str);
-  __llvm_libc::printf_core::Writer writer(
-      reinterpret_cast<void *>(&str_writer),
-      __llvm_libc::printf_core::write_to_string);
-  writer.write_chars('Z', 99);
+  __llvm_libc::printf_core::Writer writer =
+      get_writer(reinterpret_cast<void *>(&str_writer));
+  writer.write('Z', 99);
 
   str_writer.terminate();
 
@@ -113,13 +117,12 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteManyChars) {
 TEST(LlvmLibcPrintfStringWriterTest, MixedWrites) {
   char str[13];
   __llvm_libc::printf_core::StringWriter str_writer(str);
-  __llvm_libc::printf_core::Writer writer(
-      reinterpret_cast<void *>(&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<void *>(&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, MixedWrites) {
 TEST(LlvmLibcPrintfStringWriterTest, WriteWithMaxLength) {
   char str[11];
   __llvm_libc::printf_core::StringWriter str_writer(str, 10);
-  __llvm_libc::printf_core::Writer writer(
-      reinterpret_cast<void *>(&str_writer),
-      __llvm_libc::printf_core::write_to_string);
-  writer.write("abcDEF123456", 12);
+  __llvm_libc::printf_core::Writer writer =
+      get_writer(reinterpret_cast<void *>(&str_writer));
+  writer.write({"abcDEF123456", 12});
 
   str_writer.terminate();
 
@@ -144,11 +146,10 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteWithMaxLength) {
 TEST(LlvmLibcPrintfStringWriterTest, WriteCharsWithMaxLength) {
   char str[11];
   __llvm_libc::printf_core::StringWriter str_writer(str, 10);
-  __llvm_libc::printf_core::Writer writer(
-      reinterpret_cast<void *>(&str_writer),
-      __llvm_libc::printf_core::write_to_string);
+  __llvm_libc::printf_core::Writer writer =
+      get_writer(reinterpret_cast<void *>(&str_writer));
 
-  writer.write_chars('1', 15);
+  writer.write('1', 15);
 
   str_writer.terminate();
 
@@ -159,13 +160,12 @@ TEST(LlvmLibcPrintfStringWriterTest, WriteCharsWithMaxLength) {
 TEST(LlvmLibcPrintfStringWriterTest, MixedWriteWithMaxLength) {
   char str[11];
   __llvm_libc::printf_core::StringWriter str_writer(str, 10);
-  __llvm_libc::printf_core::Writer writer(
-      reinterpret_cast<void *>(&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<void *>(&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, MixedWriteWithMaxLength) {
 TEST(LlvmLibcPrintfStringWriterTest, StringWithMaxLengthOne) {
   char str[1];
   __llvm_libc::printf_core::StringWriter str_writer(str, 0);
-  __llvm_libc::printf_core::Writer writer(
-      reinterpret_cast<void *>(&str_writer),
-      __llvm_libc::printf_core::write_to_string);
+  __llvm_libc::printf_core::Writer writer =
+      get_writer(reinterpret_cast<void *>(&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, StringWithMaxLengthOne) {
 
 TEST(LlvmLibcPrintfStringWriterTest, NullStringWithZeroMaxLength) {
   __llvm_libc::printf_core::StringWriter str_writer(nullptr, 0);
-  __llvm_libc::printf_core::Writer writer(
-      reinterpret_cast<void *>(&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<void *>(&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
index 2f0fbd28db5e6..5c3debdaa41f5 100644
--- a/libc/utils/UnitTest/CMakeLists.txt
+++ b/libc/utils/UnitTest/CMakeLists.txt
@@ -64,7 +64,7 @@ target_link_libraries(LibcPrintfHelpers LibcUnitTest)
 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
index cd17060faa8b1..85bbd2d92a3db 100644
--- 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 @@ namespace {
     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 @@ void display(testutils::StreamWrapper &stream, FormatSection form) {
                     reinterpret_cast<uintptr_t>(form.conv_val_ptr))
              << "\n";
     else if (form.conv_name != '%')
-      stream << "\tvalue: " << int_to_hex<UInt128>(form.conv_val_raw) << "\n";
+      stream << "\tvalue: "
+             << int_to_hex<fputil::FPBits<long double>::UIntType>(
+                    form.conv_val_raw)
+             << "\n";
   }
 }
 } // anonymous namespace


        


More information about the libc-commits mailing list