diff --git a/format.cc b/format.cc index b8fa2c84..2790e3b6 100644 --- a/format.cc +++ b/format.cc @@ -331,8 +331,8 @@ int fmt::internal::ParseNonnegativeInt( } template -const typename fmt::BasicWriter::ArgInfo - fmt::BasicWriter::DUMMY_ARG = {fmt::BasicWriter::INT, 0}; +const typename fmt::internal::ArgInfo + fmt::BasicWriter::DUMMY_ARG = {fmt::internal::ArgInfo::INT, 0}; // Fills the padding around the content and returns the pointer to the // content area. @@ -501,15 +501,15 @@ void fmt::BasicWriter::FormatDouble(T value, const FormatSpec &spec) { } template -fmt::ULongLong fmt::BasicWriter::GetIntValue(const ArgInfo &arg) { +fmt::ULongLong fmt::BasicWriter::GetIntValue(const Arg &arg) { switch (arg.type) { - case INT: + case Arg::INT: return arg.int_value; - case UINT: + case Arg::UINT: return arg.uint_value; - case LONG_LONG: + case Arg::LONG_LONG: return arg.long_long_value; - case ULONG_LONG: + case Arg::ULONG_LONG: return arg.ulong_long_value; default: return -1; @@ -517,7 +517,24 @@ fmt::ULongLong fmt::BasicWriter::GetIntValue(const ArgInfo &arg) { } template -inline const typename fmt::BasicWriter::ArgInfo +template +void fmt::BasicWriter::FormatString( + const Arg::StringValue &str, const FormatSpec &spec) { + if (spec.type_ && spec.type_ != 's') + internal::ReportUnknownType(spec.type_, "string"); + const StringChar *s = str.value; + std::size_t size = str.size; + if (size == 0) { + if (!s) + throw FormatError("string pointer is null"); + if (*s) + size = std::char_traits::length(s); + } + FormatString(s, size, spec); +} + +template +inline const typename fmt::BasicWriter::Arg &fmt::BasicWriter::FormatParser::ParseArgIndex(const Char *&s) { unsigned arg_index = 0; if (*s < '0' || *s > '9') { @@ -539,20 +556,20 @@ inline const typename fmt::BasicWriter::ArgInfo if (error) report_error_(s, error); // TODO } - if (arg_index >= num_args_) + if (arg_index >= args_.size()) report_error_(s, "argument index is out of range in format"); return args_[arg_index]; } template void fmt::BasicWriter::FormatParser::CheckSign( - const Char *&s, const ArgInfo &arg) { + const Char *&s, const Arg &arg) { char sign = static_cast(*s); - if (arg.type > LAST_NUMERIC_TYPE) { + if (arg.type > Arg::LAST_NUMERIC_TYPE) { report_error_(s, fmt::Format("format specifier '{}' requires numeric argument") << sign); } - if (arg.type == UINT || arg.type == ULONG_LONG) { + if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) { report_error_(s, fmt::Format("format specifier '{}' requires signed argument") << sign); } @@ -615,27 +632,28 @@ unsigned fmt::BasicWriter::PrintfParser::ParseHeader( spec.width_ = internal::ParseNonnegativeInt(s, error); } else if (*s == '*') { ++s; - const ArgInfo &arg = HandleArgIndex(UINT_MAX, error); + const Arg &arg = HandleArgIndex(UINT_MAX, error); + // TODO: use ArgVisitor ULongLong width = 0; switch (arg.type) { - case INT: + case Arg::INT: width = arg.int_value; if (arg.int_value < 0) { spec.align_ = ALIGN_LEFT; width = 0 - width; } break; - case UINT: + case Arg::UINT: width = arg.uint_value; break; - case LONG_LONG: + case Arg::LONG_LONG: width = arg.long_long_value; if (arg.long_long_value < 0) { spec.align_ = ALIGN_LEFT; width = 0 - width; } break; - case ULONG_LONG: + case Arg::ULONG_LONG: width = arg.ulong_long_value; break; default: @@ -652,7 +670,7 @@ unsigned fmt::BasicWriter::PrintfParser::ParseHeader( // TODO: move to a base class that doesn't depend on template argument template -const typename fmt::BasicWriter::ArgInfo +const typename fmt::BasicWriter::Arg &fmt::BasicWriter::PrintfParser::HandleArgIndex( unsigned arg_index, const char *&error) { if (arg_index != UINT_MAX) { @@ -667,7 +685,7 @@ const typename fmt::BasicWriter::ArgInfo } else if (!error) { error = "cannot switch from manual to automatic argument indexing"; } - if (arg_index < num_args_) + if (arg_index < args_.size()) return args_[arg_index]; if (!error) error = "argument index is out of range in format"; @@ -677,9 +695,8 @@ const typename fmt::BasicWriter::ArgInfo template void fmt::BasicWriter::PrintfParser::Format( BasicWriter &writer, BasicStringRef format, - std::size_t num_args, const ArgInfo *args) { + const ArgList &args) { const Char *start = format.c_str(); - num_args_ = num_args; args_ = args; next_arg_index_ = 0; const Char *s = start; @@ -718,25 +735,37 @@ void fmt::BasicWriter::PrintfParser::Format( spec.precision_ = internal::ParseNonnegativeInt(s, error); } else if (*s == '*') { ++s; - const ArgInfo &arg = HandleArgIndex(UINT_MAX, error); - if (arg.type <= LAST_INTEGER_TYPE) + const Arg &arg = HandleArgIndex(UINT_MAX, error); + if (arg.type <= Arg::LAST_INTEGER_TYPE) spec.precision_ = GetIntValue(arg); else if (!error) error = "precision is not integer"; } } - const ArgInfo &arg = HandleArgIndex(arg_index, error); + const Arg &arg = HandleArgIndex(arg_index, error); if (spec.hash_flag() && GetIntValue(arg) == 0) spec.flags_ &= ~HASH_FLAG; if (spec.fill_ == '0') { - if (arg.type <= LAST_NUMERIC_TYPE) + if (arg.type <= Arg::LAST_NUMERIC_TYPE) spec.align_ = ALIGN_NUMERIC; else spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. } - // TODO: parse length + // Parse length. + switch (*s) { + case 'h': + // TODO: convert to short + case 'l': + case 'j': + case 'z': + case 't': + case 'L': + // TODO: handle length + ++s; + break; + } // Parse type. if (!*s) @@ -749,25 +778,25 @@ void fmt::BasicWriter::PrintfParser::Format( // Format argument. switch (arg.type) { - case INT: + case Arg::INT: writer.FormatInt(arg.int_value, spec); break; - case UINT: + case Arg::UINT: writer.FormatInt(arg.uint_value, spec); break; - case LONG_LONG: + case Arg::LONG_LONG: writer.FormatInt(arg.long_long_value, spec); break; - case ULONG_LONG: + case Arg::ULONG_LONG: writer.FormatInt(arg.ulong_long_value, spec); break; - case DOUBLE: + case Arg::DOUBLE: writer.FormatDouble(arg.double_value, spec); break; - case LONG_DOUBLE: + case Arg::LONG_DOUBLE: writer.FormatDouble(arg.long_double_value, spec); break; - case CHAR: { + case Arg::CHAR: { if (spec.type_ && spec.type_ != 'c') internal::ReportUnknownType(spec.type_, "char"); typedef typename BasicWriter::CharPtr CharPtr; @@ -789,31 +818,23 @@ void fmt::BasicWriter::PrintfParser::Format( *out = static_cast(arg.int_value); break; } - case STRING: { - if (spec.type_ && spec.type_ != 's') - internal::ReportUnknownType(spec.type_, "string"); - const Char *str = arg.string.value; - std::size_t size = arg.string.size; - if (size == 0) { - if (!str) - throw FormatError("string pointer is null"); - if (*str) - size = std::char_traits::length(str); - } - writer.FormatString(str, size, spec); + case Arg::STRING: + writer.FormatString(arg.string, spec); break; - } - case POINTER: + case Arg::WSTRING: + writer.FormatString(arg.wstring, spec); + break; + case Arg::POINTER: if (spec.type_ && spec.type_ != 'p') internal::ReportUnknownType(spec.type_, "pointer"); spec.flags_= HASH_FLAG; spec.type_ = 'x'; writer.FormatInt(reinterpret_cast(arg.pointer_value), spec); break; - case CUSTOM: + case Arg::CUSTOM: if (spec.type_) internal::ReportUnknownType(spec.type_, "object"); - arg.custom.format(writer, arg.custom.value, spec); + arg.custom.format(&writer, arg.custom.value, spec); break; default: assert(false); @@ -826,10 +847,9 @@ void fmt::BasicWriter::PrintfParser::Format( template void fmt::BasicWriter::FormatParser::Format( BasicWriter &writer, BasicStringRef format, - std::size_t num_args, const ArgInfo *args) { + const ArgList &args) { const char *error = 0; const Char *start = format.c_str(); - num_args_ = num_args; args_ = args; next_arg_index_ = 0; const Char *s = start; @@ -846,7 +866,7 @@ void fmt::BasicWriter::FormatParser::Format( report_error_.num_open_braces = 1; writer.buffer_.append(start, s - 1); - const ArgInfo &arg = ParseArgIndex(s); + const Arg &arg = ParseArgIndex(s); FormatSpec spec; if (*s == ':') { @@ -879,7 +899,7 @@ void fmt::BasicWriter::FormatParser::Format( s += 2; spec.fill_ = c; } else ++s; - if (spec.align_ == ALIGN_NUMERIC && arg.type > LAST_NUMERIC_TYPE) + if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE) report_error_(s, "format specifier '=' requires numeric argument"); break; } @@ -902,7 +922,7 @@ void fmt::BasicWriter::FormatParser::Format( } if (*s == '#') { - if (arg.type > LAST_NUMERIC_TYPE) + if (arg.type > Arg::LAST_NUMERIC_TYPE) report_error_(s, "format specifier '#' requires numeric argument"); spec.flags_ |= HASH_FLAG; ++s; @@ -911,7 +931,7 @@ void fmt::BasicWriter::FormatParser::Format( // Parse width and zero flag. if ('0' <= *s && *s <= '9') { if (*s == '0') { - if (arg.type > LAST_NUMERIC_TYPE) + if (arg.type > Arg::LAST_NUMERIC_TYPE) report_error_(s, "format specifier '0' requires numeric argument"); spec.align_ = ALIGN_NUMERIC; spec.fill_ = '0'; @@ -934,23 +954,23 @@ void fmt::BasicWriter::FormatParser::Format( } else if (*s == '{') { ++s; ++report_error_.num_open_braces; - const ArgInfo &precision_arg = ParseArgIndex(s); + const Arg &precision_arg = ParseArgIndex(s); ULongLong value = 0; switch (precision_arg.type) { - case INT: + case Arg::INT: if (precision_arg.int_value < 0) report_error_(s, "negative precision in format"); value = precision_arg.int_value; break; - case UINT: + case Arg::UINT: value = precision_arg.uint_value; break; - case LONG_LONG: + case Arg::LONG_LONG: if (precision_arg.long_long_value < 0) report_error_(s, "negative precision in format"); value = precision_arg.long_long_value; break; - case ULONG_LONG: + case Arg::ULONG_LONG: value = precision_arg.ulong_long_value; break; default: @@ -965,7 +985,7 @@ void fmt::BasicWriter::FormatParser::Format( } else { report_error_(s, "missing precision in format"); } - if (arg.type != DOUBLE && arg.type != LONG_DOUBLE) { + if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) { report_error_(s, "precision specifier requires floating-point argument"); } @@ -982,25 +1002,25 @@ void fmt::BasicWriter::FormatParser::Format( // Format argument. switch (arg.type) { - case INT: + case Arg::INT: writer.FormatInt(arg.int_value, spec); break; - case UINT: + case Arg::UINT: writer.FormatInt(arg.uint_value, spec); break; - case LONG_LONG: + case Arg::LONG_LONG: writer.FormatInt(arg.long_long_value, spec); break; - case ULONG_LONG: + case Arg::ULONG_LONG: writer.FormatInt(arg.ulong_long_value, spec); break; - case DOUBLE: + case Arg::DOUBLE: writer.FormatDouble(arg.double_value, spec); break; - case LONG_DOUBLE: + case Arg::LONG_DOUBLE: writer.FormatDouble(arg.long_double_value, spec); break; - case CHAR: { + case Arg::CHAR: { if (spec.type_ && spec.type_ != 'c') internal::ReportUnknownType(spec.type_, "char"); typedef typename BasicWriter::CharPtr CharPtr; @@ -1022,31 +1042,23 @@ void fmt::BasicWriter::FormatParser::Format( *out = static_cast(arg.int_value); break; } - case STRING: { - if (spec.type_ && spec.type_ != 's') - internal::ReportUnknownType(spec.type_, "string"); - const Char *str = arg.string.value; - std::size_t size = arg.string.size; - if (size == 0) { - if (!str) - throw FormatError("string pointer is null"); - if (*str) - size = std::char_traits::length(str); - } - writer.FormatString(str, size, spec); + case Arg::STRING: + writer.FormatString(arg.string, spec); break; - } - case POINTER: + case Arg::WSTRING: + writer.FormatString(arg.wstring, spec); + break; + case Arg::POINTER: if (spec.type_ && spec.type_ != 'p') internal::ReportUnknownType(spec.type_, "pointer"); spec.flags_= HASH_FLAG; spec.type_ = 'x'; writer.FormatInt(reinterpret_cast(arg.pointer_value), spec); break; - case CUSTOM: + case Arg::CUSTOM: if (spec.type_) internal::ReportUnknownType(spec.type_, "object"); - arg.custom.format(writer, arg.custom.value, spec); + arg.custom.format(&writer, arg.custom.value, spec); break; default: assert(false); @@ -1098,12 +1110,10 @@ template fmt::BasicWriter::CharPtr unsigned total_size, std::size_t content_size, wchar_t fill); template void fmt::BasicWriter::FormatParser::Format( - BasicWriter &writer, BasicStringRef format, - std::size_t num_args, const ArgInfo *args); + BasicWriter &writer, BasicStringRef format, const ArgList &args); template void fmt::BasicWriter::PrintfParser::Format( - BasicWriter &writer, BasicStringRef format, - std::size_t num_args, const ArgInfo *args); + BasicWriter &writer, BasicStringRef format, const ArgList &args); // Explicit instantiations for wchar_t. @@ -1113,11 +1123,11 @@ template fmt::BasicWriter::CharPtr template void fmt::BasicWriter::FormatParser::Format( BasicWriter &writer, BasicStringRef format, - std::size_t num_args, const ArgInfo *args); + const ArgList &args); template void fmt::BasicWriter::PrintfParser::Format( BasicWriter &writer, BasicStringRef format, - std::size_t num_args, const ArgInfo *args); + const ArgList &args); #if _MSC_VER # pragma warning(pop) diff --git a/format.h b/format.h index 53a34ffd..8ecc5a53 100644 --- a/format.h +++ b/format.h @@ -477,8 +477,7 @@ void FormatDecimal(Char *buffer, UInt value, unsigned num_digits) { } template -void FormatCustomArg( - BasicWriter &w, const void *arg, const FormatSpec &spec); +void FormatCustomArg(void *writer, const void *arg, const FormatSpec &spec); #ifdef _WIN32 // A converter from UTF-8 to UTF-16. @@ -563,6 +562,46 @@ template <> struct NonZero<0> { enum { VALUE = 1 }; }; + +// Information about a format argument. It is a POD type to allow +// storage in internal::Array. +struct ArgInfo { + enum Type { + // Integer types should go first, + INT, UINT, LONG_LONG, ULONG_LONG, LAST_INTEGER_TYPE = ULONG_LONG, + // followed by floating-point types. + DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE, + CHAR, STRING, WSTRING, POINTER, CUSTOM + }; + Type type; + + template + struct StringValue { + const Char *value; + std::size_t size; + }; + + typedef void (*FormatFunc)( + void *writer, const void *arg, const FormatSpec &spec); + + struct CustomValue { + const void *value; + FormatFunc format; + }; + + union { + int int_value; + unsigned uint_value; + double double_value; + LongLong long_long_value; + ULongLong ulong_long_value; + long double long_double_value; + const void *pointer_value; + StringValue string; + StringValue wstring; + CustomValue custom; + }; +}; } // namespace internal /** @@ -806,6 +845,23 @@ inline StrFormatSpec pad( return StrFormatSpec(str, width, fill); } +class ArgList { + private: + const internal::ArgInfo *args_; + std::size_t size_; + +public: + ArgList() : size_(0) {} + ArgList(const internal::ArgInfo *args, std::size_t size) + : args_(args), size_(size) {} + + std::size_t size() const { return size_; } + + const internal::ArgInfo &operator[](std::size_t index) const { + return args_[index]; + } +}; + /** \rst This template provides operations for formatting and writing data into @@ -850,6 +906,10 @@ class BasicWriter { typedef typename internal::CharTraits::CharPtr CharPtr; + typedef internal::ArgInfo Arg; + + static const Arg DUMMY_ARG; + #if _SECURE_SCL static Char *GetBase(CharPtr p) { return p.base(); } #else @@ -893,53 +953,17 @@ class BasicWriter { CharPtr FormatString( const StringChar *s, std::size_t size, const AlignSpec &spec); - // This method is private to disallow writing a wide string to a + template + void FormatString( + const Arg::StringValue &str, const FormatSpec &spec); + + // This method is private to disallow writing a wide string to a // char stream and vice versa. If you want to print a wide string // as a pointer as std::ostream does, cast it to const void*. // Do not implement! void operator<<(typename internal::CharTraits::UnsupportedStrType); - enum Type { - // Integer types should go first, - INT, UINT, LONG_LONG, ULONG_LONG, LAST_INTEGER_TYPE = ULONG_LONG, - // followed by floating-point types. - DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE, - CHAR, STRING, WSTRING, POINTER, CUSTOM - }; - - struct StringValue { - const Char *value; - std::size_t size; - }; - - typedef void (*FormatFunc)( - BasicWriter &w, const void *arg, const FormatSpec &spec); - - struct CustomValue { - const void *value; - FormatFunc format; - }; - - // Information about a format argument. It is a POD type to allow - // storage in internal::Array. - struct ArgInfo { - Type type; - union { - int int_value; - unsigned uint_value; - double double_value; - LongLong long_long_value; - ULongLong ulong_long_value; - long double long_double_value; - const void *pointer_value; - StringValue string; - CustomValue custom; - }; - }; - - static const ArgInfo DUMMY_ARG; - - static ULongLong GetIntValue(const ArgInfo &arg); + static ULongLong GetIntValue(const Arg &arg); // An argument action that does nothing. struct NullArgAction { @@ -948,7 +972,7 @@ class BasicWriter { // A wrapper around a format argument. template - class BasicArg : public Action, public ArgInfo { + class BasicArg : public Action, public Arg { private: // This method is private to disallow formatting of arbitrary pointers. // If you want to output a pointer cast it to const void*. Do not implement! @@ -961,83 +985,96 @@ class BasicWriter { BasicArg(T *value); public: - using ArgInfo::type; + using Arg::type; BasicArg() {} - BasicArg(short value) { type = INT; this->int_value = value; } - BasicArg(unsigned short value) { type = UINT; this->int_value = value; } - BasicArg(int value) { type = INT; this->int_value = value; } - BasicArg(unsigned value) { type = UINT; this->uint_value = value; } + // TODO: unsigned char & signed char + BasicArg(short value) { type = Arg::INT; Arg::int_value = value; } + BasicArg(unsigned short value) { + type = Arg::UINT; + Arg::uint_value = value; + } + BasicArg(int value) { type = Arg::INT; Arg::int_value = value; } + BasicArg(unsigned value) { type = Arg::UINT; Arg::uint_value = value; } BasicArg(long value) { if (sizeof(long) == sizeof(int)) { - type = INT; - this->int_value = static_cast(value); + type = Arg::INT; + Arg::int_value = static_cast(value); } else { - type = LONG_LONG; - this->long_long_value = value; + type = Arg::LONG_LONG; + Arg::long_long_value = value; } } BasicArg(unsigned long value) { if (sizeof(unsigned long) == sizeof(unsigned)) { - type = UINT; - this->uint_value = static_cast(value); + type = Arg::UINT; + Arg::uint_value = static_cast(value); } else { - type = ULONG_LONG; - this->ulong_long_value = value; + type = Arg::ULONG_LONG; + Arg::ulong_long_value = value; } } BasicArg(LongLong value) { - type = LONG_LONG; - this->long_long_value = value; + type = Arg::LONG_LONG; + Arg::long_long_value = value; } BasicArg(ULongLong value) { - type = ULONG_LONG; - this->ulong_long_value = value; + type = Arg::ULONG_LONG; + Arg::ulong_long_value = value; } - BasicArg(float value) { type = DOUBLE; this->double_value = value; } - BasicArg(double value) { type = DOUBLE; this->double_value = value; } + BasicArg(float value) { type = Arg::DOUBLE; Arg::double_value = value; } + BasicArg(double value) { type = Arg::DOUBLE; Arg::double_value = value; } BasicArg(long double value) { - type = LONG_DOUBLE; - this->long_double_value = value; + type = Arg::LONG_DOUBLE; + Arg::long_double_value = value; } - BasicArg(char value) { type = CHAR; this->int_value = value; } + BasicArg(char value) { type = Arg::CHAR; Arg::int_value = value; } BasicArg(wchar_t value) { - type = CHAR; - this->int_value = internal::CharTraits::ConvertChar(value); + type = Arg::CHAR; + Arg::int_value = internal::CharTraits::ConvertChar(value); } - BasicArg(const Char *value) { - type = STRING; - this->string.value = value; - this->string.size = 0; + BasicArg(const char *value) { + type = Arg::STRING; + Arg::string.value = value; + Arg::string.size = 0; + } + + BasicArg(const wchar_t *value) { + type = Arg::WSTRING; + Arg::wstring.value = value; + Arg::wstring.size = 0; } BasicArg(Char *value) { - type = STRING; - this->string.value = value; - this->string.size = 0; + type = Arg::STRING; + Arg::string.value = value; + Arg::string.size = 0; } - BasicArg(const void *value) { type = POINTER; this->pointer_value = value; } - BasicArg(void *value) { type = POINTER; this->pointer_value = value; } + BasicArg(const void *value) { + type = Arg::POINTER; + Arg::pointer_value = value; + } + BasicArg(void *value) { type = Arg::POINTER; Arg::pointer_value = value; } BasicArg(const std::basic_string &value) { - type = STRING; - this->string.value = value.c_str(); - this->string.size = value.size(); + type = Arg::STRING; + Arg::string.value = value.c_str(); + Arg::string.size = value.size(); } BasicArg(BasicStringRef value) { - type = STRING; - this->string.value = value.c_str(); - this->string.size = value.size(); + type = Arg::STRING; + Arg::string.value = value.c_str(); + Arg::string.size = value.size(); } template BasicArg(const T &value) { - type = CUSTOM; - this->custom.value = &value; - this->custom.format = &internal::FormatCustomArg; + type = Arg::CUSTOM; + Arg::custom.value = &value; + Arg::custom.format = &internal::FormatCustomArg; } // The destructor is declared noexcept(false) because the action may throw @@ -1048,31 +1085,27 @@ class BasicWriter { } }; - typedef BasicArg<> Arg; - // Format string parser. class FormatParser { private: - std::size_t num_args_; - const ArgInfo *args_; + ArgList args_; int next_arg_index_; fmt::internal::FormatErrorReporter report_error_; // Parses argument index and returns an argument with this index. - const ArgInfo &ParseArgIndex(const Char *&s); + const Arg &ParseArgIndex(const Char *&s); - void CheckSign(const Char *&s, const ArgInfo &arg); + void CheckSign(const Char *&s, const Arg &arg); public: void Format(BasicWriter &writer, - BasicStringRef format, std::size_t num_args, const ArgInfo *args); + BasicStringRef format, const ArgList &args); }; // Printf format string parser. class PrintfParser { private: - std::size_t num_args_; - const ArgInfo *args_; + ArgList args_; int next_arg_index_; void ParseFlags(FormatSpec &spec, const Char *&s); @@ -1081,11 +1114,11 @@ class BasicWriter { // argument index. unsigned ParseHeader(const Char *&s, FormatSpec &spec, const char *&error); - const ArgInfo &HandleArgIndex(unsigned arg_index, const char *&error); + const Arg &HandleArgIndex(unsigned arg_index, const char *&error); public: void Format(BasicWriter &writer, - BasicStringRef format, std::size_t num_args, const ArgInfo *args); + BasicStringRef format, const ArgList &args); }; public: @@ -1140,14 +1173,12 @@ class BasicWriter { return std::basic_string(&buffer_[0], buffer_.size()); } - inline void VFormat(BasicStringRef format, - std::size_t num_args, const ArgInfo *args) { - FormatParser().Format(*this, format, num_args, args); + inline void format(BasicStringRef format, const ArgList &args) { + FormatParser().Format(*this, format, args); } - inline void vprintf(BasicStringRef format, - std::size_t num_args, const ArgInfo *args) { - PrintfParser().Format(*this, format, num_args, args); + inline void printf(BasicStringRef format, const ArgList &args) { + PrintfParser().Format(*this, format, args); } /** @@ -1207,14 +1238,14 @@ class BasicWriter { */ template void Format(BasicStringRef format, const Args & ... args) { - Arg arg_array[] = {args...}; - VFormat(format, sizeof...(Args), arg_array); + BasicArg<> arg_array[] = {args...}; + this->format(format, ArgList(arg_array, sizeof...(Args))); } template void printf(BasicStringRef format, const Args & ... args) { - Arg arg_array[internal::NonZero::VALUE] = {args...}; - vprintf(format, sizeof...(Args), arg_array); + BasicArg<> arg_array[internal::NonZero::VALUE] = {args...}; + this->printf(format, ArgList(arg_array, sizeof...(Args))); } #endif @@ -1486,9 +1517,9 @@ void Format(BasicWriter &w, const FormatSpec &spec, const T &value) { namespace internal { // Formats an argument of a custom type, such as a user-defined class. template -void FormatCustomArg( - BasicWriter &w, const void *arg, const FormatSpec &spec) { - Format(w, spec, *static_cast(arg)); +void FormatCustomArg(void *writer, const void *arg, const FormatSpec &spec) { + Format(*static_cast*>(writer), + spec, *static_cast(arg)); } } @@ -1527,7 +1558,7 @@ class BasicFormatter { } }; - typedef typename BasicWriter::ArgInfo ArgInfo; + typedef typename internal::ArgInfo ArgInfo; typedef typename BasicWriter::template BasicArg Arg; enum { NUM_INLINE_ARGS = 10 }; @@ -1554,7 +1585,7 @@ class BasicFormatter { if (!format_) return; const Char *format = format_; format_ = 0; - writer_->VFormat(format, args_.size(), &args_[0]); + writer_->format(format, ArgList(&args_[0], args_.size())); } public: