add support for optional error messages
added the CMake #ifdef option for error messages with and without the format
This commit is contained in:
parent
264d006dd2
commit
71bd3dc544
@ -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
|
||||||
|
|||||||
44
format.cc
44
format.cc
@ -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
|
||||||
|
|||||||
16
format.h
16
format.h
@ -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_; }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user