diff --git a/fmt/format.cc b/fmt/format.cc index 1e34dabb..cd8a244c 100644 --- a/fmt/format.cc +++ b/fmt/format.cc @@ -106,7 +106,7 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) { const char RESET_COLOR[] = "\x1b[0m"; -typedef void (*FormatFunc)(writer &, int, StringRef); +typedef void (*FormatFunc)(buffer &, int, StringRef); // Portable thread-safe version of strerror. // Sets buffer to point to a string describing the error code. @@ -176,7 +176,7 @@ int safe_strerror( return StrError(error_code, buffer, buffer_size).run(); } -void format_error_code(writer &out, int error_code, +void format_error_code(buffer &out, int error_code, StringRef message) FMT_NOEXCEPT { // Report error code making sure that the output fits into // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential @@ -193,18 +193,19 @@ void format_error_code(writer &out, int error_code, ++error_code_size; } error_code_size += internal::count_digits(abs_value); + basic_writer w(out); if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) { - out.write(message); - out.write(SEP); + w.write(message); + w.write(SEP); } - out.write(ERROR_STR); - out.write(error_code); + w.write(ERROR_STR); + w.write(error_code); assert(out.size() <= internal::INLINE_BUFFER_SIZE); } void report_error(FormatFunc func, int error_code, StringRef message) FMT_NOEXCEPT { - MemoryWriter full_message; + internal::MemoryBuffer full_message; func(full_message, error_code, message); // Use Writer::data instead of Writer::c_str to avoid potential memory // allocation. @@ -213,23 +214,13 @@ void report_error(FormatFunc func, int error_code, } } // namespace -namespace internal { - -// This method is used to preserve binary compatibility with fmt 3.0. -// It can be removed in 4.0. -FMT_FUNC void format_system_error( - writer &out, int error_code, StringRef message) FMT_NOEXCEPT { - fmt::format_system_error(out, error_code, message); -} -} // namespace internal - FMT_FUNC void SystemError::init( int err_code, CStringRef format_str, args args) { error_code_ = err_code; - MemoryWriter w; - format_system_error(w, err_code, vformat(format_str, args)); + internal::MemoryBuffer buf; + format_system_error(buf, err_code, vformat(format_str, args)); std::runtime_error &base = *this; - base = std::runtime_error(w.str()); + base = std::runtime_error(to_string(buf)); } template @@ -388,7 +379,7 @@ FMT_FUNC void internal::format_windows_error( #endif // FMT_USE_WINDOWS_H FMT_FUNC void format_system_error( - writer &out, int error_code, StringRef message) FMT_NOEXCEPT { + buffer &out, int error_code, StringRef message) FMT_NOEXCEPT { FMT_TRY { internal::MemoryBuffer buffer; buffer.resize(internal::INLINE_BUFFER_SIZE); @@ -396,9 +387,10 @@ FMT_FUNC void format_system_error( char *system_message = &buffer[0]; int result = safe_strerror(error_code, system_message, buffer.size()); if (result == 0) { - out.write(message); - out.write(": "); - out.write(system_message); + basic_writer w(out); + w.write(message); + w.write(": "); + w.write(system_message); return; } if (result != ERANGE) @@ -410,7 +402,7 @@ FMT_FUNC void format_system_error( } template -void internal::FixedBuffer::grow(std::size_t) { +void FixedBuffer::grow(std::size_t) { FMT_THROW(std::runtime_error("buffer overflow")); } @@ -429,9 +421,9 @@ FMT_FUNC void report_windows_error( #endif FMT_FUNC void vprint(std::FILE *f, CStringRef format_str, args args) { - MemoryWriter w; - w.vformat(format_str, args); - std::fwrite(w.data(), 1, w.size(), f); + internal::MemoryBuffer buffer; + vformat_to(buffer, format_str, args); + std::fwrite(buffer.data(), 1, buffer.size(), f); } FMT_FUNC void vprint(CStringRef format_str, args args) { @@ -451,10 +443,11 @@ void printf(basic_writer &w, BasicCStringRef format, args args); FMT_FUNC int vfprintf(std::FILE *f, CStringRef format, printf_args args) { - MemoryWriter w; - printf(w, format, args); - std::size_t size = w.size(); - return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast(size); + internal::MemoryBuffer buffer; + printf(buffer, format, args); + std::size_t size = buffer.size(); + return std::fwrite( + buffer.data(), 1, size, f) < size ? -1 : static_cast(size); } #ifndef FMT_HEADER_ONLY @@ -463,11 +456,11 @@ template struct internal::BasicData; // Explicit instantiations for char. -template void internal::FixedBuffer::grow(std::size_t); +template void FixedBuffer::grow(std::size_t); template void internal::ArgMap::init(const args &args); -template void printf_context::format(writer &writer); +template void printf_context::format(buffer &); template int internal::CharTraits::format_float( char *buffer, std::size_t size, const char *format, @@ -481,11 +474,11 @@ template int internal::CharTraits::format_float( template class basic_context; -template void internal::FixedBuffer::grow(std::size_t); +template void FixedBuffer::grow(std::size_t); template void internal::ArgMap::init(const wargs &args); -template void printf_context::format(wwriter &writer); +template void printf_context::format(wbuffer &); template int internal::CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, diff --git a/fmt/format.h b/fmt/format.h index 3857a11e..5b8f5bd0 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -365,10 +365,13 @@ using std::move; #endif template -class basic_writer; +class basic_buffer; -typedef basic_writer writer; -typedef basic_writer wwriter; +typedef basic_buffer buffer; +typedef basic_buffer wbuffer; + +template +class basic_writer; template class basic_arg; @@ -616,6 +619,9 @@ class basic_buffer { /** Returns the capacity of this buffer. */ std::size_t capacity() const { return capacity_; } + /** Returns a pointer to the buffer data. */ + const T *data() const { return ptr_; } + /** Resizes the buffer. If T is a POD type new elements may not be initialized. */ @@ -662,11 +668,17 @@ void basic_buffer::append(const U *begin, const U *end) { size_ = new_size; } +template +inline std::basic_string to_string(const basic_buffer& buffer) { + return std::basic_string(buffer.data(), buffer.size()); +} + namespace internal { // A memory buffer for trivially copyable/constructible types with the first // SIZE elements stored in the object itself. -template > +template > class MemoryBuffer : private Allocator, public basic_buffer { private: T data_[SIZE]; @@ -741,17 +753,6 @@ void MemoryBuffer::grow(std::size_t size) { Allocator::deallocate(old_ptr, old_capacity); } -// A fixed-size buffer. -template -class FixedBuffer : public fmt::basic_buffer { - public: - FixedBuffer(Char *array, std::size_t size) - : fmt::basic_buffer(array, size) {} - - protected: - FMT_API void grow(std::size_t size); -}; - template class BasicCharTraits { public: @@ -988,7 +989,7 @@ class UTF16ToUTF8 { FMT_API int convert(WStringRef s); }; -FMT_API void format_windows_error(fmt::writer &out, int error_code, +FMT_API void format_windows_error(fmt::buffer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT; #endif @@ -1085,7 +1086,7 @@ struct string_value { template struct CustomValue { typedef void (*FormatFunc)( - basic_writer &writer, const void *arg, void *ctx); + basic_buffer &buffer, const void *arg, void *ctx); const void *value; FormatFunc format; @@ -1207,8 +1208,8 @@ class value { // Formats an argument of a custom type, such as a user-defined class. template static void format_custom_arg( - basic_writer &writer, const void *arg, void *context) { - format_value(writer, *static_cast(arg), + basic_buffer &buffer, const void *arg, void *context) { + format_value(buffer, *static_cast(arg), *static_cast(context)); } @@ -1464,7 +1465,7 @@ inline fmt::StringRef thousands_sep(...) { return ""; } #endif template -void format_value(basic_writer &, const T &, Formatter &, const Char *) { +void format_value(basic_buffer &, const T &, Formatter &, const Char *) { FMT_STATIC_ASSERT(False::value, "Cannot format argument. To enable the use of ostream " "operator<< include fmt/ostream.h. Otherwise provide " @@ -1858,7 +1859,7 @@ class ArgFormatterBase { typedef basic_format_specs format_specs; private: - basic_writer &writer_; + basic_writer writer_; format_specs &spec_; FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatterBase); @@ -1901,8 +1902,8 @@ class ArgFormatterBase { public: typedef Char char_type; - ArgFormatterBase(basic_writer &w, format_specs &s) - : writer_(w), spec_(s) {} + ArgFormatterBase(basic_buffer &b, format_specs &s) + : writer_(b), spec_(s) {} void operator()(monostate) { FMT_ASSERT(false, "invalid argument type"); @@ -1973,12 +1974,6 @@ class ArgFormatterBase { } }; -template -inline void write(basic_writer &w, const Char *start, const Char *end) { - if (start != end) - w.write(BasicStringRef(start, internal::to_unsigned(end - start))); -} - template class context_base { private: @@ -2047,20 +2042,20 @@ class ArgFormatter : public internal::ArgFormatterBase { /** \rst Constructs an argument formatter object. - *writer* is a reference to the writer to be used for output, + *buffer* is a reference to the buffer to be used for output, *ctx* is a reference to the formatting context, *spec* contains format specifier information for standard argument types. \endrst */ - ArgFormatter(basic_writer &writer, basic_context &ctx, + ArgFormatter(basic_buffer &buffer, basic_context &ctx, format_specs &spec) - : internal::ArgFormatterBase(writer, spec), ctx_(ctx) {} + : internal::ArgFormatterBase(buffer, spec), ctx_(ctx) {} using internal::ArgFormatterBase::operator(); /** Formats an argument of a custom (user-defined) type. */ void operator()(internal::CustomValue c) { - c.format(this->writer(), c.value, &ctx_); + c.format(this->writer().buffer(), c.value, &ctx_); } }; @@ -2160,7 +2155,7 @@ class SystemError : public internal::RuntimeError { may look like "Unknown error -1" and is platform-dependent. \endrst */ -FMT_API void format_system_error(fmt::writer &out, int error_code, +FMT_API void format_system_error(fmt::buffer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT; namespace internal { @@ -2298,13 +2293,12 @@ class basic_writer { template friend class PrintfArgFormatter; - protected: + public: /** Constructs a ``basic_writer`` object. */ explicit basic_writer(basic_buffer &b) : buffer_(b) {} - public: /** \rst Destroys a ``basic_writer`` object. @@ -2343,38 +2337,6 @@ class basic_writer { return std::basic_string(&buffer_[0], buffer_.size()); } - void vformat(BasicCStringRef format, - basic_args> args); - /** - \rst - Writes formatted data. - - *args* is an argument list representing arbitrary arguments. - - **Example**:: - - MemoryWriter out; - out.format("Current point:\n"); - out.format("({:+f}, {:+f})", -3.14, 3.14); - - This will write the following output to the ``out`` object: - - .. code-block:: none - - Current point: - (-3.140000, +3.140000) - - The output can be accessed using :func:`data()`, :func:`c_str` or - :func:`str` methods. - - See also :ref:`syntax`. - \endrst - */ - template - void format(BasicCStringRef format, const Args & ... args) { - vformat(format, make_args>(args...)); - } - void write(int value) { write_decimal(value); } @@ -2881,6 +2843,23 @@ class BasicMemoryWriter : public basic_writer { typedef BasicMemoryWriter MemoryWriter; typedef BasicMemoryWriter WMemoryWriter; +// A fixed-size buffer. +template +class FixedBuffer : public fmt::basic_buffer { + public: + /** + \rst + Constructs a :class:`fmt::FixedBuffer` object for *array* of the + given size. + \endrst + */ + FixedBuffer(Char *array, std::size_t size) + : fmt::basic_buffer(array, size) {} + + protected: + FMT_API void grow(std::size_t size); +}; + /** \rst This class template provides operations for formatting and writing data @@ -2904,15 +2883,9 @@ typedef BasicMemoryWriter WMemoryWriter; template class BasicArrayWriter : public basic_writer { private: - internal::FixedBuffer buffer_; + FixedBuffer buffer_; public: - /** - \rst - Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the - given size. - \endrst - */ BasicArrayWriter(Char *array, std::size_t size) : basic_writer(buffer_), buffer_(array, size) {} @@ -3000,10 +2973,34 @@ inline void print_colored(Color c, CStringRef format_str, vprint_colored(c, format_str, make_args(args...)); } +template +void vformat_to(basic_buffer &buffer, BasicCStringRef format_str, + basic_args args); + +inline void vformat_to(buffer &buf, CStringRef format_str, args args) { + vformat_to>(buf, format_str, args); +} + +inline void vformat_to(wbuffer &buf, WCStringRef format_str, wargs args) { + vformat_to>(buf, format_str, args); +} + +template +inline void format_to(buffer &buf, CStringRef format_str, + const Args & ... args) { + vformat_to(buf, format_str, make_args(args...)); +} + +template +inline void format_to(wbuffer &buf, WCStringRef format_str, + const Args & ... args) { + vformat_to(buf, format_str, make_args(args...)); +} + inline std::string vformat(CStringRef format_str, args args) { - MemoryWriter w; - w.vformat(format_str, args); - return w.str(); + internal::MemoryBuffer buffer; + vformat_to(buffer, format_str, args); + return to_string(buffer); } /** @@ -3021,15 +3018,14 @@ inline std::string format(CStringRef format_str, const Args & ... args) { } inline std::wstring vformat(WCStringRef format_str, wargs args) { - WMemoryWriter w; - w.vformat(format_str, args); - return w.str(); + internal::MemoryBuffer buffer; + vformat_to(buffer, format_str, args); + return to_string(buffer); } template inline std::wstring format(WCStringRef format_str, const Args & ... args) { - auto vargs = make_args(args...); - return vformat(format_str, vargs); + return vformat(format_str, make_args(args...)); } FMT_API void vprint(std::FILE *f, CStringRef format_str, args args); @@ -3273,15 +3269,15 @@ void check_sign(const Char *&s, const basic_arg &arg) { template class CustomFormatter { private: - basic_writer &writer_; + basic_buffer &buffer_; Context &ctx_; public: - CustomFormatter(basic_writer &writer, Context &ctx) - : writer_(writer), ctx_(ctx) {} + CustomFormatter(basic_buffer &buffer, Context &ctx) + : buffer_(buffer), ctx_(ctx) {} bool operator()(internal::CustomValue custom) { - custom.format(writer_, custom.value, &ctx_); + custom.format(buffer_, custom.value, &ctx_); return true; } @@ -3374,12 +3370,12 @@ inline typename basic_context::format_arg // Formats a single argument. template -void do_format_arg(basic_writer &writer, basic_arg arg, +void do_format_arg(basic_buffer &buffer, basic_arg arg, Context &ctx) { const Char *&s = ctx.ptr(); basic_format_specs spec; if (*s == ':') { - if (visit(internal::CustomFormatter(writer, ctx), arg)) + if (visit(internal::CustomFormatter(buffer, ctx), arg)) return; ++s; // Parse fill and alignment. @@ -3495,13 +3491,13 @@ void do_format_arg(basic_writer &writer, basic_arg arg, FMT_THROW(format_error("missing '}' in format string")); // Format argument. - visit(ArgFormatter(writer, ctx, spec), arg); + visit(ArgFormatter(buffer, ctx, spec), arg); } -/** Formats arguments and writes the output to the writer. */ +/** Formats arguments and writes the output to the buffer. */ template -void vwrite(basic_writer &writer, BasicCStringRef format_str, - basic_args args) { +void vformat_to(basic_buffer &buffer, BasicCStringRef format_str, + basic_args args) { basic_context ctx(format_str.c_str(), args); const Char *&s = ctx.ptr(); const Char *start = s; @@ -3509,26 +3505,19 @@ void vwrite(basic_writer &writer, BasicCStringRef format_str, Char c = *s++; if (c != '{' && c != '}') continue; if (*s == c) { - internal::write(writer, start, s); + buffer.append(start, s); start = ++s; continue; } if (c == '}') FMT_THROW(format_error("unmatched '}' in format string")); - internal::write(writer, start, s - 1); - do_format_arg(writer, ctx.parse_arg_id(), ctx); + buffer.append(start, s - 1); + do_format_arg(buffer, ctx.parse_arg_id(), ctx); if (*s != '}') FMT_THROW(format_error(fmt::format("unknown format specifier"))); start = ++s; } - internal::write(writer, start, s); -} - -template -inline void basic_writer::vformat( - BasicCStringRef format, - basic_args> args) { - vwrite>(*this, format, args); + buffer.append(start, s); } } // namespace fmt diff --git a/fmt/ostream.cc b/fmt/ostream.cc index d6f26985..f900664c 100644 --- a/fmt/ostream.cc +++ b/fmt/ostream.cc @@ -12,10 +12,10 @@ namespace fmt { namespace internal { -FMT_FUNC void write(std::ostream &os, writer &w) { - const char *data = w.data(); +FMT_FUNC void write(std::ostream &os, buffer &buf) { + const char *data = buf.data(); typedef internal::MakeUnsigned::Type UnsignedStreamSize; - UnsignedStreamSize size = w.size(); + UnsignedStreamSize size = buf.size(); UnsignedStreamSize max_size = internal::to_unsigned((std::numeric_limits::max)()); do { @@ -27,10 +27,9 @@ FMT_FUNC void write(std::ostream &os, writer &w) { } } -FMT_FUNC void vprint(std::ostream &os, CStringRef format_str, - args args) { - MemoryWriter w; - w.vformat(format_str, args); - internal::write(os, w); +FMT_FUNC void vprint(std::ostream &os, CStringRef format_str, args args) { + internal::MemoryBuffer buffer; + vformat_to(buffer, format_str, args); + internal::write(os, buffer); } } // namespace fmt diff --git a/fmt/ostream.h b/fmt/ostream.h index f3780354..528ee16a 100644 --- a/fmt/ostream.h +++ b/fmt/ostream.h @@ -67,28 +67,27 @@ struct ConvertToIntImpl { }; }; -// Write the content of w to os. -void write(std::ostream &os, writer &w); +// Write the content of buf to os. +void write(std::ostream &os, buffer &buf); template -BasicStringRef format_value( - internal::MemoryBuffer &buffer, - const T &value) { +void format_value(basic_buffer &buffer, const T &value) { internal::FormatBuf format_buf(buffer); std::basic_ostream output(&format_buf); output << value; - return BasicStringRef(&buffer[0], format_buf.size()); + buffer.resize(format_buf.size()); } } // namespace internal // Formats a value. template -void format_value(basic_writer &w, const T &value, +void format_value(basic_buffer &buf, const T &value, basic_context &ctx) { internal::MemoryBuffer buffer; - auto str = internal::format_value(buffer, value); + internal::format_value(buffer, value); + BasicStringRef str(buffer.data(), buffer.size()); do_format_arg< ArgFormatter >( - w, internal::make_arg< basic_context >(str), ctx); + buf, internal::make_arg< basic_context >(str), ctx); } FMT_API void vprint(std::ostream &os, CStringRef format_str, args args); diff --git a/fmt/printf.h b/fmt/printf.h index 2fa54d2f..0b77ae34 100644 --- a/fmt/printf.h +++ b/fmt/printf.h @@ -225,12 +225,12 @@ class PrintfArgFormatter : public internal::ArgFormatterBase { /** \rst Constructs an argument formatter object. - *writer* is a reference to the output writer and *spec* contains format + *buffer* is a reference to the output buffer and *spec* contains format specifier information for standard argument types. \endrst */ - PrintfArgFormatter(basic_writer &writer, format_specs &spec) - : internal::ArgFormatterBase(writer, spec) {} + PrintfArgFormatter(basic_buffer &buffer, format_specs &spec) + : internal::ArgFormatterBase(buffer, spec) {} using Base::operator(); @@ -289,7 +289,7 @@ class PrintfArgFormatter : public internal::ArgFormatterBase { const Char format_str[] = {'}', '\0'}; auto args = basic_args>(); basic_context ctx(format_str, args); - c.format(this->writer(), c.value, &ctx); + c.format(this->writer().buffer(), c.value, &ctx); } }; @@ -331,8 +331,8 @@ class printf_context : basic_args args) : Base(format_str.c_str(), args) {} - /** Formats stored arguments and writes the output to the writer. */ - FMT_API void format(basic_writer &writer); + /** Formats stored arguments and writes the output to the buffer. */ + FMT_API void format(basic_buffer &buffer); }; template @@ -408,18 +408,18 @@ unsigned printf_context::parse_header( } template -void printf_context::format(basic_writer &writer) { +void printf_context::format(basic_buffer &buffer) { const Char *start = this->ptr(); const Char *s = start; while (*s) { Char c = *s++; if (c != '%') continue; if (*s == c) { - internal::write(writer, start, s); + buffer.append(start, s); start = ++s; continue; } - internal::write(writer, start, s - 1); + buffer.append(start, s - 1); format_specs spec; spec.align_ = ALIGN_RIGHT; @@ -501,31 +501,30 @@ void printf_context::format(basic_writer &writer) { start = s; // Format argument. - visit(AF(writer, spec), arg); + visit(AF(buffer, spec), arg); } - internal::write(writer, start, s); + buffer.append(start, s); } // Formats a value. template -void format_value(basic_writer &w, const T &value, +void format_value(basic_buffer &buf, const T &value, printf_context& ctx) { - internal::MemoryBuffer buffer; - w.write(internal::format_value(buffer, value)); + internal::format_value(buf, value); } template -void printf(basic_writer &w, BasicCStringRef format, +void printf(basic_buffer &buf, BasicCStringRef format, basic_args> args) { - printf_context(format, args).format(w); + printf_context(format, args).format(buf); } typedef basic_args> printf_args; inline std::string vsprintf(CStringRef format, printf_args args) { - MemoryWriter w; - printf(w, format, args); - return w.str(); + internal::MemoryBuffer buffer; + printf(buffer, format, args); + return to_string(buffer); } /** @@ -544,9 +543,9 @@ inline std::string sprintf(CStringRef format_str, const Args & ... args) { inline std::wstring vsprintf( WCStringRef format, basic_args> args) { - WMemoryWriter w; - printf(w, format, args); - return w.str(); + internal::MemoryBuffer buffer; + printf(buffer, format, args); + return to_string(buffer); } template @@ -591,10 +590,10 @@ inline int printf(CStringRef format_str, const Args & ... args) { } inline int vfprintf(std::ostream &os, CStringRef format_str, printf_args args) { - MemoryWriter w; - printf(w, format_str, args); - internal::write(os, w); - return static_cast(w.size()); + internal::MemoryBuffer buffer; + printf(buffer, format_str, args); + internal::write(os, buffer); + return static_cast(buffer.size()); } /** diff --git a/fmt/time.h b/fmt/time.h index b5482e73..f4ec4812 100644 --- a/fmt/time.h +++ b/fmt/time.h @@ -15,7 +15,7 @@ namespace fmt { -void format_value(writer &w, const std::tm &tm, context &ctx) { +void format_value(buffer &buf, const std::tm &tm, context &ctx) { const char *&s = ctx.ptr(); if (*s == ':') ++s; @@ -27,13 +27,12 @@ void format_value(writer &w, const std::tm &tm, context &ctx) { internal::MemoryBuffer format; format.append(s, end + 1); format[format.size() - 1] = '\0'; - basic_buffer &buffer = w.buffer(); - std::size_t start = buffer.size(); + std::size_t start = buf.size(); for (;;) { - std::size_t size = buffer.capacity() - start; - std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm); + std::size_t size = buf.capacity() - start; + std::size_t count = std::strftime(&buf[start], size, &format[0], &tm); if (count != 0) { - buffer.resize(start + count); + buf.resize(start + count); break; } if (size >= format.size() * 256) { @@ -44,7 +43,7 @@ void format_value(writer &w, const std::tm &tm, context &ctx) { break; } const std::size_t MIN_GROWTH = 10; - buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH)); + buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH)); } s = end; } diff --git a/test/custom-formatter-test.cc b/test/custom-formatter-test.cc index 01d8b953..4a582c1a 100644 --- a/test/custom-formatter-test.cc +++ b/test/custom-formatter-test.cc @@ -16,9 +16,9 @@ using fmt::PrintfArgFormatter; // rounded to 0. class CustomArgFormatter : public fmt::ArgFormatter { public: - CustomArgFormatter(fmt::writer &w, fmt::basic_context &ctx, + CustomArgFormatter(fmt::buffer &buf, fmt::basic_context &ctx, fmt::format_specs &s) - : fmt::ArgFormatter(w, ctx, s) {} + : fmt::ArgFormatter(buf, ctx, s) {} using fmt::ArgFormatter::operator(); @@ -33,8 +33,8 @@ class CustomArgFormatter : public fmt::ArgFormatter { // rounded to 0. class CustomPrintfArgFormatter : public PrintfArgFormatter { public: - CustomPrintfArgFormatter(fmt::basic_writer &w, fmt::format_specs &spec) - : PrintfArgFormatter(w, spec) {} + CustomPrintfArgFormatter(fmt::buffer &buf, fmt::format_specs &spec) + : PrintfArgFormatter(buf, spec) {} using PrintfArgFormatter::operator(); @@ -46,10 +46,10 @@ class CustomPrintfArgFormatter : public PrintfArgFormatter { }; std::string custom_vformat(fmt::CStringRef format_str, fmt::args args) { - fmt::MemoryWriter writer; - // Pass custom argument formatter as a template arg to vformat. - fmt::vwrite(writer, format_str, args); - return writer.str(); + fmt::internal::MemoryBuffer buffer; + // Pass custom argument formatter as a template arg to vwrite. + fmt::vformat_to(buffer, format_str, args); + return std::string(buffer.data(), buffer.size()); } template @@ -64,10 +64,10 @@ typedef fmt::printf_context std::string custom_vsprintf( const char* format_str, fmt::basic_args args) { - fmt::MemoryWriter writer; + fmt::internal::MemoryBuffer buffer; CustomPrintfFormatter formatter(format_str, args); - formatter.format(writer); - return writer.str(); + formatter.format(buffer); + return std::string(buffer.data(), buffer.size()); } template diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index 6308273e..6c86a484 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -107,14 +107,14 @@ TEST(FormatTest, FormatErrorCode) { { fmt::MemoryWriter w; w.write("garbage"); - fmt::format_error_code(w, 42, "test"); + fmt::format_error_code(w.buffer(), 42, "test"); EXPECT_EQ("test: " + msg, w.str()); } { fmt::MemoryWriter w; std::string prefix( fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size() + 1, 'x'); - fmt::format_error_code(w, 42, prefix); + fmt::format_error_code(w.buffer(), 42, prefix); EXPECT_EQ(msg, w.str()); } int codes[] = {42, -1}; @@ -124,14 +124,14 @@ TEST(FormatTest, FormatErrorCode) { fmt::MemoryWriter w; std::string prefix( fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size(), 'x'); - fmt::format_error_code(w, codes[i], prefix); + fmt::format_error_code(w.buffer(), codes[i], prefix); EXPECT_EQ(prefix + sep + msg, w.str()); std::size_t size = fmt::internal::INLINE_BUFFER_SIZE; EXPECT_EQ(size, w.size()); w.clear(); // Test with a message that doesn't fit into the buffer. prefix += 'x'; - fmt::format_error_code(w, codes[i], prefix); + fmt::format_error_code(w.buffer(), codes[i], prefix); EXPECT_EQ(msg, w.str()); } } diff --git a/test/format-test.cc b/test/format-test.cc index f10e1b1f..02b99fd1 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -265,12 +265,6 @@ TEST(WriterTest, Data) { EXPECT_EQ("42", std::string(w.data(), w.size())); } -TEST(WriterTest, WriteWithoutArgs) { - MemoryWriter w; - w.format("test"); - EXPECT_EQ("test", std::string(w.data(), w.size())); -} - TEST(WriterTest, WriteInt) { CHECK_WRITE(42); CHECK_WRITE(-42); @@ -476,20 +470,6 @@ TEST(WriterTest, PadWString) { EXPECT_EQ(L"test******", write_wstr(L"test", width=10, fill=L'*')); } -TEST(WriterTest, Format) { - MemoryWriter w; - w.format("part{0}", 1); - EXPECT_EQ(strlen("part1"), w.size()); - EXPECT_STREQ("part1", w.c_str()); - EXPECT_STREQ("part1", w.data()); - EXPECT_EQ("part1", w.str()); - w.format("part{0}", 2); - EXPECT_EQ(strlen("part1part2"), w.size()); - EXPECT_STREQ("part1part2", w.c_str()); - EXPECT_STREQ("part1part2", w.data()); - EXPECT_EQ("part1part2", w.str()); -} - TEST(WriterTest, WWriter) { EXPECT_EQ(L"cafe", write_wstr(0xcafe, type='x')); } @@ -501,32 +481,43 @@ TEST(ArrayWriterTest, Ctor) { EXPECT_STREQ("", w.c_str()); } +TEST(FormatToTest, FormatWithoutArgs) { + fmt::internal::MemoryBuffer buffer; + format_to(buffer, "test"); + EXPECT_EQ("test", std::string(buffer.data(), buffer.size())); +} + +TEST(FormatToTest, Format) { + fmt::internal::MemoryBuffer buffer; + format_to(buffer, "part{0}", 1); + EXPECT_EQ(strlen("part1"), buffer.size()); + EXPECT_EQ("part1", std::string(buffer.data(), buffer.size())); + format_to(buffer, "part{0}", 2); + EXPECT_EQ(strlen("part1part2"), buffer.size()); + EXPECT_EQ("part1part2", std::string(buffer.data(), buffer.size())); + EXPECT_EQ("part1part2", to_string(buffer)); +} + TEST(ArrayWriterTest, CompileTimeSizeCtor) { char array[10] = "garbage"; fmt::ArrayWriter w(array); EXPECT_EQ(0u, w.size()); EXPECT_STREQ("", w.c_str()); - w.format("{:10}", 1); -} - -TEST(ArrayWriterTest, Write) { - char array[10]; - fmt::ArrayWriter w(array, sizeof(array)); - w.format("{}", 42); - EXPECT_EQ("42", w.str()); + format_to(w.buffer(), "{:10}", 1); } TEST(ArrayWriterTest, BufferOverflow) { char array[10]; fmt::ArrayWriter w(array, sizeof(array)); - w.format("{:10}", 1); - EXPECT_THROW_MSG(w.format("{}", 1), std::runtime_error, "buffer overflow"); + format_to(w.buffer(), "{:10}", 1); + EXPECT_THROW_MSG(format_to(w.buffer(), "{}", 1), std::runtime_error, + "buffer overflow"); } TEST(ArrayWriterTest, WChar) { wchar_t array[10]; fmt::WArrayWriter w(array); - w.format(L"{}", 42); + format_to(w.buffer(), L"{}", 42); EXPECT_EQ(L"42", w.str()); } @@ -1366,12 +1357,8 @@ TEST(FormatterTest, FormatCStringRef) { EXPECT_EQ("test", format("{0}", CStringRef("test"))); } -void format_value(fmt::writer &w, const Date &d, fmt::context &) { - w.write(d.year()); - w.write('-'); - w.write(d.month()); - w.write('-'); - w.write(d.day()); +void format_value(fmt::buffer &buf, const Date &d, fmt::context &) { + fmt::format_to(buf, "{}-{}-{}", d.year(), d.month(), d.day()); } TEST(FormatterTest, FormatCustom) { @@ -1383,8 +1370,8 @@ TEST(FormatterTest, FormatCustom) { class Answer {}; template -void format_value(basic_writer &w, Answer, fmt::context &) { - w.write("42"); +void format_value(fmt::basic_buffer &buf, Answer, fmt::context &) { + fmt::format_to(buf, "{}", 42); } TEST(FormatterTest, CustomFormat) { @@ -1417,13 +1404,11 @@ TEST(FormatterTest, FormatExamples) { out.write("The answer is "); out.write(42); out.write("\n"); - out.format("({:+f}, {:+f})", -3.14, 3.14); - EXPECT_EQ("The answer is 42\n(-3.140000, +3.140000)", out.str()); { MemoryWriter writer; for (int i = 0; i < 10; i++) - writer.format("{}", i); + format_to(writer.buffer(), "{}", i); std::string s = writer.str(); // s == 0123456789 EXPECT_EQ("0123456789", s); } @@ -1567,10 +1552,10 @@ TEST(StrTest, Convert) { } std::string vformat_message(int id, const char *format, fmt::args args) { - MemoryWriter w; - w.format("[{}] ", id); - w.vformat(format, args); - return w.str(); + fmt::internal::MemoryBuffer buffer; + format_to(buffer, "[{}] ", id); + vformat_to(buffer, format, args); + return to_string(buffer); } template @@ -1643,9 +1628,9 @@ class MockArgFormatter : public fmt::internal::ArgFormatterBase { public: typedef fmt::internal::ArgFormatterBase Base; - MockArgFormatter(fmt::writer &w, fmt::context &ctx, + MockArgFormatter(fmt::buffer &b, fmt::context &ctx, fmt::format_specs &s) - : fmt::internal::ArgFormatterBase(w, s) { + : fmt::internal::ArgFormatterBase(b, s) { EXPECT_CALL(*this, call(42)); } @@ -1657,8 +1642,8 @@ class MockArgFormatter : public fmt::internal::ArgFormatterBase { }; void custom_vformat(fmt::CStringRef format_str, fmt::args args) { - fmt::MemoryWriter writer; - fmt::vwrite(writer, format_str, args); + fmt::internal::MemoryBuffer buffer; + fmt::vformat_to(buffer, format_str, args); } template diff --git a/test/gtest-extra-test.cc b/test/gtest-extra-test.cc index 6a8c5676..4de17ee3 100644 --- a/test/gtest-extra-test.cc +++ b/test/gtest-extra-test.cc @@ -320,7 +320,7 @@ TEST(StreamingAssertionsTest, EXPECT_WRITE) { TEST(UtilTest, FormatSystemError) { fmt::MemoryWriter out; - fmt::format_system_error(out, EDOM, "test message"); + fmt::format_system_error(out.buffer(), EDOM, "test message"); EXPECT_EQ(out.str(), format_system_error(EDOM, "test message")); } diff --git a/test/gtest-extra.cc b/test/gtest-extra.cc index 7640d154..5708eef7 100644 --- a/test/gtest-extra.cc +++ b/test/gtest-extra.cc @@ -104,7 +104,7 @@ std::string read(File &f, std::size_t count) { #endif // FMT_USE_FILE_DESCRIPTORS std::string format_system_error(int error_code, fmt::StringRef message) { - fmt::MemoryWriter out; + fmt::internal::MemoryBuffer out; fmt::format_system_error(out, error_code, message); - return out.str(); + return to_string(out); } diff --git a/test/ostream-test.cc b/test/ostream-test.cc index eea803df..761820b6 100644 --- a/test/ostream-test.cc +++ b/test/ostream-test.cc @@ -59,17 +59,17 @@ TEST(OStreamTest, Enum) { } struct TestArgFormatter : fmt::ArgFormatter { - TestArgFormatter(fmt::writer &w, fmt::context &ctx, fmt::format_specs &s) - : fmt::ArgFormatter(w, ctx, s) {} + TestArgFormatter(fmt::buffer &buf, fmt::context &ctx, fmt::format_specs &s) + : fmt::ArgFormatter(buf, ctx, s) {} }; TEST(OStreamTest, CustomArg) { - fmt::MemoryWriter writer; + fmt::internal::MemoryBuffer buffer; fmt::context ctx("}", fmt::args()); fmt::format_specs spec; - TestArgFormatter af(writer, ctx, spec); + TestArgFormatter af(buffer, ctx, spec); visit(af, fmt::internal::make_arg(TestEnum())); - EXPECT_EQ("TestEnum", writer.str()); + EXPECT_EQ("TestEnum", std::string(buffer.data(), buffer.size())); } TEST(OStreamTest, Format) { @@ -121,9 +121,10 @@ TEST(OStreamTest, Print) { TEST(OStreamTest, WriteToOStream) { std::ostringstream os; - fmt::MemoryWriter w; - w.write("foo"); - fmt::internal::write(os, w); + fmt::internal::MemoryBuffer buffer; + const char *foo = "foo"; + buffer.append(foo, foo + std::strlen(foo)); + fmt::internal::write(os, buffer); EXPECT_EQ("foo", os.str()); } @@ -133,16 +134,10 @@ TEST(OStreamTest, WriteToOStreamMaxSize) { if (max_size <= fmt::internal::to_unsigned(max_streamsize)) return; - class TestWriter : public fmt::basic_writer { - private: - struct TestBuffer : fmt::basic_buffer { - explicit TestBuffer(std::size_t size) { size_ = size; } - void grow(std::size_t) {} - } buffer_; - public: - explicit TestWriter(std::size_t size) - : fmt::basic_writer(buffer_), buffer_(size) {} - } w(max_size); + struct TestBuffer : fmt::basic_buffer { + explicit TestBuffer(std::size_t size) { size_ = size; } + void grow(std::size_t) {} + } buffer(max_size); struct MockStreamBuf : std::streambuf { MOCK_METHOD2(xsputn, std::streamsize (const void *s, std::streamsize n)); @@ -150,11 +145,11 @@ TEST(OStreamTest, WriteToOStreamMaxSize) { const void *v = s; return xsputn(v, n); } - } buffer; + } streambuf; struct TestOStream : std::ostream { explicit TestOStream(MockStreamBuf &buffer) : std::ostream(&buffer) {} - } os(buffer); + } os(streambuf); testing::InSequence sequence; const char *data = 0; @@ -163,10 +158,10 @@ TEST(OStreamTest, WriteToOStreamMaxSize) { typedef fmt::internal::MakeUnsigned::Type UStreamSize; UStreamSize n = std::min( size, fmt::internal::to_unsigned(max_streamsize)); - EXPECT_CALL(buffer, xsputn(data, static_cast(n))) + EXPECT_CALL(streambuf, xsputn(data, static_cast(n))) .WillOnce(testing::Return(max_streamsize)); data += n; size -= static_cast(n); } while (size != 0); - fmt::internal::write(os, w); + fmt::internal::write(os, buffer); } diff --git a/test/util-test.cc b/test/util-test.cc index 84ba407f..9466c372 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -67,9 +67,10 @@ namespace { struct Test {}; template -void format_value(fmt::basic_writer &w, Test, +void format_value(fmt::basic_buffer &b, Test, fmt::basic_context &) { - w.write("test"); + const Char *test = "test"; + b.append(test, test + std::strlen(test)); } template @@ -416,7 +417,7 @@ struct CustomContext { bool called; }; -void format_value(fmt::writer &, const Test &, CustomContext &ctx) { +void format_value(fmt::buffer &, const Test &, CustomContext &ctx) { ctx.called = true; } @@ -424,8 +425,8 @@ TEST(UtilTest, MakeValueWithCustomFormatter) { ::Test t; fmt::internal::value arg(t); CustomContext ctx = {false}; - fmt::MemoryWriter w; - arg.custom.format(w, &t, &ctx); + fmt::internal::MemoryBuffer buffer; + arg.custom.format(buffer, &t, &ctx); EXPECT_TRUE(ctx.called); } @@ -568,10 +569,10 @@ TEST(UtilTest, CustomArg) { EXPECT_CALL(visitor, visit(_)).WillOnce( testing::Invoke([&](fmt::internal::CustomValue custom) { EXPECT_EQ(&test, custom.value); - fmt::MemoryWriter w; + fmt::internal::MemoryBuffer buffer; fmt::context ctx("}", fmt::args()); - custom.format(w, &test, &ctx); - EXPECT_EQ("test", w.str()); + custom.format(buffer, &test, &ctx); + EXPECT_EQ("test", std::string(buffer.data(), buffer.size())); return Visitor::Result(); })); fmt::visit(visitor, make_arg(test)); @@ -689,7 +690,7 @@ TEST(UtilTest, UTF16ToUTF8Convert) { #endif // _WIN32 typedef void (*FormatErrorMessage)( - fmt::writer &out, int error_code, StringRef message); + fmt::buffer &out, int error_code, StringRef message); template void check_throw_error(int error_code, FormatErrorMessage format) { @@ -699,20 +700,21 @@ void check_throw_error(int error_code, FormatErrorMessage format) { } catch (const fmt::SystemError &e) { error = e; } - fmt::MemoryWriter message; + fmt::internal::MemoryBuffer message; format(message, error_code, "test error"); - EXPECT_EQ(message.str(), error.what()); + EXPECT_EQ(to_string(message), error.what()); EXPECT_EQ(error_code, error.error_code()); } TEST(UtilTest, FormatSystemError) { - fmt::MemoryWriter message; + fmt::internal::MemoryBuffer message; fmt::format_system_error(message, EDOM, "test"); - EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), message.str()); + EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), + to_string(message)); message.clear(); fmt::format_system_error( message, EDOM, fmt::StringRef(0, std::numeric_limits::max())); - EXPECT_EQ(fmt::format("error {}", EDOM), message.str()); + EXPECT_EQ(fmt::format("error {}", EDOM), to_string(message)); } TEST(UtilTest, SystemError) { @@ -723,10 +725,11 @@ TEST(UtilTest, SystemError) { } TEST(UtilTest, ReportSystemError) { - fmt::MemoryWriter out; + fmt::internal::MemoryBuffer out; fmt::format_system_error(out, EDOM, "test error"); - out.write('\n'); - EXPECT_WRITE(stderr, fmt::report_system_error(EDOM, "test error"), out.str()); + out.push_back('\n'); + EXPECT_WRITE(stderr, fmt::report_system_error(EDOM, "test error"), + to_string(out)); } #ifdef _WIN32