/************************************************************************* * Copyright (C) [2023-2024] by Cambricon, Inc. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *************************************************************************/ #ifndef CSRC_COMMON_STACK_EXCEPTION_H_ #define CSRC_COMMON_STACK_EXCEPTION_H_ #include #include #include #include namespace tmo { namespace stack_exception { /** Call-stack entry datastructure. */ struct entry { /** Default constructor that clears all fields. */ entry() : line(0) {} std::string file; ///< filename size_t line; ///< line number std::string function; ///< name of function or method /** Serialize entry into a text string. */ std::string to_string() const { std::ostringstream os; os << file; if (line > 0) { os << ":" << line; } os << " @" << function; return os.str(); } }; /** Stack-trace base class, for retrieving the current call-stack. */ class call_stack { public: /** Stack-trace consructor. \param num_discard - number of stack entries to discard at the top. */ call_stack(const size_t num_discard = 0); virtual ~call_stack() throw(); /** Serializes the entire call-stack into a text string. */ std::string to_string() const { std::ostringstream os; for (size_t i = 0; i < stack.size(); i++) os << stack[i].to_string() << std::endl; return os.str(); } /** Call stack. */ std::vector stack; }; /** Abstract base-class for all stack-augmented exception classes. * Enables catching of all stack-augmented exception classes. */ class stack_exception_base : public call_stack { public: stack_exception_base(const bool _show_stack) : call_stack(2), show_stack(_show_stack) {} virtual ~stack_exception_base() throw() {} virtual const char *what() const throw() = 0; /// flag to indicate if stack-trace is included in what() messages bool show_stack; }; /** Template for stack-augmented exception classes. */ template class stack_exception : public T, public stack_exception_base { public: stack_exception(const std::string &msg) : T(msg), stack_exception_base(true) {} virtual ~stack_exception() throw() {} stack_exception(const char *file, int line, const char *pretty_function, const std::string &msg) : T(msg), stack_exception_base(true) { entry e; e.file = file; e.line = line; e.function = pretty_function; stack.insert(stack.begin(), e); } virtual const char *what() const throw() { if (show_stack) { // concatenate message with stack trace buffer = "[" + std::string(T::what()) + "]\n" + stack_exception::to_string(); return buffer.c_str(); } else { return T::what(); } } private: mutable std::string buffer; }; /** Stack-augmented exception classes for all std::exception classes. */ // typedef stack_exception TmoException; // typedef stack_exception stack_range_error; // typedef stack_exception stack_overflow_error; // typedef stack_exception stack_underflow_error; // typedef stack_exception stack_logic_error; // typedef stack_exception stack_domain_error; // typedef stack_exception stack_invalid_argument; // typedef stack_exception stack_length_error; // typedef stack_exception stack_out_of_range; } // namespace stack_exception class _TmoException : public stack_exception::stack_exception { public: _TmoException(const std::string &msg) : stack_exception(msg) {} _TmoException(const char *file, int line, const char *pretty_function, const std::string &msg) : stack_exception(file, line, pretty_function, msg) {} }; #define TmoException(msg) tmo::_TmoException(__FILE__, __LINE__, __PRETTY_FUNCTION__, msg) } // namespace tmo #endif // CSRC_COMMON_STACK_EXCEPTION_H_