From 4edc88f6092ebbd16eb2d2084b132e42e66578ee Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 16 Jul 2014 08:38:15 -0700 Subject: [PATCH] Add FormatterBase. --- format.cc | 95 +++++++++++++++++++++++++++++++------------------------ format.h | 63 ++++++++++++++++++++---------------- 2 files changed, 89 insertions(+), 69 deletions(-) diff --git a/format.cc b/format.cc index 11233006..46c5de42 100644 --- a/format.cc +++ b/format.cc @@ -415,13 +415,14 @@ template class fmt::internal::ArgFormatter : public fmt::internal::ArgVisitor, void> { private: + fmt::BasicFormatter &formatter_; fmt::BasicWriter &writer_; fmt::FormatSpec &spec_; const Char *format_; public: - ArgFormatter(fmt::BasicWriter &w, fmt::FormatSpec &s, const Char *fmt) - : writer_(w), spec_(s), format_(fmt) {} + ArgFormatter(fmt::BasicFormatter &f, fmt::FormatSpec &s, const Char *fmt) + : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {} template void visit_any_int(T value) { writer_.FormatInt(value, spec_); } @@ -467,7 +468,7 @@ class fmt::internal::ArgFormatter : } void visit_custom(Arg::CustomValue c) { - c.format(this, c.value, format_); + c.format(&formatter_, c.value, format_); } }; @@ -670,22 +671,20 @@ inline const Arg if (*s < '0' || *s > '9') { if (*s != '}' && *s != ':') report_error_(s, "invalid argument index in format string"); - if (next_arg_index_ < 0) { - report_error_(s, - "cannot switch from manual to automatic argument indexing"); - } - arg_index = next_arg_index_++; - } else { - if (next_arg_index_ > 0) { - report_error_(s, - "cannot switch from automatic to manual argument indexing"); - } - next_arg_index_ = -1; - const char *error = 0; - arg_index = ParseNonnegativeInt(s, error); - if (error) - report_error_(s, error); // TODO + const Arg &arg = next_arg(); + if (error_) + report_error_(s, error_); + return arg; } + if (next_arg_index_ > 0) { + report_error_(s, + "cannot switch from automatic to manual argument indexing"); + } + next_arg_index_ = -1; + const char *error = 0; + arg_index = ParseNonnegativeInt(s, error); + if (error) + report_error_(s, error); // TODO if (arg_index >= args_.size()) report_error_(s, "argument index is out of range in format"); return args_[arg_index]; @@ -706,6 +705,41 @@ void fmt::BasicFormatter::CheckSign( ++s; } +const Arg &fmt::internal::FormatterBase::next_arg() { + if (next_arg_index_ < 0) { + if (!error_) + error_ = "cannot switch from manual to automatic argument indexing"; + return DUMMY_ARG; + } + unsigned arg_index = next_arg_index_++; + if (arg_index < args_.size()) + return args_[arg_index]; + if (!error_) + error_ = "argument index is out of range in format"; + return DUMMY_ARG; +} + +const Arg &fmt::internal::FormatterBase::HandleArgIndex( + unsigned arg_index, const char *&error) { + if (arg_index != UINT_MAX) { + if (next_arg_index_ <= 0) { + next_arg_index_ = -1; + --arg_index; + } else if (!error) { + error = "cannot switch from automatic to manual argument indexing"; + } + } else if (next_arg_index_ >= 0) { + arg_index = next_arg_index_++; + } else if (!error) { + error = "cannot switch from manual to automatic argument indexing"; + } + if (arg_index < args_.size()) + return args_[arg_index]; + if (!error) + error = "argument index is out of range in format"; + return DUMMY_ARG; +} + template void fmt::internal::PrintfFormatter::ParseFlags( FormatSpec &spec, const Char *&s) { @@ -767,29 +801,6 @@ unsigned fmt::internal::PrintfFormatter::ParseHeader( return arg_index; } -// TODO: move to a base class that doesn't depend on template argument -template -const Arg &fmt::internal::PrintfFormatter::HandleArgIndex( - unsigned arg_index, const char *&error) { - if (arg_index != UINT_MAX) { - if (next_arg_index_ <= 0) { - next_arg_index_ = -1; - --arg_index; - } else if (!error) { - error = "cannot switch from automatic to manual argument indexing"; - } - } else if (next_arg_index_ >= 0) { - arg_index = next_arg_index_++; - } else if (!error) { - error = "cannot switch from manual to automatic argument indexing"; - } - if (arg_index < args_.size()) - return args_[arg_index]; - if (!error) - error = "argument index is out of range in format"; - return DUMMY_ARG; -} - template void fmt::internal::PrintfFormatter::Format( BasicWriter &writer, BasicStringRef format, @@ -1083,7 +1094,7 @@ const Char *fmt::BasicFormatter::format( start_ = s; // Format argument. - internal::ArgFormatter(writer_, spec, s - 1).visit(arg); + internal::ArgFormatter(*this, spec, s - 1).visit(arg); return s; } diff --git a/format.h b/format.h index 66f6a32a..87e242c4 100644 --- a/format.h +++ b/format.h @@ -845,13 +845,44 @@ class ArgList { struct FormatSpec; -// A formatter. -template -class BasicFormatter { -private: - BasicWriter &writer_; +namespace internal { + +class FormatterBase { +protected: ArgList args_; int next_arg_index_; + const char *error_; + + FormatterBase() : error_(0) {} + + const Arg &next_arg(); + + const Arg &HandleArgIndex(unsigned arg_index, const char *&error); + + // TODO +}; + +// A printf formatter. +template +class PrintfFormatter : private FormatterBase { + private: + void ParseFlags(FormatSpec &spec, const Char *&s); + + // Parses argument index, flags and width and returns the parsed + // argument index. + unsigned ParseHeader(const Char *&s, FormatSpec &spec, const char *&error); + + public: + void Format(BasicWriter &writer, + BasicStringRef format, const ArgList &args); +}; +} // namespace internal + +// A formatter. +template +class BasicFormatter : private internal::FormatterBase { +private: + BasicWriter &writer_; const Char *start_; internal::FormatErrorReporter report_error_; @@ -870,28 +901,6 @@ public: const Char *format(const Char *format_str, const internal::Arg &arg); }; -namespace internal { -// A printf formatter. -template -class PrintfFormatter { - private: - ArgList args_; - int next_arg_index_; - - void ParseFlags(FormatSpec &spec, const Char *&s); - - // Parses argument index, flags and width and returns the parsed - // argument index. - unsigned ParseHeader(const Char *&s, FormatSpec &spec, const char *&error); - - const internal::Arg &HandleArgIndex(unsigned arg_index, const char *&error); - - public: - void Format(BasicWriter &writer, - BasicStringRef format, const ArgList &args); -}; -} // namespace internal - enum Alignment { ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC };