add support for better error message back

This commit is contained in:
Gregory Czajkowski 2013-12-10 17:45:42 -08:00
parent f2e75f74cc
commit 0616edd08e
2 changed files with 276 additions and 219 deletions

View File

@ -411,10 +411,12 @@ 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_;
const Char *original = format_; // capture the format string before it is reset
format_ = 0; format_ = 0;
next_arg_index_ = 0; next_arg_index_ = 0;
const Char *s = start; const Char *s = start;
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;
@ -652,6 +654,10 @@ 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);
} }
@ -687,6 +693,18 @@ template void fmt::BasicFormatter<char>::CheckSign(
template void fmt::BasicFormatter<char>::DoFormat(); template void fmt::BasicFormatter<char>::DoFormat();
#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. // Explicit instantiations for wchar_t.
template void fmt::BasicWriter<wchar_t>::FormatDouble<double>( template void fmt::BasicWriter<wchar_t>::FormatDouble<double>(
@ -719,3 +737,21 @@ 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();
#ifdef FMT_FORMAT_STRING_IN_ERRORS
std::string fmt::FormatErrorMessage(const std::string &message, const wchar_t *format) {
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

View File

@ -315,6 +315,20 @@ 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>
class BasicFormatError : public std::runtime_error {
private:
std::basic_string<Char> format_;
public:
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(); }
};
enum Alignment { enum Alignment {
ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC
}; };
@ -402,6 +416,11 @@ class IntFormatter : public SpecT {
*/ */
IntFormatter<int, TypeSpec<'b'> > bin(int value); IntFormatter<int, TypeSpec<'b'> > bin(int value);
/**
Returns an integer formatter that formats the value in base 2.
*/
IntFormatter<int, TypeSpec<'B'> > binu(int value);
/** /**
Returns an integer formatter that formats the value in base 8. Returns an integer formatter that formats the value in base 8.
*/ */
@ -439,7 +458,9 @@ IntFormatter<int, AlignTypeSpec<TYPE_CODE> > pad(
inline IntFormatter<TYPE, TypeSpec<'b'> > bin(TYPE value) { \ inline IntFormatter<TYPE, TypeSpec<'b'> > bin(TYPE value) { \
return IntFormatter<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \ return IntFormatter<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \
} \ } \
\ inline IntFormatter<TYPE, TypeSpec<'B'> > binu(TYPE value) { \
return IntFormatter<TYPE, TypeSpec<'B'> >(value, TypeSpec<'B'>()); \
} \
inline IntFormatter<TYPE, TypeSpec<'o'> > oct(TYPE value) { \ inline IntFormatter<TYPE, TypeSpec<'o'> > oct(TYPE value) { \
return IntFormatter<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \ return IntFormatter<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
} \ } \