Implement automatic argument indexing.
This commit is contained in:
parent
73f13eeb5b
commit
8412ad6aeb
@ -48,9 +48,9 @@ copyright = u'1990-2012, Python Software Foundation'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.1'
|
version = '0.2'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.1'
|
release = '0.2'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
31
format.cc
31
format.cc
@ -171,8 +171,8 @@ void Formatter::ReportError(const char *s, StringRef message) const {
|
|||||||
// content area.
|
// content area.
|
||||||
char *FillPadding(char *buffer,
|
char *FillPadding(char *buffer,
|
||||||
unsigned total_size, std::size_t content_size, char fill) {
|
unsigned total_size, std::size_t content_size, char fill) {
|
||||||
unsigned padding = total_size - content_size;
|
std::size_t padding = total_size - content_size;
|
||||||
unsigned left_padding = padding / 2;
|
std::size_t left_padding = padding / 2;
|
||||||
std::fill_n(buffer, left_padding, fill);
|
std::fill_n(buffer, left_padding, fill);
|
||||||
buffer += left_padding;
|
buffer += left_padding;
|
||||||
char *content = buffer;
|
char *content = buffer;
|
||||||
@ -415,12 +415,26 @@ unsigned Formatter::ParseUInt(const char *&s) const {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Formatter::Arg &Formatter::ParseArgIndex(const char *&s) const {
|
const Formatter::Arg &Formatter::ParseArgIndex(const char *&s) {
|
||||||
if (*s < '0' || *s > '9')
|
unsigned arg_index = 0;
|
||||||
ReportError(s, "missing argument index in format string");
|
if (*s < '0' || *s > '9') {
|
||||||
unsigned arg_index = ParseUInt(s);
|
if (*s != '}' && *s != ':')
|
||||||
if (arg_index >= args_.size())
|
ReportError(s, "invalid argument index in format string");
|
||||||
ReportError(s, "argument index is out of range in format");
|
if (next_arg_index_ < 0) {
|
||||||
|
ReportError(s,
|
||||||
|
"cannot switch from manual to automatic argument indexing");
|
||||||
|
}
|
||||||
|
arg_index = next_arg_index_++;
|
||||||
|
} else {
|
||||||
|
if (next_arg_index_ > 0) {
|
||||||
|
ReportError(s,
|
||||||
|
"cannot switch from automatic to manual argument indexing");
|
||||||
|
}
|
||||||
|
next_arg_index_ = -1;
|
||||||
|
arg_index = ParseUInt(s);
|
||||||
|
if (arg_index >= args_.size())
|
||||||
|
ReportError(s, "argument index is out of range in format");
|
||||||
|
}
|
||||||
return *args_[arg_index];
|
return *args_[arg_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,6 +453,7 @@ void Formatter::CheckSign(const char *&s, const Arg &arg) {
|
|||||||
void Formatter::DoFormat() {
|
void Formatter::DoFormat() {
|
||||||
const char *start = format_;
|
const char *start = format_;
|
||||||
format_ = 0;
|
format_ = 0;
|
||||||
|
next_arg_index_ = 0;
|
||||||
const char *s = start;
|
const char *s = start;
|
||||||
while (*s) {
|
while (*s) {
|
||||||
char c = *s++;
|
char c = *s++;
|
||||||
|
3
format.h
3
format.h
@ -301,6 +301,7 @@ class Formatter : public BasicFormatter {
|
|||||||
|
|
||||||
const char *format_; // Format string.
|
const char *format_; // Format string.
|
||||||
int num_open_braces_;
|
int num_open_braces_;
|
||||||
|
int next_arg_index_;
|
||||||
|
|
||||||
friend class internal::ArgInserter;
|
friend class internal::ArgInserter;
|
||||||
friend class ArgFormatter;
|
friend class ArgFormatter;
|
||||||
@ -330,7 +331,7 @@ class Formatter : public BasicFormatter {
|
|||||||
unsigned ParseUInt(const char *&s) const;
|
unsigned ParseUInt(const char *&s) const;
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
void CheckSign(const char *&s, const Arg &arg);
|
void CheckSign(const char *&s, const Arg &arg);
|
||||||
|
|
||||||
|
@ -235,8 +235,8 @@ TEST(FormatterTest, ArgsInDifferentPositions) {
|
|||||||
|
|
||||||
TEST(FormatterTest, ArgErrors) {
|
TEST(FormatterTest, ArgErrors) {
|
||||||
EXPECT_THROW_MSG(Format("{"), FormatError, "unmatched '{' in format");
|
EXPECT_THROW_MSG(Format("{"), FormatError, "unmatched '{' in format");
|
||||||
EXPECT_THROW_MSG(Format("{}"), FormatError,
|
EXPECT_THROW_MSG(Format("{x}"), FormatError,
|
||||||
"missing argument index in format string");
|
"invalid argument index in format string");
|
||||||
EXPECT_THROW_MSG(Format("{0"), FormatError, "unmatched '{' in format");
|
EXPECT_THROW_MSG(Format("{0"), FormatError, "unmatched '{' in format");
|
||||||
EXPECT_THROW_MSG(Format("{0}"), FormatError,
|
EXPECT_THROW_MSG(Format("{0}"), FormatError,
|
||||||
"argument index is out of range in format");
|
"argument index is out of range in format");
|
||||||
@ -257,6 +257,19 @@ TEST(FormatterTest, ArgErrors) {
|
|||||||
EXPECT_THROW_MSG(Format(format), FormatError, "number is too big in format");
|
EXPECT_THROW_MSG(Format(format), FormatError, "number is too big in format");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(FormatterTest, AutoArgIndex) {
|
||||||
|
EXPECT_EQ("abc", str(Format("{}{}{}") << 'a' << 'b' << 'c'));
|
||||||
|
EXPECT_THROW_MSG(Format("{0}{}") << 'a' << 'b',
|
||||||
|
FormatError, "cannot switch from manual to automatic argument indexing");
|
||||||
|
EXPECT_THROW_MSG(Format("{}{0}") << 'a' << 'b',
|
||||||
|
FormatError, "cannot switch from automatic to manual argument indexing");
|
||||||
|
EXPECT_EQ("1.2", str(Format("{:.{}}") << 1.2345 << 2));
|
||||||
|
EXPECT_THROW_MSG(Format("{0}:.{}") << 1.2345 << 2,
|
||||||
|
FormatError, "cannot switch from manual to automatic argument indexing");
|
||||||
|
EXPECT_THROW_MSG(Format("{:.{0}}") << 1.2345 << 2,
|
||||||
|
FormatError, "cannot switch from automatic to manual argument indexing");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, EmptySpecs) {
|
TEST(FormatterTest, EmptySpecs) {
|
||||||
EXPECT_EQ("42", str(Format("{0:}") << 42));
|
EXPECT_EQ("42", str(Format("{0:}") << 42));
|
||||||
}
|
}
|
||||||
@ -426,7 +439,6 @@ TEST(FormatterTest, SpaceSign) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, HashFlag) {
|
TEST(FormatterTest, HashFlag) {
|
||||||
// TODO
|
|
||||||
EXPECT_EQ("42", str(Format("{0:#}") << 42));
|
EXPECT_EQ("42", str(Format("{0:#}") << 42));
|
||||||
EXPECT_EQ("-42", str(Format("{0:#}") << -42));
|
EXPECT_EQ("-42", str(Format("{0:#}") << -42));
|
||||||
EXPECT_EQ("0x42", str(Format("{0:#x}") << 0x42));
|
EXPECT_EQ("0x42", str(Format("{0:#x}") << 0x42));
|
||||||
@ -589,8 +601,8 @@ TEST(FormatterTest, RuntimePrecision) {
|
|||||||
FormatError, "unmatched '{' in format");
|
FormatError, "unmatched '{' in format");
|
||||||
EXPECT_THROW_MSG(Format("{0:.{}") << 0,
|
EXPECT_THROW_MSG(Format("{0:.{}") << 0,
|
||||||
FormatError, "unmatched '{' in format");
|
FormatError, "unmatched '{' in format");
|
||||||
EXPECT_THROW_MSG(Format("{0:.{}}") << 0,
|
EXPECT_THROW_MSG(Format("{0:.{x}}") << 0,
|
||||||
FormatError, "missing argument index in format string");
|
FormatError, "invalid argument index in format string");
|
||||||
EXPECT_THROW_MSG(Format("{0:.{1}") << 0 << 0,
|
EXPECT_THROW_MSG(Format("{0:.{1}") << 0 << 0,
|
||||||
FormatError, "unmatched '{' in format");
|
FormatError, "unmatched '{' in format");
|
||||||
EXPECT_THROW_MSG(Format("{0:.{1}}") << 0,
|
EXPECT_THROW_MSG(Format("{0:.{1}}") << 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user