Coverage Report

Created: 2026-02-14 07:07

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