diff --git a/format.h b/format.h index 7f080319..67f7b920 100644 --- a/format.h +++ b/format.h @@ -436,6 +436,19 @@ void MemoryBuffer::grow(std::size_t size) { this->deallocate(old_ptr, old_capacity); } +// A fixed-size buffer. +template +class FixedBuffer : public fmt::internal::Buffer { + public: + FixedBuffer(Char *array, std::size_t size) + : fmt::internal::Buffer(array, size) {} + + protected: + void grow(std::size_t size) { + throw std::runtime_error("buffer overflow"); + } +}; + #ifndef _MSC_VER // Portable version of signbit. inline int getsign(double x) { @@ -2111,20 +2124,20 @@ void BasicWriter::write_double( /** \rst - This template provides operations for formatting and writing data into - a character stream. The output is stored in a memory buffer that grows + This class template provides operations for formatting and writing data + into a character stream. The output is stored in a memory buffer that grows dynamically. You can use one of the following typedefs for common character types and the standard allocator: - +---------------+-----------------------------------------------+ - | Type | Definition | - +===============+===============================================+ - | MemoryWriter | BasicWriter> | - +---------------+-----------------------------------------------+ - | WMemoryWriter | BasicWriter> | - +---------------+-----------------------------------------------+ + +---------------+-----------------------------------------------------+ + | Type | Definition | + +===============+=====================================================+ + | MemoryWriter | BasicMemoryWriter> | + +---------------+-----------------------------------------------------+ + | WMemoryWriter | BasicMemoryWriter> | + +---------------+-----------------------------------------------------+ **Example**:: @@ -2174,6 +2187,55 @@ class BasicMemoryWriter : public BasicWriter { typedef BasicMemoryWriter MemoryWriter; typedef BasicMemoryWriter WMemoryWriter; +/** + \rst + This class template provides operations for formatting and writing data + into a fixed-size array. For writing into a dynamically growing buffer + use :class:`fmt::BasicMemoryWriter`. + + Any write method will throw std::runtime_error if the output doesn't fit + into the array. + + You can use one of the following typedefs for common character types: + + +--------------+---------------------------+ + | Type | Definition | + +==============+===========================+ + | ArrayWriter | BasicArrayWriter | + +--------------+---------------------------+ + | WArrayWriter | BasicArrayWriter | + +--------------+---------------------------+ + \endrst + */ +template +class BasicArrayWriter : public BasicWriter { + private: + internal::FixedBuffer buffer_; + + public: + /** + \rst + Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the + given size. + \endrst + */ + BasicArrayWriter(Char *array, std::size_t size) + : BasicWriter(buffer_), buffer_(array, size) {} + + /** + \rst + Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the + size known at compile time. + \endrst + */ + template + explicit BasicArrayWriter(Char (&array)[SIZE]) + : BasicWriter(buffer_), buffer_(array, SIZE) {} +}; + +typedef BasicArrayWriter ArrayWriter; +typedef BasicArrayWriter WArrayWriter; + // Formats a value. template void format(BasicFormatter &f, const Char *&format_str, const T &value) { diff --git a/test/format-test.cc b/test/format-test.cc index 0866213a..148526c2 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -461,6 +461,42 @@ TEST(WriterTest, WWriter) { EXPECT_EQ(L"cafe", (fmt::WMemoryWriter() << fmt::hex(0xcafe)).str()); } +TEST(ArrayWriterTest, Ctor) { + char array[10] = "garbage"; + fmt::ArrayWriter w(array, sizeof(array)); + EXPECT_EQ(0u, w.size()); + EXPECT_STREQ("", w.c_str()); +} + +TEST(ArrayWriterTest, CompileTimeSizeCtor) { + char array[10] = "garbage"; + fmt::ArrayWriter w(array); + EXPECT_EQ(0u, w.size()); + EXPECT_STREQ("", w.c_str()); + w.write("{:10}", 1); +} + +TEST(ArrayWriterTest, Write) { + char array[10]; + fmt::ArrayWriter w(array, sizeof(array)); + w.write("{}", 42); + EXPECT_EQ("42", w.str()); +} + +TEST(ArrayWriterTest, BufferOverflow) { + char array[10]; + fmt::ArrayWriter w(array, sizeof(array)); + w.write("{:10}", 1); + EXPECT_THROW_MSG(w.write("{}", 1), std::runtime_error, "buffer overflow"); +} + +TEST(ArrayWriterTest, WChar) { + wchar_t array[10]; + fmt::WArrayWriter w(array); + w.write(L"{}", 42); + EXPECT_EQ(L"42", w.str()); +} + TEST(FormatterTest, Escape) { EXPECT_EQ("{", format("{{")); EXPECT_EQ("before {", format("before {{"));