mirror of
https://github.com/fmtlib/fmt.git
synced 2025-02-04 15:40:07 +00:00
Refactor error reporting API.
This commit is contained in:
parent
d29e505568
commit
53201033f2
@ -63,9 +63,8 @@ System Errors
|
|||||||
.. doxygenclass:: fmt::SystemError
|
.. doxygenclass:: fmt::SystemError
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. doxygenfunction:: fmt::ThrowSystemError
|
.. doxygenclass:: fmt::WindowsError
|
||||||
|
:members:
|
||||||
.. doxygenfunction:: fmt::ThrowWinError
|
|
||||||
|
|
||||||
Format String Syntax
|
Format String Syntax
|
||||||
--------------------
|
--------------------
|
||||||
|
40
format.cc
40
format.cc
@ -138,6 +138,15 @@ fmt::ULongLong GetIntValue(const fmt::internal::ArgInfo &arg) {
|
|||||||
|
|
||||||
int fmt::internal::SignBitNoInline(double value) { return SignBit(value); }
|
int fmt::internal::SignBitNoInline(double value) { return SignBit(value); }
|
||||||
|
|
||||||
|
void fmt::SystemError::init(
|
||||||
|
int error_code, StringRef format_str, const ArgList &args) {
|
||||||
|
error_code_ = error_code;
|
||||||
|
Writer w;
|
||||||
|
internal::FormatSystemErrorMessage(w, error_code, format(format_str, args));
|
||||||
|
std::runtime_error &base = *this;
|
||||||
|
base = std::runtime_error(w.str());
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int fmt::internal::CharTraits<char>::FormatFloat(
|
int fmt::internal::CharTraits<char>::FormatFloat(
|
||||||
char *buffer, std::size_t size, const char *format,
|
char *buffer, std::size_t size, const char *format,
|
||||||
@ -238,6 +247,15 @@ int fmt::internal::UTF16ToUTF8::Convert(fmt::WStringRef s) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fmt::WindowsError::init(
|
||||||
|
int error_code, StringRef format_str, const ArgList &args) {
|
||||||
|
error_code_ = error_code;
|
||||||
|
Writer w;
|
||||||
|
internal::FormatWinErrorMessage(w, error_code, format(format_str, args));
|
||||||
|
std::runtime_error &base = *this;
|
||||||
|
base = std::runtime_error(w.str());
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int fmt::internal::StrError(
|
int fmt::internal::StrError(
|
||||||
@ -411,7 +429,7 @@ void fmt::BasicWriter<Char>::FormatDouble(T value, const FormatSpec &spec) {
|
|||||||
--size;
|
--size;
|
||||||
++nan;
|
++nan;
|
||||||
}
|
}
|
||||||
CharPtr out = FormatString(nan, size, spec);
|
CharPtr out = write_str(nan, size, spec);
|
||||||
if (sign)
|
if (sign)
|
||||||
*out = sign;
|
*out = sign;
|
||||||
return;
|
return;
|
||||||
@ -426,7 +444,7 @@ void fmt::BasicWriter<Char>::FormatDouble(T value, const FormatSpec &spec) {
|
|||||||
--size;
|
--size;
|
||||||
++inf;
|
++inf;
|
||||||
}
|
}
|
||||||
CharPtr out = FormatString(inf, size, spec);
|
CharPtr out = write_str(inf, size, spec);
|
||||||
if (sign)
|
if (sign)
|
||||||
*out = sign;
|
*out = sign;
|
||||||
return;
|
return;
|
||||||
@ -518,7 +536,7 @@ void fmt::BasicWriter<Char>::FormatDouble(T value, const FormatSpec &spec) {
|
|||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
template <typename StringChar>
|
template <typename StringChar>
|
||||||
void fmt::BasicWriter<Char>::FormatString(
|
void fmt::BasicWriter<Char>::write_str(
|
||||||
const Arg::StringValue<StringChar> &str, const FormatSpec &spec) {
|
const Arg::StringValue<StringChar> &str, const FormatSpec &spec) {
|
||||||
if (spec.type_ && spec.type_ != 's')
|
if (spec.type_ && spec.type_ != 's')
|
||||||
internal::ReportUnknownType(spec.type_, "string");
|
internal::ReportUnknownType(spec.type_, "string");
|
||||||
@ -530,7 +548,7 @@ void fmt::BasicWriter<Char>::FormatString(
|
|||||||
if (*s)
|
if (*s)
|
||||||
size = std::char_traits<StringChar>::length(s);
|
size = std::char_traits<StringChar>::length(s);
|
||||||
}
|
}
|
||||||
FormatString(s, size, spec);
|
write_str(s, size, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
@ -819,10 +837,10 @@ void fmt::internal::PrintfParser<Char>::Format(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Arg::STRING:
|
case Arg::STRING:
|
||||||
writer.FormatString(arg.string, spec);
|
writer.write_str(arg.string, spec);
|
||||||
break;
|
break;
|
||||||
case Arg::WSTRING:
|
case Arg::WSTRING:
|
||||||
writer.FormatString(arg.wstring, spec);
|
writer.write_str(arg.wstring, spec);
|
||||||
break;
|
break;
|
||||||
case Arg::POINTER:
|
case Arg::POINTER:
|
||||||
if (spec.type_ && spec.type_ != 'p')
|
if (spec.type_ && spec.type_ != 'p')
|
||||||
@ -1043,10 +1061,10 @@ void fmt::BasicWriter<Char>::FormatParser::Format(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Arg::STRING:
|
case Arg::STRING:
|
||||||
writer.FormatString(arg.string, spec);
|
writer.write_str(arg.string, spec);
|
||||||
break;
|
break;
|
||||||
case Arg::WSTRING:
|
case Arg::WSTRING:
|
||||||
writer.FormatString(arg.wstring, spec);
|
writer.write_str(arg.wstring, spec);
|
||||||
break;
|
break;
|
||||||
case Arg::POINTER:
|
case Arg::POINTER:
|
||||||
if (spec.type_ && spec.type_ != 'p')
|
if (spec.type_ && spec.type_ != 'p')
|
||||||
@ -1068,12 +1086,6 @@ void fmt::BasicWriter<Char>::FormatParser::Format(
|
|||||||
writer.buffer_.append(start, s);
|
writer.buffer_.append(start, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fmt::SystemErrorSink::operator()(const fmt::Writer &w) const {
|
|
||||||
Writer message;
|
|
||||||
internal::FormatSystemErrorMessage(message, error_code_, w.c_str());
|
|
||||||
throw SystemError(message.c_str(), error_code_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fmt::ReportSystemError(
|
void fmt::ReportSystemError(
|
||||||
int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
|
int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
|
||||||
// FIXME: FormatSystemErrorMessage may throw
|
// FIXME: FormatSystemErrorMessage may throw
|
||||||
|
233
format.h
233
format.h
@ -739,22 +739,62 @@ class BasicArg : public Action, public internal::ArgInfo {
|
|||||||
|
|
||||||
template <typename Char, typename T>
|
template <typename Char, typename T>
|
||||||
inline ArgInfo make_arg(const T &arg) { return BasicArg<Char>(arg); }
|
inline ArgInfo make_arg(const T &arg) { return BasicArg<Char>(arg); }
|
||||||
|
|
||||||
|
class SystemErrorBase : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
SystemErrorBase() : std::runtime_error("") {}
|
||||||
|
};
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An error returned by an operating system or a language runtime,
|
An argument list.
|
||||||
for example a file opening error.
|
|
||||||
*/
|
*/
|
||||||
class SystemError : public std::runtime_error {
|
class ArgList {
|
||||||
private:
|
private:
|
||||||
int error_code_;
|
const internal::ArgInfo *args_;
|
||||||
|
std::size_t size_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ArgList() : size_(0) {}
|
||||||
|
ArgList(const internal::ArgInfo *args, std::size_t size)
|
||||||
|
: args_(args), size_(size) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the list size (the number of arguments).
|
||||||
|
*/
|
||||||
|
std::size_t size() const { return size_; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the argument at specified index.
|
||||||
|
*/
|
||||||
|
const internal::ArgInfo &operator[](std::size_t index) const {
|
||||||
|
return args_[index];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
// Printf format string parser.
|
||||||
|
template <typename Char>
|
||||||
|
class PrintfParser {
|
||||||
|
private:
|
||||||
|
ArgList args_;
|
||||||
|
int next_arg_index_;
|
||||||
|
|
||||||
|
typedef ArgInfo Arg;
|
||||||
|
|
||||||
|
void ParseFlags(FormatSpec &spec, const Char *&s);
|
||||||
|
|
||||||
|
// Parses argument index, flags and width and returns the parsed
|
||||||
|
// argument index.
|
||||||
|
unsigned ParseHeader(const Char *&s, FormatSpec &spec, const char *&error);
|
||||||
|
|
||||||
|
const ArgInfo &HandleArgIndex(unsigned arg_index, const char *&error);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SystemError(StringRef message, int error_code)
|
void Format(BasicWriter<Char> &writer,
|
||||||
: std::runtime_error(message), error_code_(error_code) {}
|
BasicStringRef<Char> format, const ArgList &args);
|
||||||
|
|
||||||
int error_code() const { return error_code_; }
|
|
||||||
};
|
};
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
enum Alignment {
|
enum Alignment {
|
||||||
ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC
|
ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC
|
||||||
@ -982,56 +1022,6 @@ inline StrFormatSpec<wchar_t> pad(
|
|||||||
return StrFormatSpec<wchar_t>(str, width, fill);
|
return StrFormatSpec<wchar_t>(str, width, fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
An argument list.
|
|
||||||
*/
|
|
||||||
class ArgList {
|
|
||||||
private:
|
|
||||||
const internal::ArgInfo *args_;
|
|
||||||
std::size_t size_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ArgList() : size_(0) {}
|
|
||||||
ArgList(const internal::ArgInfo *args, std::size_t size)
|
|
||||||
: args_(args), size_(size) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the list size (the number of arguments).
|
|
||||||
*/
|
|
||||||
std::size_t size() const { return size_; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the argument at specified index.
|
|
||||||
*/
|
|
||||||
const internal::ArgInfo &operator[](std::size_t index) const {
|
|
||||||
return args_[index];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
// Printf format string parser.
|
|
||||||
template <typename Char>
|
|
||||||
class PrintfParser {
|
|
||||||
private:
|
|
||||||
ArgList args_;
|
|
||||||
int next_arg_index_;
|
|
||||||
|
|
||||||
typedef ArgInfo Arg;
|
|
||||||
|
|
||||||
void ParseFlags(FormatSpec &spec, const Char *&s);
|
|
||||||
|
|
||||||
// Parses argument index, flags and width and returns the parsed
|
|
||||||
// argument index.
|
|
||||||
unsigned ParseHeader(const Char *&s, FormatSpec &spec, const char *&error);
|
|
||||||
|
|
||||||
const ArgInfo &HandleArgIndex(unsigned arg_index, const char *&error);
|
|
||||||
|
|
||||||
public:
|
|
||||||
void Format(BasicWriter<Char> &writer,
|
|
||||||
BasicStringRef<Char> format, const ArgList &args);
|
|
||||||
};
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
// Generates a comma-separated list with results of applying f to numbers 0..n-1.
|
// Generates a comma-separated list with results of applying f to numbers 0..n-1.
|
||||||
# define FMT_GEN(n, f) FMT_GEN##n(f)
|
# define FMT_GEN(n, f) FMT_GEN##n(f)
|
||||||
# define FMT_GEN1(f) f(0)
|
# define FMT_GEN1(f) f(0)
|
||||||
@ -1060,7 +1050,19 @@ class PrintfParser {
|
|||||||
}; \
|
}; \
|
||||||
func(arg1, ArgList(arg_array, sizeof...(Args))); \
|
func(arg1, ArgList(arg_array, sizeof...(Args))); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defines a variadic constructor.
|
||||||
|
# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
|
||||||
|
template<typename... Args> \
|
||||||
|
ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
|
||||||
|
const internal::ArgInfo arg_array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
|
||||||
|
fmt::internal::make_arg<Char>(args)... \
|
||||||
|
}; \
|
||||||
|
func(arg0, arg1, ArgList(arg_array, sizeof...(Args))); \
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# define FMT_MAKE_REF(n) fmt::internal::make_arg<Char>(v##n)
|
# define FMT_MAKE_REF(n) fmt::internal::make_arg<Char>(v##n)
|
||||||
// Defines a wrapper for a function taking one argument of type arg_type
|
// Defines a wrapper for a function taking one argument of type arg_type
|
||||||
// and n additional arguments of arbitrary types.
|
// and n additional arguments of arbitrary types.
|
||||||
@ -1078,6 +1080,26 @@ class PrintfParser {
|
|||||||
FMT_WRAP1(func, arg_type, 5) FMT_WRAP1(func, arg_type, 6) \
|
FMT_WRAP1(func, arg_type, 5) FMT_WRAP1(func, arg_type, 6) \
|
||||||
FMT_WRAP1(func, arg_type, 7) FMT_WRAP1(func, arg_type, 8) \
|
FMT_WRAP1(func, arg_type, 7) FMT_WRAP1(func, arg_type, 8) \
|
||||||
FMT_WRAP1(func, arg_type, 9) FMT_WRAP1(func, arg_type, 10)
|
FMT_WRAP1(func, arg_type, 9) FMT_WRAP1(func, arg_type, 10)
|
||||||
|
|
||||||
|
# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \
|
||||||
|
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
||||||
|
ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
|
||||||
|
const fmt::internal::ArgInfo args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
|
||||||
|
func(arg0, arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emulates a variadic function returning void on a pre-C++11 compiler.
|
||||||
|
# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 1) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 2) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 3) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 4) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 5) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 6) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 7) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 8) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 9) \
|
||||||
|
FMT_CTOR(ctor, func, arg0_type, arg1_type, 10)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Generates a comma-separated list with results of applying f to pairs
|
// Generates a comma-separated list with results of applying f to pairs
|
||||||
@ -1102,6 +1124,37 @@ class PrintfParser {
|
|||||||
#define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \
|
#define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \
|
||||||
FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9)
|
FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9)
|
||||||
|
|
||||||
|
/**
|
||||||
|
An error returned by an operating system or a language runtime,
|
||||||
|
for example a file opening error.
|
||||||
|
*/
|
||||||
|
class SystemError : public internal::SystemErrorBase {
|
||||||
|
private:
|
||||||
|
typedef char Char; // For FMT_VARIADIC_CTOR.
|
||||||
|
|
||||||
|
void init(int error_code, StringRef format_str, const ArgList &args);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int error_code_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Constructs a :cpp:class:`fmt::SystemError` object with the description
|
||||||
|
of the form "*<message>*: *<system-message>*", where *<message>* is the
|
||||||
|
formatted message and *<system-message>* is the system message corresponding
|
||||||
|
to the error code.
|
||||||
|
*error_code* is a system error code as given by ``errno``.
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
SystemError(int error_code, StringRef message) {
|
||||||
|
init(error_code, message, ArgList());
|
||||||
|
}
|
||||||
|
FMT_VARIADIC_CTOR(SystemError, init, int, StringRef)
|
||||||
|
|
||||||
|
int error_code() const { return error_code_; }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
This template provides operations for formatting and writing data into
|
This template provides operations for formatting and writing data into
|
||||||
@ -1187,13 +1240,13 @@ class BasicWriter {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void FormatDouble(T value, const FormatSpec &spec);
|
void FormatDouble(T value, const FormatSpec &spec);
|
||||||
|
|
||||||
// Formats a string.
|
// Writes a formatted string.
|
||||||
template <typename StringChar>
|
template <typename StringChar>
|
||||||
CharPtr FormatString(
|
CharPtr write_str(
|
||||||
const StringChar *s, std::size_t size, const AlignSpec &spec);
|
const StringChar *s, std::size_t size, const AlignSpec &spec);
|
||||||
|
|
||||||
template <typename StringChar>
|
template <typename StringChar>
|
||||||
void FormatString(
|
void write_str(
|
||||||
const Arg::StringValue<StringChar> &str, const FormatSpec &spec);
|
const Arg::StringValue<StringChar> &str, const FormatSpec &spec);
|
||||||
|
|
||||||
// This method is private to disallow writing a wide string to a
|
// This method is private to disallow writing a wide string to a
|
||||||
@ -1378,12 +1431,12 @@ class BasicWriter {
|
|||||||
template <typename StringChar>
|
template <typename StringChar>
|
||||||
BasicWriter &operator<<(const StrFormatSpec<StringChar> &spec) {
|
BasicWriter &operator<<(const StrFormatSpec<StringChar> &spec) {
|
||||||
const StringChar *s = spec.str();
|
const StringChar *s = spec.str();
|
||||||
FormatString(s, std::char_traits<Char>::length(s), spec);
|
write_str(s, std::char_traits<Char>::length(s), spec);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const std::basic_string<Char> &s, const FormatSpec &spec) {
|
void write(const std::basic_string<Char> &s, const FormatSpec &spec) {
|
||||||
FormatString(s.data(), s.size(), spec);
|
write_str(s.data(), s.size(), spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() { buffer_.clear(); }
|
void clear() { buffer_.clear(); }
|
||||||
@ -1415,7 +1468,7 @@ inline void BasicWriter<Char>::Clear() { clear(); }
|
|||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
template <typename StringChar>
|
template <typename StringChar>
|
||||||
typename BasicWriter<Char>::CharPtr BasicWriter<Char>::FormatString(
|
typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
|
||||||
const StringChar *s, std::size_t size, const AlignSpec &spec) {
|
const StringChar *s, std::size_t size, const AlignSpec &spec) {
|
||||||
CharPtr out = CharPtr();
|
CharPtr out = CharPtr();
|
||||||
if (spec.width() > size) {
|
if (spec.width() > size) {
|
||||||
@ -1807,19 +1860,16 @@ class SystemErrorSink {
|
|||||||
public:
|
public:
|
||||||
explicit SystemErrorSink(int error_code) : error_code_(error_code) {}
|
explicit SystemErrorSink(int error_code) : error_code_(error_code) {}
|
||||||
|
|
||||||
void operator()(const Writer &w) const;
|
void operator()(const Writer &w) const {
|
||||||
|
throw SystemError(error_code_, "{}", w.c_str());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
FMT_DEPRECATED(Formatter<SystemErrorSink> ThrowSystemError(
|
||||||
\rst
|
int error_code, StringRef format));
|
||||||
Formats a message and throws :cpp:class:`fmt::SystemError` with
|
|
||||||
the description of the form "*<message>*: *<system-message>*",
|
// This function is deprecated. Use fmt::SystemError instead.
|
||||||
where *<message>* is the formatted message and *<system-message>*
|
|
||||||
is the system message corresponding to the error code.
|
|
||||||
*error_code* is a system error code as given by ``errno``.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
inline Formatter<SystemErrorSink> ThrowSystemError(
|
inline Formatter<SystemErrorSink> ThrowSystemError(
|
||||||
int error_code, StringRef format) {
|
int error_code, StringRef format) {
|
||||||
Formatter<SystemErrorSink> f(format, SystemErrorSink(error_code));
|
Formatter<SystemErrorSink> f(format, SystemErrorSink(error_code));
|
||||||
@ -1844,16 +1894,31 @@ class WinErrorSink {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
A Windows error.
|
||||||
Formats a message and throws :cpp:class:`fmt::SystemError` with
|
*/
|
||||||
the description of the form "*<message>*: *<system-message>*",
|
class WindowsError : public SystemError {
|
||||||
where *<message>* is the formatted message and *<system-message>*
|
private:
|
||||||
is the system message corresponding to the error code.
|
void init(int error_code, StringRef format_str, const ArgList &args);
|
||||||
*error_code* is a Windows error code as given by ``GetLastError``.
|
|
||||||
|
|
||||||
This function is only available on Windows.
|
public:
|
||||||
\endrst
|
/**
|
||||||
*/
|
\rst
|
||||||
|
Constructs a :cpp:class:`fmt::WindowsError` object with the description
|
||||||
|
of the form "*<message>*: *<system-message>*", where *<message>* is the
|
||||||
|
formatted message and *<system-message>* is the system message corresponding
|
||||||
|
to the error code.
|
||||||
|
*error_code* is a Windows error code as given by ``GetLastError``.
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
WindowsError(int error_code, StringRef message) {
|
||||||
|
init(error_code, message, ArgList());
|
||||||
|
}
|
||||||
|
FMT_VARIADIC_CTOR(WindowsError, init, int, StringRef)
|
||||||
|
};
|
||||||
|
|
||||||
|
FMT_DEPRECATED(Formatter<WinErrorSink> ThrowWinError(int error_code, StringRef format));
|
||||||
|
|
||||||
|
// This function is deprecated. Use WindowsError instead.
|
||||||
inline Formatter<WinErrorSink> ThrowWinError(int error_code, StringRef format) {
|
inline Formatter<WinErrorSink> ThrowWinError(int error_code, StringRef format) {
|
||||||
Formatter<WinErrorSink> f(format, WinErrorSink(error_code));
|
Formatter<WinErrorSink> f(format, WinErrorSink(error_code));
|
||||||
return f;
|
return f;
|
||||||
@ -1875,7 +1940,7 @@ class FileSink {
|
|||||||
|
|
||||||
void operator()(const BasicWriter<char> &w) const {
|
void operator()(const BasicWriter<char> &w) const {
|
||||||
if (std::fwrite(w.data(), w.size(), 1, file_) == 0)
|
if (std::fwrite(w.data(), w.size(), 1, file_) == 0)
|
||||||
ThrowSystemError(errno, "cannot write to file");
|
throw SystemError(errno, "cannot write to file");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
26
posix.cc
26
posix.cc
@ -70,13 +70,13 @@ void fmt::BufferedFile::close() {
|
|||||||
int result = FMT_SYSTEM(fclose(file_));
|
int result = FMT_SYSTEM(fclose(file_));
|
||||||
file_ = 0;
|
file_ = 0;
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
fmt::ThrowSystemError(errno, "cannot close file");
|
throw SystemError(errno, "cannot close file");
|
||||||
}
|
}
|
||||||
|
|
||||||
int fmt::BufferedFile::fileno() const {
|
int fmt::BufferedFile::fileno() const {
|
||||||
int fd = FMT_POSIX_CALL(fileno(file_));
|
int fd = FMT_POSIX_CALL(fileno(file_));
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
fmt::ThrowSystemError(errno, "cannot get file descriptor");
|
throw SystemError(errno, "cannot get file descriptor");
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ fmt::File::File(const char *path, int oflag) {
|
|||||||
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path, oflag, mode)));
|
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path, oflag, mode)));
|
||||||
#endif
|
#endif
|
||||||
if (fd_ == -1)
|
if (fd_ == -1)
|
||||||
fmt::ThrowSystemError(errno, "cannot open file {}") << path;
|
throw SystemError(errno, "cannot open file {}", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::File::~File() FMT_NOEXCEPT(true) {
|
fmt::File::~File() FMT_NOEXCEPT(true) {
|
||||||
@ -107,14 +107,14 @@ void fmt::File::close() {
|
|||||||
int result = FMT_POSIX_CALL(close(fd_));
|
int result = FMT_POSIX_CALL(close(fd_));
|
||||||
fd_ = -1;
|
fd_ = -1;
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
fmt::ThrowSystemError(errno, "cannot close file");
|
throw SystemError(errno, "cannot close file");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::streamsize fmt::File::read(void *buffer, std::size_t count) {
|
std::streamsize fmt::File::read(void *buffer, std::size_t count) {
|
||||||
std::streamsize result = 0;
|
std::streamsize result = 0;
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, ConvertRWCount(count))));
|
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, ConvertRWCount(count))));
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
fmt::ThrowSystemError(errno, "cannot read from file");
|
throw SystemError(errno, "cannot read from file");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ std::streamsize fmt::File::write(const void *buffer, std::size_t count) {
|
|||||||
std::streamsize result = 0;
|
std::streamsize result = 0;
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, ConvertRWCount(count))));
|
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, ConvertRWCount(count))));
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
fmt::ThrowSystemError(errno, "cannot write to file");
|
throw SystemError(errno, "cannot write to file");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ fmt::File fmt::File::dup(int fd) {
|
|||||||
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
|
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
|
||||||
int new_fd = FMT_POSIX_CALL(dup(fd));
|
int new_fd = FMT_POSIX_CALL(dup(fd));
|
||||||
if (new_fd == -1)
|
if (new_fd == -1)
|
||||||
fmt::ThrowSystemError(errno, "cannot duplicate file descriptor {}") << fd;
|
throw SystemError(errno, "cannot duplicate file descriptor {}", fd);
|
||||||
return File(new_fd);
|
return File(new_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,8 +139,8 @@ void fmt::File::dup2(int fd) {
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
fmt::ThrowSystemError(errno,
|
throw SystemError(errno,
|
||||||
"cannot duplicate file descriptor {} to {}") << fd_ << fd;
|
"cannot duplicate file descriptor {} to {}", fd_, fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ void fmt::File::pipe(File &read_end, File &write_end) {
|
|||||||
int result = FMT_POSIX_CALL(pipe(fds));
|
int result = FMT_POSIX_CALL(pipe(fds));
|
||||||
#endif
|
#endif
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
fmt::ThrowSystemError(errno, "cannot create pipe");
|
throw SystemError(errno, "cannot create pipe");
|
||||||
// The following assignments don't throw because read_fd and write_fd
|
// The following assignments don't throw because read_fd and write_fd
|
||||||
// are closed.
|
// are closed.
|
||||||
read_end = File(fds[0]);
|
read_end = File(fds[0]);
|
||||||
@ -177,10 +177,8 @@ void fmt::File::pipe(File &read_end, File &write_end) {
|
|||||||
fmt::BufferedFile fmt::File::fdopen(const char *mode) {
|
fmt::BufferedFile fmt::File::fdopen(const char *mode) {
|
||||||
// Don't retry as fdopen doesn't return EINTR.
|
// Don't retry as fdopen doesn't return EINTR.
|
||||||
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
||||||
if (!f) {
|
if (!f)
|
||||||
fmt::ThrowSystemError(errno,
|
throw SystemError(errno, "cannot associate stream with file descriptor");
|
||||||
"cannot associate stream with file descriptor");
|
|
||||||
}
|
|
||||||
BufferedFile file(f);
|
BufferedFile file(f);
|
||||||
fd_ = -1;
|
fd_ = -1;
|
||||||
return file;
|
return file;
|
||||||
|
@ -1369,7 +1369,7 @@ TEST(FormatterTest, FormatExamples) {
|
|||||||
EXPECT_SYSTEM_ERROR({
|
EXPECT_SYSTEM_ERROR({
|
||||||
FILE *f = fopen(filename, "r");
|
FILE *f = fopen(filename, "r");
|
||||||
if (!f)
|
if (!f)
|
||||||
fmt::ThrowSystemError(errno, "Cannot open file '{}'") << filename;
|
throw fmt::SystemError(errno, "Cannot open file '{}'", filename);
|
||||||
}, error_code, "Cannot open file 'nonexistent'");
|
}, error_code, "Cannot open file 'nonexistent'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ void ThrowException() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThrowSystemError() {
|
void ThrowSystemError() {
|
||||||
fmt::ThrowSystemError(EDOM, "test");
|
throw fmt::SystemError(EDOM, "test");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that when EXPECT_THROW_MSG fails, it evaluates its message argument
|
// Tests that when EXPECT_THROW_MSG fails, it evaluates its message argument
|
||||||
@ -236,12 +236,11 @@ TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
|
|||||||
// EXPECT_SYSTEM_ERROR macro.
|
// EXPECT_SYSTEM_ERROR macro.
|
||||||
TEST(ExpectSystemErrorTest, DoesNotGenerateUnreachableCodeWarning) {
|
TEST(ExpectSystemErrorTest, DoesNotGenerateUnreachableCodeWarning) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
EXPECT_SYSTEM_ERROR(throw fmt::SystemError(
|
EXPECT_SYSTEM_ERROR(throw fmt::SystemError(EDOM, "test"), EDOM, "test");
|
||||||
FormatSystemErrorMessage(EDOM, "test"), EDOM), EDOM, "test");
|
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(n++, EDOM, ""), "");
|
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(n++, EDOM, ""), "");
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw 1, EDOM, ""), "");
|
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw 1, EDOM, ""), "");
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(
|
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(
|
||||||
throw fmt::SystemError("aaa", EDOM), EDOM, "bbb"), "");
|
throw fmt::SystemError(EDOM, "aaa"), EDOM, "bbb"), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AssertionSyntaxTest, ExceptionAssertionBehavesLikeSingleStatement) {
|
TEST(AssertionSyntaxTest, ExceptionAssertionBehavesLikeSingleStatement) {
|
||||||
|
@ -38,7 +38,7 @@ void OutputRedirect::Flush() {
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
FMT_RETRY(result, fflush(file_));
|
FMT_RETRY(result, fflush(file_));
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
fmt::ThrowSystemError(errno, "cannot flush stream");
|
throw fmt::SystemError(errno, "cannot flush stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputRedirect::Restore() {
|
void OutputRedirect::Restore() {
|
||||||
|
@ -163,9 +163,9 @@ TEST(UtilTest, StrError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, SystemError) {
|
TEST(UtilTest, SystemError) {
|
||||||
fmt::SystemError e(StringRef("test"), 42);
|
fmt::SystemError e(EDOM, "test");
|
||||||
EXPECT_STREQ("test", e.what());
|
EXPECT_EQ(fmt::format("test: {}", GetSystemErrorMessage(EDOM)), e.what());
|
||||||
EXPECT_EQ(42, e.error_code());
|
EXPECT_EQ(EDOM, e.error_code());
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*FormatErrorMessage)(
|
typedef void (*FormatErrorMessage)(
|
||||||
@ -173,7 +173,7 @@ typedef void (*FormatErrorMessage)(
|
|||||||
|
|
||||||
template <typename Sink>
|
template <typename Sink>
|
||||||
void CheckErrorSink(int error_code, FormatErrorMessage format) {
|
void CheckErrorSink(int error_code, FormatErrorMessage format) {
|
||||||
fmt::SystemError error("", 0);
|
fmt::SystemError error(0, "");
|
||||||
Sink sink(error_code);
|
Sink sink(error_code);
|
||||||
fmt::Writer w;
|
fmt::Writer w;
|
||||||
w << "test";
|
w << "test";
|
||||||
@ -188,12 +188,11 @@ void CheckErrorSink(int error_code, FormatErrorMessage format) {
|
|||||||
EXPECT_EQ(error_code, error.error_code());
|
EXPECT_EQ(error_code, error.error_code());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Sink>
|
template <typename Error>
|
||||||
void CheckThrowError(int error_code, FormatErrorMessage format,
|
void CheckThrowError(int error_code, FormatErrorMessage format) {
|
||||||
fmt::Formatter<Sink> (*throw_error)(int error_code, StringRef format)) {
|
fmt::SystemError error(0, "");
|
||||||
fmt::SystemError error("", 0);
|
|
||||||
try {
|
try {
|
||||||
throw_error(error_code, "test {}") << "error";
|
throw Error(error_code, "test {}", "error");
|
||||||
} catch (const fmt::SystemError &e) {
|
} catch (const fmt::SystemError &e) {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
||||||
@ -216,8 +215,7 @@ TEST(UtilTest, SystemErrorSink) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, ThrowSystemError) {
|
TEST(UtilTest, ThrowSystemError) {
|
||||||
CheckThrowError(EDOM,
|
CheckThrowError<fmt::SystemError>(EDOM, fmt::internal::FormatSystemErrorMessage);
|
||||||
fmt::internal::FormatSystemErrorMessage, fmt::ThrowSystemError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, ReportSystemError) {
|
TEST(UtilTest, ReportSystemError) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user