add support for optional error messages

added the CMake #ifdef option for error messages with and without the
format
This commit is contained in:
Gregory Czajkowski 2013-11-22 20:57:29 -08:00
parent 264d006dd2
commit 71bd3dc544
3 changed files with 50 additions and 15 deletions

View File

@ -16,6 +16,11 @@ if (HAVE_STD_CPP11_FLAG)
add_definitions(-std=c++11) add_definitions(-std=c++11)
endif () 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) add_library(format format.cc)
if (CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(format PROPERTIES COMPILE_FLAGS set_target_properties(format PROPERTIES COMPILE_FLAGS

View File

@ -400,7 +400,7 @@ void fmt::BasicFormatter<Char>::CheckSign(const Char *&s, const Arg &arg) {
ReportError(s, ReportError(s,
Format("format specifier '{0}' requires numeric argument") << *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, ReportError(s,
Format("format specifier '{0}' requires signed argument") << *s); Format("format specifier '{0}' requires signed argument") << *s);
} }
@ -522,7 +522,7 @@ void fmt::BasicFormatter<Char>::DoFormat() {
++s; ++s;
++num_open_braces_; ++num_open_braces_;
const Arg &precision_arg = ParseArgIndex(s); const Arg &precision_arg = ParseArgIndex(s);
unsigned long value = 0; unsigned long long value = 0;
switch (precision_arg.type) { switch (precision_arg.type) {
case INT: case INT:
if (precision_arg.int_value < 0) if (precision_arg.int_value < 0)
@ -540,6 +540,9 @@ void fmt::BasicFormatter<Char>::DoFormat() {
case ULONG: case ULONG:
value = precision_arg.ulong_value; value = precision_arg.ulong_value;
break; break;
case ULLONG:
value = precision_arg.ulong_long_value;
break;
default: default:
ReportError(s, "precision is not integer"); ReportError(s, "precision is not integer");
} }
@ -581,6 +584,9 @@ void fmt::BasicFormatter<Char>::DoFormat() {
case ULONG: case ULONG:
writer.FormatInt(arg.ulong_value, spec); writer.FormatInt(arg.ulong_value, spec);
break; break;
case ULLONG:
writer.FormatInt(arg.ulong_long_value, spec);
break;
case DOUBLE: case DOUBLE:
writer.FormatDouble(arg.double_value, spec, precision); writer.FormatDouble(arg.double_value, spec, precision);
break; break;
@ -680,12 +686,17 @@ template void fmt::BasicFormatter<char>::CheckSign(
template void fmt::BasicFormatter<char>::DoFormat(); template void fmt::BasicFormatter<char>::DoFormat();
template<> fmt::BasicFormatError<char>::BasicFormatError(const std::string &message, const char *format) #ifdef FMT_FORMAT_STRING_IN_ERRORS
: std::runtime_error(message), format_(format) {} std::string fmt::FormatErrorMessage(const std::string &message, const char *format) {
fmt::Writer w;
template<> fmt::BasicFormatError<char>::~BasicFormatError() { w << "error: " << message << " while parsing format string " << format;
std::runtime_error::~runtime_error(); return w.str();
} }
#else
std::string fmt::FormatErrorMessage(const std::string &message, const char *format) {
return message;
}
#endif
// Explicit instantiations for wchar_t. // Explicit instantiations for wchar_t.
@ -720,9 +731,20 @@ template void fmt::BasicFormatter<wchar_t>::CheckSign(
template void fmt::BasicFormatter<wchar_t>::DoFormat(); template void fmt::BasicFormatter<wchar_t>::DoFormat();
template<> fmt::BasicFormatError<wchar_t>::BasicFormatError(const std::string &message, const wchar_t *format) #ifdef FMT_FORMAT_STRING_IN_ERRORS
: std::runtime_error(message), format_(format){} std::string fmt::FormatErrorMessage(const std::string &message, const wchar_t *format) {
template<> fmt::BasicFormatError<wchar_t>::~BasicFormatError() { int size = FMT_SNPRINTF(NULL, 0, "%ls", format);
std::runtime_error::~runtime_error(); 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

View File

@ -292,13 +292,17 @@ class FormatError : public std::runtime_error {
: std::runtime_error(message) {} : 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 <typename Char> template <typename Char>
class BasicFormatError : public std::runtime_error { class BasicFormatError : public std::runtime_error {
private: private:
std::basic_string<Char> format_; std::basic_string<Char> format_;
public: public:
explicit BasicFormatError(const std::string &message, const Char *format); explicit BasicFormatError(const std::string &message, const Char *format)
virtual ~BasicFormatError() throw(); : std::runtime_error(fmt::FormatErrorMessage(message, format)), format_(format){}
virtual ~BasicFormatError() throw() {}
const Char *format() const { return format_.c_str(); } const Char *format() const { return format_.c_str(); }
}; };
@ -361,7 +365,7 @@ struct FormatSpec : AlignSpec {
char type_; char type_;
FormatSpec(unsigned width = 0, char type = 0, wchar_t fill = ' ') 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_; } Alignment align() const { return align_; }
@ -464,6 +468,7 @@ DEFINE_INT_FORMATTERS(int)
DEFINE_INT_FORMATTERS(long) DEFINE_INT_FORMATTERS(long)
DEFINE_INT_FORMATTERS(unsigned) DEFINE_INT_FORMATTERS(unsigned)
DEFINE_INT_FORMATTERS(unsigned long) DEFINE_INT_FORMATTERS(unsigned long)
DEFINE_INT_FORMATTERS(unsigned long long)
template <typename Char> template <typename Char>
class BasicFormatter; class BasicFormatter;
@ -832,7 +837,7 @@ class BasicFormatter {
enum Type { enum Type {
// Numeric types should go first. // 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, LAST_NUMERIC_TYPE = LONG_DOUBLE,
CHAR, STRING, WSTRING, POINTER, CUSTOM CHAR, STRING, WSTRING, POINTER, CUSTOM
}; };
@ -867,6 +872,7 @@ class BasicFormatter {
double double_value; double double_value;
long long_value; long long_value;
unsigned long ulong_value; unsigned long ulong_value;
unsigned long long ulong_long_value;
long double long_double_value; long double long_double_value;
const void *pointer_value; const void *pointer_value;
struct { struct {
@ -886,6 +892,7 @@ class BasicFormatter {
Arg(unsigned value) : type(UINT), uint_value(value), formatter(0) {} Arg(unsigned value) : type(UINT), uint_value(value), formatter(0) {}
Arg(long value) : type(LONG), long_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 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(float value) : type(DOUBLE), double_value(value), formatter(0) {}
Arg(double value) : type(DOUBLE), double_value(value), formatter(0) {} Arg(double value) : type(DOUBLE), double_value(value), formatter(0) {}
Arg(long double value) Arg(long double value)
@ -1199,6 +1206,7 @@ class FormatInt {
*--str_ = '-'; *--str_ = '-';
} }
explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {} explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {}
explicit FormatInt(uint64_t value) : str_(FormatDecimal(value)) {}
inline const char *c_str() const { return str_; } inline const char *c_str() const { return str_; }
inline std::string str() const { return str_; } inline std::string str() const { return str_; }