std.check.src.error.hpp: src/error.hpp
/*!
\file error.hpp
\brief Header file which declares exception types and
defines error handling code used in the library.
*/
#ifndef CHECK_ERROR_HPP
#define CHECK_ERROR_HPP
#include
#include "global.hpp"
#include "formatter.hpp"
namespace Check
{
/*!
\ingroup error
\relates CheckError
Replacement for the standard terminating function. If any exception based on
CheckError was thrown, this function terminates program with error message
and testing outcome stored in exception object.
\warning Replacing of the terminating function in client program may cause
an undefined behaviour and mess up exception handling process inside the
library.
*/
void terminateLibrary();
/*!
\ingroup error
Throws an exception of type \a Exception with message formatted using printf
syntax \a format string and outcome \a result. If exception does not caught
program will terminate with \a result testing outcome.
\throws Exception
\see incite() and raiseUnless()
*/
template
void raise(const Decision result, const char *format, ...);
/*!
\ingroup error
Works in the same way as raise() only if \a cond is false;
otherwise does nothing.
\throws Exception
\see raise() and inciteUnless()
*/
template
void raiseUnless(
const bool cond, const Decision result, const char *format, ...);
/*!
\ingroup error
Throws an exception of type \a Exception with message formatted using printf
syntax \a format string and outcome \a result. If exception does not caught
program will terminate with \a result testing outcome.
Argument \a message is not mandatory, if message is empty a default one used.
\throws Exception
\see raise() and inciteUnless()
*/
template
inline void incite(
const Decision result = UnhandledError, const char *message = NULL);
/*!
\ingroup error
Works in the same way as incite() only if \a cond is false;
otherwise does nothing.
\throws Exception
\see incite() and raiseUnless()
*/
template
inline void inciteUnless(
const bool cond, const Decision result = UnhandledError,
const char *message = NULL);
/*!
\ingroup error
This is an overloaded function, provided for convenience.
Exactly alike incite(const Decision, const char *)
except type of \a message parameter.
\throws Exception
\see raise() and inciteUnless()
*/
template
inline void incite(const Decision result, const std::string &message)
{ incite(result, message.c_str()); }
/*!
\ingroup error
This is an overloaded function, provided for convenience.
Exactly alike inciteUnless(const bool, const Decision, const char *)
except type of \a message parameter.
\throws Exception
\see incite() and raiseUnless()
*/
template
inline void inciteUnless(
const bool cond, const Decision result, const std::string &message)
{ inciteUnless(cond, result, message.c_str()); }
/*!
\ingroup error
\brief The %CheckError class is the base class for all exceptions used inside
the library.
This class stores testing outcome and message printed before program
termination if exception will not be caught.
*/
class CheckError
{
protected:
//! Pointer to the last exception thrown inside the library.
static const CheckError *lastError;
//! Testing outcome associated with this instance of exception.
const Decision result;
//! Error message associated with this instance of exception.
const std::string text;
/*!
Constructs an exception with testing outcome \a decision and error string
\a message.
*/
explicit CheckError(
const Decision decision, const char *message = NULL) throw()
: result(decision), text(message != NULL ? message : "")
{ lastError = this; }
/*!
This is an overloaded constructor, provided for convenience.
Constructs an exception with testing outcome \a decision and error string
\a message.
*/
CheckError(const Decision decision, const std::string &message) throw()
: result(decision), text(message)
{ lastError = this; }
//! Constructs a copy of \a error.
CheckError(const CheckError &error)
: result(error.result), text(error.text)
{ lastError = this; }
public:
//! Pure virtual destructor.
virtual ~CheckError() throw() { /* Do Nothing */ }
/*!
Returns decision associated with currect instance of exception.
\see Decision and message()
*/
virtual Decision decision() const throw() { return result; }
/*!
Returns a \c std::string object containing message associated with currect
instance of exception.
\see decision()
*/
virtual const std::string &message() const throw() { return text; }
friend void terminateLibrary();
template
friend void raise(const Decision result, const char *format, ...);
template
friend void raiseUnless(
const bool cond, const Decision result, const char *format, ...);
template
friend inline void incite(const Decision result, const char *message);
template
friend inline void inciteUnless(
const bool cond, const Decision result, const char *message);
};
/*!
Declares simple exception class \a TYPE derived from \a BASE with default
message \a MESSAGE.
*/
#define CHECK_DECLARE_ERROR(TYPE, BASE, MESSAGE) \
class TYPE : public BASE \
{ \
protected: \
/*! \cond */ \
explicit TYPE( \
const Decision decision, const char *message = MESSAGE) throw() \
: BASE(decision, message) \
{ } \
TYPE(const Decision decision, const std::string &message) throw() \
: BASE(decision, message) \
{ } \
\
template \
friend void raise(const Decision result, const char *format, ...); \
template \
friend void raiseUnless( \
const bool cond, const Decision result, const char *format, ...); \
template \
friend inline void incite(const Decision result, const char *message); \
template \
friend inline void inciteUnless( \
const bool cond, const Decision result, const char *message); \
/*! \endcond */ \
}
/*!
\ingroup error
\brief The %TestError class is used to report errors occurred during
check process in client programs, not inside library.
\note Does not used inside the library.
\see InternalError and FormatError
*/
CHECK_DECLARE_ERROR(TestError, CheckError, NULL);
/*!
\ingroup error
\brief The %InternalError class is used to report various fatal errors
occurred inside the library which is not test-related.
\see InternalError
*/
CHECK_DECLARE_ERROR(InternalError, CheckError, NULL);
/*!
\ingroup error
\brief The %MemoryError class is used to report specific fatal errors related
to memory management of the library.
\see InternalError
*/
CHECK_DECLARE_ERROR(MemoryError, InternalError, "Out of memory");
/*!
\ingroup error
\brief The %FormatError class is used to report various errors related to data
formatting.
\see TestError and InternalError
*/
CHECK_DECLARE_ERROR(FormatError, CheckError, NULL);
/*!
\ingroup error
\brief The %WhitespaceError class is used to report error occurred when
unexpected whitespace symbols are found.
\see FormatError
*/
CHECK_DECLARE_ERROR(WhitespaceError, FormatError, "Unexpected whitespace");
/*!
\ingroup error
\brief The %EndOfFileError class is used to report error occurred when
unexpected end of file is found.
\see FormatError
*/
CHECK_DECLARE_ERROR(EndOfFileError, FormatError, "Unexpected end of file");
/*!
\ingroup error
\brief The %UnhopedDataError class is used to report error occurred when
data itself or its formatting are unexpected.
\see FormatError
*/
CHECK_DECLARE_ERROR(UnhopedDataError, FormatError, "Unexpected data");
#undef CHECK_DECLARE_ERROR
template
void raise(const Decision result, const char *format, ...)
{
va_list argList;
va_start(argList, format);
throw Exception(result, formatArgs(format, argList));
va_end(argList);
}
template
void raiseUnless(
const bool cond, const Decision result, const char *format, ...)
{
if (!cond)
{
va_list argList;
va_start(argList, format);
throw Exception(result, formatArgs(format, argList));
va_end(argList);
}
}
template
void incite(const Decision result, const char *message)
{
throw Exception(result, message);
}
template
void inciteUnless(const bool cond, const Decision result, const char *message)
{
if (!cond)
throw Exception(result, message);
}
}
#endif /* CHECK_ERROR_HPP */