Merge ArgInserter into TempFormatter and replace BasicFormatter::operator() with BasicWriter::Format.

This commit is contained in:
Victor Zverovich
2013-09-03 18:58:13 -07:00
parent 6829819b8d
commit 50cf5e17a7
2 changed files with 77 additions and 118 deletions

163
format.h
View File

@@ -227,9 +227,6 @@ inline unsigned CountDigits(uint64_t n) {
} }
} }
template <typename Char>
class ArgInserter;
template <typename Char> template <typename Char>
class FormatterProxy; class FormatterProxy;
} }
@@ -435,6 +432,22 @@ DEFINE_INT_FORMATTERS(long)
DEFINE_INT_FORMATTERS(unsigned) DEFINE_INT_FORMATTERS(unsigned)
DEFINE_INT_FORMATTERS(unsigned long) DEFINE_INT_FORMATTERS(unsigned long)
template <typename Action>
class BasicFormatter;
template <typename Action, typename Char>
class TempFormatter;
/**
A formatting action that does nothing.
*/
class NoAction {
public:
/** Does nothing. */
template <typename Char>
void operator()(const BasicFormatter<Char> &) const {}
};
template <typename Char> template <typename Char>
class BasicWriter { class BasicWriter {
protected: protected:
@@ -545,6 +558,15 @@ private:
FormatString(s.data(), s.size(), spec); FormatString(s.data(), s.size(), spec);
} }
/**
Formats a string appending the output to the internal buffer.
Arguments are accepted through the returned `TempFormatter` object
using inserter operator `<<`.
*/
TempFormatter<NoAction, Char> Format(StringRef format) {
return TempFormatter<NoAction, Char>(format);
}
void Clear() { void Clear() {
buffer_.clear(); buffer_.clear();
} }
@@ -1004,7 +1026,7 @@ class BasicFormatter : public BasicWriter<Char> {
// constructed before the Arg object, it will be destroyed after, // constructed before the Arg object, it will be destroyed after,
// so it will be alive in the Arg's destructor where Format is called. // so it will be alive in the Arg's destructor where Format is called.
// Note that the string object will not necessarily be alive when // Note that the string object will not necessarily be alive when
// the destructor of ArgInserter is called. // the destructor of TempFormatter is called.
if (formatter) if (formatter)
formatter->CompleteFormatting(); formatter->CompleteFormatting();
} }
@@ -1017,7 +1039,9 @@ class BasicFormatter : public BasicWriter<Char> {
int num_open_braces_; int num_open_braces_;
int next_arg_index_; int next_arg_index_;
friend class internal::ArgInserter<Char>; template <typename Action, typename CharT>
friend class TempFormatter; // TODO
friend class internal::FormatterProxy<Char>; friend class internal::FormatterProxy<Char>;
void Add(const Arg &arg) { void Add(const Arg &arg) {
@@ -1044,14 +1068,7 @@ class BasicFormatter : public BasicWriter<Char> {
/** /**
Constructs a formatter with an empty output buffer. Constructs a formatter with an empty output buffer.
*/ */
BasicFormatter() : format_(0) {} BasicFormatter(const Char *format = 0) : format_(format) {}
/**
Formats a string appending the output to the internal buffer.
Arguments are accepted through the returned `ArgInserter` object
using inserter operator `<<`.
*/
internal::ArgInserter<Char> operator()(StringRef format);
}; };
typedef BasicFormatter<char> Formatter; typedef BasicFormatter<char> Formatter;
@@ -1093,66 +1110,6 @@ class FormatterProxy {
// formatter. // formatter.
template <typename Char> template <typename Char>
class ArgInserter { class ArgInserter {
private:
mutable BasicFormatter<Char> *formatter_;
friend class fmt::BasicFormatter<Char>;
friend class fmt::StringRef;
// Do not implement.
void operator=(const ArgInserter& other);
protected:
explicit ArgInserter(BasicFormatter<Char> *f = 0) : formatter_(f) {}
void Init(BasicFormatter<Char> &f, const char *format) {
const ArgInserter &other = f(format);
formatter_ = other.formatter_;
other.formatter_ = 0;
}
ArgInserter(const ArgInserter& other)
: formatter_(other.formatter_) {
other.formatter_ = 0;
}
const BasicFormatter<Char> *Format() const {
BasicFormatter<Char> *f = formatter_;
if (f) {
formatter_ = 0;
f->CompleteFormatting();
}
return f;
}
BasicFormatter<Char> *formatter() const { return formatter_; }
const char *format() const { return formatter_->format_; }
void ResetFormatter() const { formatter_ = 0; }
public:
~ArgInserter() {
if (formatter_)
formatter_->CompleteFormatting();
}
// Feeds an argument to a formatter.
ArgInserter &operator<<(const typename BasicFormatter<Char>::Arg &arg) {
arg.formatter = formatter_;
formatter_->Add(arg);
return *this;
}
operator FormatterProxy<Char>() {
BasicFormatter<Char> *f = formatter_;
formatter_ = 0;
return FormatterProxy<Char>(f);
}
operator StringRef() {
const BasicFormatter<Char> *f = Format();
return StringRef(f->c_str(), f->size());
}
}; };
} }
@@ -1171,35 +1128,21 @@ inline const char *c_str(internal::FormatterProxy<char> p) {
return p.Format()->c_str(); return p.Format()->c_str();
} }
template <typename Char>
inline internal::ArgInserter<Char>
BasicFormatter<Char>::operator()(StringRef format) {
internal::ArgInserter<Char> inserter(this);
format_ = format.c_str();
args_.clear();
return inserter;
}
/**
A formatting action that does nothing.
*/
class NoAction {
public:
/** Does nothing. */
template <typename Char>
void operator()(const BasicFormatter<Char> &) const {}
};
/** /**
A formatter with an action performed when formatting is complete. A formatter with an action performed when formatting is complete.
Objects of this class normally exist only as temporaries returned Objects of this class normally exist only as temporaries returned
by one of the formatting functions which explains the name. by one of the formatting functions which explains the name.
*/ */
template <typename Action = NoAction, typename Char = char> template <typename Action = NoAction, typename Char = char>
class TempFormatter : public internal::ArgInserter<Char> { class TempFormatter {
private:
friend class fmt::BasicFormatter<Char>;
friend class fmt::StringRef;
private: private:
BasicFormatter<Char> formatter_; BasicFormatter<Char> formatter_;
Action action_; Action action_;
bool inactive_;
// Forbid copying other than from a temporary. Do not implement. // Forbid copying other than from a temporary. Do not implement.
TempFormatter(TempFormatter &); TempFormatter(TempFormatter &);
@@ -1225,33 +1168,47 @@ class TempFormatter : public internal::ArgInserter<Char> {
\endrst \endrst
*/ */
explicit TempFormatter(StringRef format, Action a = Action()) explicit TempFormatter(StringRef format, Action a = Action())
: action_(a) { : formatter_(format.c_str()), action_(a), inactive_(false) {
this->Init(formatter_, format.c_str());
} }
/** /**
Constructs a temporary formatter from a proxy object. Constructs a temporary formatter from a proxy object.
*/ */
TempFormatter(const Proxy &p) TempFormatter(const Proxy &p)
: internal::ArgInserter<Char>(0), action_(p.action) { : formatter_(p.format), action_(p.action), inactive_(false) {}
this->Init(formatter_, p.format);
}
/** /**
Performs the actual formatting, invokes the action and destroys the object. Performs the actual formatting, invokes the action and destroys the object.
*/ */
~TempFormatter() FMT_NOEXCEPT(false) { ~TempFormatter() FMT_NOEXCEPT(false) {
if (this->formatter()) if (!inactive_) {
action_(*this->Format()); formatter_.CompleteFormatting();
action_(formatter_);
}
} }
/** /**
Converts a temporary formatter into a proxy object. Converts a temporary formatter into a proxy object.
*/ */
operator Proxy() { operator Proxy() {
const char *fmt = this->format(); inactive_ = true;
this->ResetFormatter(); return Proxy(formatter_.format_, action_);
return Proxy(fmt, action_); }
// Feeds an argument to a formatter.
TempFormatter &operator<<(const typename BasicFormatter<Char>::Arg &arg) {
arg.formatter = &formatter_;
formatter_.Add(arg);
return *this;
}
operator internal::FormatterProxy<Char>() {
return internal::FormatterProxy<Char>(&formatter_);
}
operator StringRef() {
formatter_.CompleteFormatting();
return StringRef(formatter_.c_str(), formatter_.size());
} }
}; };

View File

@@ -1015,17 +1015,17 @@ TEST(FormatterTest, FormatStringFromSpeedTest) {
<< reinterpret_cast<void*>(1000) << 'X')); << reinterpret_cast<void*>(1000) << 'X'));
} }
TEST(FormatterTest, FormatterCtor) { TEST(WriterTest, WriterCtor) {
Formatter format; Writer w;
EXPECT_EQ(0u, format.size()); EXPECT_EQ(0u, w.size());
EXPECT_STREQ("", format.c_str()); EXPECT_STREQ("", w.c_str());
EXPECT_EQ("", format.str()); EXPECT_EQ("", w.str());
format("part{0}") << 1; w.Format("part{0}") << 1;
format("part{0}") << 2; w.Format("part{0}") << 2;
EXPECT_EQ("part1part2", format.str()); EXPECT_EQ("part1part2", w.str());
} }
TEST(FormatterTest, FormatterAppend) { /*TEST(FormatterTest, FormatterAppend) {
Formatter format; Formatter format;
format("part{0}") << 1; format("part{0}") << 1;
EXPECT_EQ(strlen("part1"), format.size()); EXPECT_EQ(strlen("part1"), format.size());
@@ -1037,9 +1037,9 @@ TEST(FormatterTest, FormatterAppend) {
EXPECT_STREQ("part1part2", format.c_str()); EXPECT_STREQ("part1part2", format.c_str());
EXPECT_STREQ("part1part2", format.data()); EXPECT_STREQ("part1part2", format.data());
EXPECT_EQ("part1part2", format.str()); EXPECT_EQ("part1part2", format.str());
} }*/
TEST(FormatterTest, FormatterExamples) { TEST(FormatTest, FormatExamples) {
using fmt::hex; using fmt::hex;
EXPECT_EQ("0000cafe", str(BasicWriter<char>() << pad(hex(0xcafe), 8, '0'))); EXPECT_EQ("0000cafe", str(BasicWriter<char>() << pad(hex(0xcafe), 8, '0')));
@@ -1050,7 +1050,8 @@ TEST(FormatterTest, FormatterExamples) {
EXPECT_EQ("42", str(Format(std::string("{}")) << 42)); EXPECT_EQ("42", str(Format(std::string("{}")) << 42));
EXPECT_EQ("42", str(Format(Format("{{}}")) << 42)); EXPECT_EQ("42", str(Format(Format("{{}}")) << 42));
Formatter format; // TODO
/*Formatter format;
format("Current point:\n"); format("Current point:\n");
format("({0:+f}, {1:+f})\n") << -3.14 << 3.14; format("({0:+f}, {1:+f})\n") << -3.14 << 3.14;
EXPECT_EQ("Current point:\n(-3.140000, +3.140000)\n", format.str()); EXPECT_EQ("Current point:\n(-3.140000, +3.140000)\n", format.str());
@@ -1061,14 +1062,15 @@ TEST(FormatterTest, FormatterExamples) {
format("{0}") << i; format("{0}") << i;
std::string s = format.str(); // s == 0123456789 std::string s = format.str(); // s == 0123456789
EXPECT_EQ("0123456789", s); EXPECT_EQ("0123456789", s);
} }*/
} }
TEST(FormatterTest, ArgInserter) { // TODO
/*TEST(FormatterTest, ArgInserter) {
Formatter format; Formatter format;
EXPECT_EQ("1", str(format("{0}") << 1)); EXPECT_EQ("1", str(format("{0}") << 1));
EXPECT_STREQ("12", c_str(format("{0}") << 2)); EXPECT_STREQ("12", c_str(format("{0}") << 2));
} }*/
TEST(FormatterTest, StrNamespace) { TEST(FormatterTest, StrNamespace) {
fmt::str(Format("")); fmt::str(Format(""));