From 1b345ca10aaa73f9c32cef9597813f5bf370318e Mon Sep 17 00:00:00 2001 From: Gregory Czajkowski Date: Mon, 9 Dec 2013 15:55:03 -0800 Subject: [PATCH] merge with latest vitaut/format merge with latest vitaut/format and adds support for error messages with original format string --- format.cc | 20 +++++++---- format.h | 104 ++++++++++++++++++++++++++++++------------------------ 2 files changed, 71 insertions(+), 53 deletions(-) diff --git a/format.cc b/format.cc index 483446b4..2971be5d 100644 --- a/format.cc +++ b/format.cc @@ -400,7 +400,7 @@ void fmt::BasicFormatter::CheckSign(const Char *&s, const Arg &arg) { ReportError(s, Format("format specifier '{0}' requires numeric argument") << *s); } - if (arg.type == UINT || arg.type == ULONG || arg.type == ULLONG) { + if (arg.type == UINT || arg.type == ULONG || arg.type == ULONG_LONG) { ReportError(s, Format("format specifier '{0}' requires signed argument") << *s); } @@ -414,7 +414,6 @@ void fmt::BasicFormatter::DoFormat() { format_ = 0; next_arg_index_ = 0; const Char *s = start; - typedef internal::Array::INLINE_BUFFER_SIZE> Buffer; BasicWriter &writer = *writer_; try { while (*s) { @@ -540,9 +539,14 @@ void fmt::BasicFormatter::DoFormat() { case ULONG: value = precision_arg.ulong_value; break; - case ULLONG: + case LONG_LONG: + if (precision_arg.long_long_value < 0) + ReportError(s, "negative precision in format"); + value = precision_arg.long_long_value; + break; + case ULONG_LONG: value = precision_arg.ulong_long_value; - break; + break; default: ReportError(s, "precision is not integer"); } @@ -584,9 +588,12 @@ void fmt::BasicFormatter::DoFormat() { case ULONG: writer.FormatInt(arg.ulong_value, spec); break; - case ULLONG: + case LONG_LONG: + writer.FormatInt(arg.long_long_value, spec); + break; + case ULONG_LONG: writer.FormatInt(arg.ulong_long_value, spec); - break; + break; case DOUBLE: writer.FormatDouble(arg.double_value, spec, precision); break; @@ -650,7 +657,6 @@ void fmt::BasicFormatter::DoFormat() { // rethrow FormatError with the format string pointed to by start throw BasicFormatError(e.what(), original); } - writer.buffer_.append(start, s); } diff --git a/format.h b/format.h index 243f0dd4..4fec8eb4 100644 --- a/format.h +++ b/format.h @@ -49,17 +49,22 @@ // Define FMT_USE_NOEXCEPT to make format use noexcept (C++11 feature). #if FMT_USE_NOEXCEPT || \ - (defined(__has_feature) && __has_feature(cxx_noexcept)) + (defined(__has_feature) && __has_feature(cxx_noexcept)) || \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) # define FMT_NOEXCEPT(expr) noexcept(expr) #else # define FMT_NOEXCEPT(expr) #endif -#ifdef __GNUC__ #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +# define FMT_GCC_DIAGNOSTIC # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wlong-long" #endif + +#if _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4521) #endif namespace fmt { @@ -189,9 +194,6 @@ struct SignedIntTraits { template <> struct IntTraits : SignedIntTraits {}; -template <> -struct IntTraits : SignedIntTraits {}; - template <> struct IntTraits : SignedIntTraits {}; @@ -468,6 +470,7 @@ DEFINE_INT_FORMATTERS(int) DEFINE_INT_FORMATTERS(long) DEFINE_INT_FORMATTERS(unsigned) DEFINE_INT_FORMATTERS(unsigned long) +DEFINE_INT_FORMATTERS(long long) DEFINE_INT_FORMATTERS(unsigned long long) template @@ -763,9 +766,8 @@ BasicWriter &BasicWriter::operator<<( } while ((n >>= 1) != 0); Char *p = GetBase(PrepareFilledBuffer(size, f, sign)); n = abs_value; - const char *digits = "01"; do { - *p-- = digits[n & 0x1]; + *p-- = '0' + (n & 1); } while ((n >>= 1) != 0); if (print_prefix) { *p-- = f.type(); @@ -798,7 +800,8 @@ BasicWriter &BasicWriter::operator<<( template BasicFormatter BasicWriter::Format(StringRef format) { - return BasicFormatter(*this, format.c_str()); + BasicFormatter f(*this, format.c_str()); + return f; } typedef BasicWriter Writer; @@ -837,7 +840,7 @@ class BasicFormatter { enum Type { // Numeric types should go first. - INT, UINT, LONG, ULONG, ULLONG, DOUBLE, LONG_DOUBLE, + INT, UINT, LONG, ULONG, LONG_LONG, ULONG_LONG, DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE, CHAR, STRING, WSTRING, POINTER, CUSTOM }; @@ -872,6 +875,7 @@ class BasicFormatter { double double_value; long long_value; unsigned long ulong_value; + long long long_long_value; unsigned long long ulong_long_value; long double long_double_value; const void *pointer_value; @@ -892,7 +896,10 @@ class BasicFormatter { Arg(unsigned value) : type(UINT), uint_value(value), formatter(0) {} Arg(long value) : type(LONG), long_value(value), formatter(0) {} Arg(unsigned long value) : type(ULONG), ulong_value(value), formatter(0) {} - Arg(unsigned long long value) : type(ULLONG), ulong_long_value(value), formatter(0) {} + Arg(long long value) + : type(LONG_LONG), long_long_value(value), formatter(0) {} + Arg(unsigned long long value) + : type(ULONG_LONG), ulong_long_value(value), formatter(0) {} Arg(float value) : type(DOUBLE), double_value(value), formatter(0) {} Arg(double value) : type(DOUBLE), double_value(value), formatter(0) {} Arg(long double value) @@ -919,6 +926,11 @@ class BasicFormatter { string.size = value.size(); } + Arg(StringRef value) : type(STRING), formatter(0) { + string.value = value.c_str(); + string.size = value.size(); + } + template Arg(const T &value) : type(CUSTOM), formatter(0) { custom.value = &value; @@ -949,10 +961,16 @@ class BasicFormatter { int num_open_braces_; int next_arg_index_; + typedef unsigned long long ULongLong; + friend class internal::FormatterProxy; - // Forbid copying other than from a temporary. Do not implement. - BasicFormatter(BasicFormatter &); + // Forbid copying from a temporary as in the following example: + // fmt::Formatter<> f = Format("test"); // not allowed + // This is done because BasicFormatter objects should normally exist + // only as temporaries returned by one of the formatting functions. + // Do not implement. + BasicFormatter(const BasicFormatter &); BasicFormatter& operator=(const BasicFormatter &); void Add(const Arg &arg) { @@ -968,6 +986,8 @@ class BasicFormatter { void CheckSign(const Char *&s, const Arg &arg); + // Parses the format string and performs the actual formatting, + // writing the output to writer_. void DoFormat(); struct Proxy { @@ -991,21 +1011,18 @@ class BasicFormatter { public: // Constructs a formatter with a writer to be used for output and a format - // format string. + // string. BasicFormatter(BasicWriter &w, const Char *format = 0) : writer_(&w), format_(format) {} + // Performs formatting if the format string is non-null. The format string + // can be null if its ownership has been transferred to another formatter. ~BasicFormatter() { CompleteFormatting(); } - // Constructs a formatter from a proxy object. - BasicFormatter(const Proxy &p) : writer_(p.writer), format_(p.format) {} - - operator Proxy() { - const Char *format = format_; - format_ = 0; - return Proxy(writer_, format); + BasicFormatter(BasicFormatter &f) : writer_(f.writer_), format_(f.format_) { + f.format_ = 0; } // Feeds an argument to a formatter. @@ -1100,7 +1117,7 @@ class NoAction { // Formats an error message and prints it to stdout. fmt::Formatter ReportError(const char *format) { - return fmt::Formatter(format); + return Move(fmt::Formatter(format)); } ReportError("File not found: {}") << path; @@ -1113,16 +1130,9 @@ class Formatter : private Action, public BasicFormatter { bool inactive_; // Forbid copying other than from a temporary. Do not implement. - Formatter(Formatter &); + Formatter(const Formatter &); Formatter& operator=(const Formatter &); - struct Proxy { - const Char *format; - Action action; - - Proxy(const Char *fmt, Action a) : format(fmt), action(a) {} - }; - public: /** \rst @@ -1138,10 +1148,10 @@ class Formatter : private Action, public BasicFormatter { inactive_(false) { } - // Constructs a formatter from a proxy object. - Formatter(const Proxy &p) - : Action(p.action), BasicFormatter(writer_, p.format), + Formatter(Formatter &f) + : Action(f), BasicFormatter(writer_, f.TakeFormatString()), inactive_(false) { + f.inactive_ = true; } /** @@ -1153,14 +1163,14 @@ class Formatter : private Action, public BasicFormatter { (*this)(writer_); } } - - // Converts the formatter into a proxy object. - operator Proxy() { - inactive_ = true; - return Proxy(this->TakeFormatString(), *this); - } }; +// Removes a const qualifier from a formatter object making it moveable. +template +Formatter &Move(const Formatter &f) { + return const_cast &>(f); +} + /** Fast integer formatter. */ @@ -1171,7 +1181,7 @@ class FormatInt { enum {BUFFER_SIZE = std::numeric_limits::digits10 + 3}; char buffer_[BUFFER_SIZE]; char *str_; - + // Formats value in reverse and returns the number of digits. char *FormatDecimal(uint64_t value) { char *buffer_end = buffer_ + BUFFER_SIZE; @@ -1208,8 +1218,8 @@ class FormatInt { explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {} explicit FormatInt(uint64_t value) : str_(FormatDecimal(value)) {} - inline const char *c_str() const { return str_; } - inline std::string str() const { return str_; } + const char *c_str() const { return str_; } + std::string str() const { return str_; } }; /** @@ -1234,11 +1244,11 @@ class FormatInt { \endrst */ inline Formatter<> Format(StringRef format) { - return Formatter<>(format); + return Move(Formatter<>(format)); } inline Formatter Format(WStringRef format) { - return Formatter(format); + return Move(Formatter(format)); } /** A formatting action that writes formatted output to stdout. */ @@ -1254,14 +1264,16 @@ class Write { // Example: // Print("Elapsed time: {0:.2f} seconds") << 1.23; inline Formatter Print(StringRef format) { - return Formatter(format); + return Move(Formatter(format)); } } -#ifdef __GNUC__ -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#ifdef FMT_GCC_DIAGNOSTIC # pragma GCC diagnostic pop #endif + +#if _MSC_VER +# pragma warning(pop) #endif #endif // FORMAT_H_