/src/ogre/OgreMain/include/OgreException.h
Line | Count | Source |
1 | | /* |
2 | | ----------------------------------------------------------------------------- |
3 | | This source file is part of OGRE |
4 | | (Object-oriented Graphics Rendering Engine) |
5 | | For the latest info, see http://www.ogre3d.org/ |
6 | | |
7 | | Copyright (c) 2000-2014 Torus Knot Software Ltd |
8 | | |
9 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
10 | | of this software and associated documentation files (the "Software"), to deal |
11 | | in the Software without restriction, including without limitation the rights |
12 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
13 | | copies of the Software, and to permit persons to whom the Software is |
14 | | furnished to do so, subject to the following conditions: |
15 | | |
16 | | The above copyright notice and this permission notice shall be included in |
17 | | all copies or substantial portions of the Software. |
18 | | |
19 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
20 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
22 | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
24 | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
25 | | THE SOFTWARE. |
26 | | ----------------------------------------------------------------------------- |
27 | | */ |
28 | | #ifndef __Exception_H_ |
29 | | #define __Exception_H_ |
30 | | |
31 | | // Precompiler options |
32 | | #include "OgrePrerequisites.h" |
33 | | #include "OgreString.h" |
34 | | #include <exception> |
35 | | #include "OgreHeaderPrefix.h" |
36 | | |
37 | | // Check for OGRE assert mode |
38 | | |
39 | | // RELEASE_EXCEPTIONS mode |
40 | | #if OGRE_ASSERT_MODE == 1 |
41 | | # if OGRE_DEBUG_MODE |
42 | | # define OgreAssert( a, b ) assert( (a) && (b) ) |
43 | | # else |
44 | | # define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT_2( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (#a " failed. " b) ) |
45 | | # endif |
46 | | |
47 | | // EXCEPTIONS mode |
48 | | #elif OGRE_ASSERT_MODE == 2 |
49 | | # define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT_2( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (#a " failed. " b) ) |
50 | | // STANDARD mode |
51 | | #else |
52 | | /** Checks a condition at runtime and throws exception/ aborts if it fails. |
53 | | * |
54 | | * The macros OgreAssert (and OgreAssertDbg) evaluate the specified expression. |
55 | | * If it is 0, OgreAssert raises an error (see Ogre::RuntimeAssertionException) in Release configuration |
56 | | * and aborts in Debug configuration. |
57 | | * The macro OgreAssert checks the condition in both Debug and Release configurations |
58 | | * while OgreAssertDbg is only retained in the Debug configuration. |
59 | | * |
60 | | * To always abort instead of throwing an exception or disabling OgreAssert in Release configuration altogether, |
61 | | * set OGRE_ASSERT_MODE in CMake accordingly. |
62 | | */ |
63 | | # define OgreAssert( expr, mesg ) assert( (expr) && (mesg) ) |
64 | | #endif |
65 | | |
66 | | #if OGRE_DEBUG_MODE |
67 | | # define OgreAssertDbg( a, b ) OgreAssert( a, b ) |
68 | | #else |
69 | | /// replaced with OgreAssert(expr, mesg) in Debug configuration |
70 | | # define OgreAssertDbg( expr, mesg ) |
71 | | #endif |
72 | | |
73 | | namespace Ogre { |
74 | | |
75 | | /** \addtogroup Core |
76 | | * @{ |
77 | | */ |
78 | | /** \addtogroup General |
79 | | * @{ |
80 | | */ |
81 | | /** When thrown, provides information about an error that has occurred inside the engine. |
82 | | |
83 | | OGRE never uses return values to indicate errors. Instead, if an |
84 | | error occurs, an exception is thrown, and this is the object that |
85 | | encapsulates the detail of the problem. The application using |
86 | | OGRE should always ensure that the exceptions are caught, so all |
87 | | OGRE engine functions should occur within a |
88 | | try{} catch(Ogre::Exception& e) {} block. |
89 | | @par |
90 | | The user application should never create any instances of this |
91 | | object unless it wishes to unify its error handling using the |
92 | | same object. |
93 | | */ |
94 | | class _OgreExport Exception : public std::exception |
95 | | { |
96 | | protected: |
97 | | long line; |
98 | | const char* typeName; |
99 | | String description; |
100 | | String source; |
101 | | const char* file; |
102 | | String fullDesc; // storage for char* returned by what() |
103 | | public: |
104 | | /** Static definitions of error codes. |
105 | | @todo |
106 | | Add many more exception codes, since we want the user to be able |
107 | | to catch most of them. |
108 | | */ |
109 | | enum ExceptionCodes { |
110 | | ERR_CANNOT_WRITE_TO_FILE, |
111 | | ERR_INVALID_STATE, |
112 | | ERR_INVALIDPARAMS, |
113 | | ERR_RENDERINGAPI_ERROR, |
114 | | ERR_DUPLICATE_ITEM, |
115 | | ERR_ITEM_NOT_FOUND = ERR_DUPLICATE_ITEM, |
116 | | ERR_FILE_NOT_FOUND, |
117 | | ERR_INTERNAL_ERROR, |
118 | | ERR_RT_ASSERTION_FAILED, |
119 | | ERR_NOT_IMPLEMENTED, |
120 | | ERR_INVALID_CALL |
121 | | }; |
122 | | |
123 | | /** Default constructor. |
124 | | */ |
125 | | Exception( int number, const String& description, const String& source ); |
126 | | |
127 | | /** Advanced constructor. |
128 | | */ |
129 | | Exception( int number, const String& description, const String& source, const char* type, const char* file, long line ); |
130 | | |
131 | | /** Copy constructor. |
132 | | */ |
133 | | Exception(const Exception& rhs); |
134 | | |
135 | | /// Needed for compatibility with std::exception |
136 | 512 | ~Exception() throw() {} |
137 | | |
138 | | /** Returns a string with the full description of this error. |
139 | | |
140 | | The description contains the error number, the description |
141 | | supplied by the thrower, what routine threw the exception, |
142 | | and will also supply extra platform-specific information |
143 | | where applicable. For example - in the case of a rendering |
144 | | library error, the description of the error will include both |
145 | | the place in which OGRE found the problem, and a text |
146 | | description from the 3D rendering library, if available. |
147 | | */ |
148 | 0 | const String& getFullDescription(void) const { return fullDesc; } |
149 | | |
150 | | /** Gets the source function. |
151 | | */ |
152 | 0 | const String &getSource() const { return source; } |
153 | | |
154 | | /** Gets source file name. |
155 | | */ |
156 | 0 | const char* getFile() const { return file; } |
157 | | |
158 | | /** Gets line number. |
159 | | */ |
160 | 0 | long getLine() const { return line; } |
161 | | |
162 | | /** Returns a string with only the 'description' field of this exception. Use |
163 | | getFullDescriptionto get a full description of the error including line number, |
164 | | error number and what function threw the exception. |
165 | | */ |
166 | 0 | const String &getDescription(void) const { return description; } |
167 | | |
168 | 0 | const char* what() const throw() override { return fullDesc.c_str(); } |
169 | | |
170 | | }; |
171 | | |
172 | | |
173 | | /** Template struct which creates a distinct type for each exception code. |
174 | | @note |
175 | | This is useful because it allows us to create an overloaded method |
176 | | for returning different exception types by value without ambiguity. |
177 | | From 'Modern C++ Design' (Alexandrescu 2001). |
178 | | */ |
179 | | class _OgreExport UnimplementedException : public Exception |
180 | | { |
181 | | public: |
182 | | UnimplementedException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
183 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
184 | | }; |
185 | | class _OgreExport FileNotFoundException : public Exception |
186 | | { |
187 | | public: |
188 | | FileNotFoundException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
189 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
190 | | }; |
191 | | class _OgreExport IOException : public Exception |
192 | | { |
193 | | public: |
194 | | IOException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
195 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
196 | | }; |
197 | | class _OgreExport InvalidStateException : public Exception |
198 | | { |
199 | | public: |
200 | | InvalidStateException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
201 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
202 | | }; |
203 | | class _OgreExport InvalidParametersException : public Exception |
204 | | { |
205 | | public: |
206 | | InvalidParametersException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
207 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
208 | | }; |
209 | | class _OgreExport ItemIdentityException : public Exception |
210 | | { |
211 | | public: |
212 | | ItemIdentityException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
213 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
214 | | }; |
215 | | class _OgreExport InternalErrorException : public Exception |
216 | | { |
217 | | public: |
218 | | InternalErrorException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
219 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
220 | | }; |
221 | | class _OgreExport RenderingAPIException : public Exception |
222 | | { |
223 | | public: |
224 | | RenderingAPIException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
225 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
226 | | }; |
227 | | class _OgreExport RuntimeAssertionException : public Exception |
228 | | { |
229 | | public: |
230 | | RuntimeAssertionException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
231 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
232 | | }; |
233 | | class _OgreExport InvalidCallException : public Exception |
234 | | { |
235 | | public: |
236 | | InvalidCallException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine) |
237 | 0 | : Exception(inNumber, inDescription, inSource, __FUNCTION__, inFile, inLine) {} |
238 | | }; |
239 | | |
240 | | /** Class implementing dispatch methods in order to construct by-value |
241 | | exceptions of a derived type based just on an exception code. |
242 | | |
243 | | This nicely handles construction of derived Exceptions by value (needed |
244 | | for throwing) without suffering from ambiguity - each code is turned into |
245 | | a distinct type so that methods can be overloaded. This allows OGRE_EXCEPT |
246 | | to stay small in implementation (desirable since it is embedded) whilst |
247 | | still performing rich code-to-type mapping. |
248 | | */ |
249 | | class ExceptionFactory |
250 | | { |
251 | | private: |
252 | | /// Private constructor, no construction |
253 | 0 | ExceptionFactory() {} |
254 | | static OGRE_NORETURN void _throwException( |
255 | | Exception::ExceptionCodes code, int number, |
256 | | const String& desc, |
257 | | const String& src, const char* file, long line) |
258 | 0 | { |
259 | 0 | switch (code) |
260 | 0 | { |
261 | 0 | case Exception::ERR_CANNOT_WRITE_TO_FILE: throw IOException(number, desc, src, file, line); |
262 | 0 | case Exception::ERR_INVALID_STATE: throw InvalidStateException(number, desc, src, file, line); |
263 | 0 | case Exception::ERR_INVALIDPARAMS: throw InvalidParametersException(number, desc, src, file, line); |
264 | 0 | case Exception::ERR_RENDERINGAPI_ERROR: throw RenderingAPIException(number, desc, src, file, line); |
265 | 0 | case Exception::ERR_DUPLICATE_ITEM: throw ItemIdentityException(number, desc, src, file, line); |
266 | 0 | case Exception::ERR_FILE_NOT_FOUND: throw FileNotFoundException(number, desc, src, file, line); |
267 | 0 | case Exception::ERR_INTERNAL_ERROR: throw InternalErrorException(number, desc, src, file, line); |
268 | 0 | case Exception::ERR_RT_ASSERTION_FAILED: throw RuntimeAssertionException(number, desc, src, file, line); |
269 | 0 | case Exception::ERR_NOT_IMPLEMENTED: throw UnimplementedException(number, desc, src, file, line); |
270 | 0 | case Exception::ERR_INVALID_CALL: throw InvalidCallException(number, desc, src, file, line); |
271 | 0 | default: throw Exception(number, desc, src, "Exception", file, line); |
272 | 0 | } |
273 | 0 | } |
274 | | public: |
275 | | static OGRE_NORETURN void throwException( |
276 | | Exception::ExceptionCodes code, |
277 | | const String& desc, |
278 | | const String& src, const char* file, long line) |
279 | 0 | { |
280 | 0 | _throwException(code, code, desc, src, file, line); |
281 | 0 | } |
282 | | }; |
283 | | |
284 | | |
285 | | |
286 | | #ifndef OGRE_EXCEPT |
287 | | #define OGRE_EXCEPT_3(code, desc, src) Ogre::ExceptionFactory::throwException(code, desc, src, __FILE__, __LINE__) |
288 | | #define OGRE_EXCEPT_2(code, desc) Ogre::ExceptionFactory::throwException(code, desc, __FUNCTION__, __FILE__, __LINE__) |
289 | | #define OGRE_EXCEPT_CHOOSER(arg1, arg2, arg3, arg4, ...) arg4 |
290 | | #define OGRE_EXPAND(x) x // MSVC workaround |
291 | | #define OGRE_EXCEPT(...) OGRE_EXPAND(OGRE_EXCEPT_CHOOSER(__VA_ARGS__, OGRE_EXCEPT_3, OGRE_EXCEPT_2)(__VA_ARGS__)) |
292 | | #endif |
293 | | /** @} */ |
294 | | /** @} */ |
295 | | |
296 | | } // Namespace Ogre |
297 | | |
298 | | #include "OgreHeaderSuffix.h" |
299 | | |
300 | | #endif |