From 641df9549131493fcf31df40d00f2864c1bc87b4 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Tue, 31 Dec 2013 09:43:32 -0800 Subject: [PATCH] Implement string padding. --- format.cc | 14 ++++++------- format.h | 56 +++++++++++++++++++++++++++++++++++++++++--------- format_test.cc | 4 ++++ 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/format.cc b/format.cc index 497ff56e..25bb1925 100644 --- a/format.cc +++ b/format.cc @@ -583,22 +583,22 @@ void fmt::BasicFormatter::DoFormat() { // Format argument. switch (arg.type) { case INT: - writer.FormatInt(arg.int_value, spec); + FormatInt(arg.int_value, spec); break; case UINT: - writer.FormatInt(arg.uint_value, spec); + FormatInt(arg.uint_value, spec); break; case LONG: - writer.FormatInt(arg.long_value, spec); + FormatInt(arg.long_value, spec); break; case ULONG: - writer.FormatInt(arg.ulong_value, spec); + FormatInt(arg.ulong_value, spec); break; case LONG_LONG: - writer.FormatInt(arg.long_long_value, spec); + FormatInt(arg.long_long_value, spec); break; case ULONG_LONG: - writer.FormatInt(arg.ulong_long_value, spec); + FormatInt(arg.ulong_long_value, spec); break; case DOUBLE: writer.FormatDouble(arg.double_value, spec, precision); @@ -647,7 +647,7 @@ void fmt::BasicFormatter::DoFormat() { internal::ReportUnknownType(spec.type_, "pointer"); spec.flags_= HASH_FLAG; spec.type_ = 'x'; - writer.FormatInt(reinterpret_cast(arg.pointer_value), spec); + FormatInt(reinterpret_cast(arg.pointer_value), spec); break; case CUSTOM: if (spec.type_) diff --git a/format.h b/format.h index f03e959d..e3e27197 100644 --- a/format.h +++ b/format.h @@ -397,6 +397,18 @@ class IntFormatter : public SpecT { T value() const { return value_; } }; +template +class StrFormatter : public AlignSpec { + private: + const T *str_; + + public: + StrFormatter(const T *str, const AlignSpec &spec = AlignSpec()) + : AlignSpec(spec), str_(str) {} + + const T *str() const { return str_; } +}; + /** Returns an integer formatter that formats the value in base 2. */ @@ -422,7 +434,7 @@ IntFormatter > hexu(int value); /** \rst Returns an integer formatter that pads the formatted argument with the fill - character to the specified width using the default (right) alignment. + character to the specified width using the default (right) numeric alignment. **Example**:: @@ -473,6 +485,23 @@ DEFINE_INT_FORMATTERS(unsigned long) DEFINE_INT_FORMATTERS(long long) DEFINE_INT_FORMATTERS(unsigned long long) +/** + \rst + Returns a string formatter that pads the formatted argument with the fill + character to the specified width using the default (left) string alignment. + + **Example**:: + + std::string s = str(Writer() << pad("abc", 8)); + // s == "abc " + + \endrst + */ +inline StrFormatter pad( + const char *str, unsigned width, wchar_t fill = ' ') { + return StrFormatter(str, AlignSpec(width, fill)); +} + template class BasicFormatter; @@ -547,19 +576,13 @@ class BasicWriter { CharPtr PrepareFilledBuffer(unsigned size, const AlignSpec &spec, char sign); - // Formats an integer. - template - void FormatInt(T value, const FormatSpec &spec) { - *this << IntFormatter(value, spec); - } - // Formats a floating-point number (double or long double). template void FormatDouble(T value, const FormatSpec &spec, int precision); template - CharPtr FormatString(const StringChar *s, - std::size_t size, const FormatSpec &spec); + CharPtr FormatString( + const StringChar *s, std::size_t size, const AlignSpec &spec); // This method is private to disallow writing a wide string to a // char stream and vice versa. If you want to print a wide string @@ -680,6 +703,13 @@ class BasicWriter { template BasicWriter &operator<<(const IntFormatter &f); + template + BasicWriter &operator<<(const StrFormatter &f) { + const char *s = f.str(); + FormatString(s, std::strlen(s), f); + return *this; + } + void Write(const std::basic_string &s, const FormatSpec &spec) { FormatString(s.data(), s.size(), spec); } @@ -692,7 +722,7 @@ class BasicWriter { template template typename BasicWriter::CharPtr BasicWriter::FormatString( - const StringChar *s, std::size_t size, const FormatSpec &spec) { + const StringChar *s, std::size_t size, const AlignSpec &spec) { CharPtr out = CharPtr(); if (spec.width() > size) { out = GrowBuffer(spec.width()); @@ -987,6 +1017,12 @@ class BasicFormatter { // writing the output to writer_. void DoFormat(); + // Formats an integer. + template + void FormatInt(T value, const FormatSpec &spec) { + *writer_ << IntFormatter(value, spec); + } + struct Proxy { BasicWriter *writer; const Char *format; diff --git a/format_test.cc b/format_test.cc index 016687e1..9c9b05d8 100644 --- a/format_test.cc +++ b/format_test.cc @@ -442,6 +442,10 @@ TEST(WriterTest, pad) { EXPECT_EQ("2012-01-09", f.str()); } +TEST(WriterTest, PadString) { + EXPECT_EQ("test ", str(Writer() << pad("test", 8))); +} + TEST(WriterTest, NoConflictWithIOManip) { using namespace std; using namespace fmt;