Implement right alignment.

This commit is contained in:
Victor Zverovich
2012-12-22 17:53:13 -08:00
parent 231409f69a
commit 1b9c22c161
3 changed files with 55 additions and 42 deletions

View File

@ -119,15 +119,15 @@ char *Formatter::PrepareFilledBuffer(
*p = sign; *p = sign;
p += size; p += size;
std::fill(p, end, spec.fill); std::fill(p, end, spec.fill);
} else if (spec.align == ALIGN_NUMERIC) {
if (sign) {
*p++ = sign;
--size;
}
std::fill(p, end - size, spec.fill);
p = end;
} else { } else {
*(end - size) = sign; if (spec.align == ALIGN_NUMERIC) {
if (sign) {
*p++ = sign;
--size;
}
} else {
*(end - size) = sign;
}
std::fill(p, end - size, spec.fill); std::fill(p, end - size, spec.fill);
p = end; p = end;
} }
@ -270,6 +270,21 @@ void Formatter::FormatDouble(T value, const FormatSpec &spec, int precision) {
} }
} }
void Formatter::FormatString(
const char *s, std::size_t size, const FormatSpec &spec) {
char *out = 0;
if (spec.width > size) {
out = GrowBuffer(spec.width);
if (spec.align == ALIGN_RIGHT)
out = std::fill_n(out, spec.width - size, spec.fill);
else
std::fill_n(out + size, spec.width - size, spec.fill);
} else {
out = GrowBuffer(size);
}
std::copy(s, s + size, out);
}
// Parses an unsigned integer advancing s to the end of the parsed input. // Parses an unsigned integer advancing s to the end of the parsed input.
// This function assumes that the first character of s is a digit. // This function assumes that the first character of s is a digit.
unsigned Formatter::ParseUInt(const char *&s) const { unsigned Formatter::ParseUInt(const char *&s) const {
@ -455,10 +470,17 @@ void Formatter::DoFormat() {
case CHAR: { case CHAR: {
if (spec.type && spec.type != 'c') if (spec.type && spec.type != 'c')
ReportUnknownType(spec.type, "char"); ReportUnknownType(spec.type, "char");
char *out = GrowBuffer(std::max(spec.width, 1u)); char *out = 0;
*out++ = arg.int_value; if (spec.width > 1) {
if (spec.width > 1) out = GrowBuffer(spec.width);
std::fill_n(out, spec.width - 1, spec.fill); if (spec.align == ALIGN_RIGHT)
out = std::fill_n(out, spec.width - 1, spec.fill);
else
std::fill_n(out + 1, spec.width - 1, spec.fill);
} else {
out = GrowBuffer(1);
}
*out = arg.int_value;
break; break;
} }
case STRING: { case STRING: {
@ -472,10 +494,7 @@ void Formatter::DoFormat() {
if (*str) if (*str)
size = std::strlen(str); size = std::strlen(str);
} }
char *out = GrowBuffer(std::max<size_t>(spec.width, size)); FormatString(str, size, spec);
out = std::copy(str, str + size, out);
if (spec.width > size)
std::fill_n(out, spec.width - size, spec.fill);
break; break;
} }
case POINTER: case POINTER:
@ -498,10 +517,3 @@ void Formatter::DoFormat() {
buffer_.append(start, s + 1); buffer_.append(start, s + 1);
buffer_.resize(buffer_.size() - 1); // Don't count the terminating zero. buffer_.resize(buffer_.size() - 1); // Don't count the terminating zero.
} }
void Formatter::Write(const std::string &s, const FormatSpec &spec) {
char *out = GrowBuffer(std::max<std::size_t>(spec.width, s.size()));
std::copy(s.begin(), s.end(), out);
if (spec.width > s.size())
std::fill_n(out + s.size(), spec.width - s.size(), spec.fill);
}

View File

@ -281,6 +281,8 @@ class Formatter {
template <typename T> template <typename T>
void FormatDouble(T value, const FormatSpec &spec, int precision); void FormatDouble(T value, const FormatSpec &spec, int precision);
void FormatString(const char *s, std::size_t size, const FormatSpec &spec);
// Formats an argument of a custom type, such as a user-defined class. // Formats an argument of a custom type, such as a user-defined class.
template <typename T> template <typename T>
void FormatCustomArg(const void *arg, const FormatSpec &spec); void FormatCustomArg(const void *arg, const FormatSpec &spec);
@ -323,10 +325,6 @@ class Formatter {
const char *c_str() const { return &buffer_[0]; } const char *c_str() const { return &buffer_[0]; }
std::string str() const { return std::string(&buffer_[0], buffer_.size()); } std::string str() const { return std::string(&buffer_[0], buffer_.size()); }
// Writes a string to the output buffer padding with spaces if
// necessary to achieve the desired width.
void Write(const std::string &s, const FormatSpec &spec);
}; };
// A reference to a string. It can be constructed from a C string, // A reference to a string. It can be constructed from a C string,
@ -464,7 +462,7 @@ class ArgFormatter {
explicit ArgFormatter(Formatter &f) : formatter_(f) {} explicit ArgFormatter(Formatter &f) : formatter_(f) {}
void Write(const std::string &s, const FormatSpec &spec) { void Write(const std::string &s, const FormatSpec &spec) {
formatter_.Write(s, spec); formatter_.FormatString(s.data(), s.size(), spec);
} }
}; };

View File

@ -276,6 +276,23 @@ TEST(FormatterTest, LeftAlign) {
EXPECT_EQ("def ", str(Format("{0:<5}") << TestString("def"))); EXPECT_EQ("def ", str(Format("{0:<5}") << TestString("def")));
} }
TEST(FormatterTest, RightAlign) {
EXPECT_EQ(" 42", str(Format("{0:>4}") << 42));
EXPECT_EQ(" 42", str(Format("{0:>4o}") << 042));
EXPECT_EQ(" 42", str(Format("{0:>4x}") << 0x42));
EXPECT_EQ(" -42", str(Format("{0:>5}") << -42));
EXPECT_EQ(" 42", str(Format("{0:>5}") << 42u));
EXPECT_EQ(" -42", str(Format("{0:>5}") << -42l));
EXPECT_EQ(" 42", str(Format("{0:>5}") << 42ul));
EXPECT_EQ(" -42", str(Format("{0:>5}") << -42.0));
EXPECT_EQ(" -42", str(Format("{0:>5}") << -42.0l));
EXPECT_EQ(" c", str(Format("{0:>5}") << 'c'));
EXPECT_EQ(" abc", str(Format("{0:>5}") << "abc"));
EXPECT_EQ(" 0xface",
str(Format("{0:>8}") << reinterpret_cast<void*>(0xface)));
EXPECT_EQ(" def", str(Format("{0:>5}") << TestString("def")));
}
TEST(FormatterTest, Fill) { TEST(FormatterTest, Fill) {
EXPECT_EQ("**42", str(Format("{0:*>4}") << 42)); EXPECT_EQ("**42", str(Format("{0:*>4}") << 42));
EXPECT_EQ("**-42", str(Format("{0:*>5}") << -42)); EXPECT_EQ("**-42", str(Format("{0:*>5}") << -42));
@ -662,20 +679,6 @@ TEST(FormatterTest, FormatString) {
EXPECT_EQ("test", str(Format("{0}") << std::string("test"))); EXPECT_EQ("test", str(Format("{0}") << std::string("test")));
} }
TEST(FormatterTest, Write) {
Formatter format;
fmt::FormatSpec spec;
spec.width = 2;
format.Write("12", spec);
EXPECT_EQ("12", format.str());
spec.width = 4;
format.Write("34", spec);
EXPECT_EQ("1234 ", format.str());
spec.width = 0;
format.Write("56", spec);
EXPECT_EQ("1234 56", format.str());
}
TEST(ArgFormatterTest, Write) { TEST(ArgFormatterTest, Write) {
Formatter formatter; Formatter formatter;
fmt::ArgFormatter format(formatter); fmt::ArgFormatter format(formatter);