Implement minus flag.
This commit is contained in:
parent
d96337914f
commit
0a138ad865
20
format.cc
20
format.cc
@ -137,7 +137,7 @@ void FormatDecimal(char *buffer, uint64_t value, unsigned num_digits) {
|
||||
// Throws Exception(message) if format contains '}', otherwise throws
|
||||
// FormatError reporting unmatched '{'. The idea is that unmatched '{'
|
||||
// should override other errors.
|
||||
void Formatter::ReportError(const char *s, const std::string &message) const {
|
||||
void Formatter::ReportError(const char *s, StringRef message) const {
|
||||
for (int num_open_braces = num_open_braces_; *s; ++s) {
|
||||
if (*s == '{') {
|
||||
++num_open_braces;
|
||||
@ -459,15 +459,21 @@ void Formatter::DoFormat() {
|
||||
}
|
||||
|
||||
// Parse sign.
|
||||
if (*s == '+') {
|
||||
++s;
|
||||
if (arg.type > LAST_NUMERIC_TYPE)
|
||||
ReportError(s, "format specifier '+' requires numeric argument");
|
||||
switch (*s) {
|
||||
case '+':
|
||||
spec.flags |= PLUS_FLAG;
|
||||
// Fall through.
|
||||
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 specifier '+' requires signed argument");
|
||||
Format("format specifier '{0}' requires signed argument") << *s);
|
||||
}
|
||||
spec.flags |= PLUS_FLAG;
|
||||
++s;
|
||||
break;
|
||||
}
|
||||
|
||||
// Parse width and zero flag.
|
||||
|
56
format.h
56
format.h
@ -117,6 +117,33 @@ void Array<T, SIZE>::append(const T *begin, const T *end) {
|
||||
class ArgInserter;
|
||||
}
|
||||
|
||||
// A reference to a string. It can be constructed from a C string,
|
||||
// std::string or as a result of a formatting operation. It is most useful
|
||||
// as a parameter type to allow passing different types of strings in a
|
||||
// function, for example:
|
||||
// void SetName(StringRef s) {
|
||||
// std::string name = s;
|
||||
// ...
|
||||
// }
|
||||
class StringRef {
|
||||
private:
|
||||
const char *data_;
|
||||
mutable std::size_t size_;
|
||||
|
||||
public:
|
||||
StringRef(const char *s, std::size_t size = 0) : data_(s), size_(size) {}
|
||||
StringRef(const std::string &s) : data_(s.c_str()), size_(s.size()) {}
|
||||
|
||||
operator std::string() const { return std::string(data_, size()); }
|
||||
|
||||
const char *c_str() const { return data_; }
|
||||
|
||||
std::size_t size() const {
|
||||
if (size_ == 0) size_ = std::strlen(data_);
|
||||
return size_;
|
||||
}
|
||||
};
|
||||
|
||||
class FormatError : public std::runtime_error {
|
||||
public:
|
||||
explicit FormatError(const std::string &message)
|
||||
@ -269,7 +296,7 @@ class Formatter {
|
||||
args_.push_back(&arg);
|
||||
}
|
||||
|
||||
void ReportError(const char *s, const std::string &message) const;
|
||||
void ReportError(const char *s, StringRef message) const;
|
||||
|
||||
char *PrepareFilledBuffer(unsigned size, const FormatSpec &spec, char sign);
|
||||
|
||||
@ -325,33 +352,6 @@ class Formatter {
|
||||
std::string str() const { return std::string(&buffer_[0], buffer_.size()); }
|
||||
};
|
||||
|
||||
// A reference to a string. It can be constructed from a C string,
|
||||
// std::string or as a result of a formatting operation. It is most useful
|
||||
// as a parameter type to allow passing different types of strings in a
|
||||
// function, for example:
|
||||
// void SetName(StringRef s) {
|
||||
// std::string name = s;
|
||||
// ...
|
||||
// }
|
||||
class StringRef {
|
||||
private:
|
||||
const char *data_;
|
||||
mutable std::size_t size_;
|
||||
|
||||
public:
|
||||
StringRef(const char *s, std::size_t size = 0) : data_(s), size_(size) {}
|
||||
StringRef(const std::string &s) : data_(s.c_str()), size_(s.size()) {}
|
||||
|
||||
operator std::string() const { return std::string(data_, size()); }
|
||||
|
||||
const char *c_str() const { return data_; }
|
||||
|
||||
std::size_t size() const {
|
||||
if (size_ == 0) size_ = std::strlen(data_);
|
||||
return size_;
|
||||
}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// This is a transient object that normally exists only as a temporary
|
||||
|
@ -356,7 +356,7 @@ TEST(FormatterTest, Fill) {
|
||||
EXPECT_EQ("def**", str(Format("{0:*<5}") << TestString("def")));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, PlusFlag) {
|
||||
TEST(FormatterTest, PlusSign) {
|
||||
EXPECT_EQ("+42", str(Format("{0:+}") << 42));
|
||||
EXPECT_EQ("-42", str(Format("{0:+}") << -42));
|
||||
EXPECT_EQ("+42", str(Format("{0:+}") << 42));
|
||||
@ -379,6 +379,29 @@ TEST(FormatterTest, PlusFlag) {
|
||||
FormatError, "format specifier '+' requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, MinusSign) {
|
||||
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