Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: CPL - Common Portability Library
4 : * Author: Frank Warmerdam, warmerdam@pobox.com
5 : * Purpose: Include file providing low level portability services for CPL.
6 : * This should be the first include file for any CPL based code.
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, 2005, Frank Warmerdam <warmerdam@pobox.com>
10 : * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #ifndef CPL_BASE_H_INCLUDED
16 : #define CPL_BASE_H_INCLUDED
17 :
18 : /**
19 : * \file cpl_port.h
20 : *
21 : * Core portability definitions for CPL.
22 : *
23 : */
24 :
25 : /* -------------------------------------------------------------------- */
26 : /* The following apparently allow you to use strcpy() and other */
27 : /* functions judged "unsafe" by microsoft in VS 8 (2005). */
28 : /* -------------------------------------------------------------------- */
29 : #ifdef _MSC_VER
30 : #ifndef _CRT_SECURE_NO_DEPRECATE
31 : #define _CRT_SECURE_NO_DEPRECATE
32 : #endif
33 : #ifndef _CRT_NONSTDC_NO_DEPRECATE
34 : #define _CRT_NONSTDC_NO_DEPRECATE
35 : #endif
36 : #endif
37 :
38 : #include "cpl_config.h"
39 :
40 : /* ==================================================================== */
41 : /* A few sanity checks, mainly to detect problems that sometimes */
42 : /* arise with bad configured cross-compilation. */
43 : /* ==================================================================== */
44 :
45 : #if !defined(SIZEOF_INT) || SIZEOF_INT != 4
46 : #error "Unexpected value for SIZEOF_INT"
47 : #endif
48 :
49 : #if !defined(SIZEOF_UNSIGNED_LONG) || \
50 : (SIZEOF_UNSIGNED_LONG != 4 && SIZEOF_UNSIGNED_LONG != 8)
51 : #error "Unexpected value for SIZEOF_UNSIGNED_LONG"
52 : #endif
53 :
54 : #if !defined(SIZEOF_VOIDP)
55 : #error "Unexpected value for SIZEOF_VOIDP"
56 : #endif
57 :
58 : /* ==================================================================== */
59 : /* This will disable most WIN32 stuff in a Cygnus build which */
60 : /* defines unix to 1. */
61 : /* ==================================================================== */
62 :
63 : #ifdef unix
64 : #undef WIN32
65 : #endif
66 :
67 : /*! @cond Doxygen_Suppress */
68 : #if defined(VSI_NEED_LARGEFILE64_SOURCE) && !defined(_LARGEFILE64_SOURCE)
69 : #define _LARGEFILE64_SOURCE 1
70 : #endif
71 :
72 : /* ==================================================================== */
73 : /* If iconv() is available use extended recoding module. */
74 : /* Stub implementation is always compiled in, because it works */
75 : /* faster than iconv() for encodings it supports. */
76 : /* ==================================================================== */
77 :
78 : #if defined(HAVE_ICONV)
79 : #define CPL_RECODE_ICONV
80 : #endif
81 :
82 : #define CPL_RECODE_STUB
83 : /*! @endcond */
84 :
85 : /* ==================================================================== */
86 : /* MinGW stuff */
87 : /* ==================================================================== */
88 :
89 : /* Needed for std=c11 on Solaris to have strcasecmp() */
90 : #if defined(GDAL_COMPILATION) && defined(__sun__) && \
91 : (__STDC_VERSION__ + 0) >= 201112L && (_XOPEN_SOURCE + 0) < 600
92 : #ifdef _XOPEN_SOURCE
93 : #undef _XOPEN_SOURCE
94 : #endif
95 : #define _XOPEN_SOURCE 600
96 : #endif
97 :
98 : /* ==================================================================== */
99 : /* Standard include files. */
100 : /* ==================================================================== */
101 :
102 : #include <stdio.h>
103 : #include <stdlib.h>
104 : #include <math.h>
105 : #include <stdarg.h>
106 : #include <string.h>
107 : #include <ctype.h>
108 : #include <limits.h>
109 :
110 : #include <time.h>
111 :
112 : #include <errno.h>
113 :
114 : #ifdef HAVE_LOCALE_H
115 : #include <locale.h>
116 : #endif
117 :
118 : #ifdef HAVE_DIRECT_H
119 : #include <direct.h>
120 : #endif
121 :
122 : #if !defined(_WIN32)
123 : #include <strings.h>
124 : #endif
125 :
126 : #ifdef __cplusplus
127 : extern "C++"
128 : {
129 : #include <cmath>
130 : }
131 : #endif
132 :
133 : /* ==================================================================== */
134 : /* Base portability stuff ... this stuff may need to be */
135 : /* modified for new platforms. */
136 : /* ==================================================================== */
137 :
138 : /* MSVC fails to define a decent value of __cplusplus. Try to target VS2015*/
139 : /* as a minimum */
140 :
141 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
142 : #if !(__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900))
143 : #error Must have C++11 or newer.
144 : #endif
145 : #endif /* __cplusplus */
146 :
147 : /*---------------------------------------------------------------------
148 : * types for 16 and 32 bits integers, etc...
149 : *--------------------------------------------------------------------*/
150 : #if UINT_MAX == 65535
151 : typedef long GInt32;
152 : typedef unsigned long GUInt32;
153 : #else
154 : /** Int32 type */
155 : typedef int GInt32;
156 : /** Unsigned int32 type */
157 : typedef unsigned int GUInt32;
158 : #endif
159 :
160 : /** Int16 type */
161 : typedef short GInt16;
162 : /** Unsigned int16 type */
163 : typedef unsigned short GUInt16;
164 : /** Unsigned byte type */
165 : typedef unsigned char GByte;
166 : /** Signed int8 type */
167 : typedef signed char GInt8;
168 : /* hack for PDF driver and poppler >= 0.15.0 that defines incompatible "typedef
169 : * bool GBool" */
170 : /* in include/poppler/goo/gtypes.h */
171 : #ifndef CPL_GBOOL_DEFINED
172 : /*! @cond Doxygen_Suppress */
173 : #define CPL_GBOOL_DEFINED
174 : /*! @endcond */
175 : /** Type for boolean values (alias to int) */
176 : typedef int GBool;
177 : #endif
178 :
179 : /*! @cond Doxygen_Suppress */
180 : #ifdef __cplusplus
181 : #define CPL_STATIC_CAST(type, expr) static_cast<type>(expr)
182 : #define CPL_REINTERPRET_CAST(type, expr) reinterpret_cast<type>(expr)
183 : #else
184 : #define CPL_STATIC_CAST(type, expr) ((type)(expr))
185 : #define CPL_REINTERPRET_CAST(type, expr) ((type)(expr))
186 : #endif
187 : /*! @endcond */
188 :
189 : /* -------------------------------------------------------------------- */
190 : /* 64bit support */
191 : /* -------------------------------------------------------------------- */
192 :
193 : /** Large signed integer type (generally 64-bit integer type).
194 : * Use GInt64 when exactly 64 bit is needed */
195 : typedef long long GIntBig;
196 : /** Large unsigned integer type (generally 64-bit unsigned integer type).
197 : * Use GUInt64 when exactly 64 bit is needed */
198 : typedef unsigned long long GUIntBig;
199 :
200 : /** Minimum GIntBig value */
201 : #define GINTBIG_MIN (CPL_STATIC_CAST(GIntBig, 0x80000000) << 32)
202 : /** Maximum GIntBig value */
203 : #define GINTBIG_MAX ((CPL_STATIC_CAST(GIntBig, 0x7FFFFFFF) << 32) | 0xFFFFFFFFU)
204 : /** Maximum GUIntBig value */
205 : #define GUINTBIG_MAX \
206 : ((CPL_STATIC_CAST(GUIntBig, 0xFFFFFFFFU) << 32) | 0xFFFFFFFFU)
207 :
208 : /*! @cond Doxygen_Suppress */
209 : #define CPL_HAS_GINT64 1
210 : /*! @endcond */
211 :
212 : /* Note: we might want to use instead int64_t / uint64_t if they are available
213 : */
214 :
215 : /** Signed 64 bit integer type */
216 : typedef GIntBig GInt64;
217 : /** Unsigned 64 bit integer type */
218 : typedef GUIntBig GUInt64;
219 :
220 : /** Minimum GInt64 value */
221 : #define GINT64_MIN GINTBIG_MIN
222 : /** Maximum GInt64 value */
223 : #define GINT64_MAX GINTBIG_MAX
224 : /** Minimum GUInt64 value */
225 : #define GUINT64_MAX GUINTBIG_MAX
226 :
227 : #if SIZEOF_VOIDP > 8
228 : #include <stddef.h> // ptrdiff_t
229 : /** Integer type large enough to hold the difference between 2 addresses */
230 : typedef ptrdiff_t GPtrDiff_t;
231 : #elif SIZEOF_VOIDP == 8
232 : /** Integer type large enough to hold the difference between 2 addresses */
233 : typedef GIntBig GPtrDiff_t;
234 : #else
235 : /** Integer type large enough to hold the difference between 2 addresses */
236 : typedef int GPtrDiff_t;
237 : #endif
238 :
239 : #ifdef GDAL_COMPILATION
240 : #include <stdint.h>
241 : typedef uintptr_t GUIntptr_t;
242 : #define CPL_IS_ALIGNED(ptr, quant) \
243 : ((CPL_REINTERPRET_CAST(GUIntptr_t, CPL_STATIC_CAST(const void *, ptr)) % \
244 : (quant)) == 0)
245 :
246 : #endif
247 :
248 : #if (defined(__MSVCRT__) && !(defined(__MINGW64__) && __GNUC__ >= 10)) || \
249 : (defined(_WIN32) && defined(_MSC_VER))
250 : #define CPL_FRMT_GB_WITHOUT_PREFIX "I64"
251 : #else
252 : /** Printf formatting suffix for GIntBig */
253 : #define CPL_FRMT_GB_WITHOUT_PREFIX "ll"
254 : #endif
255 :
256 : /** Printf formatting for GIntBig */
257 : #define CPL_FRMT_GIB "%" CPL_FRMT_GB_WITHOUT_PREFIX "d"
258 : /** Printf formatting for GUIntBig */
259 : #define CPL_FRMT_GUIB "%" CPL_FRMT_GB_WITHOUT_PREFIX "u"
260 :
261 : /*! @cond Doxygen_Suppress */
262 : #ifdef COMPAT_WITH_ICC_CONVERSION_CHECK
263 : #define CPL_INT64_FITS_ON_INT32(x) ((x) >= INT_MIN && (x) <= INT_MAX)
264 : #else
265 : #define CPL_INT64_FITS_ON_INT32(x) \
266 : (CPL_STATIC_CAST(GIntBig, CPL_STATIC_CAST(int, x)) == (x))
267 : #endif
268 : /*! @endcond */
269 :
270 : /* ==================================================================== */
271 : /* Other standard services. */
272 : /* ==================================================================== */
273 : #ifdef __cplusplus
274 : /** Macro to start a block of C symbols */
275 : #define CPL_C_START \
276 : extern "C" \
277 : {
278 : /** Macro to end a block of C symbols */
279 : #define CPL_C_END }
280 : #else
281 : #define CPL_C_START
282 : #define CPL_C_END
283 : #endif
284 :
285 : #ifndef CPL_DLL
286 : #if defined(_MSC_VER) && !defined(CPL_DISABLE_DLL)
287 : #ifdef GDAL_COMPILATION
288 : #define CPL_DLL __declspec(dllexport)
289 : #else
290 : #define CPL_DLL
291 : #endif
292 : #define CPL_INTERNAL
293 : #else
294 : #if defined(USE_GCC_VISIBILITY_FLAG)
295 : #define CPL_DLL __attribute__((visibility("default")))
296 : #if !defined(__MINGW32__)
297 : #define CPL_INTERNAL __attribute__((visibility("hidden")))
298 : #else
299 : #define CPL_INTERNAL
300 : #endif
301 : #else
302 : #define CPL_DLL
303 : #define CPL_INTERNAL
304 : #endif
305 : #endif
306 :
307 : // Marker for unstable API
308 : #define CPL_UNSTABLE_API CPL_DLL
309 :
310 : #endif
311 :
312 : /*! @cond Doxygen_Suppress */
313 : /* Should optional (normally private) interfaces be exported? */
314 : #ifdef CPL_OPTIONAL_APIS
315 : #define CPL_ODLL CPL_DLL
316 : #else
317 : #define CPL_ODLL
318 : #endif
319 : /*! @endcond */
320 :
321 : #ifndef CPL_STDCALL
322 : #if defined(_MSC_VER) && !defined(CPL_DISABLE_STDCALL)
323 : #define CPL_STDCALL __stdcall
324 : #else
325 : #define CPL_STDCALL
326 : #endif
327 : #endif
328 :
329 : /*! @cond Doxygen_Suppress */
330 : #ifdef _MSC_VER
331 : #define FORCE_CDECL __cdecl
332 : #else
333 : #define FORCE_CDECL
334 : #endif
335 : /*! @endcond */
336 :
337 : /*! @cond Doxygen_Suppress */
338 : /* TODO : support for other compilers needed */
339 : #if (defined(__GNUC__) && !defined(__NO_INLINE__)) || defined(_MSC_VER)
340 : #define HAS_CPL_INLINE 1
341 : #define CPL_INLINE __inline
342 : #elif defined(__SUNPRO_CC)
343 : #define HAS_CPL_INLINE 1
344 : #define CPL_INLINE inline
345 : #else
346 : #define CPL_INLINE
347 : #endif
348 : /*! @endcond*/
349 :
350 : /** Macro to compute the minimum of 2 values */
351 : #define CPL_MIN(a, b) (((a) < (b)) ? (a) : (b))
352 : /** Macro to compute the maximum of 2 values */
353 : #define CPL_MAX(a, b) (((a) > (b)) ? (a) : (b))
354 :
355 : /** Macro to compute the absolute value */
356 : #define CPL_ABS(x) (((x) < 0) ? (-1 * (x)) : (x))
357 :
358 : /*! @cond Doxygen_Suppress */
359 :
360 : #if defined(GDAL_COMPILATION)
361 : #ifndef M_PI
362 : #define M_PI 3.14159265358979323846
363 : /* 3.1415926535897932384626433832795 */
364 : #endif
365 :
366 : #endif
367 : /*! @endcond*/
368 :
369 : /* -------------------------------------------------------------------- */
370 : /* Macro to test equality of two floating point values. */
371 : /* We use fabs() function instead of ABS() macro to avoid side */
372 : /* effects. */
373 : /* -------------------------------------------------------------------- */
374 : /*! @cond Doxygen_Suppress */
375 : #ifndef CPLIsEqual
376 : #define CPLIsEqual(x, y) (fabs((x) - (y)) < 0.0000000000001)
377 : #endif
378 : /*! @endcond */
379 :
380 : /* -------------------------------------------------------------------- */
381 : /* Provide macros for case insensitive string comparisons. */
382 : /* -------------------------------------------------------------------- */
383 : #ifndef EQUAL
384 :
385 : #if defined(AFL_FRIENDLY) && defined(__GNUC__)
386 :
387 : static inline int CPL_afl_friendly_memcmp(const void *ptr1, const void *ptr2,
388 : size_t len)
389 : __attribute__((always_inline));
390 :
391 : static inline int CPL_afl_friendly_memcmp(const void *ptr1, const void *ptr2,
392 : size_t len)
393 : {
394 : const unsigned char *bptr1 = (const unsigned char *)ptr1;
395 : const unsigned char *bptr2 = (const unsigned char *)ptr2;
396 : while (len--)
397 : {
398 : unsigned char b1 = *(bptr1++);
399 : unsigned char b2 = *(bptr2++);
400 : if (b1 != b2)
401 : return b1 - b2;
402 : }
403 : return 0;
404 : }
405 :
406 : static inline int CPL_afl_friendly_strcmp(const char *ptr1, const char *ptr2)
407 : __attribute__((always_inline));
408 :
409 : static inline int CPL_afl_friendly_strcmp(const char *ptr1, const char *ptr2)
410 : {
411 : const unsigned char *usptr1 = (const unsigned char *)ptr1;
412 : const unsigned char *usptr2 = (const unsigned char *)ptr2;
413 : while (1)
414 : {
415 : unsigned char ch1 = *(usptr1++);
416 : unsigned char ch2 = *(usptr2++);
417 : if (ch1 == 0 || ch1 != ch2)
418 : return ch1 - ch2;
419 : }
420 : }
421 :
422 : static inline int CPL_afl_friendly_strncmp(const char *ptr1, const char *ptr2,
423 : size_t len)
424 : __attribute__((always_inline));
425 :
426 : static inline int CPL_afl_friendly_strncmp(const char *ptr1, const char *ptr2,
427 : size_t len)
428 : {
429 : const unsigned char *usptr1 = (const unsigned char *)ptr1;
430 : const unsigned char *usptr2 = (const unsigned char *)ptr2;
431 : while (len--)
432 : {
433 : unsigned char ch1 = *(usptr1++);
434 : unsigned char ch2 = *(usptr2++);
435 : if (ch1 == 0 || ch1 != ch2)
436 : return ch1 - ch2;
437 : }
438 : return 0;
439 : }
440 :
441 : static inline int CPL_afl_friendly_strcasecmp(const char *ptr1,
442 : const char *ptr2)
443 : __attribute__((always_inline));
444 :
445 : static inline int CPL_afl_friendly_strcasecmp(const char *ptr1,
446 : const char *ptr2)
447 : {
448 : const unsigned char *usptr1 = (const unsigned char *)ptr1;
449 : const unsigned char *usptr2 = (const unsigned char *)ptr2;
450 : while (1)
451 : {
452 : unsigned char ch1 = *(usptr1++);
453 : unsigned char ch2 = *(usptr2++);
454 : ch1 = (unsigned char)toupper(ch1);
455 : ch2 = (unsigned char)toupper(ch2);
456 : if (ch1 == 0 || ch1 != ch2)
457 : return ch1 - ch2;
458 : }
459 : }
460 :
461 : static inline int CPL_afl_friendly_strncasecmp(const char *ptr1,
462 : const char *ptr2, size_t len)
463 : __attribute__((always_inline));
464 :
465 : static inline int CPL_afl_friendly_strncasecmp(const char *ptr1,
466 : const char *ptr2, size_t len)
467 : {
468 : const unsigned char *usptr1 = (const unsigned char *)ptr1;
469 : const unsigned char *usptr2 = (const unsigned char *)ptr2;
470 : while (len--)
471 : {
472 : unsigned char ch1 = *(usptr1++);
473 : unsigned char ch2 = *(usptr2++);
474 : ch1 = (unsigned char)toupper(ch1);
475 : ch2 = (unsigned char)toupper(ch2);
476 : if (ch1 == 0 || ch1 != ch2)
477 : return ch1 - ch2;
478 : }
479 : return 0;
480 : }
481 :
482 : static inline char *CPL_afl_friendly_strstr(const char *haystack,
483 : const char *needle)
484 : __attribute__((always_inline));
485 :
486 : static inline char *CPL_afl_friendly_strstr(const char *haystack,
487 : const char *needle)
488 : {
489 : const char *ptr_haystack = haystack;
490 : while (1)
491 : {
492 : const char *ptr_haystack2 = ptr_haystack;
493 : const char *ptr_needle = needle;
494 : while (1)
495 : {
496 : char ch1 = *(ptr_haystack2++);
497 : char ch2 = *(ptr_needle++);
498 : if (ch2 == 0)
499 : return (char *)ptr_haystack;
500 : if (ch1 != ch2)
501 : break;
502 : }
503 : if (*ptr_haystack == 0)
504 : return NULL;
505 : ptr_haystack++;
506 : }
507 : }
508 :
509 : #undef strcmp
510 : #undef strncmp
511 : #define memcmp CPL_afl_friendly_memcmp
512 : #define strcmp CPL_afl_friendly_strcmp
513 : #define strncmp CPL_afl_friendly_strncmp
514 : #define strcasecmp CPL_afl_friendly_strcasecmp
515 : #define strncasecmp CPL_afl_friendly_strncasecmp
516 : #define strstr CPL_afl_friendly_strstr
517 :
518 : #endif /* defined(AFL_FRIENDLY) && defined(__GNUC__) */
519 :
520 : #if defined(_WIN32)
521 : #define STRCASECMP(a, b) (_stricmp(a, b))
522 : #define STRNCASECMP(a, b, n) (_strnicmp(a, b, n))
523 : #else
524 : /** Alias for strcasecmp() */
525 : #define STRCASECMP(a, b) (strcasecmp(a, b))
526 : /** Alias for strncasecmp() */
527 : #define STRNCASECMP(a, b, n) (strncasecmp(a, b, n))
528 : #endif
529 : /** Alias for strncasecmp() == 0 */
530 : #define EQUALN(a, b, n) (STRNCASECMP(a, b, n) == 0)
531 : /** Alias for strcasecmp() == 0 */
532 : #define EQUAL(a, b) (STRCASECMP(a, b) == 0)
533 : #endif
534 :
535 : /*---------------------------------------------------------------------
536 : * Does a string "a" start with string "b". Search is case-sensitive or,
537 : * with CI, it is a case-insensitive comparison.
538 : *--------------------------------------------------------------------- */
539 : #ifndef STARTS_WITH_CI
540 : /** Returns whether a starts with b */
541 : #define STARTS_WITH(a, b) (strncmp(a, b, strlen(b)) == 0)
542 : /** Returns whether a starts with b (case insensitive comparison) */
543 : #define STARTS_WITH_CI(a, b) EQUALN(a, b, strlen(b))
544 : #endif
545 :
546 : /*! @cond Doxygen_Suppress */
547 : #ifndef CPL_THREADLOCAL
548 : #define CPL_THREADLOCAL
549 : #endif
550 : /*! @endcond */
551 :
552 : /*! @cond Doxygen_Suppress */
553 : #ifndef __cplusplus
554 : /* -------------------------------------------------------------------- */
555 : /* Handle isnan() and isinf(). Note that isinf() and isnan() */
556 : /* are supposed to be macros according to C99, defined in math.h */
557 : /* Some systems (i.e. Tru64) don't have isinf() at all, so if */
558 : /* the macro is not defined we just assume nothing is infinite. */
559 : /* This may mean we have no real CPLIsInf() on systems with isinf()*/
560 : /* function but no corresponding macro, but I can live with */
561 : /* that since it isn't that important a test. */
562 : /* -------------------------------------------------------------------- */
563 : #ifdef _MSC_VER
564 : #include <float.h>
565 : #define CPLIsNan(x) _isnan(x)
566 : #define CPLIsInf(x) (!_isnan(x) && !_finite(x))
567 : #define CPLIsFinite(x) _finite(x)
568 : #elif defined(__GNUC__) && \
569 : (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
570 : /* When including <cmath> in C++11 the isnan() macro is undefined, so that */
571 : /* std::isnan() can work (#6489). This is a GCC specific workaround for now. */
572 : #define CPLIsNan(x) __builtin_isnan(x)
573 : #define CPLIsInf(x) __builtin_isinf(x)
574 : #define CPLIsFinite(x) __builtin_isfinite(x)
575 : #elif defined(isinf) || defined(__FreeBSD__)
576 : /** Return whether a floating-pointer number is nan */
577 : #define CPLIsNan(x) isnan(x)
578 : /** Return whether a floating-pointer number is +/- infinity */
579 : #define CPLIsInf(x) isinf(x)
580 : /** Return whether a floating-pointer number is finite */
581 : #define CPLIsFinite(x) (!isnan(x) && !isinf(x))
582 : #elif defined(__sun__)
583 : #include <ieeefp.h>
584 : #define CPLIsNan(x) isnan(x)
585 : #define CPLIsInf(x) (!finite(x) && !isnan(x))
586 : #define CPLIsFinite(x) finite(x)
587 : #else
588 : #define CPLIsNan(x) ((x) != (x))
589 : #define CPLIsInf(x) (0)
590 : #define CPLIsFinite(x) (!isnan(x))
591 : #endif
592 : #endif
593 : /*! @endcond */
594 :
595 : /*! @cond Doxygen_Suppress */
596 : /*---------------------------------------------------------------------
597 : * CPL_LSB and CPL_MSB
598 : * Only one of these 2 macros should be defined and specifies the byte
599 : * ordering for the current platform.
600 : * This should be defined in the Makefile, but if it is not then
601 : * the default is CPL_LSB (Intel ordering, LSB first).
602 : *--------------------------------------------------------------------*/
603 : #if defined(WORDS_BIGENDIAN) && !defined(CPL_MSB) && !defined(CPL_LSB)
604 : #define CPL_MSB
605 : #endif
606 :
607 : #if !(defined(CPL_LSB) || defined(CPL_MSB))
608 : #define CPL_LSB
609 : #endif
610 :
611 : #if defined(CPL_LSB)
612 : #define CPL_IS_LSB 1
613 : #else
614 : #define CPL_IS_LSB 0
615 : #endif
616 : /*! @endcond */
617 :
618 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
619 :
620 : /*! @cond Doxygen_Suppress */
621 : extern "C++"
622 : {
623 :
624 : template <bool b> struct CPLStaticAssert
625 : {
626 : };
627 :
628 : template <> struct CPLStaticAssert<true>
629 : {
630 239446244 : static void my_function()
631 : {
632 239446244 : }
633 : };
634 :
635 : } /* extern "C++" */
636 :
637 : #define CPL_STATIC_ASSERT(x) CPLStaticAssert<x>::my_function()
638 : #define CPL_STATIC_ASSERT_IF_AVAILABLE(x) CPL_STATIC_ASSERT(x)
639 :
640 : #else /* __cplusplus */
641 :
642 : #define CPL_STATIC_ASSERT_IF_AVAILABLE(x)
643 :
644 : #endif /* __cplusplus */
645 : /*! @endcond */
646 :
647 : /*---------------------------------------------------------------------
648 : * Little endian <==> big endian byte swap macros.
649 : *--------------------------------------------------------------------*/
650 :
651 : /** Byte-swap a 16bit unsigned integer */
652 : #define CPL_SWAP16(x) \
653 : CPL_STATIC_CAST(GUInt16, (CPL_STATIC_CAST(GUInt16, x) << 8) | \
654 : (CPL_STATIC_CAST(GUInt16, x) >> 8))
655 :
656 : #ifdef __GNUC__
657 : /** Byte-swap a 32bit unsigned integer */
658 : #define CPL_SWAP32(x) \
659 : CPL_STATIC_CAST(GUInt32, __builtin_bswap32(CPL_STATIC_CAST(GUInt32, x)))
660 : /** Byte-swap a 64bit unsigned integer */
661 : #define CPL_SWAP64(x) \
662 : CPL_STATIC_CAST(GUInt64, __builtin_bswap64(CPL_STATIC_CAST(GUInt64, x)))
663 : #elif defined(_MSC_VER)
664 : #define CPL_SWAP32(x) \
665 : CPL_STATIC_CAST(GUInt32, _byteswap_ulong(CPL_STATIC_CAST(GUInt32, x)))
666 : #define CPL_SWAP64(x) \
667 : CPL_STATIC_CAST(GUInt64, _byteswap_uint64(CPL_STATIC_CAST(GUInt64, x)))
668 : #else
669 : /** Byte-swap a 32bit unsigned integer */
670 : #define CPL_SWAP32(x) \
671 : CPL_STATIC_CAST(GUInt32, \
672 : ((CPL_STATIC_CAST(GUInt32, x) & 0x000000ffU) << 24) | \
673 : ((CPL_STATIC_CAST(GUInt32, x) & 0x0000ff00U) << 8) | \
674 : ((CPL_STATIC_CAST(GUInt32, x) & 0x00ff0000U) >> 8) | \
675 : ((CPL_STATIC_CAST(GUInt32, x) & 0xff000000U) >> 24))
676 :
677 : /** Byte-swap a 64bit unsigned integer */
678 : #define CPL_SWAP64(x) \
679 : ((CPL_STATIC_CAST(GUInt64, CPL_SWAP32(CPL_STATIC_CAST(GUInt32, x))) \
680 : << 32) | \
681 : (CPL_STATIC_CAST(GUInt64, \
682 : CPL_SWAP32(CPL_STATIC_CAST( \
683 : GUInt32, CPL_STATIC_CAST(GUInt64, x) >> 32)))))
684 :
685 : #endif
686 :
687 : /** Byte-swap a 16 bit pointer */
688 : #define CPL_SWAP16PTR(x) \
689 : do \
690 : { \
691 : GUInt16 _n16; \
692 : void *_lx = x; \
693 : memcpy(&_n16, _lx, 2); \
694 : CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || \
695 : sizeof(*(x)) == 2); \
696 : _n16 = CPL_SWAP16(_n16); \
697 : memcpy(_lx, &_n16, 2); \
698 : } while (0)
699 :
700 : /** Byte-swap a 32 bit pointer */
701 : #define CPL_SWAP32PTR(x) \
702 : do \
703 : { \
704 : GUInt32 _n32; \
705 : void *_lx = x; \
706 : memcpy(&_n32, _lx, 4); \
707 : CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || \
708 : sizeof(*(x)) == 4); \
709 : _n32 = CPL_SWAP32(_n32); \
710 : memcpy(_lx, &_n32, 4); \
711 : } while (0)
712 :
713 : /** Byte-swap a 64 bit pointer */
714 : #define CPL_SWAP64PTR(x) \
715 : do \
716 : { \
717 : GUInt64 _n64; \
718 : void *_lx = x; \
719 : memcpy(&_n64, _lx, 8); \
720 : CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || \
721 : sizeof(*(x)) == 8); \
722 : _n64 = CPL_SWAP64(_n64); \
723 : memcpy(_lx, &_n64, 8); \
724 : } while (0)
725 :
726 : /** Byte-swap a 64 bit pointer */
727 : #define CPL_SWAPDOUBLE(p) CPL_SWAP64PTR(p)
728 :
729 : #ifdef CPL_MSB
730 : #define CPL_MSBWORD16(x) (x)
731 : #define CPL_LSBWORD16(x) CPL_SWAP16(x)
732 : #define CPL_MSBWORD32(x) (x)
733 : #define CPL_LSBWORD32(x) CPL_SWAP32(x)
734 : #define CPL_MSBPTR16(x) \
735 : CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 2)
736 : #define CPL_LSBPTR16(x) CPL_SWAP16PTR(x)
737 : #define CPL_MSBPTR32(x) \
738 : CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 4)
739 : #define CPL_LSBPTR32(x) CPL_SWAP32PTR(x)
740 : #define CPL_MSBPTR64(x) \
741 : CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 8)
742 : #define CPL_LSBPTR64(x) CPL_SWAP64PTR(x)
743 : #else
744 : /** Return a 16bit word from a originally LSB ordered word */
745 : #define CPL_LSBWORD16(x) (x)
746 : /** Return a 16bit word from a originally MSB ordered word */
747 : #define CPL_MSBWORD16(x) CPL_SWAP16(x)
748 : /** Return a 32bit word from a originally LSB ordered word */
749 : #define CPL_LSBWORD32(x) (x)
750 : /** Return a 32bit word from a originally MSB ordered word */
751 : #define CPL_MSBWORD32(x) CPL_SWAP32(x)
752 : /** Byte-swap if necessary a 16bit word at the location pointed from a
753 : * originally LSB ordered pointer */
754 : #define CPL_LSBPTR16(x) \
755 : CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 2)
756 : /** Byte-swap if necessary a 16bit word at the location pointed from a
757 : * originally MSB ordered pointer */
758 : #define CPL_MSBPTR16(x) CPL_SWAP16PTR(x)
759 : /** Byte-swap if necessary a 32bit word at the location pointed from a
760 : * originally LSB ordered pointer */
761 : #define CPL_LSBPTR32(x) \
762 : CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 4)
763 : /** Byte-swap if necessary a 32bit word at the location pointed from a
764 : * originally MSB ordered pointer */
765 : #define CPL_MSBPTR32(x) CPL_SWAP32PTR(x)
766 : /** Byte-swap if necessary a 64bit word at the location pointed from a
767 : * originally LSB ordered pointer */
768 : #define CPL_LSBPTR64(x) \
769 : CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 8)
770 : /** Byte-swap if necessary a 64bit word at the location pointed from a
771 : * originally MSB ordered pointer */
772 : #define CPL_MSBPTR64(x) CPL_SWAP64PTR(x)
773 : #endif
774 :
775 : /** Return a Int16 from the 2 bytes ordered in LSB order at address x.
776 : * @deprecated Use rather CPL_LSBSINT16PTR or CPL_LSBUINT16PTR for explicit
777 : * signedness. */
778 : #define CPL_LSBINT16PTR(x) \
779 : ((*CPL_REINTERPRET_CAST(const GByte *, x)) | \
780 : (*((CPL_REINTERPRET_CAST(const GByte *, x)) + 1) << 8))
781 :
782 : /** Return a Int32 from the 4 bytes ordered in LSB order at address x.
783 : * @deprecated Use rather CPL_LSBSINT32PTR or CPL_LSBUINT32PTR for explicit
784 : * signedness. */
785 : #define CPL_LSBINT32PTR(x) \
786 : ((*CPL_REINTERPRET_CAST(const GByte *, x)) | \
787 : (*((CPL_REINTERPRET_CAST(const GByte *, x)) + 1) << 8) | \
788 : (*((CPL_REINTERPRET_CAST(const GByte *, x)) + 2) << 16) | \
789 : (*((CPL_REINTERPRET_CAST(const GByte *, x)) + 3) << 24))
790 :
791 : /** Return a signed Int16 from the 2 bytes ordered in LSB order at address x */
792 : #define CPL_LSBSINT16PTR(x) CPL_STATIC_CAST(GInt16, CPL_LSBINT16PTR(x))
793 :
794 : /** Return a unsigned Int16 from the 2 bytes ordered in LSB order at address x
795 : */
796 : #define CPL_LSBUINT16PTR(x) CPL_STATIC_CAST(GUInt16, CPL_LSBINT16PTR(x))
797 :
798 : /** Return a signed Int32 from the 4 bytes ordered in LSB order at address x */
799 : #define CPL_LSBSINT32PTR(x) CPL_STATIC_CAST(GInt32, CPL_LSBINT32PTR(x))
800 :
801 : /** Return a unsigned Int32 from the 4 bytes ordered in LSB order at address x
802 : */
803 : #define CPL_LSBUINT32PTR(x) CPL_STATIC_CAST(GUInt32, CPL_LSBINT32PTR(x))
804 :
805 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
806 :
807 : extern "C++"
808 : {
809 : #include <cstddef>
810 : #include <cstdint>
811 :
812 : /*! @cond Doxygen_Suppress */
813 : // workaround before CWG2518/P2593R1
814 : template <class T> struct CPL_T_IsAlwaysFalse
815 : {
816 : static const bool value = false;
817 : };
818 :
819 : /*! @endcond */
820 :
821 : /** Return the provided value as a LSB ordered one.
822 : *
823 : * Only available for primitive types: [u]int[8|16|32|64], float and double.
824 : */
825 : template <class T> T CPL_AS_LSB(T)
826 : {
827 : // See https://youtu.be/b6j6SZiXmoo?t=1659 for rationale for CPL_T_IsAlwaysFalse
828 : static_assert(CPL_T_IsAlwaysFalse<T>::value, "Unsupported value for T");
829 : }
830 :
831 : /*! @cond Doxygen_Suppress */
832 1 : template <> inline int8_t CPL_AS_LSB<int8_t>(int8_t x)
833 : {
834 1 : return x;
835 : }
836 :
837 8301 : template <> inline uint8_t CPL_AS_LSB<uint8_t>(uint8_t x)
838 : {
839 8301 : return x;
840 : }
841 :
842 1 : template <> inline int16_t CPL_AS_LSB<int16_t>(int16_t x)
843 : {
844 1 : CPL_LSBPTR16(&x);
845 1 : return x;
846 : }
847 :
848 23020 : template <> inline uint16_t CPL_AS_LSB<uint16_t>(uint16_t x)
849 : {
850 23020 : CPL_LSBPTR16(&x);
851 23020 : return x;
852 : }
853 :
854 5 : template <> inline int32_t CPL_AS_LSB<int32_t>(int32_t x)
855 : {
856 5 : CPL_LSBPTR32(&x);
857 5 : return x;
858 : }
859 :
860 209 : template <> inline uint32_t CPL_AS_LSB<uint32_t>(uint32_t x)
861 : {
862 209 : CPL_LSBPTR32(&x);
863 209 : return x;
864 : }
865 :
866 1 : template <> inline int64_t CPL_AS_LSB<int64_t>(int64_t x)
867 : {
868 1 : CPL_LSBPTR64(&x);
869 1 : return x;
870 : }
871 :
872 5228 : template <> inline uint64_t CPL_AS_LSB<uint64_t>(uint64_t x)
873 : {
874 5228 : CPL_LSBPTR64(&x);
875 5228 : return x;
876 : }
877 :
878 1 : template <> inline float CPL_AS_LSB<float>(float x)
879 : {
880 1 : CPL_LSBPTR32(&x);
881 1 : return x;
882 : }
883 :
884 1 : template <> inline double CPL_AS_LSB<double>(double x)
885 : {
886 1 : CPL_LSBPTR64(&x);
887 1 : return x;
888 : }
889 :
890 : /*! @endcond */
891 :
892 : /** Return a primitive type from a memory buffer containing its LSB
893 : * ordered byte sequence
894 : *
895 : * Only available for primitive types: [u]int[8|16|32|64], float and double.
896 : */
897 14172 : template <class T> inline T CPL_FROM_LSB(const void *ptr)
898 : {
899 : T x;
900 14172 : memcpy(&x, ptr, sizeof(x));
901 14172 : return CPL_AS_LSB(x);
902 : }
903 :
904 : /** Return the byte swapped version of the provided value.
905 : *
906 : * Only available for primitive types: [u]int[8|16|32|64], float and double.
907 : */
908 : template <class T> T CPL_SWAP(T)
909 : {
910 : // See https://youtu.be/b6j6SZiXmoo?t=1659 for rationale for CPL_T_IsAlwaysFalse
911 : static_assert(CPL_T_IsAlwaysFalse<T>::value, "Unsupported value for T");
912 : }
913 :
914 : /*! @cond Doxygen_Suppress */
915 1 : template <> inline int8_t CPL_SWAP<int8_t>(int8_t x)
916 : {
917 1 : return x;
918 : }
919 :
920 1 : template <> inline uint8_t CPL_SWAP<uint8_t>(uint8_t x)
921 : {
922 1 : return x;
923 : }
924 :
925 14 : template <> inline uint16_t CPL_SWAP<uint16_t>(uint16_t x)
926 : {
927 14 : return CPL_SWAP16(x);
928 : }
929 :
930 14 : template <> inline int16_t CPL_SWAP<int16_t>(int16_t x)
931 : {
932 14 : uint16_t ux = CPL_SWAP16(x);
933 14 : memcpy(&x, &ux, sizeof(x));
934 14 : return x;
935 : }
936 :
937 14 : template <> inline uint32_t CPL_SWAP<uint32_t>(uint32_t x)
938 : {
939 14 : return CPL_SWAP32(x);
940 : }
941 :
942 14 : template <> inline int32_t CPL_SWAP<int32_t>(int32_t x)
943 : {
944 14 : uint32_t ux = CPL_SWAP32(x);
945 14 : memcpy(&x, &ux, sizeof(x));
946 14 : return x;
947 : }
948 :
949 14 : template <> inline uint64_t CPL_SWAP<uint64_t>(uint64_t x)
950 : {
951 14 : return CPL_SWAP64(x);
952 : }
953 :
954 14 : template <> inline int64_t CPL_SWAP<int64_t>(int64_t x)
955 : {
956 14 : uint64_t ux = CPL_SWAP64(x);
957 14 : memcpy(&x, &ux, sizeof(x));
958 14 : return x;
959 : }
960 :
961 2 : template <> inline float CPL_SWAP<float>(float x)
962 : {
963 2 : float ret = x;
964 2 : CPL_SWAP32PTR(&ret);
965 2 : return ret;
966 : }
967 :
968 2 : template <> inline double CPL_SWAP<double>(double x)
969 : {
970 2 : double ret = x;
971 2 : CPL_SWAP64PTR(&ret);
972 2 : return ret;
973 : }
974 :
975 : /*! @endcond */
976 : }
977 : #endif // defined(__cplusplus) && defined(GDAL_COMPILATION)
978 :
979 : /*! @cond Doxygen_Suppress */
980 : /* Utility macro to explicitly mark intentionally unreferenced parameters. */
981 : #ifndef UNREFERENCED_PARAM
982 : #ifdef UNREFERENCED_PARAMETER /* May be defined by Windows API */
983 : #define UNREFERENCED_PARAM(param) UNREFERENCED_PARAMETER(param)
984 : #else
985 : #define UNREFERENCED_PARAM(param) ((void)param)
986 : #endif /* UNREFERENCED_PARAMETER */
987 : #endif /* UNREFERENCED_PARAM */
988 : /*! @endcond */
989 :
990 : /* We exclude mingw64 4.6 which seems to be broken regarding this */
991 : #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP) && \
992 : !(defined(__MINGW64__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6)
993 : /** Null terminated variadic */
994 : #define CPL_NULL_TERMINATED __attribute__((__sentinel__))
995 : #else
996 : /** Null terminated variadic */
997 : #define CPL_NULL_TERMINATED
998 : #endif
999 :
1000 : #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP)
1001 : /** Tag a function to have printf() formatting */
1002 : #define CPL_PRINT_FUNC_FORMAT(format_idx, arg_idx) \
1003 : __attribute__((__format__(__printf__, format_idx, arg_idx)))
1004 : /** Tag a function to have scanf() formatting */
1005 : #define CPL_SCAN_FUNC_FORMAT(format_idx, arg_idx) \
1006 : __attribute__((__format__(__scanf__, format_idx, arg_idx)))
1007 : #else
1008 : /** Tag a function to have printf() formatting */
1009 : #define CPL_PRINT_FUNC_FORMAT(format_idx, arg_idx)
1010 : /** Tag a function to have scanf() formatting */
1011 : #define CPL_SCAN_FUNC_FORMAT(format_idx, arg_idx)
1012 : #endif
1013 :
1014 : #if defined(_MSC_VER) && \
1015 : (defined(GDAL_COMPILATION) || defined(CPL_ENABLE_MSVC_ANNOTATIONS))
1016 : #include <sal.h>
1017 : /** Macro into which to wrap the format argument of a printf-like function.
1018 : * Only used if ANALYZE=1 is specified to nmake */
1019 : #define CPL_FORMAT_STRING(arg) _Printf_format_string_ arg
1020 : /** Macro into which to wrap the format argument of a sscanf-like function.
1021 : * Only used if ANALYZE=1 is specified to nmake */
1022 : #define CPL_SCANF_FORMAT_STRING(arg) _Scanf_format_string_ arg
1023 : #else
1024 : /** Macro into which to wrap the format argument of a printf-like function */
1025 : #define CPL_FORMAT_STRING(arg) arg
1026 : /** Macro into which to wrap the format argument of a sscanf-like function. */
1027 : #define CPL_SCANF_FORMAT_STRING(arg) arg
1028 : #endif /* defined(_MSC_VER) && defined(GDAL_COMPILATION) */
1029 :
1030 : #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
1031 : /** Qualifier to warn when the return value of a function is not used */
1032 : #define CPL_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
1033 : #else
1034 : /** Qualifier to warn when the return value of a function is not used */
1035 : #define CPL_WARN_UNUSED_RESULT
1036 : #endif
1037 :
1038 : #if defined(__GNUC__) && __GNUC__ >= 4
1039 : /** Qualifier for an argument that is unused */
1040 : #define CPL_UNUSED __attribute((__unused__))
1041 : #else
1042 : /* TODO: add cases for other compilers */
1043 : /** Qualifier for an argument that is unused */
1044 : #define CPL_UNUSED
1045 : #endif
1046 :
1047 : #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP)
1048 : /** Qualifier for a function that does not return at all (terminates the
1049 : * process) */
1050 : #define CPL_NO_RETURN __attribute__((noreturn))
1051 : #else
1052 : /** Qualifier for a function that does not return at all (terminates the
1053 : * process) */
1054 : #define CPL_NO_RETURN
1055 : #endif
1056 :
1057 : /*! @cond Doxygen_Suppress */
1058 : /* Clang __has_attribute */
1059 : #ifndef __has_attribute
1060 : #define __has_attribute(x) 0 // Compatibility with non-clang compilers.
1061 : #endif
1062 :
1063 : /*! @endcond */
1064 :
1065 : #if ((defined(__GNUC__) && \
1066 : (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) || \
1067 : __has_attribute(returns_nonnull)) && \
1068 : !defined(DOXYGEN_SKIP) && !defined(__INTEL_COMPILER)
1069 : /** Qualifier for a function that does not return NULL */
1070 : #define CPL_RETURNS_NONNULL __attribute__((returns_nonnull))
1071 : #else
1072 : /** Qualifier for a function that does not return NULL */
1073 : #define CPL_RETURNS_NONNULL
1074 : #endif
1075 :
1076 : #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
1077 : /** restrict keyword to declare that pointers do not alias */
1078 : #define CPL_RESTRICT __restrict__
1079 : #else
1080 : /** restrict keyword to declare that pointers do not alias */
1081 : #define CPL_RESTRICT
1082 : #endif
1083 :
1084 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
1085 :
1086 : /** To be used in public headers only. For non-public headers or .cpp files,
1087 : * use override directly. */
1088 : #define CPL_OVERRIDE override
1089 :
1090 : /** C++11 final qualifier */
1091 : #define CPL_FINAL final
1092 :
1093 : /** Mark that a class is explicitly recognized as non-final */
1094 : #define CPL_NON_FINAL
1095 :
1096 : /** Helper to remove the copy and assignment constructors so that the compiler
1097 : will not generate the default versions.
1098 :
1099 : Must be placed in the private section of a class and should be at the end.
1100 : */
1101 : #define CPL_DISALLOW_COPY_ASSIGN(ClassName) \
1102 : ClassName(const ClassName &) = delete; \
1103 : ClassName &operator=(const ClassName &) = delete;
1104 :
1105 : #endif /* __cplusplus */
1106 :
1107 : #ifdef CPL_DISABLE_WARN_DEPRECATED
1108 : #define CPL_WARN_DEPRECATED(x)
1109 : #elif !defined(DOXYGEN_SKIP) && !defined(CPL_WARN_DEPRECATED)
1110 : #if defined(__has_extension)
1111 : #if __has_extension(attribute_deprecated_with_message)
1112 : /* Clang extension */
1113 : #define CPL_WARN_DEPRECATED(x) __attribute__((deprecated(x)))
1114 : #else
1115 : #define CPL_WARN_DEPRECATED(x)
1116 : #endif
1117 : #elif defined(__GNUC__)
1118 : #define CPL_WARN_DEPRECATED(x) __attribute__((deprecated))
1119 : #else
1120 : #define CPL_WARN_DEPRECATED(x)
1121 : #endif
1122 : #endif
1123 :
1124 : #if !defined(_MSC_VER) && !defined(__APPLE__) && !defined(_FORTIFY_SOURCE)
1125 : CPL_C_START
1126 : #if defined(GDAL_COMPILATION) && defined(WARN_STANDARD_PRINTF)
1127 : int vsnprintf(char *str, size_t size, const char *fmt, va_list args)
1128 : CPL_WARN_DEPRECATED("Use CPLvsnprintf() instead");
1129 : int snprintf(char *str, size_t size, const char *fmt, ...)
1130 : CPL_PRINT_FUNC_FORMAT(3, 4)
1131 : CPL_WARN_DEPRECATED("Use CPLsnprintf() instead");
1132 : int sprintf(char *str, const char *fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3)
1133 : CPL_WARN_DEPRECATED("Use CPLsnprintf() instead");
1134 : #elif defined(GDAL_COMPILATION) && !defined(DONT_DEPRECATE_SPRINTF)
1135 : int sprintf(char *str, const char *fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3)
1136 : CPL_WARN_DEPRECATED("Use snprintf() or CPLsnprintf() instead");
1137 : #endif /* defined(GDAL_COMPILATION) && defined(WARN_STANDARD_PRINTF) */
1138 : CPL_C_END
1139 : #endif /* !defined(_MSC_VER) && !defined(__APPLE__) */
1140 :
1141 : #if defined(__cplusplus)
1142 : #ifndef CPPCHECK
1143 : /** Returns the size of C style arrays. */
1144 : #define CPL_ARRAYSIZE(array) \
1145 : ((sizeof(array) / sizeof(*(array))) / \
1146 : static_cast<size_t>(!(sizeof(array) % sizeof(*(array)))))
1147 : #else
1148 : /* simplified version for cppcheck */
1149 : #define CPL_ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
1150 : #endif
1151 :
1152 : extern "C++"
1153 : {
1154 33001718 : template <class T> static void CPL_IGNORE_RET_VAL(const T &)
1155 : {
1156 32974500 : }
1157 :
1158 92297254 : inline static bool CPL_TO_BOOL(int x)
1159 : {
1160 92297254 : return x != 0;
1161 : }
1162 : } /* extern "C++" */
1163 :
1164 : #endif /* __cplusplus */
1165 :
1166 : #if (((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) || \
1167 : (defined(__clang__) && __clang_major__ >= 3)) && \
1168 : !defined(_MSC_VER))
1169 : #define HAVE_GCC_DIAGNOSTIC_PUSH
1170 : #endif
1171 :
1172 : #if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && \
1173 : !defined(_MSC_VER))
1174 : #define HAVE_GCC_SYSTEM_HEADER
1175 : #endif
1176 :
1177 : /*! @cond Doxygen_Suppress */
1178 :
1179 : #ifndef FALSE
1180 : #define FALSE 0
1181 : #endif
1182 :
1183 : #ifndef TRUE
1184 : #define TRUE 1
1185 : #endif
1186 :
1187 : #if __clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ >= 8)
1188 : #define CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW \
1189 : __attribute__((no_sanitize("unsigned-integer-overflow")))
1190 : #else
1191 : #define CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
1192 : #endif
1193 :
1194 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) && \
1195 : defined(GDAL_COMPILATION)
1196 : extern "C++"
1197 : {
1198 : template <class C, class A, class B>
1199 25375322 : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW inline C CPLUnsanitizedAdd(A a, B b)
1200 : {
1201 25375322 : return a + b;
1202 : }
1203 : }
1204 : #endif
1205 :
1206 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
1207 : #define CPL_NULLPTR nullptr
1208 : #else
1209 : #define CPL_NULLPTR NULL
1210 : #endif
1211 :
1212 : #if defined(__cplusplus) && defined(GDAL_COMPILATION)
1213 : extern "C++"
1214 : {
1215 : namespace cpl
1216 : {
1217 : /** Function to indicate that the result of an arithmetic operation
1218 : * does fit on the specified type. Typically used to avoid warnings
1219 : * about potentially overflowing multiplications by static analyzers.
1220 : */
1221 196365502 : template <typename T> inline T fits_on(T t)
1222 : {
1223 196365502 : return t;
1224 : }
1225 :
1226 : /** Emulates the C++20 .contains() method */
1227 : template <typename C, typename V>
1228 3986687 : inline bool contains(const C &container, const V &value)
1229 : {
1230 3986687 : return container.find(value) != container.end();
1231 : }
1232 :
1233 : } // namespace cpl
1234 : }
1235 : #endif
1236 :
1237 : /*! @endcond */
1238 :
1239 : /* This typedef is for C functions that take char** as argument, but */
1240 : /* with the semantics of a const list. In C, char** is not implicitly cast to */
1241 : /* const char* const*, contrary to C++. So when seen for C++, it is OK */
1242 : /* to expose the prototypes as const char* const*, but for C we keep the */
1243 : /* historical definition to avoid warnings. */
1244 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) && \
1245 : !defined(DOXYGEN_SKIP)
1246 : /** Type of a constant null-terminated list of nul terminated strings.
1247 : * Seen as char** from C and const char* const* from C++ */
1248 : typedef const char *const *CSLConstList;
1249 : #else
1250 : /** Type of a constant null-terminated list of nul terminated strings.
1251 : * Seen as char** from C and const char* const* from C++ */
1252 : typedef char **CSLConstList;
1253 : #endif
1254 :
1255 : #if defined(__cplusplus) && defined(GDAL_COMPILATION)
1256 : #if defined(__GNUC__) && !defined(DOXYGEN_SKIP)
1257 : /** Macro that evaluates to (cond), and possibly gives a hint to the compiler
1258 : * than (cond) is unlikely to be true.
1259 : */
1260 : #define CPL_UNLIKELY(cond) __builtin_expect(static_cast<bool>(cond), 0)
1261 : #else
1262 : #define CPL_UNLIKELY(cond) (cond)
1263 : #endif
1264 : #endif
1265 :
1266 : #endif /* ndef CPL_BASE_H_INCLUDED */
|