From d4885cea62d685db17f2d73819dbfcaff7534aa6 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 14 Jul 2016 07:41:00 -0700 Subject: [PATCH] Document BasicStringWriter --- doc/api.rst | 3 ++ fmt/string.h | 83 +++++++++++++++++++++++++++++++++++++++++++++ test/string-test.cc | 57 +++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) diff --git a/doc/api.rst b/doc/api.rst index 4ed9ae8a..2cde812b 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -157,6 +157,9 @@ store output elsewhere by subclassing `~fmt::BasicWriter`. .. doxygenclass:: fmt::BasicArrayWriter :members: +.. doxygenclass:: fmt::BasicStringWriter + :members: + .. doxygenfunction:: bin(int) .. doxygenfunction:: oct(int) diff --git a/fmt/string.h b/fmt/string.h index 4fc1f767..1f82f957 100644 --- a/fmt/string.h +++ b/fmt/string.h @@ -14,6 +14,89 @@ namespace fmt { +namespace internal { + +// A buffer that stores data in ``std::string``. +template +class StringBuffer : public Buffer { + private: + std::string data_; + + protected: + virtual void grow(std::size_t size) { + data_.resize(size); + this->ptr_ = &data_[0]; + this->capacity_ = size; + } + + public: + // Moves the data to ``str`` clearing the buffer. + void move_to(std::string &str) { + data_.resize(this->size_); + str.swap(data_); + this->capacity_ = this->size_ = 0; + this->ptr_ = 0; + } +}; +} // namespace internal + +/** + \rst + This class template provides operations for formatting and writing data + into a character stream. The output is stored in ``std::string`` that grows + dynamically. + + You can use one of the following typedefs for common character types + and the standard allocator: + + +---------------+----------------------------+ + | Type | Definition | + +===============+============================+ + | StringWriter | BasicStringWriter | + +---------------+----------------------------+ + | WStringWriter | BasicStringWriter | + +---------------+----------------------------+ + + **Example**:: + + StringWriter out; + out << "The answer is " << 42 << "\n"; + + This will write the following output to the ``out`` object: + + .. code-block:: none + + The answer is 42 + + The output can be moved to an ``std::string`` with ``out.move_to()``. + \endrst + */ +template +class BasicStringWriter : public BasicWriter { + private: + internal::StringBuffer buffer_; + + public: + /** + \rst + Constructs a :class:`fmt::BasicStringWriter` object. + \endrst + */ + BasicStringWriter() : Writer(buffer_) {} + + /** + \rst + Moves the buffer content to *str* clearing the buffer. + \endrst + */ + void move_to(std::string &str) { + buffer_.move_to(str); + } +}; + +typedef BasicStringWriter StringWriter; +typedef BasicStringWriter WStringWriter; + /** \rst Converts *value* to ``std::string`` using the default format for type *T*. diff --git a/test/string-test.cc b/test/string-test.cc index 5ef8877c..06265daa 100644 --- a/test/string-test.cc +++ b/test/string-test.cc @@ -10,6 +10,63 @@ #include "fmt/string.h" #include "gtest/gtest.h" +using fmt::internal::StringBuffer; + +TEST(StringBufferTest, Empty) { + StringBuffer buffer; + EXPECT_EQ(0, buffer.size()); + EXPECT_EQ(0, buffer.capacity()); + std::string data; + // std::string may have initial capacity. + std::size_t capacity = data.capacity(); + buffer.move_to(data); + EXPECT_EQ("", data); + EXPECT_EQ(capacity, data.capacity()); +} + +TEST(StringBufferTest, Reserve) { + StringBuffer buffer; + std::size_t capacity = std::string().capacity() + 10; + buffer.reserve(capacity); + EXPECT_EQ(0, buffer.size()); + EXPECT_EQ(capacity, buffer.capacity()); + std::string data; + buffer.move_to(data); + EXPECT_EQ("", data); +} + +TEST(StringBufferTest, Resize) { + StringBuffer buffer; + std::size_t size = std::string().capacity() + 10; + buffer.resize(size); + EXPECT_EQ(size, buffer.size()); + EXPECT_EQ(size, buffer.capacity()); + std::string data; + buffer.move_to(data); + EXPECT_EQ(size, data.size()); +} + +TEST(StringBufferTest, MoveTo) { + StringBuffer buffer; + std::size_t size = std::string().capacity() + 10; + buffer.resize(size); + const char *p = &buffer[0]; + std::string data; + buffer.move_to(data); + EXPECT_EQ(p, &data[0]); + EXPECT_EQ(0, buffer.size()); + EXPECT_EQ(0, buffer.capacity()); +} + +TEST(StringWriterTest, MoveTo) { + fmt::StringWriter out; + out << "The answer is " << 42 << "\n"; + std::string s; + out.move_to(s); + EXPECT_EQ("The answer is 42\n", s); + EXPECT_EQ(0, out.size()); +} + TEST(StringTest, ToString) { EXPECT_EQ("42", fmt::to_string(42)); }