diff --git a/format.h b/format.h index 4303c9d9..5714b237 100644 --- a/format.h +++ b/format.h @@ -227,9 +227,6 @@ inline unsigned CountDigits(uint64_t n) { } } -template -class ArgInserter; - template class FormatterProxy; } @@ -435,6 +432,22 @@ DEFINE_INT_FORMATTERS(long) DEFINE_INT_FORMATTERS(unsigned) DEFINE_INT_FORMATTERS(unsigned long) +template +class BasicFormatter; + +template +class TempFormatter; + +/** + A formatting action that does nothing. + */ +class NoAction { + public: + /** Does nothing. */ + template + void operator()(const BasicFormatter &) const {} +}; + template class BasicWriter { protected: @@ -545,6 +558,15 @@ private: 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 Format(StringRef format) { + return TempFormatter(format); + } + void Clear() { buffer_.clear(); } @@ -1004,7 +1026,7 @@ class BasicFormatter : public BasicWriter { // constructed before the Arg object, it will be destroyed after, // 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 - // the destructor of ArgInserter is called. + // the destructor of TempFormatter is called. if (formatter) formatter->CompleteFormatting(); } @@ -1017,7 +1039,9 @@ class BasicFormatter : public BasicWriter { int num_open_braces_; int next_arg_index_; - friend class internal::ArgInserter; + template + friend class TempFormatter; // TODO + friend class internal::FormatterProxy; void Add(const Arg &arg) { @@ -1044,14 +1068,7 @@ class BasicFormatter : public BasicWriter { /** Constructs a formatter with an empty output buffer. */ - BasicFormatter() : format_(0) {} - - /** - Formats a string appending the output to the internal buffer. - Arguments are accepted through the returned `ArgInserter` object - using inserter operator `<<`. - */ - internal::ArgInserter operator()(StringRef format); + BasicFormatter(const Char *format = 0) : format_(format) {} }; typedef BasicFormatter Formatter; @@ -1093,66 +1110,6 @@ class FormatterProxy { // formatter. template class ArgInserter { - private: - mutable BasicFormatter *formatter_; - - friend class fmt::BasicFormatter; - friend class fmt::StringRef; - - // Do not implement. - void operator=(const ArgInserter& other); - - protected: - explicit ArgInserter(BasicFormatter *f = 0) : formatter_(f) {} - - void Init(BasicFormatter &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 *Format() const { - BasicFormatter *f = formatter_; - if (f) { - formatter_ = 0; - f->CompleteFormatting(); - } - return f; - } - - BasicFormatter *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::Arg &arg) { - arg.formatter = formatter_; - formatter_->Add(arg); - return *this; - } - - operator FormatterProxy() { - BasicFormatter *f = formatter_; - formatter_ = 0; - return FormatterProxy(f); - } - - operator StringRef() { - const BasicFormatter *f = Format(); - return StringRef(f->c_str(), f->size()); - } }; } @@ -1171,35 +1128,21 @@ inline const char *c_str(internal::FormatterProxy p) { return p.Format()->c_str(); } -template -inline internal::ArgInserter -BasicFormatter::operator()(StringRef format) { - internal::ArgInserter inserter(this); - format_ = format.c_str(); - args_.clear(); - return inserter; -} - -/** - A formatting action that does nothing. - */ -class NoAction { - public: - /** Does nothing. */ - template - void operator()(const BasicFormatter &) const {} -}; - /** A formatter with an action performed when formatting is complete. Objects of this class normally exist only as temporaries returned by one of the formatting functions which explains the name. */ template -class TempFormatter : public internal::ArgInserter { +class TempFormatter { +private: + friend class fmt::BasicFormatter; + friend class fmt::StringRef; + private: BasicFormatter formatter_; Action action_; + bool inactive_; // Forbid copying other than from a temporary. Do not implement. TempFormatter(TempFormatter &); @@ -1225,33 +1168,47 @@ class TempFormatter : public internal::ArgInserter { \endrst */ explicit TempFormatter(StringRef format, Action a = Action()) - : action_(a) { - this->Init(formatter_, format.c_str()); + : formatter_(format.c_str()), action_(a), inactive_(false) { } /** Constructs a temporary formatter from a proxy object. */ TempFormatter(const Proxy &p) - : internal::ArgInserter(0), action_(p.action) { - this->Init(formatter_, p.format); - } + : formatter_(p.format), action_(p.action), inactive_(false) {} /** Performs the actual formatting, invokes the action and destroys the object. */ ~TempFormatter() FMT_NOEXCEPT(false) { - if (this->formatter()) - action_(*this->Format()); + if (!inactive_) { + formatter_.CompleteFormatting(); + action_(formatter_); + } } /** Converts a temporary formatter into a proxy object. */ operator Proxy() { - const char *fmt = this->format(); - this->ResetFormatter(); - return Proxy(fmt, action_); + inactive_ = true; + return Proxy(formatter_.format_, action_); + } + + // Feeds an argument to a formatter. + TempFormatter &operator<<(const typename BasicFormatter::Arg &arg) { + arg.formatter = &formatter_; + formatter_.Add(arg); + return *this; + } + + operator internal::FormatterProxy() { + return internal::FormatterProxy(&formatter_); + } + + operator StringRef() { + formatter_.CompleteFormatting(); + return StringRef(formatter_.c_str(), formatter_.size()); } }; diff --git a/format_test.cc b/format_test.cc index 34197665..a90087cf 100644 --- a/format_test.cc +++ b/format_test.cc @@ -1015,17 +1015,17 @@ TEST(FormatterTest, FormatStringFromSpeedTest) { << reinterpret_cast(1000) << 'X')); } -TEST(FormatterTest, FormatterCtor) { - Formatter format; - EXPECT_EQ(0u, format.size()); - EXPECT_STREQ("", format.c_str()); - EXPECT_EQ("", format.str()); - format("part{0}") << 1; - format("part{0}") << 2; - EXPECT_EQ("part1part2", format.str()); +TEST(WriterTest, WriterCtor) { + Writer w; + EXPECT_EQ(0u, w.size()); + EXPECT_STREQ("", w.c_str()); + EXPECT_EQ("", w.str()); + w.Format("part{0}") << 1; + w.Format("part{0}") << 2; + EXPECT_EQ("part1part2", w.str()); } -TEST(FormatterTest, FormatterAppend) { +/*TEST(FormatterTest, FormatterAppend) { Formatter format; format("part{0}") << 1; EXPECT_EQ(strlen("part1"), format.size()); @@ -1037,9 +1037,9 @@ TEST(FormatterTest, FormatterAppend) { EXPECT_STREQ("part1part2", format.c_str()); EXPECT_STREQ("part1part2", format.data()); EXPECT_EQ("part1part2", format.str()); -} +}*/ -TEST(FormatterTest, FormatterExamples) { +TEST(FormatTest, FormatExamples) { using fmt::hex; EXPECT_EQ("0000cafe", str(BasicWriter() << 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(Format("{{}}")) << 42)); - Formatter format; + // TODO + /*Formatter format; format("Current point:\n"); format("({0:+f}, {1:+f})\n") << -3.14 << 3.14; EXPECT_EQ("Current point:\n(-3.140000, +3.140000)\n", format.str()); @@ -1061,14 +1062,15 @@ TEST(FormatterTest, FormatterExamples) { format("{0}") << i; std::string s = format.str(); // s == 0123456789 EXPECT_EQ("0123456789", s); - } + }*/ } -TEST(FormatterTest, ArgInserter) { +// TODO +/*TEST(FormatterTest, ArgInserter) { Formatter format; EXPECT_EQ("1", str(format("{0}") << 1)); EXPECT_STREQ("12", c_str(format("{0}") << 2)); -} +}*/ TEST(FormatterTest, StrNamespace) { fmt::str(Format(""));