1 /*
2 * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #ifndef ErrorHandling_h
27 #define ErrorHandling_h
28
29
30 #include <stdexcept>
31
32 #include "SourceCodePos.h"
33 #include "tstrings.h"
34
35
36 //
37 // Exception handling helpers. Allow transparent exception logging.
38 // Use as follows:
39 //
40 // void foo () {
41 // JP_TRY;
42 //
43 // if (!do_something()) {
44 // JP_THROW("do_something() failed");
45 // }
46 //
47 // JP_CATCH_ALL;
48 // }
49 //
50
51
52 // Logs std::exception caught at 'pos'.
53 void reportError(const SourceCodePos& pos, const std::runtime_error& e);
54 // Logs unknown exception caught at 'pos'.
55 // Assumed to be called from catch (...) {}
56 void reportUnknownError(const SourceCodePos& pos);
57
58 std::string makeMessage(const std::runtime_error& e, const SourceCodePos& pos);
59
60 std::string joinErrorMessages(const std::string& a, const std::string& b);
61
62 std::string lastCRTError();
63
64
65 class JpErrorBase {
66 public:
67 virtual const char* rawMessage() const throw() = 0;
68 };
69
70
71 template <class Base>
72 class JpError: public JpErrorBase, public Base {
73 public:
JpError(const Base & e,const SourceCodePos & pos)74 JpError(const Base& e, const SourceCodePos& pos):
75 Base(e), msg(::makeMessage(e, pos)) {
76 }
77
throw()78 ~JpError() throw() {
79 }
80
81 // override Base::what()
what()82 const char* what() const throw() {
83 return msg.c_str();
84 }
85
86 // override JpErrorBase
rawMessage()87 const char* rawMessage() const throw() {
88 return Base::what();
89 }
90 private:
91 // Assert Base is derived from std::runtime_error
92 enum { isDerivedFromStdException =
93 sizeof(static_cast<std::runtime_error*>((Base*)0)) };
94
95 std::string msg;
96 };
97
98 template <class T>
makeException(const T & obj,const SourceCodePos & p)99 inline JpError<T> makeException(const T& obj, const SourceCodePos& p) {
100 return JpError<T>(obj, p);
101 }
102
makeException(const std::string & msg,const SourceCodePos & p)103 inline JpError<std::runtime_error> makeException(
104 const std::string& msg, const SourceCodePos& p) {
105 return JpError<std::runtime_error>(std::runtime_error(msg), p);
106 }
107
makeException(const tstrings::any & msg,const SourceCodePos & p)108 inline JpError<std::runtime_error> makeException(
109 const tstrings::any& msg, const SourceCodePos& p) {
110 return makeException(msg.str(), p);
111 }
112
makeException(std::string::const_pointer msg,const SourceCodePos & p)113 inline JpError<std::runtime_error> makeException(
114 std::string::const_pointer msg, const SourceCodePos& p) {
115 return makeException(std::string(msg), p);
116 }
117
118
119 #define JP_REPORT_ERROR(e) reportError(JP_SOURCE_CODE_POS, e)
120 #define JP_REPORT_UNKNOWN_ERROR reportUnknownError(JP_SOURCE_CODE_POS)
121
122 // Redefine locally in cpp file(s) if need more handling than just reporting
123 #define JP_HANDLE_ERROR(e) JP_REPORT_ERROR(e)
124 #define JP_HANDLE_UNKNOWN_ERROR JP_REPORT_UNKNOWN_ERROR
125
126
127 #define JP_TRY \
128 try \
129 { \
130 do {} while(0)
131
132 #define JP_DEFAULT_CATCH_EXCEPTIONS \
133 JP_CATCH_STD_EXCEPTION \
134 JP_CATCH_UNKNOWN_EXCEPTION
135
136 #define JP_CATCH_EXCEPTIONS \
137 JP_DEFAULT_CATCH_EXCEPTIONS
138
139 #define JP_CATCH_ALL \
140 } \
141 JP_CATCH_EXCEPTIONS \
142 do {} while(0)
143
144 #define JP_CATCH_STD_EXCEPTION \
145 catch (const std::runtime_error& e) \
146 { \
147 JP_HANDLE_ERROR(e); \
148 }
149
150 #define JP_CATCH_UNKNOWN_EXCEPTION \
151 catch (...) \
152 { \
153 JP_HANDLE_UNKNOWN_ERROR; \
154 }
155
156
157 #define JP_THROW(e) throw makeException((e), JP_SOURCE_CODE_POS)
158
159 #define JP_NO_THROW(expr) \
160 JP_TRY; \
161 expr; \
162 JP_CATCH_ALL
163
164 #endif // #ifndef ErrorHandling_h
165