ВШ 2019: паросочетания / std.check.src.error.hpp

ru en cn

с начала прошло: 2045 д. 22:52
страница обновлена: 27.11.2024 10:37

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 */
Дальневосточный федеральный университет