diff --git a/format.cc b/format.cc index 5f8a86e0..2a11fe86 100644 --- a/format.cc +++ b/format.cc @@ -42,6 +42,7 @@ #include using std::size_t; +using fmt::BasicFormatter; using fmt::Formatter; using fmt::FormatSpec; using fmt::StringRef; @@ -135,6 +136,22 @@ void FormatDecimal(char *buffer, uint64_t value, unsigned num_digits) { } } +void BasicFormatter::operator<<(int value) { + unsigned abs_value = value; + unsigned num_digits = 0; + char *out = 0; + if (value >= 0) { + num_digits = CountDigits(abs_value); + out = GrowBuffer(num_digits); + } else { + abs_value = 0 - abs_value; + num_digits = CountDigits(abs_value); + out = GrowBuffer(num_digits + 1); + *out++ = '-'; + } + FormatDecimal(out, abs_value, num_digits); +} + // Throws Exception(message) if format contains '}', otherwise throws // FormatError reporting unmatched '{'. The idea is that unmatched '{' // should override other errors. @@ -153,7 +170,7 @@ void Formatter::ReportError(const char *s, StringRef message) const { // Fills the padding around the content and returns the pointer to the // content area. char *FillPadding(char *buffer, - unsigned total_size, unsigned content_size, char fill) { + unsigned total_size, std::size_t content_size, char fill) { unsigned padding = total_size - content_size; unsigned left_padding = padding / 2; std::fill_n(buffer, left_padding, fill); @@ -634,19 +651,3 @@ void Formatter::DoFormat() { buffer_.append(start, s + 1); buffer_.resize(buffer_.size() - 1); // Don't count the terminating zero. } - -void Formatter::operator<<(int value) { - unsigned abs_value = value; - unsigned num_digits = 0; - char *out = 0; - if (value >= 0) { - num_digits = CountDigits(abs_value); - out = GrowBuffer(num_digits); - } else { - abs_value = 0 - abs_value; - num_digits = CountDigits(abs_value); - out = GrowBuffer(num_digits + 1); - *out++ = '-'; - } - FormatDecimal(out, abs_value, num_digits); -} diff --git a/format.h b/format.h index 96b45dac..8e3b7711 100644 --- a/format.h +++ b/format.h @@ -164,6 +164,23 @@ struct FormatSpec { FormatSpec() : align(ALIGN_DEFAULT), flags(0), width(0), type(0), fill(' ') {} }; +class BasicFormatter { + protected: + enum { INLINE_BUFFER_SIZE = 500 }; + internal::Array buffer_; // Output buffer. + + // Grows the buffer by n characters and returns a pointer to the newly + // allocated area. + char *GrowBuffer(std::size_t n) { + std::size_t size = buffer_.size(); + buffer_.resize(size + n); + return &buffer_[size]; + } + + public: + void operator<<(int value); +}; + // Formatter provides string formatting functionality similar to Python's // str.format. The output is stored in a memory buffer that grows dynamically. // Usage: @@ -178,11 +195,7 @@ struct FormatSpec { // (-3.140000, +3.140000) // // The buffer can be accessed using Formatter::data() or Formatter::c_str(). -class Formatter { - private: - enum { INLINE_BUFFER_SIZE = 500 }; - internal::Array buffer_; // Output buffer. - +class Formatter : public BasicFormatter { enum Type { // Numeric types should go first. INT, UINT, LONG, ULONG, DOUBLE, LONG_DOUBLE, @@ -328,14 +341,6 @@ class Formatter { DoFormat(); } - // Grows the buffer by n characters and returns a pointer to the newly - // allocated area. - char *GrowBuffer(std::size_t n) { - std::size_t size = buffer_.size(); - buffer_.resize(size + n); - return &buffer_[size]; - } - public: Formatter() : format_(0) { buffer_[0] = 0; } @@ -344,8 +349,6 @@ class Formatter { // using inserter operator<<. internal::ArgInserter operator()(const char *format); - void operator<<(int value); - std::size_t size() const { return buffer_.size(); } const char *data() const { return &buffer_[0]; }