Commit 17ca8091 authored by Victor Zverovich's avatar Victor Zverovich

Implement space sign.

parent 0f46a3df
...@@ -54,7 +54,7 @@ using fmt::StringRef; ...@@ -54,7 +54,7 @@ using fmt::StringRef;
namespace { namespace {
// Flags. // 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) { void ReportUnknownType(char code, const char *type) {
if (std::isprint(static_cast<unsigned char>(code))) { if (std::isprint(static_cast<unsigned char>(code))) {
...@@ -129,7 +129,7 @@ void FormatDecimal(char *buffer, uint64_t value, unsigned num_digits) { ...@@ -129,7 +129,7 @@ void FormatDecimal(char *buffer, uint64_t value, unsigned num_digits) {
*buffer = static_cast<char>('0' + value); *buffer = static_cast<char>('0' + value);
return; return;
} }
unsigned index = value * 2; unsigned index = static_cast<unsigned>(value * 2);
buffer[1] = DIGITS[index + 1]; buffer[1] = DIGITS[index + 1];
buffer[0] = DIGITS[index]; buffer[0] = DIGITS[index];
} }
...@@ -205,8 +205,8 @@ void Formatter::FormatInt(T value, const FormatSpec &spec) { ...@@ -205,8 +205,8 @@ void Formatter::FormatInt(T value, const FormatSpec &spec) {
sign = '-'; sign = '-';
++size; ++size;
abs_value = 0 - abs_value; abs_value = 0 - abs_value;
} else if ((spec.flags & PLUS_FLAG) != 0) { } else if ((spec.flags & SIGN_FLAG) != 0) {
sign = '+'; sign = (spec.flags & PLUS_FLAG) != 0 ? '+' : ' ';
++size; ++size;
} }
switch (spec.type) { switch (spec.type) {
...@@ -280,8 +280,8 @@ void Formatter::FormatDouble(T value, const FormatSpec &spec, int precision) { ...@@ -280,8 +280,8 @@ void Formatter::FormatDouble(T value, const FormatSpec &spec, int precision) {
if (value < 0) { if (value < 0) {
sign = '-'; sign = '-';
value = -value; value = -value;
} else if ((spec.flags & PLUS_FLAG) != 0) { } else if ((spec.flags & SIGN_FLAG) != 0) {
sign = '+'; sign = (spec.flags & PLUS_FLAG) != 0 ? '+' : ' ';
} }
size_t offset = buffer_.size(); size_t offset = buffer_.size();
unsigned width = spec.width; unsigned width = spec.width;
...@@ -401,6 +401,18 @@ const Formatter::Arg &Formatter::ParseArgIndex(const char *&s) const { ...@@ -401,6 +401,18 @@ const Formatter::Arg &Formatter::ParseArgIndex(const char *&s) const {
return *args_[arg_index]; 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() { void Formatter::DoFormat() {
const char *start = format_; const char *start = format_;
format_ = 0; format_ = 0;
...@@ -462,18 +474,15 @@ void Formatter::DoFormat() { ...@@ -462,18 +474,15 @@ void Formatter::DoFormat() {
// Parse sign. // Parse sign.
switch (*s) { switch (*s) {
case '+': case '+':
spec.flags |= PLUS_FLAG; CheckSign(s, arg);
// Fall through. spec.flags |= SIGN_FLAG | PLUS_FLAG;
break;
case '-': case '-':
if (arg.type > LAST_NUMERIC_TYPE) { CheckSign(s, arg);
ReportError(s, break;
Format("format specifier '{0}' requires numeric argument") << *s); case ' ':
} CheckSign(s, arg);
if (arg.type == UINT || arg.type == ULONG) { spec.flags |= SIGN_FLAG;
ReportError(s,
Format("format specifier '{0}' requires signed argument") << *s);
}
++s;
break; break;
} }
......
...@@ -319,6 +319,8 @@ class Formatter { ...@@ -319,6 +319,8 @@ class Formatter {
// Parses argument index and returns an argument with this index. // Parses argument index and returns an argument with this index.
const Arg &ParseArgIndex(const char *&s) const; const Arg &ParseArgIndex(const char *&s) const;
void CheckSign(const char *&s, const Arg &arg);
void DoFormat(); void DoFormat();
void CompleteFormatting() { void CompleteFormatting() {
......
...@@ -402,6 +402,29 @@ TEST(FormatterTest, MinusSign) { ...@@ -402,6 +402,29 @@ TEST(FormatterTest, MinusSign) {
FormatError, "format specifier '-' requires numeric argument"); 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) { TEST(FormatterTest, ZeroFlag) {
EXPECT_EQ("42", str(Format("{0:0}") << 42)); EXPECT_EQ("42", str(Format("{0:0}") << 42));
EXPECT_EQ("-0042", str(Format("{0:05}") << -42)); EXPECT_EQ("-0042", str(Format("{0:05}") << -42));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment