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 += size;
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 {
*(end - size) = sign;
if (spec.align == ALIGN_NUMERIC) {
if (sign) {
*p++ = sign;
--size;
}
} else {
*(end - size) = sign;
}
std::fill(p, end - size, spec.fill);
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.
// This function assumes that the first character of s is a digit.
unsigned Formatter::ParseUInt(const char *&s) const {
@ -455,10 +470,17 @@ void Formatter::DoFormat() {
case CHAR: {
if (spec.type && spec.type != 'c')
ReportUnknownType(spec.type, "char");
char *out = GrowBuffer(std::max(spec.width, 1u));
*out++ = arg.int_value;
if (spec.width > 1)
std::fill_n(out, spec.width - 1, spec.fill);
char *out = 0;
if (spec.width > 1) {
out = GrowBuffer(spec.width);
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;
}
case STRING: {
@ -472,10 +494,7 @@ void Formatter::DoFormat() {
if (*str)
size = std::strlen(str);
}
char *out = GrowBuffer(std::max<size_t>(spec.width, size));
out = std::copy(str, str + size, out);
if (spec.width > size)
std::fill_n(out, spec.width - size, spec.fill);
FormatString(str, size, spec);
break;
}
case POINTER:
@ -498,10 +517,3 @@ void Formatter::DoFormat() {
buffer_.append(start, s + 1);
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>
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.
template <typename T>
void FormatCustomArg(const void *arg, const FormatSpec &spec);
@ -323,10 +325,6 @@ class Formatter {
const char *c_str() const { return &buffer_[0]; }
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,
@ -464,7 +462,7 @@ class ArgFormatter {
explicit ArgFormatter(Formatter &f) : formatter_(f) {}
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")));
}
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) {
EXPECT_EQ("**42", str(Format("{0:*>4}") << 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")));
}
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) {
Formatter formatter;
fmt::ArgFormatter format(formatter);