diff --git a/format.h b/format.h index 1d3dffbe..7e6c88f7 100644 --- a/format.h +++ b/format.h @@ -38,6 +38,7 @@ #include #include #include +#include #ifndef FMT_USE_IOSTREAMS # define FMT_USE_IOSTREAMS 1 @@ -478,6 +479,11 @@ class Buffer { T &operator[](std::size_t index) { return ptr_[index]; } const T &operator[](std::size_t index) const { return ptr_[index]; } + + + template > + friend class basic_formatbuf; + }; template @@ -2027,6 +2033,11 @@ class BasicWriter { */ std::size_t size() const { return buffer_.size(); } + /** + Returns underlying buffer. + */ + Buffer& buffer() const { return buffer_; } + /** Returns a pointer to the output buffer content. No terminating null character is appended. @@ -2628,16 +2639,39 @@ class BasicArrayWriter : public BasicWriter { typedef BasicArrayWriter ArrayWriter; typedef BasicArrayWriter WArrayWriter; +template > +class basic_formatbuf : public std::basic_streambuf { + + typedef typename std::basic_streambuf::int_type int_type; + + Buffer& buffer_; + +public: + basic_formatbuf(BasicFormatter &formatter) : buffer_(formatter.writer().buffer()) { + setp(buffer_.ptr_, buffer_.ptr_ + buffer_.size_, buffer_.ptr_ + buffer_.capacity_); + } + + virtual int_type overflow(int_type _Meta = Traits::eof()) { + buffer_.grow(buffer_.capacity_ * 2); + setp(buffer_.ptr_, buffer_.ptr_ + buffer_.size_, buffer_.ptr_ + buffer_.capacity_); + + return traits_type::to_int_type(*pptr()); + } + + int_type flush() { + buffer_.size_ = pptr() - pbase(); + return traits_type::to_int_type(*pptr()); + } +}; + // Formats a value. template -void format(BasicFormatter &f, const Char *&format_str, const T &value) { - std::basic_ostringstream os; - os << value; - std::basic_string str = os.str(); - internal::Arg arg = internal::MakeValue(str); - arg.type = static_cast( - internal::MakeValue::type(str)); - format_str = f.format(format_str, arg); +void format(BasicFormatter &formatter, const Char *&format_str, const T &value) { + + basic_formatbuf format_buf(formatter); + std::basic_ostream output(&format_buf); + output << value; + format_buf.flush(); } // Reports a system error without throwing an exception.