|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| #ifndef BASE_EXCEPTION_H
|
| #define BASE_EXCEPTION_H
|
|
|
| #include <FCConfig.h>
|
|
|
| #include <csignal>
|
| #include <source_location>
|
| #include <string>
|
|
|
| #include "BaseClass.h"
|
| #include "FileInfo.h"
|
|
|
| using PyObject = struct _object;
|
|
|
|
|
| #if defined(__cpp_lib_source_location)
|
| # define HAVE_STD_SOURCE_LOCATION 1
|
| #else
|
| # undef HAVE_STD_SOURCE_LOCATION
|
| #endif
|
|
|
| #if defined(__clang__) && __clang_major__ <= 15
|
| # undef HAVE_STD_SOURCE_LOCATION
|
| #endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| #if defined(HAVE_STD_SOURCE_LOCATION)
|
|
|
| # define THROWM(exc, msg) Base::setupAndThrowException<exc>((msg), std::source_location::current());
|
| # define THROWMT(exc, msg) \
|
| Base::setupAndThrowException<exc>((msg), std::source_location::current(), true);
|
| # define FC_THROWM(exception, msg) \
|
| do { \
|
| std::stringstream ss; \
|
| ss << msg; \
|
| THROWM(exception, ss.str()); \
|
| } while (0)
|
|
|
|
|
| namespace Base
|
| {
|
| template<typename ExceptionType>
|
| [[noreturn]] void setupAndThrowException(
|
| const std::string message,
|
| const std::source_location location,
|
| const bool translatable = false
|
| )
|
| {
|
| ExceptionType exception {message};
|
| exception.setTranslatable(translatable);
|
| exception.setDebugInformation(location);
|
| throw exception;
|
| }
|
| }
|
|
|
| #else
|
|
|
| # ifdef _MSC_VER
|
| # define FC_THROW_INFO __FILE__, __LINE__, __FUNCSIG__
|
| # elif __GNUC__
|
| # define FC_THROW_INFO __FILE__, __LINE__, __PRETTY_FUNCTION__
|
| # else
|
| # define FC_THROW_INFO __FILE__, __LINE__, __func__
|
| # endif
|
|
|
| # define THROWM(exc, msg) Base::setupAndThrowException<exc>(msg, FC_THROW_INFO);
|
| # define THROWMT(exc, msg) Base::setupAndThrowException<exc>(msg, FC_THROW_INFO, true);
|
| # define FC_THROWM(exception, msg) \
|
| do { \
|
| std::stringstream ss; \
|
| ss << msg; \
|
| THROWM(exception, ss.str()); \
|
| } while (0)
|
| namespace Base
|
| {
|
| template<typename ExceptionType>
|
| [[noreturn]] void setupAndThrowException(
|
| const std::string message,
|
| const char* file,
|
| const int line,
|
| const char* func,
|
| const bool translatable = false
|
| )
|
| {
|
| ExceptionType exception {message};
|
| exception.setTranslatable(translatable);
|
| exception.setDebugInformation(file, line, func);
|
| throw exception;
|
| }
|
| }
|
|
|
| #endif
|
|
|
|
|
|
|
| template<typename Exception>
|
| constexpr void THROWM_(
|
| const std::string& msg,
|
| const std::source_location location = std::source_location::current()
|
| )
|
| {
|
| Base::setupAndThrowException<Exception>(msg, location);
|
| }
|
|
|
| template<typename Exception>
|
| constexpr void THROWMT_(
|
| const std::string& msg,
|
| const std::source_location location = std::source_location::current()
|
| )
|
| {
|
| Base::setupAndThrowException<Exception>(msg, location, true);
|
| }
|
|
|
| template<typename Exception>
|
| constexpr void FC_THROWM_(
|
| const std::string& raw_msg,
|
| const std::source_location location = std::source_location::current()
|
| )
|
| {
|
| THROWM_<Exception>(raw_msg, location);
|
| }
|
|
|
| namespace Base
|
| {
|
|
|
| class BaseExport Exception: public BaseClass
|
| {
|
| TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
|
|
| public:
|
| explicit Exception(std::string message = "FreeCAD Exception");
|
| ~Exception() noexcept override = default;
|
|
|
| Exception& operator=(const Exception& inst);
|
| Exception& operator=(Exception&& inst) noexcept;
|
|
|
| virtual const char* what() const noexcept;
|
| virtual void reportException() const;
|
|
|
| inline void setMessage(const std::string& message);
|
|
|
|
|
| inline std::string getMessage() const;
|
| inline std::string getFile() const;
|
| inline int getLine() const;
|
| inline std::string getFunction() const;
|
| inline bool getTranslatable() const;
|
| inline bool getReported() const;
|
| inline void setReported(bool reported) const;
|
|
|
| #if defined(HAVE_STD_SOURCE_LOCATION)
|
| inline void setDebugInformation(const std::source_location& location);
|
| #else
|
| inline void setDebugInformation(const char* file, int line, const char* func);
|
| #endif
|
|
|
| inline void setTranslatable(bool translatable);
|
|
|
| PyObject* getPyObject() override;
|
| void setPyObject(PyObject* pydict) override;
|
|
|
| virtual PyObject* getPyExceptionType() const;
|
| virtual void setPyException() const;
|
|
|
| protected:
|
| Exception(const Exception& inst);
|
| Exception(Exception&& inst) noexcept;
|
|
|
| private:
|
| std::string errorMessage;
|
| std::string fileName;
|
| int lineNum {0};
|
| std::string functionName;
|
| bool isTranslatable {false};
|
| mutable bool hasBeenReported {false};
|
| };
|
|
|
| class BaseExport AbortException: public Exception
|
| {
|
| TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
|
|
| public:
|
| explicit AbortException(const std::string& message = "Aborted operation");
|
|
|
| const char* what() const noexcept override;
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport XMLBaseException: public Exception
|
| {
|
| public:
|
| explicit XMLBaseException(const std::string& message = "XML base exception");
|
|
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport XMLParseException: public XMLBaseException
|
| {
|
| public:
|
| explicit XMLParseException(const std::string& message = "XML parse exception");
|
|
|
| const char* what() const noexcept override;
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport XMLAttributeError: public XMLBaseException
|
| {
|
| public:
|
| explicit XMLAttributeError(const std::string& message = "XML attribute error");
|
|
|
| const char* what() const noexcept override;
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport FileException: public Exception
|
| {
|
| public:
|
| explicit FileException(
|
| const std::string& message = "Unknown file exception happened",
|
| const std::string& fileName = ""
|
| );
|
| FileException(const std::string& message, const FileInfo& File);
|
|
|
| const char* what() const noexcept override;
|
| void reportException() const override;
|
| std::string getFileName() const;
|
| PyObject* getPyObject() override;
|
|
|
| void setPyObject(PyObject* pydict) override;
|
|
|
| PyObject* getPyExceptionType() const override;
|
|
|
| private:
|
| FileInfo file;
|
|
|
|
|
| std::string _sErrMsgAndFileName;
|
| void setFileName(const std::string& fileName);
|
| };
|
|
|
| class BaseExport FileSystemError: public Exception
|
| {
|
| public:
|
| explicit FileSystemError(const std::string& message = "File system error");
|
| FileSystemError(const FileSystemError&) = default;
|
| FileSystemError(FileSystemError&&) = default;
|
|
|
| ~FileSystemError() noexcept override = default;
|
| FileSystemError& operator=(const FileSystemError&) = default;
|
| FileSystemError& operator=(FileSystemError&&) = default;
|
|
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
|
|
| class BaseExport BadFormatError: public Exception
|
| {
|
| public:
|
| explicit BadFormatError(const std::string& message = "Bad format error");
|
| BadFormatError(const BadFormatError&) = default;
|
| BadFormatError(BadFormatError&&) = default;
|
|
|
| ~BadFormatError() noexcept override = default;
|
| BadFormatError& operator=(const BadFormatError&) = default;
|
| BadFormatError& operator=(BadFormatError&&) = default;
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| #if defined(__GNUC__)
|
|
|
| class BaseExport MemoryException: public Exception, virtual public std::bad_alloc
|
| #else
|
| class BaseExport MemoryException: public Exception
|
| #endif
|
| {
|
| public:
|
| explicit MemoryException(const std::string& = "Not enough memory available");
|
|
|
| #if defined(__GNUC__)
|
| const char* what() const noexcept override;
|
| #endif
|
|
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
|
|
| class BaseExport AccessViolation: public Exception
|
| {
|
| public:
|
| explicit AccessViolation(const std::string& message = "Access violation");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
|
|
| class BaseExport AbnormalProgramTermination: public Exception
|
| {
|
| public:
|
| explicit AbnormalProgramTermination(const std::string& message = "Abnormal program termination");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport UnknownProgramOption: public Exception
|
| {
|
| public:
|
| explicit UnknownProgramOption(const std::string& message = "Unknown program option");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport ProgramInformation: public Exception
|
| {
|
| public:
|
| explicit ProgramInformation(const std::string& message = "Program information");
|
| };
|
|
|
| class BaseExport TypeError: public Exception
|
| {
|
| public:
|
| explicit TypeError(const std::string& message = "Type error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport ValueError: public Exception
|
| {
|
| public:
|
| explicit ValueError(const std::string& message = "Value error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
|
|
| class BaseExport IndexError: public Exception
|
| {
|
| public:
|
| explicit IndexError(const std::string& message = "Index error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport NameError: public Exception
|
| {
|
| public:
|
| explicit NameError(const std::string& message = "Name error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport ImportError: public Exception
|
| {
|
| public:
|
| explicit ImportError(const std::string& message = "Import error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport AttributeError: public Exception
|
| {
|
| public:
|
| explicit AttributeError(const std::string& message = "Attribute error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport PropertyError: public AttributeError
|
| {
|
| public:
|
| explicit PropertyError(const std::string& message = "Property error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport RuntimeError: public Exception
|
| {
|
| public:
|
| explicit RuntimeError(const std::string& message = "Runtime error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport BadGraphError: public RuntimeError
|
| {
|
| public:
|
| explicit BadGraphError(const std::string& message = "Bad graph error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport NotImplementedError: public Exception
|
| {
|
| public:
|
| explicit NotImplementedError(const std::string& message = "Not implemented error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport ZeroDivisionError: public Exception
|
| {
|
| public:
|
| explicit ZeroDivisionError(const std::string& message = "Zero division error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport ReferenceError: public Exception
|
| {
|
| public:
|
| explicit ReferenceError(const std::string& message = "Reference error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport ExpressionError: public Exception
|
| {
|
| public:
|
| explicit ExpressionError(const std::string& message = "Expression error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport ParserError: public Exception
|
| {
|
| public:
|
| explicit ParserError(const std::string& message = "Parser error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport UnicodeError: public Exception
|
| {
|
| public:
|
| explicit UnicodeError(const std::string& message = "Unicode error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport OverflowError: public Exception
|
| {
|
| public:
|
| explicit OverflowError(const std::string& message = "Overflow error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport UnderflowError: public Exception
|
| {
|
| public:
|
| explicit UnderflowError(const std::string& message = "Underflow error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport UnitsMismatchError: public Exception
|
| {
|
| public:
|
| explicit UnitsMismatchError(const std::string& message = "Units mismatch error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport CADKernelError: public Exception
|
| {
|
| public:
|
| explicit CADKernelError(const std::string& message = "CAD kernel error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| class BaseExport RestoreError: public Exception
|
| {
|
| public:
|
| explicit RestoreError(const std::string& message = "Restore error");
|
| PyObject* getPyExceptionType() const override;
|
| };
|
|
|
| inline void Exception::setMessage(const std::string& message)
|
| {
|
| errorMessage = message;
|
| }
|
|
|
| inline std::string Exception::getMessage() const
|
| {
|
| return errorMessage;
|
| }
|
|
|
| inline std::string Exception::getFile() const
|
| {
|
| return fileName;
|
| }
|
|
|
| inline int Exception::getLine() const
|
| {
|
| return lineNum;
|
| }
|
|
|
| inline std::string Exception::getFunction() const
|
| {
|
| return functionName;
|
| }
|
|
|
| inline bool Exception::getTranslatable() const
|
| {
|
| return isTranslatable;
|
| }
|
|
|
| inline bool Exception::getReported() const
|
| {
|
| return hasBeenReported;
|
| }
|
|
|
| inline void Exception::setReported(const bool reported) const
|
| {
|
| hasBeenReported = reported;
|
| }
|
|
|
| #if defined(HAVE_STD_SOURCE_LOCATION)
|
| inline void Exception::setDebugInformation(const std::source_location& location)
|
| {
|
| fileName = location.file_name();
|
| lineNum = static_cast<int>(location.line());
|
| functionName = location.function_name();
|
| }
|
| #else
|
| inline void Exception::setDebugInformation(const char* file, int line, const char* func)
|
| {
|
| fileName = file;
|
| lineNum = line;
|
| functionName = func;
|
| }
|
| #endif
|
|
|
| inline void Exception::setTranslatable(const bool translatable)
|
| {
|
| isTranslatable = translatable;
|
| }
|
|
|
| #if defined(__GNUC__) && defined(FC_OS_LINUX)
|
| class SignalException
|
| {
|
| public:
|
| SignalException();
|
| ~SignalException();
|
|
|
| private:
|
| static void throw_signal(int signum);
|
|
|
| struct sigaction new_action {};
|
| struct sigaction old_action {};
|
| bool ok {false};
|
| };
|
| #endif
|
|
|
| }
|
|
|
| #endif
|
|
|