From 71bd3dc5443e8c8eecbf97e1de8643bc343b66f4 Mon Sep 17 00:00:00 2001 From: Gregory Czajkowski Date: Fri, 22 Nov 2013 20:57:29 -0800 Subject: [PATCH] add support for optional error messages added the CMake #ifdef option for error messages with and without the format --- CMakeLists.txt | 5 +++++ format.cc | 44 +++++++++++++++++++++++++++++++++----------- format.h | 16 ++++++++++++---- 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 192cc420..94312b60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,11 @@ if (HAVE_STD_CPP11_FLAG) add_definitions(-std=c++11) endif () +option(FORMAT_STRING_IN_ERRORS "Report format string in errors" OFF) +if (FORMAT_STRING_IN_ERRORS) + add_definitions(-DFMT_FORMAT_STRING_IN_ERRORS=1) +endif () + add_library(format format.cc) if (CMAKE_COMPILER_IS_GNUCXX) set_target_properties(format PROPERTIES COMPILE_FLAGS diff --git a/format.cc b/format.cc index 2ffe3738..483446b4 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) { + if (arg.type == UINT || arg.type == ULONG || arg.type == ULLONG) { ReportError(s, Format("format specifier '{0}' requires signed argument") << *s); } @@ -522,7 +522,7 @@ void fmt::BasicFormatter::DoFormat() { ++s; ++num_open_braces_; const Arg &precision_arg = ParseArgIndex(s); - unsigned long value = 0; + unsigned long long value = 0; switch (precision_arg.type) { case INT: if (precision_arg.int_value < 0) @@ -540,6 +540,9 @@ void fmt::BasicFormatter::DoFormat() { case ULONG: value = precision_arg.ulong_value; break; + case ULLONG: + value = precision_arg.ulong_long_value; + break; default: ReportError(s, "precision is not integer"); } @@ -581,6 +584,9 @@ void fmt::BasicFormatter::DoFormat() { case ULONG: writer.FormatInt(arg.ulong_value, spec); break; + case ULLONG: + writer.FormatInt(arg.ulong_long_value, spec); + break; case DOUBLE: writer.FormatDouble(arg.double_value, spec, precision); break; @@ -680,12 +686,17 @@ template void fmt::BasicFormatter::CheckSign( template void fmt::BasicFormatter::DoFormat(); -template<> fmt::BasicFormatError::BasicFormatError(const std::string &message, const char *format) - : std::runtime_error(message), format_(format) {} - -template<> fmt::BasicFormatError::~BasicFormatError() { - std::runtime_error::~runtime_error(); +#ifdef FMT_FORMAT_STRING_IN_ERRORS +std::string fmt::FormatErrorMessage(const std::string &message, const char *format) { + fmt::Writer w; + w << "error: " << message << " while parsing format string " << format; + return w.str(); } +#else +std::string fmt::FormatErrorMessage(const std::string &message, const char *format) { + return message; +} +#endif // Explicit instantiations for wchar_t. @@ -720,9 +731,20 @@ template void fmt::BasicFormatter::CheckSign( template void fmt::BasicFormatter::DoFormat(); -template<> fmt::BasicFormatError::BasicFormatError(const std::string &message, const wchar_t *format) - : std::runtime_error(message), format_(format){} +#ifdef FMT_FORMAT_STRING_IN_ERRORS +std::string fmt::FormatErrorMessage(const std::string &message, const wchar_t *format) { -template<> fmt::BasicFormatError::~BasicFormatError() { - std::runtime_error::~runtime_error(); + int size = FMT_SNPRINTF(NULL, 0, "%ls", format); + char* buf = (char*)malloc(size+1); + FMT_SNPRINTF(buf, size+1, "%ls", format); + + fmt::Writer w; + w << "error: " << message << " while parsing format string " << buf; + free(buf); + return w.str(); } +#else +std::string fmt::FormatErrorMessage(const std::string &message, const wchar_t *format) { + return message; +} +#endif diff --git a/format.h b/format.h index 22833a9b..243f0dd4 100644 --- a/format.h +++ b/format.h @@ -292,13 +292,17 @@ class FormatError : public std::runtime_error { : std::runtime_error(message) {} }; +std::string FormatErrorMessage(const std::string &message, const char *format); +std::string FormatErrorMessage(const std::string &message, const wchar_t *format); + template class BasicFormatError : public std::runtime_error { private: std::basic_string format_; public: - explicit BasicFormatError(const std::string &message, const Char *format); - virtual ~BasicFormatError() throw(); + explicit BasicFormatError(const std::string &message, const Char *format) + : std::runtime_error(fmt::FormatErrorMessage(message, format)), format_(format){} + virtual ~BasicFormatError() throw() {} const Char *format() const { return format_.c_str(); } }; @@ -361,7 +365,7 @@ struct FormatSpec : AlignSpec { char type_; FormatSpec(unsigned width = 0, char type = 0, wchar_t fill = ' ') - : AlignSpec(width, fill), flags_(0), type_(type) {} + : AlignSpec(width, fill), flags_(0), type_(type) {} Alignment align() const { return align_; } @@ -464,6 +468,7 @@ DEFINE_INT_FORMATTERS(int) DEFINE_INT_FORMATTERS(long) DEFINE_INT_FORMATTERS(unsigned) DEFINE_INT_FORMATTERS(unsigned long) +DEFINE_INT_FORMATTERS(unsigned long long) template class BasicFormatter; @@ -832,7 +837,7 @@ class BasicFormatter { enum Type { // Numeric types should go first. - INT, UINT, LONG, ULONG, DOUBLE, LONG_DOUBLE, + INT, UINT, LONG, ULONG, ULLONG, DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE, CHAR, STRING, WSTRING, POINTER, CUSTOM }; @@ -867,6 +872,7 @@ class BasicFormatter { double double_value; long long_value; unsigned long ulong_value; + unsigned long long ulong_long_value; long double long_double_value; const void *pointer_value; struct { @@ -886,6 +892,7 @@ 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(float value) : type(DOUBLE), double_value(value), formatter(0) {} Arg(double value) : type(DOUBLE), double_value(value), formatter(0) {} Arg(long double value) @@ -1199,6 +1206,7 @@ class FormatInt { *--str_ = '-'; } 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_; }