add support for better error messages

This includes extended error messages which show the original format
string. It works for 'char' type with wchar_t returning only the
message.

The thrown exception class now has a format() method to retrieve the
pointer to the original format.
This commit is contained in:
Gregory Czajkowski 2013-11-19 20:48:36 -08:00
parent 225d4f7032
commit 62466cc3d9
2 changed files with 246 additions and 211 deletions

View File

@ -409,12 +409,14 @@ void fmt::BasicFormatter<Char>::CheckSign(const Char *&s, const Arg &arg) {
template <typename Char> template <typename Char>
void fmt::BasicFormatter<Char>::DoFormat() { void fmt::BasicFormatter<Char>::DoFormat() {
const Char *start = format_; const Char *start = format_; // capture the format string before it is reset
const Char *original = format_;
format_ = 0; format_ = 0;
next_arg_index_ = 0; next_arg_index_ = 0;
const Char *s = start; const Char *s = start;
typedef internal::Array<Char, BasicWriter<Char>::INLINE_BUFFER_SIZE> Buffer; typedef internal::Array<Char, BasicWriter<Char>::INLINE_BUFFER_SIZE> Buffer;
BasicWriter<Char> &writer = *writer_; BasicWriter<Char> &writer = *writer_;
try {
while (*s) { while (*s) {
Char c = *s++; Char c = *s++;
if (c != '{' && c != '}') continue; if (c != '{' && c != '}') continue;
@ -644,6 +646,11 @@ void fmt::BasicFormatter<Char>::DoFormat() {
break; break;
} }
} }
} catch (const FormatError &e) {
// rethrow FormatError with the format string pointed to by start
throw BasicFormatError<Char>(e.what(), original);
}
writer.buffer_.append(start, s); writer.buffer_.append(start, s);
} }
@ -679,6 +686,17 @@ template void fmt::BasicFormatter<char>::CheckSign(
template void fmt::BasicFormatter<char>::DoFormat(); template void fmt::BasicFormatter<char>::DoFormat();
const char* FormatErrorMessage(const std::string &message, const char* format) {
return fmt::c_str(fmt::Format("error: {} while parsing {}") << message << format);
}
template<> fmt::BasicFormatError<char>::BasicFormatError(const std::string &message, const char *format)
: std::runtime_error(FormatErrorMessage(message, format)), format_(format) {}
template<> fmt::BasicFormatError<char>::~BasicFormatError() {
std::runtime_error::~runtime_error();
}
// Explicit instantiations for wchar_t. // Explicit instantiations for wchar_t.
template void fmt::BasicWriter<wchar_t>::FormatDouble<double>( template void fmt::BasicWriter<wchar_t>::FormatDouble<double>(
@ -711,3 +729,10 @@ template void fmt::BasicFormatter<wchar_t>::CheckSign(
const wchar_t *&s, const Arg &arg); const wchar_t *&s, const Arg &arg);
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)
: std::runtime_error(message), format_(format){}
template<> fmt::BasicFormatError<wchar_t>::~BasicFormatError() {
std::runtime_error::~runtime_error();
}

View File

@ -292,6 +292,16 @@ class FormatError : public std::runtime_error {
: std::runtime_error(message) {} : std::runtime_error(message) {}
}; };
template <typename Char>
class BasicFormatError : public std::runtime_error {
private:
std::basic_string<Char> format_;
public:
explicit BasicFormatError(const std::string &message, const Char *format);
virtual ~BasicFormatError() throw();
const Char *format() const { return format_.c_str(); }
};
enum Alignment { enum Alignment {
ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC
}; };