From 768061c85eafa4631acba555e06d5a6432b25093 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 28 Jan 2018 20:08:51 -0800 Subject: [PATCH] Fix FormatBuf implementation (#491) --- include/fmt/ostream.h | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h index 9f868b32..a518d0fa 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -22,28 +22,27 @@ class FormatBuf : public std::basic_streambuf { typedef typename std::basic_streambuf::traits_type traits_type; basic_buffer &buffer_; - Char *start_; public: - FormatBuf(basic_buffer &buffer) : buffer_(buffer), start_(&buffer[0]) { - this->setp(start_, start_ + buffer_.capacity()); - } + FormatBuf(basic_buffer &buffer) : buffer_(buffer) {} + + protected: + // The put-area is actually always empty. This makes the implementation + // simpler and has the advantage that the streambuf and the buffer are always + // in sync and sputc never writes into uninitialized memory. The obvious + // disadvantage is that each call to sputc always results in a (virtual) call + // to overflow. There is no disadvantage here for sputn since this always + // results in a call to xsputn. int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE { - if (!traits_type::eq_int_type(ch, traits_type::eof())) { - size_t buf_size = size(); - buffer_.resize(buf_size); - buffer_.reserve(buf_size * 2); - - start_ = &buffer_[0]; - start_[buf_size] = traits_type::to_char_type(ch); - this->setp(start_+ buf_size + 1, start_ + buf_size * 2); - } + if (!traits_type::eq_int_type(ch, traits_type::eof())) + buffer_.push_back(static_cast(ch)); return ch; } - size_t size() const { - return to_unsigned(this->pptr() - start_); + std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE { + buffer_.append(s, s + count); + return count; } }; @@ -92,7 +91,7 @@ void format_value(basic_buffer &buffer, const T &value) { internal::FormatBuf format_buf(buffer); std::basic_ostream output(&format_buf); output << value; - buffer.resize(format_buf.size()); + buffer.resize(buffer.size()); } // Disable builtin formatting of enums and use operator<< instead.