mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-26 21:35:42 +00:00
Implement center alignment.
This commit is contained in:
parent
4d1ee0bb5b
commit
84310c3a84
56
format.cc
56
format.cc
@ -121,6 +121,19 @@ void Formatter::ReportError(const char *s, const std::string &message) const {
|
|||||||
throw fmt::FormatError("unmatched '{' in format");
|
throw fmt::FormatError("unmatched '{' in format");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 padding = total_size - content_size;
|
||||||
|
unsigned left_padding = padding / 2;
|
||||||
|
std::fill_n(buffer, left_padding, fill);
|
||||||
|
buffer += left_padding;
|
||||||
|
char *content = buffer;
|
||||||
|
std::fill_n(buffer + content_size, padding - left_padding, fill);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
char *Formatter::PrepareFilledBuffer(
|
char *Formatter::PrepareFilledBuffer(
|
||||||
unsigned size, const FormatSpec &spec, char sign) {
|
unsigned size, const FormatSpec &spec, char sign) {
|
||||||
if (spec.width <= size) {
|
if (spec.width <= size) {
|
||||||
@ -130,7 +143,15 @@ char *Formatter::PrepareFilledBuffer(
|
|||||||
}
|
}
|
||||||
char *p = GrowBuffer(spec.width);
|
char *p = GrowBuffer(spec.width);
|
||||||
char *end = p + spec.width;
|
char *end = p + spec.width;
|
||||||
if (spec.align != ALIGN_LEFT) {
|
if (spec.align == ALIGN_LEFT) {
|
||||||
|
*p = sign;
|
||||||
|
p += size;
|
||||||
|
std::fill(p, end, spec.fill);
|
||||||
|
} else if (spec.align == ALIGN_CENTER) {
|
||||||
|
p = FillPadding(p, spec.width, size, spec.fill);
|
||||||
|
*p = sign;
|
||||||
|
p += size;
|
||||||
|
} else {
|
||||||
if (spec.align == ALIGN_NUMERIC) {
|
if (spec.align == ALIGN_NUMERIC) {
|
||||||
if (sign) {
|
if (sign) {
|
||||||
*p++ = sign;
|
*p++ = sign;
|
||||||
@ -141,10 +162,6 @@ char *Formatter::PrepareFilledBuffer(
|
|||||||
}
|
}
|
||||||
std::fill(p, end - size, spec.fill);
|
std::fill(p, end - size, spec.fill);
|
||||||
p = end;
|
p = end;
|
||||||
} else {
|
|
||||||
*p = sign;
|
|
||||||
p += size;
|
|
||||||
std::fill(p, end, spec.fill);
|
|
||||||
}
|
}
|
||||||
return p - 1;
|
return p - 1;
|
||||||
}
|
}
|
||||||
@ -256,10 +273,15 @@ void Formatter::FormatDouble(T value, const FormatSpec &spec, int precision) {
|
|||||||
char format[MAX_FORMAT_SIZE];
|
char format[MAX_FORMAT_SIZE];
|
||||||
char *format_ptr = format;
|
char *format_ptr = format;
|
||||||
*format_ptr++ = '%';
|
*format_ptr++ = '%';
|
||||||
if (spec.align == ALIGN_LEFT)
|
unsigned width_for_sprintf = width;
|
||||||
*format_ptr++ = '-';
|
if (spec.align == ALIGN_CENTER) {
|
||||||
if (width != 0)
|
width_for_sprintf = 0;
|
||||||
*format_ptr++ = '*';
|
} else {
|
||||||
|
if (spec.align == ALIGN_LEFT)
|
||||||
|
*format_ptr++ = '-';
|
||||||
|
if (width != 0)
|
||||||
|
*format_ptr++ = '*';
|
||||||
|
}
|
||||||
if (precision >= 0) {
|
if (precision >= 0) {
|
||||||
*format_ptr++ = '.';
|
*format_ptr++ = '.';
|
||||||
*format_ptr++ = '*';
|
*format_ptr++ = '*';
|
||||||
@ -274,14 +296,14 @@ void Formatter::FormatDouble(T value, const FormatSpec &spec, int precision) {
|
|||||||
size_t size = buffer_.capacity() - offset;
|
size_t size = buffer_.capacity() - offset;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
char *start = &buffer_[offset];
|
char *start = &buffer_[offset];
|
||||||
if (width == 0) {
|
if (width_for_sprintf == 0) {
|
||||||
n = precision < 0 ?
|
n = precision < 0 ?
|
||||||
snprintf(start, size, format, value) :
|
snprintf(start, size, format, value) :
|
||||||
snprintf(start, size, format, precision, value);
|
snprintf(start, size, format, precision, value);
|
||||||
} else {
|
} else {
|
||||||
n = precision < 0 ?
|
n = precision < 0 ?
|
||||||
snprintf(start, size, format, width, value) :
|
snprintf(start, size, format, width_for_sprintf, value) :
|
||||||
snprintf(start, size, format, width, precision, value);
|
snprintf(start, size, format, width_for_sprintf, precision, value);
|
||||||
}
|
}
|
||||||
if (n >= 0 && offset + n < buffer_.capacity()) {
|
if (n >= 0 && offset + n < buffer_.capacity()) {
|
||||||
if (sign) {
|
if (sign) {
|
||||||
@ -294,6 +316,12 @@ void Formatter::FormatDouble(T value, const FormatSpec &spec, int precision) {
|
|||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
|
if (spec.align == ALIGN_CENTER && spec.width > static_cast<unsigned>(n)) {
|
||||||
|
char *p = GrowBuffer(spec.width);
|
||||||
|
std::copy(p, p + n, p + (spec.width - n) / 2);
|
||||||
|
FillPadding(p, spec.width, n, spec.fill);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (spec.fill != ' ' || sign) {
|
if (spec.fill != ' ' || sign) {
|
||||||
while (*start == ' ')
|
while (*start == ' ')
|
||||||
*start++ = spec.fill;
|
*start++ = spec.fill;
|
||||||
@ -315,6 +343,8 @@ void Formatter::FormatString(
|
|||||||
if (spec.align == ALIGN_RIGHT) {
|
if (spec.align == ALIGN_RIGHT) {
|
||||||
std::fill_n(out, spec.width - size, spec.fill);
|
std::fill_n(out, spec.width - size, spec.fill);
|
||||||
out += spec.width - size;
|
out += spec.width - size;
|
||||||
|
} else if (spec.align == ALIGN_CENTER) {
|
||||||
|
out = FillPadding(out, spec.width, size, spec.fill);
|
||||||
} else {
|
} else {
|
||||||
std::fill_n(out + size, spec.width - size, spec.fill);
|
std::fill_n(out + size, spec.width - size, spec.fill);
|
||||||
}
|
}
|
||||||
@ -520,6 +550,8 @@ void Formatter::DoFormat() {
|
|||||||
if (spec.align == ALIGN_RIGHT) {
|
if (spec.align == ALIGN_RIGHT) {
|
||||||
std::fill_n(out, spec.width - 1, spec.fill);
|
std::fill_n(out, spec.width - 1, spec.fill);
|
||||||
out += spec.width - 1;
|
out += spec.width - 1;
|
||||||
|
} else if (spec.align == ALIGN_CENTER) {
|
||||||
|
out = FillPadding(out, spec.width, 1, spec.fill);
|
||||||
} else {
|
} else {
|
||||||
std::fill_n(out + 1, spec.width - 1, spec.fill);
|
std::fill_n(out + 1, spec.width - 1, spec.fill);
|
||||||
}
|
}
|
||||||
|
@ -320,6 +320,23 @@ TEST(FormatterTest, NumericAlign) {
|
|||||||
FormatError, "format specifier '=' requires numeric argument");
|
FormatError, "format specifier '=' requires numeric argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(FormatterTest, CenterAlign) {
|
||||||
|
EXPECT_EQ(" 42 ", str(Format("{0:^5}") << 42));
|
||||||
|
EXPECT_EQ(" 42 ", str(Format("{0:^5o}") << 042));
|
||||||
|
EXPECT_EQ(" 42 ", str(Format("{0:^5x}") << 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:^6}") << -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:^6}") << "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_THROW_MSG(Format("{0:{<5}") << 'c',
|
EXPECT_THROW_MSG(Format("{0:{<5}") << 'c',
|
||||||
FormatError, "unmatched '{' in format");
|
FormatError, "unmatched '{' in format");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user