diff --git a/client/Doxygen/docker-finance.dox b/client/Doxygen/docker-finance.dox index 0fe357b..548d05c 100644 --- a/client/Doxygen/docker-finance.dox +++ b/client/Doxygen/docker-finance.dox @@ -80,6 +80,10 @@ //! \brief Group for tags marked for internal and public consumption //! \since docker-finance 1.0.0 +//! \defgroup cpp_type_exceptions docker-finance C++ exceptions +//! \brief Group for internal exception handling +//! \since docker-finance 1.0.0 + //! \defgroup cpp_utils docker-finance C++ utilities //! \brief Group for public-facing utility code //! \since docker-finance 1.0.0 diff --git a/container/src/root/src/internal/type.hh b/container/src/root/src/internal/type.hh index ad98757..b6143c6 100644 --- a/container/src/root/src/internal/type.hh +++ b/container/src/root/src/internal/type.hh @@ -25,10 +25,36 @@ #include #include +#include #include #include #include +//! \brief Conditional throw handler +//! \ingroup cpp_type_exceptions +#define THROW_IF(condition, exception, message) \ + if (condition) \ + THROW(exception, message); + +//! \brief Throw handler +//! \ingroup cpp_type_exceptions +#define THROW(exception, message) \ + THROW_IMPL(exception, \ + \n\tFILE = __FILE__ \ + \n\tLINE = __LINE__ \ + \n\tWHAT = message); + +//! \brief Throw handler implementation +//! \warning Should not be called directly, use THROW handlers +//! \ingroup cpp_type_exceptions +#define THROW_IMPL(exception, message) \ + throw exception(THROW_IMPL_EXPAND(message)); + +//! \brief Throw handler implementation (message) +//! \warning Should not be called directly, use THROW handlers +//! \ingroup cpp_type_exceptions +#define THROW_IMPL_EXPAND(message) #message + //! \namespace docker_finance //! \since docker-finance 1.0.0 namespace docker_finance @@ -44,6 +70,63 @@ namespace internal //! \todo *_v for all the booleans namespace type { +//! \brief Base exception class +//! \ingroup cpp_type_exceptions +class Exception : virtual public std::exception +{ + public: + //! \brief Exception type + enum struct kType : uint8_t + { + RuntimeError, + InvalidArgument, + }; + + //! \brief Construct by type with given message + Exception(const kType type, const std::string_view what) + : m_type(type), m_what(what) + { + } + virtual ~Exception() = default; + + Exception(const Exception&) = default; + Exception& operator=(const Exception&) = default; + + Exception(Exception&&) = default; + Exception& operator=(Exception&&) = default; + + public: + //! \return Exeption type + kType type() const noexcept { return m_type; } + + //! \return Exception message + const char* what() const noexcept { return m_what.data(); } + + private: + kType m_type; + std::string_view m_what; +}; + +//! \brief Exception class for runtime errors +//! \ingroup cpp_type_exceptions +struct RuntimeError final : public Exception +{ + explicit RuntimeError(const std::string_view what = {}) + : Exception(Exception::kType::RuntimeError, what) + { + } +}; + +//! \brief Exception class for invalid arguments (logic error) +//! \ingroup cpp_type_exceptions +struct InvalidArgument final : public Exception +{ + explicit InvalidArgument(const std::string_view what = {}) + : Exception(Exception::kType::InvalidArgument, what) + { + } +}; + //! \ingroup cpp_type_traits template struct is_byte : std::false_type