GDAL
cpl_port.h
Go to the documentation of this file.
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
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
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
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
127extern "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
151typedef long GInt32;
152typedef unsigned long GUInt32;
153#else
155typedef int GInt32;
157typedef unsigned int GUInt32;
158#endif
159
161typedef short GInt16;
163typedef unsigned short GUInt16;
165typedef unsigned char GByte;
167typedef 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
173#define CPL_GBOOL_DEFINED
176typedef int GBool;
177#endif
178
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
189/* -------------------------------------------------------------------- */
190/* 64bit support */
191/* -------------------------------------------------------------------- */
192
195typedef long long GIntBig;
198typedef unsigned long long GUIntBig;
199
201#define GINTBIG_MIN (CPL_STATIC_CAST(GIntBig, 0x80000000) << 32)
203#define GINTBIG_MAX ((CPL_STATIC_CAST(GIntBig, 0x7FFFFFFF) << 32) | 0xFFFFFFFFU)
205#define GUINTBIG_MAX \
206 ((CPL_STATIC_CAST(GUIntBig, 0xFFFFFFFFU) << 32) | 0xFFFFFFFFU)
207
209#define CPL_HAS_GINT64 1
212/* Note: we might want to use instead int64_t / uint64_t if they are available
213 */
214
219
221#define GINT64_MIN GINTBIG_MIN
223#define GINT64_MAX GINTBIG_MAX
225#define GUINT64_MAX GUINTBIG_MAX
226
227#if SIZEOF_VOIDP > 8
228#include <stddef.h> // ptrdiff_t
230typedef ptrdiff_t GPtrDiff_t;
231#elif SIZEOF_VOIDP == 8
233typedef GIntBig GPtrDiff_t;
234#else
236typedef int GPtrDiff_t;
237#endif
238
239#ifdef GDAL_COMPILATION
240#include <stdint.h>
241typedef 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
253#define CPL_FRMT_GB_WITHOUT_PREFIX "ll"
254#endif
255
257#define CPL_FRMT_GIB "%" CPL_FRMT_GB_WITHOUT_PREFIX "d"
259#define CPL_FRMT_GUIB "%" CPL_FRMT_GB_WITHOUT_PREFIX "u"
260
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
270/* ==================================================================== */
271/* Other standard services. */
272/* ==================================================================== */
273#ifdef __cplusplus
275#define CPL_C_START \
276 extern "C" \
277 {
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
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
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
330#ifdef _MSC_VER
331#define FORCE_CDECL __cdecl
332#else
333#define FORCE_CDECL
334#endif
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
351#define CPL_MIN(a, b) (((a) < (b)) ? (a) : (b))
353#define CPL_MAX(a, b) (((a) > (b)) ? (a) : (b))
354
356#define CPL_ABS(x) (((x) < 0) ? (-1 * (x)) : (x))
357
360#if defined(GDAL_COMPILATION)
361#ifndef M_PI
362#define M_PI 3.14159265358979323846
363/* 3.1415926535897932384626433832795 */
364#endif
365
366#endif
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/* -------------------------------------------------------------------- */
375#ifndef CPLIsEqual
376#define CPLIsEqual(x, y) (fabs((x) - (y)) < 0.0000000000001)
377#endif
380/* -------------------------------------------------------------------- */
381/* Provide macros for case insensitive string comparisons. */
382/* -------------------------------------------------------------------- */
383#ifndef EQUAL
384
385#if defined(AFL_FRIENDLY) && defined(__GNUC__)
386
387static inline int CPL_afl_friendly_memcmp(const void *ptr1, const void *ptr2,
388 size_t len)
389 __attribute__((always_inline));
390
391static 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
406static inline int CPL_afl_friendly_strcmp(const char *ptr1, const char *ptr2)
407 __attribute__((always_inline));
408
409static 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
422static inline int CPL_afl_friendly_strncmp(const char *ptr1, const char *ptr2,
423 size_t len)
424 __attribute__((always_inline));
425
426static 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
441static inline int CPL_afl_friendly_strcasecmp(const char *ptr1,
442 const char *ptr2)
443 __attribute__((always_inline));
444
445static 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
461static inline int CPL_afl_friendly_strncasecmp(const char *ptr1,
462 const char *ptr2, size_t len)
463 __attribute__((always_inline));
464
465static 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
482static inline char *CPL_afl_friendly_strstr(const char *haystack,
483 const char *needle)
484 __attribute__((always_inline));
485
486static 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
525#define STRCASECMP(a, b) (strcasecmp(a, b))
527#define STRNCASECMP(a, b, n) (strncasecmp(a, b, n))
528#endif
530#define EQUALN(a, b, n) (STRNCASECMP(a, b, n) == 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
541#define STARTS_WITH(a, b) (strncmp(a, b, strlen(b)) == 0)
543#define STARTS_WITH_CI(a, b) EQUALN(a, b, strlen(b))
544#endif
545
547#ifndef CPL_THREADLOCAL
548#define CPL_THREADLOCAL
549#endif
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__)
577#define CPLIsNan(x) isnan(x)
579#define CPLIsInf(x) isinf(x)
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
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
618#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
619
621extern "C++"
622{
623
624 template <bool b> struct CPLStaticAssert
625 {
626 };
627
628 template <> struct CPLStaticAssert<true>
629 {
630 static void my_function()
631 {
632 }
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 */
647/*---------------------------------------------------------------------
648 * Little endian <==> big endian byte swap macros.
649 *--------------------------------------------------------------------*/
650
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__
658#define CPL_SWAP32(x) \
659 CPL_STATIC_CAST(GUInt32, __builtin_bswap32(CPL_STATIC_CAST(GUInt32, x)))
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
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
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
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
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
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
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
745#define CPL_LSBWORD16(x) (x)
747#define CPL_MSBWORD16(x) CPL_SWAP16(x)
749#define CPL_LSBWORD32(x) (x)
751#define CPL_MSBWORD32(x) CPL_SWAP32(x)
754#define CPL_LSBPTR16(x) \
755 CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 2)
758#define CPL_MSBPTR16(x) CPL_SWAP16PTR(x)
761#define CPL_LSBPTR32(x) \
762 CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 4)
765#define CPL_MSBPTR32(x) CPL_SWAP32PTR(x)
768#define CPL_LSBPTR64(x) \
769 CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 8)
772#define CPL_MSBPTR64(x) CPL_SWAP64PTR(x)
773#endif
774
778#define CPL_LSBINT16PTR(x) \
779 ((*CPL_REINTERPRET_CAST(const GByte *, x)) | \
780 (*((CPL_REINTERPRET_CAST(const GByte *, x)) + 1) << 8))
781
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
792#define CPL_LSBSINT16PTR(x) CPL_STATIC_CAST(GInt16, CPL_LSBINT16PTR(x))
793
796#define CPL_LSBUINT16PTR(x) CPL_STATIC_CAST(GUInt16, CPL_LSBINT16PTR(x))
797
799#define CPL_LSBSINT32PTR(x) CPL_STATIC_CAST(GInt32, CPL_LSBINT32PTR(x))
800
803#define CPL_LSBUINT32PTR(x) CPL_STATIC_CAST(GUInt32, CPL_LSBINT32PTR(x))
804
805#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
806
807extern "C++"
808{
809#include <cstddef>
810#include <cstdint>
811
813 // workaround before CWG2518/P2593R1
814 template <class T> struct CPL_T_IsAlwaysFalse
815 {
816 static const bool value = false;
817 };
818
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
832 template <> inline int8_t CPL_AS_LSB<int8_t>(int8_t x)
833 {
834 return x;
835 }
836
837 template <> inline uint8_t CPL_AS_LSB<uint8_t>(uint8_t x)
838 {
839 return x;
840 }
841
842 template <> inline int16_t CPL_AS_LSB<int16_t>(int16_t x)
843 {
844 CPL_LSBPTR16(&x);
845 return x;
846 }
847
848 template <> inline uint16_t CPL_AS_LSB<uint16_t>(uint16_t x)
849 {
850 CPL_LSBPTR16(&x);
851 return x;
852 }
853
854 template <> inline int32_t CPL_AS_LSB<int32_t>(int32_t x)
855 {
856 CPL_LSBPTR32(&x);
857 return x;
858 }
859
860 template <> inline uint32_t CPL_AS_LSB<uint32_t>(uint32_t x)
861 {
862 CPL_LSBPTR32(&x);
863 return x;
864 }
865
866 template <> inline int64_t CPL_AS_LSB<int64_t>(int64_t x)
867 {
868 CPL_LSBPTR64(&x);
869 return x;
870 }
871
872 template <> inline uint64_t CPL_AS_LSB<uint64_t>(uint64_t x)
873 {
874 CPL_LSBPTR64(&x);
875 return x;
876 }
877
878 template <> inline float CPL_AS_LSB<float>(float x)
879 {
880 CPL_LSBPTR32(&x);
881 return x;
882 }
883
884 template <> inline double CPL_AS_LSB<double>(double x)
885 {
886 CPL_LSBPTR64(&x);
887 return x;
888 }
889
897 template <class T> inline T CPL_FROM_LSB(const void *ptr)
898 {
899 T x;
900 memcpy(&x, ptr, sizeof(x));
901 return CPL_AS_LSB(x);
902 }
903
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
915 template <> inline int8_t CPL_SWAP<int8_t>(int8_t x)
916 {
917 return x;
918 }
919
920 template <> inline uint8_t CPL_SWAP<uint8_t>(uint8_t x)
921 {
922 return x;
923 }
924
925 template <> inline uint16_t CPL_SWAP<uint16_t>(uint16_t x)
926 {
927 return CPL_SWAP16(x);
928 }
929
930 template <> inline int16_t CPL_SWAP<int16_t>(int16_t x)
931 {
932 uint16_t ux = CPL_SWAP16(x);
933 memcpy(&x, &ux, sizeof(x));
934 return x;
935 }
936
937 template <> inline uint32_t CPL_SWAP<uint32_t>(uint32_t x)
938 {
939 return CPL_SWAP32(x);
940 }
941
942 template <> inline int32_t CPL_SWAP<int32_t>(int32_t x)
943 {
944 uint32_t ux = CPL_SWAP32(x);
945 memcpy(&x, &ux, sizeof(x));
946 return x;
947 }
948
949 template <> inline uint64_t CPL_SWAP<uint64_t>(uint64_t x)
950 {
951 return CPL_SWAP64(x);
952 }
953
954 template <> inline int64_t CPL_SWAP<int64_t>(int64_t x)
955 {
956 uint64_t ux = CPL_SWAP64(x);
957 memcpy(&x, &ux, sizeof(x));
958 return x;
959 }
960
961 template <> inline float CPL_SWAP<float>(float x)
962 {
963 float ret = x;
964 CPL_SWAP32PTR(&ret);
965 return ret;
966 }
967
968 template <> inline double CPL_SWAP<double>(double x)
969 {
970 double ret = x;
971 CPL_SWAP64PTR(&ret);
972 return ret;
973 }
974
976}
977#endif // defined(__cplusplus) && defined(GDAL_COMPILATION)
978
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 */
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)
994#define CPL_NULL_TERMINATED __attribute__((__sentinel__))
995#else
997#define CPL_NULL_TERMINATED
998#endif
999
1000#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP)
1002#define CPL_PRINT_FUNC_FORMAT(format_idx, arg_idx) \
1003 __attribute__((__format__(__printf__, format_idx, arg_idx)))
1005#define CPL_SCAN_FUNC_FORMAT(format_idx, arg_idx) \
1006 __attribute__((__format__(__scanf__, format_idx, arg_idx)))
1007#else
1009#define CPL_PRINT_FUNC_FORMAT(format_idx, arg_idx)
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>
1019#define CPL_FORMAT_STRING(arg) _Printf_format_string_ arg
1022#define CPL_SCANF_FORMAT_STRING(arg) _Scanf_format_string_ arg
1023#else
1025#define CPL_FORMAT_STRING(arg) arg
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)
1032#define CPL_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
1033#else
1035#define CPL_WARN_UNUSED_RESULT
1036#endif
1037
1038#if defined(__GNUC__) && __GNUC__ >= 4
1040#define CPL_UNUSED __attribute((__unused__))
1041#else
1042/* TODO: add cases for other compilers */
1044#define CPL_UNUSED
1045#endif
1046
1047#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP)
1050#define CPL_NO_RETURN __attribute__((noreturn))
1051#else
1054#define CPL_NO_RETURN
1055#endif
1056
1058/* Clang __has_attribute */
1059#ifndef __has_attribute
1060#define __has_attribute(x) 0 // Compatibility with non-clang compilers.
1061#endif
1062
1065#if ((defined(__GNUC__) && \
1066 (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) || \
1067 __has_attribute(returns_nonnull)) && \
1068 !defined(DOXYGEN_SKIP) && !defined(__INTEL_COMPILER)
1070#define CPL_RETURNS_NONNULL __attribute__((returns_nonnull))
1071#else
1073#define CPL_RETURNS_NONNULL
1074#endif
1075
1076#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
1078#define CPL_RESTRICT __restrict__
1079#else
1081#define CPL_RESTRICT
1082#endif
1083
1084#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
1085
1088#define CPL_OVERRIDE override
1089
1091#define CPL_FINAL final
1092
1094#define CPL_NON_FINAL
1095
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)
1126#if defined(GDAL_COMPILATION) && defined(WARN_STANDARD_PRINTF)
1127int vsnprintf(char *str, size_t size, const char *fmt, va_list args)
1128 CPL_WARN_DEPRECATED("Use CPLvsnprintf() instead");
1129int snprintf(char *str, size_t size, const char *fmt, ...)
1131 CPL_WARN_DEPRECATED("Use CPLsnprintf() instead");
1132int 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)
1135int 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) */
1139#endif /* !defined(_MSC_VER) && !defined(__APPLE__) */
1140
1141#if defined(__cplusplus)
1142#ifndef CPPCHECK
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
1152extern "C++"
1153{
1154 template <class T> static void CPL_IGNORE_RET_VAL(const T &)
1155 {
1156 }
1157
1158 inline static bool CPL_TO_BOOL(int x)
1159 {
1160 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
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)
1196extern "C++"
1197{
1198 template <class C, class A, class B>
1199 CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW inline C CPLUnsanitizedAdd(A a, B b)
1200 {
1201 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)
1213extern "C++"
1214{
1215 namespace cpl
1216 {
1221 template <typename T> inline T fits_on(T t)
1222 {
1223 return t;
1224 }
1225
1227 template <typename C, typename V>
1228 inline bool contains(const C &container, const V &value)
1229 {
1230 return container.find(value) != container.end();
1231 }
1232
1233 } // namespace cpl
1234}
1235#endif
1236
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)
1248typedef const char *const *CSLConstList;
1249#else
1252typedef char **CSLConstList;
1253#endif
1254
1255#if defined(__cplusplus) && defined(GDAL_COMPILATION)
1256#if defined(__GNUC__) && !defined(DOXYGEN_SKIP)
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 */
#define CPL_LSBPTR64(x)
Byte-swap if necessary a 64bit word at the location pointed from a originally LSB ordered pointer.
Definition cpl_port.h:768
int GPtrDiff_t
Integer type large enough to hold the difference between 2 addresses.
Definition cpl_port.h:236
#define CPL_LSBPTR16(x)
Byte-swap if necessary a 16bit word at the location pointed from a originally LSB ordered pointer.
Definition cpl_port.h:754
#define CPL_SWAP64PTR(x)
Byte-swap a 64 bit pointer.
Definition cpl_port.h:714
#define CPL_SWAP32PTR(x)
Byte-swap a 32 bit pointer.
Definition cpl_port.h:701
unsigned long long GUIntBig
Large unsigned integer type (generally 64-bit unsigned integer type).
Definition cpl_port.h:198
short GInt16
Int16 type.
Definition cpl_port.h:161
#define CPL_C_END
Macro to end a block of C symbols.
Definition cpl_port.h:279
#define CPL_C_START
Macro to start a block of C symbols.
Definition cpl_port.h:275
#define CPL_LSBPTR32(x)
Byte-swap if necessary a 32bit word at the location pointed from a originally LSB ordered pointer.
Definition cpl_port.h:761
GIntBig GInt64
Signed 64 bit integer type.
Definition cpl_port.h:216
int GBool
Type for boolean values (alias to int)
Definition cpl_port.h:176
#define CPL_SWAP16(x)
Byte-swap a 16bit unsigned integer.
Definition cpl_port.h:652
#define CPL_SWAP32(x)
Byte-swap a 32bit unsigned integer.
Definition cpl_port.h:670
unsigned int GUInt32
Unsigned int32 type.
Definition cpl_port.h:157
#define CPL_SWAP64(x)
Byte-swap a 64bit unsigned integer.
Definition cpl_port.h:678
#define CPL_PRINT_FUNC_FORMAT(format_idx, arg_idx)
Tag a function to have printf() formatting.
Definition cpl_port.h:1009
char ** CSLConstList
Type of a constant null-terminated list of nul terminated strings.
Definition cpl_port.h:1252
GUIntBig GUInt64
Unsigned 64 bit integer type.
Definition cpl_port.h:218
unsigned short GUInt16
Unsigned int16 type.
Definition cpl_port.h:163
T CPL_SWAP(T)
Return the byte swapped version of the provided value.
Definition cpl_port.h:908
unsigned char GByte
Unsigned byte type.
Definition cpl_port.h:165
T CPL_AS_LSB(T)
Return the provided value as a LSB ordered one.
Definition cpl_port.h:825
T CPL_FROM_LSB(const void *ptr)
Return a primitive type from a memory buffer containing its LSB ordered byte sequence.
Definition cpl_port.h:897
int GInt32
Int32 type.
Definition cpl_port.h:155
signed char GInt8
Signed int8 type.
Definition cpl_port.h:167
long long GIntBig
Large signed integer type (generally 64-bit integer type).
Definition cpl_port.h:195