Implement string padding.

This commit is contained in:
Victor Zverovich
2013-12-31 09:43:32 -08:00
parent fb7b11ead0
commit 641df95491
3 changed files with 57 additions and 17 deletions

View File

@@ -583,22 +583,22 @@ void fmt::BasicFormatter<Char>::DoFormat() {
// Format argument. // Format argument.
switch (arg.type) { switch (arg.type) {
case INT: case INT:
writer.FormatInt(arg.int_value, spec); FormatInt(arg.int_value, spec);
break; break;
case UINT: case UINT:
writer.FormatInt(arg.uint_value, spec); FormatInt(arg.uint_value, spec);
break; break;
case LONG: case LONG:
writer.FormatInt(arg.long_value, spec); FormatInt(arg.long_value, spec);
break; break;
case ULONG: case ULONG:
writer.FormatInt(arg.ulong_value, spec); FormatInt(arg.ulong_value, spec);
break; break;
case LONG_LONG: case LONG_LONG:
writer.FormatInt(arg.long_long_value, spec); FormatInt(arg.long_long_value, spec);
break; break;
case ULONG_LONG: case ULONG_LONG:
writer.FormatInt(arg.ulong_long_value, spec); FormatInt(arg.ulong_long_value, spec);
break; break;
case DOUBLE: case DOUBLE:
writer.FormatDouble(arg.double_value, spec, precision); writer.FormatDouble(arg.double_value, spec, precision);
@@ -647,7 +647,7 @@ void fmt::BasicFormatter<Char>::DoFormat() {
internal::ReportUnknownType(spec.type_, "pointer"); internal::ReportUnknownType(spec.type_, "pointer");
spec.flags_= HASH_FLAG; spec.flags_= HASH_FLAG;
spec.type_ = 'x'; spec.type_ = 'x';
writer.FormatInt(reinterpret_cast<uintptr_t>(arg.pointer_value), spec); FormatInt(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
break; break;
case CUSTOM: case CUSTOM:
if (spec.type_) if (spec.type_)

View File

@@ -397,6 +397,18 @@ class IntFormatter : public SpecT {
T value() const { return value_; } T value() const { return value_; }
}; };
template <typename T>
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. Returns an integer formatter that formats the value in base 2.
*/ */
@@ -422,7 +434,7 @@ IntFormatter<int, TypeSpec<'X'> > hexu(int value);
/** /**
\rst \rst
Returns an integer formatter that pads the formatted argument with the fill 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**:: **Example**::
@@ -473,6 +485,23 @@ DEFINE_INT_FORMATTERS(unsigned long)
DEFINE_INT_FORMATTERS(long long) DEFINE_INT_FORMATTERS(long long)
DEFINE_INT_FORMATTERS(unsigned 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<char> pad(
const char *str, unsigned width, wchar_t fill = ' ') {
return StrFormatter<char>(str, AlignSpec(width, fill));
}
template <typename Char> template <typename Char>
class BasicFormatter; class BasicFormatter;
@@ -547,19 +576,13 @@ class BasicWriter {
CharPtr PrepareFilledBuffer(unsigned size, const AlignSpec &spec, char sign); CharPtr PrepareFilledBuffer(unsigned size, const AlignSpec &spec, char sign);
// Formats an integer.
template <typename T>
void FormatInt(T value, const FormatSpec &spec) {
*this << IntFormatter<T, FormatSpec>(value, spec);
}
// Formats a floating-point number (double or long double). // Formats a floating-point number (double or long double).
template <typename T> template <typename T>
void FormatDouble(T value, const FormatSpec &spec, int precision); void FormatDouble(T value, const FormatSpec &spec, int precision);
template <typename StringChar> template <typename StringChar>
CharPtr FormatString(const StringChar *s, CharPtr FormatString(
std::size_t size, const FormatSpec &spec); const StringChar *s, std::size_t size, const AlignSpec &spec);
// This method is private to disallow writing a wide string to a // 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 // char stream and vice versa. If you want to print a wide string
@@ -680,6 +703,13 @@ class BasicWriter {
template <typename T, typename Spec> template <typename T, typename Spec>
BasicWriter &operator<<(const IntFormatter<T, Spec> &f); BasicWriter &operator<<(const IntFormatter<T, Spec> &f);
template <typename T>
BasicWriter &operator<<(const StrFormatter<T> &f) {
const char *s = f.str();
FormatString(s, std::strlen(s), f);
return *this;
}
void Write(const std::basic_string<char> &s, const FormatSpec &spec) { void Write(const std::basic_string<char> &s, const FormatSpec &spec) {
FormatString(s.data(), s.size(), spec); FormatString(s.data(), s.size(), spec);
} }
@@ -692,7 +722,7 @@ class BasicWriter {
template <typename Char> template <typename Char>
template <typename StringChar> template <typename StringChar>
typename BasicWriter<Char>::CharPtr BasicWriter<Char>::FormatString( typename BasicWriter<Char>::CharPtr BasicWriter<Char>::FormatString(
const StringChar *s, std::size_t size, const FormatSpec &spec) { const StringChar *s, std::size_t size, const AlignSpec &spec) {
CharPtr out = CharPtr(); CharPtr out = CharPtr();
if (spec.width() > size) { if (spec.width() > size) {
out = GrowBuffer(spec.width()); out = GrowBuffer(spec.width());
@@ -987,6 +1017,12 @@ class BasicFormatter {
// writing the output to writer_. // writing the output to writer_.
void DoFormat(); void DoFormat();
// Formats an integer.
template <typename T>
void FormatInt(T value, const FormatSpec &spec) {
*writer_ << IntFormatter<T, FormatSpec>(value, spec);
}
struct Proxy { struct Proxy {
BasicWriter<Char> *writer; BasicWriter<Char> *writer;
const Char *format; const Char *format;

View File

@@ -442,6 +442,10 @@ TEST(WriterTest, pad) {
EXPECT_EQ("2012-01-09", f.str()); EXPECT_EQ("2012-01-09", f.str());
} }
TEST(WriterTest, PadString) {
EXPECT_EQ("test ", str(Writer() << pad("test", 8)));
}
TEST(WriterTest, NoConflictWithIOManip) { TEST(WriterTest, NoConflictWithIOManip) {
using namespace std; using namespace std;
using namespace fmt; using namespace fmt;