Coverage Report

Created: 2026-01-17 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zlib-ng/zbuild.h
Line
Count
Source
1
#ifndef _ZBUILD_H
2
#define _ZBUILD_H
3
4
#define _POSIX_SOURCE 1  /* fileno */
5
#ifndef _POSIX_C_SOURCE
6
#  define _POSIX_C_SOURCE 200809L /* snprintf, posix_memalign, strdup */
7
#endif
8
#ifndef _ISOC11_SOURCE
9
#  define _ISOC11_SOURCE 1 /* aligned_alloc */
10
#endif
11
#ifdef __OpenBSD__
12
#  define _BSD_SOURCE 1
13
#endif
14
15
#include <stddef.h>
16
#include <string.h>
17
#include <stdlib.h>
18
#include <stdint.h>
19
#include <stdio.h>
20
21
/* Determine compiler version of C Standard */
22
#ifdef __STDC_VERSION__
23
#  if __STDC_VERSION__ >= 199901L
24
#    ifndef STDC99
25
#      define STDC99
26
#    endif
27
#  endif
28
#  if __STDC_VERSION__ >= 201112L
29
#    ifndef STDC11
30
#      define STDC11
31
#    endif
32
#  endif
33
#endif
34
35
#ifndef Z_HAS_ATTRIBUTE
36
#  if defined(__has_attribute)
37
#    define Z_HAS_ATTRIBUTE(a) __has_attribute(a)
38
#  else
39
#    define Z_HAS_ATTRIBUTE(a) 0
40
#  endif
41
#endif
42
43
#ifndef Z_FALLTHROUGH
44
#  if Z_HAS_ATTRIBUTE(__fallthrough__) || (defined(__GNUC__) && (__GNUC__ >= 7))
45
379k
#    define Z_FALLTHROUGH __attribute__((__fallthrough__))
46
#  else
47
#    define Z_FALLTHROUGH do {} while(0) /* fallthrough */
48
#  endif
49
#endif
50
51
/* Hint to compiler that a block of code is unreachable, typically in a switch default condition */
52
#ifndef Z_UNREACHABLE
53
#  if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
54
#    define Z_UNREACHABLE() unreachable()           // C23 approach
55
#  elif (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__)
56
0
#    define Z_UNREACHABLE() __builtin_unreachable()
57
#  else
58
#    define Z_UNREACHABLE()
59
#  endif
60
#endif
61
62
#ifndef Z_TARGET
63
#  if Z_HAS_ATTRIBUTE(__target__)
64
#    define Z_TARGET(x) __attribute__((__target__(x)))
65
#  else
66
#    define Z_TARGET(x)
67
#  endif
68
#endif
69
70
/* This has to be first include that defines any types */
71
#if defined(_MSC_VER)
72
#  if defined(_WIN64)
73
    typedef __int64 ssize_t;
74
#  else
75
    typedef long ssize_t;
76
#  endif
77
78
#  if defined(_WIN64)
79
    #define SSIZE_MAX _I64_MAX
80
#  else
81
    #define SSIZE_MAX LONG_MAX
82
#  endif
83
#endif
84
85
/* A forced inline decorator */
86
#if defined(_MSC_VER)
87
#  define Z_FORCEINLINE __forceinline
88
#elif defined(__GNUC__)
89
#  define Z_FORCEINLINE inline __attribute__((always_inline))
90
#else
91
    /* It won't actually force inlining but it will suggest it */
92
#  define Z_FORCEINLINE inline
93
#endif
94
95
/* MS Visual Studio does not allow inline in C, only C++.
96
   But it provides __inline instead, so use that. */
97
#if defined(_MSC_VER) && !defined(inline) && !defined(__cplusplus)
98
#  define inline __inline
99
#endif
100
101
#if defined(ZLIB_COMPAT)
102
#  define PREFIX(x) x
103
#  define PREFIX2(x) ZLIB_ ## x
104
#  define PREFIX3(x) z_ ## x
105
#  define PREFIX4(x) x ## 64
106
#  define zVersion zlibVersion
107
#else
108
20.4k
#  define PREFIX(x) zng_ ## x
109
0
#  define PREFIX2(x) ZLIBNG_ ## x
110
365k
#  define PREFIX3(x) zng_ ## x
111
#  define PREFIX4(x) zng_ ## x
112
#  define zVersion zlibng_version
113
#  define z_size_t size_t
114
#endif
115
116
/* In zlib-compat some functions and types use unsigned long, but zlib-ng use size_t */
117
#if defined(ZLIB_COMPAT)
118
#  define z_uintmax_t unsigned long
119
#else
120
#  define z_uintmax_t size_t
121
#endif
122
123
/* In zlib-compat headers some function return values and parameter types use int or unsigned, but zlib-ng headers use
124
   int32_t and uint32_t, which will cause type mismatch when compiling zlib-ng if int32_t is long and uint32_t is
125
   unsigned long */
126
#if defined(ZLIB_COMPAT)
127
#  define z_int32_t int
128
#  define z_uint32_t unsigned int
129
#else
130
#  define z_int32_t int32_t
131
#  define z_uint32_t uint32_t
132
#endif
133
134
/* Minimum of a and b. */
135
648k
#define MIN(a, b) ((a) > (b) ? (b) : (a))
136
/* Maximum of a and b. */
137
76.5k
#define MAX(a, b) ((a) < (b) ? (b) : (a))
138
/* Ignore unused variable warning */
139
12.3M
#define Z_UNUSED(var) (void)(var)
140
141
/* Force the compiler to treat variable as modified. Empty asm statement with a "+r" constraint prevents
142
   the compiler from reordering or eliminating loads into the variable. This can help keep critical latency
143
   chains in the hot path from being shortened or optimized away. */
144
#if (defined(__GNUC__) || defined(__clang__)) && \
145
        (defined(ARCH_X86) || (defined(ARCH_ARM) && defined(ARCH_64BIT)))
146
9.99M
#  define Z_TOUCH(var) __asm__ ("" : "+r"(var))
147
#else
148
#  define Z_TOUCH(var) (void)(var)
149
#endif
150
151
#if defined(HAVE_VISIBILITY_INTERNAL)
152
#  define Z_INTERNAL __attribute__((visibility ("internal")))
153
#elif defined(HAVE_VISIBILITY_HIDDEN)
154
#  define Z_INTERNAL __attribute__((visibility ("hidden")))
155
#else
156
#  define Z_INTERNAL
157
#endif
158
159
/* Symbol versioning helpers, allowing multiple versions of a function to exist.
160
 * Functions using this must also be added to zlib-ng.map for each version.
161
 * Double @@ means this is the default for newly compiled applications to link against.
162
 * Single @ means this is kept for backwards compatibility.
163
 * This is only used for Zlib-ng native API, and only on platforms supporting this.
164
 */
165
#if defined(HAVE_SYMVER)
166
#  define ZSYMVER(func,alias,ver) __asm__(".symver " func ", " alias "@ZLIB_NG_" ver);
167
#  define ZSYMVER_DEF(func,alias,ver) __asm__(".symver " func ", " alias "@@ZLIB_NG_" ver);
168
#else
169
#  define ZSYMVER(func,alias,ver)
170
#  define ZSYMVER_DEF(func,alias,ver)
171
#endif
172
173
#ifndef __cplusplus
174
#  define Z_REGISTER register
175
#else
176
#  define Z_REGISTER
177
#endif
178
179
/* Reverse the bytes in a value. Use compiler intrinsics when
180
   possible to take advantage of hardware implementations. */
181
#if defined(_MSC_VER) && (_MSC_VER >= 1300)
182
#  include <stdlib.h>
183
#  pragma intrinsic(_byteswap_ulong)
184
#  define ZSWAP16(q) _byteswap_ushort(q)
185
#  define ZSWAP32(q) _byteswap_ulong(q)
186
#  define ZSWAP64(q) _byteswap_uint64(q)
187
188
#elif defined(__clang__) || (defined(__GNUC__) && \
189
        (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
190
10.2k
#  define ZSWAP16(q) __builtin_bswap16(q)
191
40.1k
#  define ZSWAP32(q) __builtin_bswap32(q)
192
#  define ZSWAP64(q) __builtin_bswap64(q)
193
194
#elif defined(__GNUC__) && (__GNUC__ >= 2) && defined(__linux__)
195
#  include <byteswap.h>
196
#  define ZSWAP16(q) bswap_16(q)
197
#  define ZSWAP32(q) bswap_32(q)
198
#  define ZSWAP64(q) bswap_64(q)
199
200
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
201
#  include <sys/endian.h>
202
#  define ZSWAP16(q) bswap16(q)
203
#  define ZSWAP32(q) bswap32(q)
204
#  define ZSWAP64(q) bswap64(q)
205
#elif defined(__OpenBSD__)
206
#  include <sys/endian.h>
207
#  define ZSWAP16(q) swap16(q)
208
#  define ZSWAP32(q) swap32(q)
209
#  define ZSWAP64(q) swap64(q)
210
#elif defined(__INTEL_COMPILER)
211
/* ICC does not provide a two byte swap. */
212
#  define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8))
213
#  define ZSWAP32(q) _bswap(q)
214
#  define ZSWAP64(q) _bswap64(q)
215
216
#else
217
#  define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8))
218
#  define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
219
                     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
220
#  define ZSWAP64(q)                           \
221
         (((q & 0xFF00000000000000u) >> 56u) | \
222
          ((q & 0x00FF000000000000u) >> 40u) | \
223
          ((q & 0x0000FF0000000000u) >> 24u) | \
224
          ((q & 0x000000FF00000000u) >> 8u)  | \
225
          ((q & 0x00000000FF000000u) << 8u)  | \
226
          ((q & 0x0000000000FF0000u) << 24u) | \
227
          ((q & 0x000000000000FF00u) << 40u) | \
228
          ((q & 0x00000000000000FFu) << 56u))
229
#endif
230
231
/* Only enable likely/unlikely if the compiler is known to support it */
232
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__INTEL_COMPILER) || defined(__clang__)
233
#  define LIKELY_NULL(x)        __builtin_expect((x) != 0, 0)
234
20.5M
#  define LIKELY(x)             __builtin_expect(!!(x), 1)
235
13.7M
#  define UNLIKELY(x)           __builtin_expect(!!(x), 0)
236
#else
237
#  define LIKELY_NULL(x)        x
238
#  define LIKELY(x)             x
239
#  define UNLIKELY(x)           x
240
#endif /* (un)likely */
241
242
#if defined(HAVE_ATTRIBUTE_ALIGNED)
243
1.44k
#  define ALIGNED_(x) __attribute__ ((aligned(x)))
244
#elif defined(_MSC_VER)
245
#  define ALIGNED_(x) __declspec(align(x))
246
#else
247
/* TODO: Define ALIGNED_ for your compiler */
248
#  define ALIGNED_(x)
249
#endif
250
251
#ifdef HAVE_BUILTIN_ASSUME_ALIGNED
252
91.8k
#  define HINT_ALIGNED(p,n) __builtin_assume_aligned((void *)(p),(n))
253
#else
254
#  define HINT_ALIGNED(p,n) (p)
255
#endif
256
10.2k
#define HINT_ALIGNED_16(p) HINT_ALIGNED((p),16)
257
81.6k
#define HINT_ALIGNED_64(p) HINT_ALIGNED((p),64)
258
#define HINT_ALIGNED_4096(p) HINT_ALIGNED((p),4096)
259
260
/* Number of bytes needed to align ptr to the next alignment boundary */
261
#define ALIGN_DIFF(ptr, align) \
262
0
    (((uintptr_t)(align) - ((uintptr_t)(ptr) & ((align) - 1))) & ((align) - 1))
263
264
/* PADSZ returns needed bytes to pad bpos to pad size
265
 * PAD_NN calculates pad size and adds it to bpos, returning the result.
266
 * All take an integer or a pointer as bpos input.
267
 */
268
112k
#define PADSZ(bpos, pad) (((pad) - ((uintptr_t)(bpos) % (pad))) % (pad))
269
20.4k
#define PAD_16(bpos) ((bpos) + PADSZ((bpos),16))
270
91.8k
#define PAD_64(bpos) ((bpos) + PADSZ((bpos),64))
271
#define PAD_4096(bpos) ((bpos) + PADSZ((bpos),4096))
272
273
/* Diagnostic functions */
274
#ifdef ZLIB_DEBUG
275
   extern int Z_INTERNAL z_verbose;
276
   extern void Z_INTERNAL z_error(const char *m);
277
#  define Assert(cond, msg) {int _cond = (cond); if (!(_cond)) z_error(msg);}
278
#  define Trace(x) {if (z_verbose >= 0) fprintf x;}
279
#  define Tracev(x) {if (z_verbose > 0) fprintf x;}
280
#  define Tracevv(x) {if (z_verbose > 1) fprintf x;}
281
#  define Tracec(c, x) {if (z_verbose > 0 && (c)) fprintf x;}
282
#  define Tracecv(c, x) {if (z_verbose > 1 && (c)) fprintf x;}
283
#else
284
#  define Assert(cond, msg)
285
#  define Trace(x)
286
#  define Tracev(x)
287
#  define Tracevv(x)
288
#  define Tracec(c, x)
289
#  define Tracecv(c, x)
290
#endif
291
292
/* OPTIMAL_CMP values determine the comparison width:
293
 * 64: Best for 64-bit architectures with unaligned access
294
 * 32: Best for 32-bit architectures with unaligned access
295
 * 16: Safe default for unknown architectures
296
 * 8:  Safe fallback for architectures without unaligned access
297
 * Note: The unaligned access mentioned is cpu-support, this allows compiler or
298
 *       separate unaligned intrinsics to utilize safe unaligned access, without
299
 *       utilizing unaligned C pointers that are known to have undefined behavior.
300
 */
301
#if !defined(OPTIMAL_CMP)
302
#  ifdef ARCH_64BIT
303
#    ifdef ARCH_ARM
304
#      if defined(__ARM_FEATURE_UNALIGNED) || defined(_WIN32)
305
#        define OPTIMAL_CMP 64
306
#      else
307
#        define OPTIMAL_CMP 8
308
#      endif
309
#    else
310
#      define OPTIMAL_CMP 64
311
#    endif
312
#  elif defined(ARCH_32BIT)
313
#    ifdef ARCH_ARM
314
#      if defined(__ARM_FEATURE_UNALIGNED) || defined(_WIN32)
315
#        define OPTIMAL_CMP 32
316
#      else
317
#        define OPTIMAL_CMP 8
318
#      endif
319
#    else
320
#      define OPTIMAL_CMP 32
321
#    endif
322
#  endif
323
#endif
324
#if !defined(OPTIMAL_CMP)
325
#  define OPTIMAL_CMP 16
326
#endif
327
328
#if defined(__has_feature)
329
#  if __has_feature(address_sanitizer)
330
#    define Z_ADDRESS_SANITIZER 1
331
#  endif
332
#elif defined(__SANITIZE_ADDRESS__)
333
#  define Z_ADDRESS_SANITIZER 1
334
#endif
335
336
/*
337
 * __asan_loadN() and __asan_storeN() calls are inserted by compilers in order to check memory accesses.
338
 * They can be called manually too, with the following caveats:
339
 * gcc says: "warning: implicit declaration of function '...'"
340
 * g++ says: "error: new declaration '...' ambiguates built-in declaration '...'"
341
 * Accommodate both.
342
 */
343
#ifdef Z_ADDRESS_SANITIZER
344
#ifndef __cplusplus
345
void __asan_loadN(void *, long);
346
void __asan_storeN(void *, long);
347
#endif
348
#else
349
#  define __asan_loadN(a, size) do { Z_UNUSED(a); Z_UNUSED(size); } while (0)
350
#  define __asan_storeN(a, size) do { Z_UNUSED(a); Z_UNUSED(size); } while (0)
351
#endif
352
353
#if defined(__has_feature)
354
#  if __has_feature(memory_sanitizer)
355
#    define Z_MEMORY_SANITIZER 1
356
#    include <sanitizer/msan_interface.h>
357
#  endif
358
#endif
359
360
#ifndef Z_MEMORY_SANITIZER
361
#  define __msan_check_mem_is_initialized(a, size) do { Z_UNUSED(a); Z_UNUSED(size); } while (0)
362
10.5k
#  define __msan_unpoison(a, size) do { Z_UNUSED(a); Z_UNUSED(size); } while (0)
363
#endif
364
365
/* Notify sanitizer runtime about an upcoming read access. */
366
#define instrument_read(a, size) do {             \
367
    void *__a = (void *)(a);                      \
368
    long __size = size;                           \
369
    __asan_loadN(__a, __size);                    \
370
    __msan_check_mem_is_initialized(__a, __size); \
371
} while (0)
372
373
/* Notify sanitizer runtime about an upcoming write access. */
374
#define instrument_write(a, size) do { \
375
   void *__a = (void *)(a);            \
376
   long __size = size;                 \
377
   __asan_storeN(__a, __size);         \
378
} while (0)
379
380
/* Notify sanitizer runtime about an upcoming read/write access. */
381
#define instrument_read_write(a, size) do {       \
382
    void *__a = (void *)(a);                      \
383
    long __size = size;                           \
384
    __asan_storeN(__a, __size);                   \
385
    __msan_check_mem_is_initialized(__a, __size); \
386
} while (0)
387
388
#endif