/* * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #ifndef ErrorHandling_h #define ErrorHandling_h #include #include "SourceCodePos.h" #include "tstrings.h" // // Exception handling helpers. Allow transparent exception logging. // Use as follows: // // void foo () { // JP_TRY; // // if (!do_something()) { // JP_THROW("do_something() failed"); // } // // JP_CATCH_ALL; // } // // Logs std::exception caught at 'pos'. void reportError(const SourceCodePos& pos, const std::exception& e); // Logs unknown exception caught at 'pos'. // Assumed to be called from catch (...) {} void reportUnknownError(const SourceCodePos& pos); std::string makeMessage(const std::exception& e, const SourceCodePos& pos); std::string joinErrorMessages(const std::string& a, const std::string& b); template class JpError: public Base { public: JpError(const Base& e, const SourceCodePos& pos): Base(e), msg(::makeMessage(e, pos)) { } ~JpError() throw() { } // override Base::what() const char* what() const throw() { return msg.c_str(); } private: // Assert Base is derived from std::exception enum { isDerivedFromStdException = sizeof(static_cast((Base*)0)) }; std::string msg; }; template inline JpError makeException(const T& obj, const SourceCodePos& p) { return JpError(obj, p); } inline JpError makeException( const std::string& msg, const SourceCodePos& p) { return JpError(std::runtime_error(msg), p); } inline JpError makeException( const tstrings::any& msg, const SourceCodePos& p) { return makeException(msg.str(), p); } inline JpError makeException( std::string::const_pointer msg, const SourceCodePos& p) { return makeException(std::string(msg), p); } #define JP_REPORT_ERROR(e) reportError(JP_SOURCE_CODE_POS, e) #define JP_REPORT_UNKNOWN_ERROR reportUnknownError(JP_SOURCE_CODE_POS) // Redefine locally in cpp file(s) if need more handling than just reporting #define JP_HANDLE_ERROR(e) JP_REPORT_ERROR(e) #define JP_HANDLE_UNKNOWN_ERROR JP_REPORT_UNKNOWN_ERROR #define JP_TRY \ try \ { \ do {} while(0) #define JP_DEFAULT_CATCH_EXCEPTIONS \ JP_CATCH_STD_EXCEPTION \ JP_CATCH_UNKNOWN_EXCEPTION #define JP_CATCH_EXCEPTIONS \ JP_DEFAULT_CATCH_EXCEPTIONS #define JP_CATCH_ALL \ } \ JP_CATCH_EXCEPTIONS \ do {} while(0) #define JP_CATCH_STD_EXCEPTION \ catch (const std::exception& e) \ { \ JP_HANDLE_ERROR(e); \ } #define JP_CATCH_UNKNOWN_EXCEPTION \ catch (...) \ { \ JP_HANDLE_UNKNOWN_ERROR; \ } #define JP_THROW(e) throw makeException((e), JP_SOURCE_CODE_POS) #define JP_NO_THROW(expr) \ JP_TRY; \ expr; \ JP_CATCH_ALL #endif // #ifndef ErrorHandling_h