Implement space sign.
This commit is contained in:
parent
0f46a3df6a
commit
17ca809135
43
format.cc
43
format.cc
@ -54,7 +54,7 @@ using fmt::StringRef;
|
||||
namespace {
|
||||
|
||||
// Flags.
|
||||
enum { PLUS_FLAG = 1, HEX_PREFIX_FLAG = 2 };
|
||||
enum { SIGN_FLAG = 1, PLUS_FLAG = 2, HEX_PREFIX_FLAG = 4 };
|
||||
|
||||
void ReportUnknownType(char code, const char *type) {
|
||||
if (std::isprint(static_cast<unsigned char>(code))) {
|
||||
@ -129,7 +129,7 @@ void FormatDecimal(char *buffer, uint64_t value, unsigned num_digits) {
|
||||
*buffer = static_cast<char>('0' + value);
|
||||
return;
|
||||
}
|
||||
unsigned index = value * 2;
|
||||
unsigned index = static_cast<unsigned>(value * 2);
|
||||
buffer[1] = DIGITS[index + 1];
|
||||
buffer[0] = DIGITS[index];
|
||||
}
|
||||
@ -205,8 +205,8 @@ void Formatter::FormatInt(T value, const FormatSpec &spec) {
|
||||
sign = '-';
|
||||
++size;
|
||||
abs_value = 0 - abs_value;
|
||||
} else if ((spec.flags & PLUS_FLAG) != 0) {
|
||||
sign = '+';
|
||||
} else if ((spec.flags & SIGN_FLAG) != 0) {
|
||||
sign = (spec.flags & PLUS_FLAG) != 0 ? '+' : ' ';
|
||||
++size;
|
||||
}
|
||||
switch (spec.type) {
|
||||
@ -280,8 +280,8 @@ void Formatter::FormatDouble(T value, const FormatSpec &spec, int precision) {
|
||||
if (value < 0) {
|
||||
sign = '-';
|
||||
value = -value;
|
||||
} else if ((spec.flags & PLUS_FLAG) != 0) {
|
||||
sign = '+';
|
||||
} else if ((spec.flags & SIGN_FLAG) != 0) {
|
||||
sign = (spec.flags & PLUS_FLAG) != 0 ? '+' : ' ';
|
||||
}
|
||||
size_t offset = buffer_.size();
|
||||
unsigned width = spec.width;
|
||||
@ -401,6 +401,18 @@ const Formatter::Arg &Formatter::ParseArgIndex(const char *&s) const {
|
||||
return *args_[arg_index];
|
||||
}
|
||||
|
||||
void Formatter::CheckSign(const char *&s, const Arg &arg) {
|
||||
if (arg.type > LAST_NUMERIC_TYPE) {
|
||||
ReportError(s,
|
||||
Format("format specifier '{0}' requires numeric argument") << *s);
|
||||
}
|
||||
if (arg.type == UINT || arg.type == ULONG) {
|
||||
ReportError(s,
|
||||
Format("format specifier '{0}' requires signed argument") << *s);
|
||||
}
|
||||
++s;
|
||||
}
|
||||
|
||||
void Formatter::DoFormat() {
|
||||
const char *start = format_;
|
||||
format_ = 0;
|
||||
@ -462,18 +474,15 @@ void Formatter::DoFormat() {
|
||||
// Parse sign.
|
||||
switch (*s) {
|
||||
case '+':
|
||||
spec.flags |= PLUS_FLAG;
|
||||
// Fall through.
|
||||
CheckSign(s, arg);
|
||||
spec.flags |= SIGN_FLAG | PLUS_FLAG;
|
||||
break;
|
||||
case '-':
|
||||
if (arg.type > LAST_NUMERIC_TYPE) {
|
||||
ReportError(s,
|
||||
Format("format specifier '{0}' requires numeric argument") << *s);
|
||||
}
|
||||
if (arg.type == UINT || arg.type == ULONG) {
|
||||
ReportError(s,
|
||||
Format("format specifier '{0}' requires signed argument") << *s);
|
||||
}
|
||||
++s;
|
||||
CheckSign(s, arg);
|
||||
break;
|
||||
case ' ':
|
||||
CheckSign(s, arg);
|
||||
spec.flags |= SIGN_FLAG;
|
||||
break;
|
||||
}
|
||||
|
||||
|
2
format.h
2
format.h
@ -319,6 +319,8 @@ class Formatter {
|
||||
// Parses argument index and returns an argument with this index.
|
||||
const Arg &ParseArgIndex(const char *&s) const;
|
||||
|
||||
void CheckSign(const char *&s, const Arg &arg);
|
||||
|
||||
void DoFormat();
|
||||
|
||||
void CompleteFormatting() {
|
||||
|
@ -402,6 +402,29 @@ TEST(FormatterTest, MinusSign) {
|
||||
FormatError, "format specifier '-' requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, SpaceSign) {
|
||||
EXPECT_EQ(" 42", str(Format("{0: }") << 42));
|
||||
EXPECT_EQ("-42", str(Format("{0: }") << -42));
|
||||
EXPECT_EQ(" 42", str(Format("{0: }") << 42));
|
||||
EXPECT_THROW_MSG(Format("{0: }") << 42u,
|
||||
FormatError, "format specifier ' ' requires signed argument");
|
||||
EXPECT_EQ(" 42", str(Format("{0: }") << 42l));
|
||||
EXPECT_THROW_MSG(Format("{0: }") << 42ul,
|
||||
FormatError, "format specifier ' ' requires signed argument");
|
||||
EXPECT_EQ(" 42", str(Format("{0: }") << 42.0));
|
||||
EXPECT_EQ(" 42", str(Format("{0: }") << 42.0l));
|
||||
EXPECT_THROW_MSG(Format("{0: ") << 'c',
|
||||
FormatError, "unmatched '{' in format");
|
||||
EXPECT_THROW_MSG(Format("{0: }") << 'c',
|
||||
FormatError, "format specifier ' ' requires numeric argument");
|
||||
EXPECT_THROW_MSG(Format("{0: }") << "abc",
|
||||
FormatError, "format specifier ' ' requires numeric argument");
|
||||
EXPECT_THROW_MSG(Format("{0: }") << reinterpret_cast<void*>(0x42),
|
||||
FormatError, "format specifier ' ' requires numeric argument");
|
||||
EXPECT_THROW_MSG(Format("{0: }") << TestString(),
|
||||
FormatError, "format specifier ' ' requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, ZeroFlag) {
|
||||
EXPECT_EQ("42", str(Format("{0:0}") << 42));
|
||||
EXPECT_EQ("-0042", str(Format("{0:05}") << -42));
|
||||
|
Loading…
Reference in New Issue
Block a user