Line data Source code
1 : /**********************************************************************
2 : * $Id$
3 : *
4 : * Name: cpl_error.h
5 : * Project: CPL - Common Portability Library
6 : * Purpose: CPL Error handling
7 : * Author: Daniel Morissette, danmo@videotron.ca
8 : *
9 : **********************************************************************
10 : * Copyright (c) 1998, Daniel Morissette
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #ifndef CPL_ERROR_H_INCLUDED
32 : #define CPL_ERROR_H_INCLUDED
33 :
34 : #include "cpl_port.h"
35 :
36 : #include <stdarg.h>
37 : #include <stddef.h>
38 :
39 : /*=====================================================================
40 : Error handling functions (cpl_error.c)
41 : =====================================================================*/
42 :
43 : /**
44 : * \file cpl_error.h
45 : *
46 : * CPL error handling services.
47 : */
48 :
49 : CPL_C_START
50 :
51 : /** Error category */
52 : typedef enum
53 : {
54 : CE_None = 0,
55 : CE_Debug = 1,
56 : CE_Warning = 2,
57 : CE_Failure = 3,
58 : CE_Fatal = 4
59 : } CPLErr;
60 :
61 : /* ==================================================================== */
62 : /* Well known error codes. */
63 : /* ==================================================================== */
64 :
65 : #ifdef STRICT_CPLERRORNUM_TYPE
66 :
67 : /* This is not appropriate for the general case, as there are parts */
68 : /* of GDAL which use custom error codes, but this can help diagnose confusions
69 : */
70 : /* between CPLErr and CPLErrorNum */
71 : typedef enum
72 : {
73 : CPLE_None,
74 : CPLE_AppDefined,
75 : CPLE_OutOfMemory,
76 : CPLE_FileIO,
77 : CPLE_OpenFailed,
78 : CPLE_IllegalArg,
79 : CPLE_NotSupported,
80 : CPLE_AssertionFailed,
81 : CPLE_NoWriteAccess,
82 : CPLE_UserInterrupt,
83 : CPLE_ObjectNull,
84 : CPLE_HttpResponse,
85 : CPLE_AWSBucketNotFound,
86 : CPLE_AWSObjectNotFound,
87 : CPLE_AWSAccessDenied,
88 : CPLE_AWSInvalidCredentials,
89 : CPLE_AWSSignatureDoesNotMatch,
90 : } CPLErrorNum;
91 :
92 : #else
93 :
94 : /** Error number */
95 : typedef int CPLErrorNum;
96 :
97 : /** No error */
98 : #define CPLE_None 0
99 : /** Application defined error */
100 : #define CPLE_AppDefined 1
101 : /** Out of memory error */
102 : #define CPLE_OutOfMemory 2
103 : /** File I/O error */
104 : #define CPLE_FileIO 3
105 : /** Open failed */
106 : #define CPLE_OpenFailed 4
107 : /** Illegal argument */
108 : #define CPLE_IllegalArg 5
109 : /** Not supported */
110 : #define CPLE_NotSupported 6
111 : /** Assertion failed */
112 : #define CPLE_AssertionFailed 7
113 : /** No write access */
114 : #define CPLE_NoWriteAccess 8
115 : /** User interrupted */
116 : #define CPLE_UserInterrupt 9
117 : /** NULL object */
118 : #define CPLE_ObjectNull 10
119 :
120 : /*
121 : * Filesystem-specific errors
122 : */
123 : /** HTTP response */
124 : #define CPLE_HttpResponse 11
125 : /** AWSBucketNotFound */
126 : #define CPLE_AWSBucketNotFound 12
127 : /** AWSObjectNotFound */
128 : #define CPLE_AWSObjectNotFound 13
129 : /** AWSAccessDenied */
130 : #define CPLE_AWSAccessDenied 14
131 : /** AWSInvalidCredentials */
132 : #define CPLE_AWSInvalidCredentials 15
133 : /** AWSSignatureDoesNotMatch */
134 : #define CPLE_AWSSignatureDoesNotMatch 16
135 : /** VSIE_AWSError */
136 : #define CPLE_AWSError 17
137 :
138 : /* 100 - 299 reserved for GDAL */
139 :
140 : #endif
141 :
142 : void CPL_DLL CPLError(CPLErr eErrClass, CPLErrorNum err_no,
143 : CPL_FORMAT_STRING(const char *fmt), ...)
144 : CPL_PRINT_FUNC_FORMAT(3, 4);
145 : void CPL_DLL CPLErrorV(CPLErr, CPLErrorNum, const char *, va_list);
146 : void CPL_DLL CPLEmergencyError(const char *) CPL_NO_RETURN;
147 : void CPL_DLL CPL_STDCALL CPLErrorReset(void);
148 : CPLErrorNum CPL_DLL CPL_STDCALL CPLGetLastErrorNo(void);
149 : CPLErr CPL_DLL CPL_STDCALL CPLGetLastErrorType(void);
150 : const char CPL_DLL *CPL_STDCALL CPLGetLastErrorMsg(void);
151 : GUInt32 CPL_DLL CPL_STDCALL CPLGetErrorCounter(void);
152 : void CPL_DLL *CPL_STDCALL CPLGetErrorHandlerUserData(void);
153 : void CPL_DLL CPLErrorSetState(CPLErr eErrClass, CPLErrorNum err_no,
154 : const char *pszMsg);
155 : void CPL_DLL CPLCallPreviousHandler(CPLErr eErrClass, CPLErrorNum err_no,
156 : const char *pszMsg);
157 : /*! @cond Doxygen_Suppress */
158 : void CPL_DLL CPLCleanupErrorMutex(void);
159 : /*! @endcond */
160 :
161 : /** Callback for a custom error handler */
162 : typedef void(CPL_STDCALL *CPLErrorHandler)(CPLErr, CPLErrorNum, const char *);
163 :
164 : void CPL_DLL CPL_STDCALL CPLLoggingErrorHandler(CPLErr, CPLErrorNum,
165 : const char *);
166 : void CPL_DLL CPL_STDCALL CPLDefaultErrorHandler(CPLErr, CPLErrorNum,
167 : const char *);
168 : void CPL_DLL CPL_STDCALL CPLQuietErrorHandler(CPLErr, CPLErrorNum,
169 : const char *);
170 : void CPLTurnFailureIntoWarning(int bOn);
171 :
172 : CPLErrorHandler CPL_DLL CPLGetErrorHandler(void **ppUserData);
173 :
174 : CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandler(CPLErrorHandler);
175 : CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandlerEx(CPLErrorHandler,
176 : void *);
177 : void CPL_DLL CPL_STDCALL CPLPushErrorHandler(CPLErrorHandler);
178 : void CPL_DLL CPL_STDCALL CPLPushErrorHandlerEx(CPLErrorHandler, void *);
179 : void CPL_DLL CPL_STDCALL CPLSetCurrentErrorHandlerCatchDebug(int bCatchDebug);
180 : void CPL_DLL CPL_STDCALL CPLPopErrorHandler(void);
181 :
182 : #ifdef WITHOUT_CPLDEBUG
183 : #define CPLDebug(...) /* Eat all CPLDebug calls. */
184 : #define CPLDebugProgress(...) /* Eat all CPLDebugProgress calls. */
185 : #else
186 : void CPL_DLL CPLDebug(const char *, CPL_FORMAT_STRING(const char *), ...)
187 : CPL_PRINT_FUNC_FORMAT(2, 3);
188 : void CPL_DLL CPLDebugProgress(const char *, CPL_FORMAT_STRING(const char *),
189 : ...) CPL_PRINT_FUNC_FORMAT(2, 3);
190 : #endif
191 :
192 : #ifdef DEBUG
193 : /** Same as CPLDebug(), but expands to nothing for non-DEBUG builds.
194 : * @since GDAL 3.1
195 : */
196 : #define CPLDebugOnly(...) CPLDebug(__VA_ARGS__)
197 : #else
198 : /** Same as CPLDebug(), but expands to nothing for non-DEBUG builds.
199 : * @since GDAL 3.1
200 : */
201 : #define CPLDebugOnly(...)
202 : #endif
203 :
204 : void CPL_DLL CPL_STDCALL _CPLAssert(const char *, const char *,
205 : int) CPL_NO_RETURN;
206 :
207 : #if defined(DEBUG) && !defined(CPPCHECK)
208 : /** Assert on an expression. Only enabled in DEBUG mode */
209 : #define CPLAssert(expr) \
210 : ((expr) ? (void)(0) : _CPLAssert(#expr, __FILE__, __LINE__))
211 : /** Assert on an expression in DEBUG mode. Evaluate it also in non-DEBUG mode
212 : * (useful to 'consume' a error return variable) */
213 : #define CPLAssertAlwaysEval(expr) CPLAssert(expr)
214 : #else
215 : /** Assert on an expression. Only enabled in DEBUG mode */
216 : #define CPLAssert(expr)
217 : #ifdef __cplusplus
218 : /** Assert on an expression in DEBUG mode. Evaluate it also in non-DEBUG mode
219 : * (useful to 'consume' a error return variable) */
220 : #define CPLAssertAlwaysEval(expr) CPL_IGNORE_RET_VAL(expr)
221 : #else
222 : /** Assert on an expression in DEBUG mode. Evaluate it also in non-DEBUG mode
223 : * (useful to 'consume' a error return variable) */
224 : #define CPLAssertAlwaysEval(expr) (void)(expr)
225 : #endif
226 : #endif
227 :
228 : CPL_C_END
229 :
230 : /*! @cond Doxygen_Suppress */
231 : /*
232 : * Helper macros used for input parameters validation.
233 : */
234 : #ifdef DEBUG
235 : #define VALIDATE_POINTER_ERR CE_Fatal
236 : #else
237 : #define VALIDATE_POINTER_ERR CE_Failure
238 : #endif
239 :
240 : /*! @endcond */
241 :
242 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
243 :
244 : extern "C++"
245 : {
246 : /*! @cond Doxygen_Suppress */
247 : template <class T> T *CPLAssertNotNull(T *x) CPL_RETURNS_NONNULL;
248 :
249 99 : template <class T> T *CPLAssertNotNull(T *x)
250 : {
251 99 : CPLAssert(x);
252 99 : return x;
253 : }
254 :
255 : #include <memory>
256 : #include <string>
257 :
258 : /*! @endcond */
259 :
260 : /** Class that installs a (thread-local) error handler on construction, and
261 : * restore the initial one on destruction.
262 : */
263 : class CPL_DLL CPLErrorHandlerPusher
264 : {
265 : public:
266 : /** Constructor that installs a thread-local temporary error handler
267 : * (typically CPLQuietErrorHandler)
268 : */
269 54132 : explicit CPLErrorHandlerPusher(CPLErrorHandler hHandler)
270 : {
271 54132 : CPLPushErrorHandler(hHandler);
272 54113 : }
273 :
274 : /** Constructor that installs a thread-local temporary error handler,
275 : * and its user data.
276 : */
277 3735 : CPLErrorHandlerPusher(CPLErrorHandler hHandler, void *user_data)
278 : {
279 3735 : CPLPushErrorHandlerEx(hHandler, user_data);
280 3732 : }
281 :
282 : /** Destructor that restores the initial error handler. */
283 57879 : ~CPLErrorHandlerPusher()
284 : {
285 57879 : CPLPopErrorHandler();
286 57855 : }
287 : };
288 :
289 : /** Class that saves the error state on construction, and
290 : * restores it on destruction.
291 : */
292 : class CPL_DLL CPLErrorStateBackuper
293 : {
294 : CPLErrorNum m_nLastErrorNum;
295 : CPLErr m_nLastErrorType;
296 : std::string m_osLastErrorMsg;
297 : GUInt32 m_nLastErrorCounter;
298 : std::unique_ptr<CPLErrorHandlerPusher> m_poErrorHandlerPusher;
299 :
300 : public:
301 : /** Constructor that backs up the error state, and optionally installs
302 : * a thread-local temporary error handler (typically CPLQuietErrorHandler).
303 : */
304 : explicit CPLErrorStateBackuper(CPLErrorHandler hHandler = nullptr);
305 :
306 : /** Destructor that restores the error state to its initial state
307 : * before construction.
308 : */
309 : ~CPLErrorStateBackuper();
310 : };
311 : }
312 :
313 : #ifdef GDAL_COMPILATION
314 : /*! @cond Doxygen_Suppress */
315 : // internal only
316 : bool CPLIsDefaultErrorHandlerAndCatchDebug();
317 : /*! @endcond */
318 : #endif
319 :
320 : #endif
321 :
322 : /** Validate that a pointer is not NULL */
323 : #define VALIDATE_POINTER0(ptr, func) \
324 : do \
325 : { \
326 : if (CPL_NULLPTR == ptr) \
327 : { \
328 : CPLErr const ret = VALIDATE_POINTER_ERR; \
329 : CPLError(ret, CPLE_ObjectNull, \
330 : "Pointer \'%s\' is NULL in \'%s\'.\n", #ptr, (func)); \
331 : return; \
332 : } \
333 : } while (0)
334 :
335 : /** Validate that a pointer is not NULL, and return rc if it is NULL */
336 : #define VALIDATE_POINTER1(ptr, func, rc) \
337 : do \
338 : { \
339 : if (CPL_NULLPTR == ptr) \
340 : { \
341 : CPLErr const ret = VALIDATE_POINTER_ERR; \
342 : CPLError(ret, CPLE_ObjectNull, \
343 : "Pointer \'%s\' is NULL in \'%s\'.\n", #ptr, (func)); \
344 : return (rc); \
345 : } \
346 : } while (0)
347 :
348 : #endif /* CPL_ERROR_H_INCLUDED */
|