diff --git a/format.cc b/format.cc index 4857b3f4..9faebf47 100644 --- a/format.cc +++ b/format.cc @@ -51,6 +51,7 @@ #endif using fmt::ULongLong; +using fmt::internal::Arg; #if _MSC_VER # pragma warning(push) @@ -118,10 +119,9 @@ void ReportError(FormatFunc func, } catch (...) {} } -const fmt::internal::ArgInfo DUMMY_ARG = {fmt::internal::ArgInfo::INT, 0}; +const Arg DUMMY_ARG = {Arg::INT, 0}; -fmt::ULongLong GetIntValue(const fmt::internal::ArgInfo &arg) { - typedef fmt::internal::ArgInfo Arg; +fmt::ULongLong GetIntValue(const Arg &arg) { switch (arg.type) { case Arg::INT: return arg.int_value; @@ -135,6 +135,25 @@ fmt::ULongLong GetIntValue(const fmt::internal::ArgInfo &arg) { return -1; } } + +// Parses an unsigned integer advancing s to the end of the parsed input. +// This function assumes that the first character of s is a digit. +template +int ParseNonnegativeInt(const Char *&s, const char *&error) FMT_NOEXCEPT(true) { + assert('0' <= *s && *s <= '9'); + unsigned value = 0; + do { + unsigned new_value = value * 10 + (*s++ - '0'); + // Check if value wrapped around. + value = new_value >= value ? new_value : UINT_MAX; + } while ('0' <= *s && *s <= '9'); + if (value > INT_MAX) { + if (!error) + error = "number is too big in format"; + return 0; + } + return value; +} } // namespace int fmt::internal::SignBitNoInline(double value) { return SignBit(value); } @@ -349,26 +368,6 @@ void fmt::internal::FormatErrorReporter::operator()( throw fmt::FormatError("unmatched '{' in format"); } -// Parses an unsigned integer advancing s to the end of the parsed input. -// This function assumes that the first character of s is a digit. -template -int fmt::internal::ParseNonnegativeInt( - const Char *&s, const char *&error) FMT_NOEXCEPT(true) { - assert('0' <= *s && *s <= '9'); - unsigned value = 0; - do { - unsigned new_value = value * 10 + (*s++ - '0'); - // Check if value wrapped around. - value = new_value >= value ? new_value : UINT_MAX; - } while ('0' <= *s && *s <= '9'); - if (value > INT_MAX) { - if (!error) - error = "number is too big in format"; - return 0; - } - return value; -} - // Fills the padding around the content and returns the pointer to the // content area. template @@ -553,7 +552,7 @@ void fmt::BasicWriter::write_str( } template -inline const typename fmt::BasicWriter::Arg +inline const Arg &fmt::BasicWriter::FormatParser::ParseArgIndex(const Char *&s) { unsigned arg_index = 0; if (*s < '0' || *s > '9') { @@ -571,7 +570,7 @@ inline const typename fmt::BasicWriter::Arg } next_arg_index_ = -1; const char *error = 0; - arg_index = internal::ParseNonnegativeInt(s, error); + arg_index = ParseNonnegativeInt(s, error); if (error) report_error_(s, error); // TODO } @@ -630,7 +629,7 @@ unsigned fmt::internal::PrintfParser::ParseHeader( if (c >= '0' && c <= '9') { // Parse an argument index (if followed by '$') or a width possibly // preceded with '0' flag(s). - unsigned value = internal::ParseNonnegativeInt(s, error); + unsigned value = ParseNonnegativeInt(s, error); if (*s == '$') { // value is an argument index ++s; arg_index = value; @@ -648,7 +647,7 @@ unsigned fmt::internal::PrintfParser::ParseHeader( ParseFlags(spec, s); // Parse width. if (*s >= '0' && *s <= '9') { - spec.width_ = internal::ParseNonnegativeInt(s, error); + spec.width_ = ParseNonnegativeInt(s, error); } else if (*s == '*') { ++s; const Arg &arg = HandleArgIndex(UINT_MAX, error); @@ -689,8 +688,7 @@ unsigned fmt::internal::PrintfParser::ParseHeader( // TODO: move to a base class that doesn't depend on template argument template -const fmt::internal::ArgInfo - &fmt::internal::PrintfParser::HandleArgIndex( +const Arg &fmt::internal::PrintfParser::HandleArgIndex( unsigned arg_index, const char *&error) { if (arg_index != UINT_MAX) { if (next_arg_index_ <= 0) { @@ -751,7 +749,7 @@ void fmt::internal::PrintfParser::Format( if (*s == '.') { ++s; if ('0' <= *s && *s <= '9') { - spec.precision_ = internal::ParseNonnegativeInt(s, error); + spec.precision_ = ParseNonnegativeInt(s, error); } else if (*s == '*') { ++s; const Arg &arg = HandleArgIndex(UINT_MAX, error); @@ -957,7 +955,7 @@ void fmt::BasicWriter::FormatParser::Format( } // Zero may be parsed again as a part of the width, but it is simpler // and more efficient than checking if the next char is a digit. - spec.width_ = internal::ParseNonnegativeInt(s, error); + spec.width_ = ParseNonnegativeInt(s, error); if (error) report_error_(s, error); } @@ -967,7 +965,7 @@ void fmt::BasicWriter::FormatParser::Format( ++s; spec.precision_ = 0; if ('0' <= *s && *s <= '9') { - spec.precision_ = internal::ParseNonnegativeInt(s, error); + spec.precision_ = ParseNonnegativeInt(s, error); if (error) report_error_(s, error); } else if (*s == '{') { diff --git a/format.h b/format.h index e101c5fa..f7120cff 100644 --- a/format.h +++ b/format.h @@ -562,12 +562,6 @@ struct FormatErrorReporter { void operator()(const Char *s, fmt::StringRef message) const; }; -// Parses a nonnegative integer advancing s to the end of the parsed input. -// This function assumes that the first character of s is a digit. -template -int ParseNonnegativeInt( - const Char *&s, const char *&error) FMT_NOEXCEPT(true); - // Computes max(Arg, 1) at compile time. It is used to avoid errors about // allocating an array of 0 size. template @@ -580,9 +574,8 @@ struct NonZero<0> { enum { VALUE = 1 }; }; -// Information about a format argument. It is a POD type to allow -// storage in internal::Array. -struct ArgInfo { +// A formatting argument. It is a POD type to allow storage in internal::Array. +struct Arg { enum Type { // Integer types should go first, INT, UINT, LONG_LONG, ULONG_LONG, LAST_INTEGER_TYPE = ULONG_LONG, @@ -614,9 +607,9 @@ struct ArgInfo { }; }; -// Makes an ArgInfo object from any type. +// Makes an Arg object from any type. template -class MakeArg : public internal::ArgInfo { +class MakeArg : 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! @@ -629,8 +622,6 @@ class MakeArg : public internal::ArgInfo { MakeArg(T *value); public: - using internal::ArgInfo::type; - MakeArg() {} // TODO: unsigned char & signed char MakeArg(short value) { type = INT; int_value = value; } @@ -718,12 +709,12 @@ class RuntimeError : public std::runtime_error { */ class ArgList { private: - const internal::ArgInfo *args_; + const internal::Arg *args_; std::size_t size_; public: ArgList() : size_(0) {} - ArgList(const internal::ArgInfo *args, std::size_t size) + ArgList(const internal::Arg *args, std::size_t size) : args_(args), size_(size) {} /** @@ -734,7 +725,7 @@ class ArgList { /** Returns the argument at specified index. */ - const internal::ArgInfo &operator[](std::size_t index) const { + const internal::Arg &operator[](std::size_t index) const { return args_[index]; } }; @@ -747,15 +738,13 @@ class PrintfParser { ArgList args_; int next_arg_index_; - typedef ArgInfo Arg; - 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 ArgInfo &HandleArgIndex(unsigned arg_index, const char *&error); + const internal::Arg &HandleArgIndex(unsigned arg_index, const char *&error); public: void Format(BasicWriter &writer, @@ -1012,7 +1001,8 @@ inline StrFormatSpec pad( # define FMT_VARIADIC_VOID(func, arg_type) \ template \ void func(arg_type arg1, const Args & ... args) { \ - const internal::ArgInfo arg_array[fmt::internal::NonZero::VALUE] = { \ + using fmt::internal::Arg; \ + const Arg arg_array[fmt::internal::NonZero::VALUE] = { \ fmt::internal::MakeArg(args)... \ }; \ func(arg1, ArgList(arg_array, sizeof...(Args))); \ @@ -1022,7 +1012,8 @@ inline StrFormatSpec pad( # define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ template \ ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \ - const internal::ArgInfo arg_array[fmt::internal::NonZero::VALUE] = { \ + using fmt::internal::Arg; \ + const Arg arg_array[fmt::internal::NonZero::VALUE] = { \ fmt::internal::MakeArg(args)... \ }; \ func(arg0, arg1, ArgList(arg_array, sizeof...(Args))); \ @@ -1036,7 +1027,7 @@ inline StrFormatSpec pad( # define FMT_WRAP1(func, arg_type, n) \ template \ inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ - const fmt::internal::ArgInfo args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \ + const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \ func(arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \ } @@ -1051,7 +1042,7 @@ inline StrFormatSpec pad( # define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \ template \ ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ - const fmt::internal::ArgInfo args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \ + const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \ func(arg0, arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \ } @@ -1165,8 +1156,6 @@ class BasicWriter { typedef typename internal::CharTraits::CharPtr CharPtr; - typedef internal::ArgInfo Arg; - #if _SECURE_SCL static Char *GetBase(CharPtr p) { return p.base(); } #else @@ -1228,9 +1217,9 @@ class BasicWriter { fmt::internal::FormatErrorReporter report_error_; // Parses argument index and returns an argument with this index. - const Arg &ParseArgIndex(const Char *&s); + const internal::Arg &ParseArgIndex(const Char *&s); - void CheckSign(const Char *&s, const Arg &arg); + void CheckSign(const Char *&s, const internal::Arg &arg); public: void Format(BasicWriter &writer, @@ -1834,8 +1823,8 @@ inline void FormatDec(char *&buffer, T value) { template \ ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ const Args & ... args) { \ - enum {N = fmt::internal::NonZero::VALUE}; \ - const fmt::internal::ArgInfo array[N] = { \ + using fmt::internal::Arg; \ + const Arg array[fmt::internal::NonZero::VALUE] = { \ fmt::internal::MakeArg(args)... \ }; \ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ @@ -1848,7 +1837,7 @@ inline void FormatDec(char *&buffer, T value) { template \ inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ FMT_GEN(n, FMT_MAKE_ARG)) { \ - const fmt::internal::ArgInfo args[] = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \ + const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ fmt::ArgList(args, sizeof(args) / sizeof(*args))); \ }