diff --git a/include/fmt/core.h b/include/fmt/core.h index 3805d44e..08032412 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -725,6 +725,41 @@ class container_buffer : public buffer { : buffer(c.size()), container_(c) {} }; +// A buffer that writes to an output iterator when flushed. +template +class iterator_buffer : public buffer { + private: + enum { buffer_size = 256 }; + + OutputIt out_; + T data_[buffer_size]; + + protected: + void grow(size_t) final { + if (this->size() == buffer_size) flush(); + } + + public: + explicit iterator_buffer(OutputIt out) + : buffer(data_, 0, buffer_size), out_(out) {} + ~iterator_buffer() { flush(); } + + OutputIt out() { return out_; } + void flush(); +}; + +template +class iterator_buffer : public buffer { + protected: + void grow(size_t) final {} + + public: + explicit iterator_buffer(T* out) : buffer(out, 0, ~size_t()) {} + + T* out() { return &*this->end(); } + void flush() {} +}; + // An output iterator that appends to the buffer. // It is used to reduce symbol sizes for the common case. template @@ -1229,6 +1264,9 @@ struct is_contiguous_back_insert_iterator : std::false_type {}; template struct is_contiguous_back_insert_iterator> : is_contiguous {}; +template +struct is_contiguous_back_insert_iterator> + : std::true_type {}; // A type-erased reference to an std::locale to avoid heavy include. class locale_ref { diff --git a/include/fmt/format.h b/include/fmt/format.h index d0908038..2a82e2e5 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -581,6 +581,12 @@ void buffer::append(const U* begin, const U* end) { begin += count; } while (begin != end); } + +template +void iterator_buffer::flush() { + out_ = std::copy(data_, data_ + this->size(), out_); + this->clear(); +} } // namespace detail // The number of characters to store in the basic_memory_buffer object itself @@ -3560,9 +3566,12 @@ template ::value)> inline OutputIt format_to(OutputIt out, const S& format_str, Args&&... args) { detail::check_format_string(format_str); - using context = format_context_t>; - return vformat_to(out, to_string_view(format_str), - make_format_args(args...)); + using Char = char_t; + detail::iterator_buffer buf(out); + detail::vformat_to(buf, to_string_view(format_str), + make_format_args>(args...)); + buf.flush(); + return buf.out(); } template struct format_to_n_result {