tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Defines.h (19540B)


      1 /***************************************************************************************************
      2 
      3  Zyan Core Library (Zycore-C)
      4 
      5  Original Author : Florian Bernd, Joel Hoener
      6 
      7 * Permission is hereby granted, free of charge, to any person obtaining a copy
      8 * of this software and associated documentation files (the "Software"), to deal
      9 * in the Software without restriction, including without limitation the rights
     10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11 * copies of the Software, and to permit persons to whom the Software is
     12 * furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice shall be included in all
     15 * copies or substantial portions of the Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23 * SOFTWARE.
     24 
     25 ***************************************************************************************************/
     26 
     27 /**
     28 * @file
     29 * General helper and platform detection macros.
     30 */
     31 
     32 #ifndef ZYCORE_DEFINES_H
     33 #define ZYCORE_DEFINES_H
     34 
     35 /* ============================================================================================== */
     36 /* Meta macros                                                                                    */
     37 /* ============================================================================================== */
     38 
     39 /**
     40 * Concatenates two values using the stringify operator (`##`).
     41 *
     42 * @param   x   The first value.
     43 * @param   y   The second value.
     44 *
     45 * @return  The combined string of the given values.
     46 */
     47 #define ZYAN_MACRO_CONCAT(x, y) x ## y
     48 
     49 /**
     50 * Concatenates two values using the stringify operator (`##`) and expands the value to
     51 *          be used in another macro.
     52 *
     53 * @param   x   The first value.
     54 * @param   y   The second value.
     55 *
     56 * @return  The combined string of the given values.
     57 */
     58 #define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
     59 
     60 /* ============================================================================================== */
     61 /* Compiler detection                                                                             */
     62 /* ============================================================================================== */
     63 
     64 #if defined(__clang__)
     65 #   define ZYAN_CLANG
     66 #   define ZYAN_GNUC
     67 #elif defined(__ICC) || defined(__INTEL_COMPILER)
     68 #   define ZYAN_ICC
     69 #elif defined(__GNUC__) || defined(__GNUG__)
     70 #   define ZYAN_GCC
     71 #   define ZYAN_GNUC
     72 #elif defined(_MSC_VER)
     73 #   define ZYAN_MSVC
     74 #elif defined(__BORLANDC__)
     75 #   define ZYAN_BORLAND
     76 #else
     77 #   define ZYAN_UNKNOWN_COMPILER
     78 #endif
     79 
     80 /* ============================================================================================== */
     81 /* Platform detection                                                                             */
     82 /* ============================================================================================== */
     83 
     84 #if defined(_WIN32)
     85 #   define ZYAN_WINDOWS
     86 #elif defined(__EMSCRIPTEN__)
     87 #   define ZYAN_EMSCRIPTEN
     88 #elif defined(__wasi__) || defined(__WASI__)
     89 // via: https://reviews.llvm.org/D57155
     90 #   define ZYAN_WASI
     91 #elif defined(__APPLE__)
     92 #   define ZYAN_APPLE
     93 #   define ZYAN_POSIX
     94 #elif defined(__linux)
     95 #   define ZYAN_LINUX
     96 #   define ZYAN_POSIX
     97 #elif defined(__FreeBSD__)
     98 #   define ZYAN_FREEBSD
     99 #   define ZYAN_POSIX
    100 #elif defined(__NetBSD__)
    101 #   define ZYAN_NETBSD
    102 #   define ZYAN_POSIX
    103 #elif defined(sun) || defined(__sun)
    104 #   define ZYAN_SOLARIS
    105 #   define ZYAN_POSIX
    106 #elif defined(__unix) || defined(__unix__)
    107 #   define ZYAN_UNIX
    108 #   define ZYAN_POSIX
    109 #elif defined(__posix)
    110 #   define ZYAN_POSIX
    111 #else
    112 #   define ZYAN_UNKNOWN_PLATFORM
    113 #endif
    114 
    115 /* ============================================================================================== */
    116 /* Kernel mode detection                                                                          */
    117 /* ============================================================================================== */
    118 
    119 #if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
    120    (defined(ZYAN_APPLE) && defined(KERNEL)) || \
    121    (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
    122    (defined(__FreeBSD_kernel__))
    123 #   define ZYAN_KERNEL
    124 #else
    125 #   define ZYAN_USER
    126 #endif
    127 
    128 /* ============================================================================================== */
    129 /* Architecture detection                                                                         */
    130 /* ============================================================================================== */
    131 
    132 #if defined(_M_AMD64) || defined(__x86_64__)
    133 #   define ZYAN_X64
    134 #elif defined(_M_IX86) || defined(__i386__)
    135 #   define ZYAN_X86
    136 #elif defined(_M_ARM64) || defined(__aarch64__)
    137 #   define ZYAN_AARCH64
    138 #elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
    139 #   define ZYAN_ARM
    140 #elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__WASM__)
    141 #   define ZYAN_WASM
    142 #elif defined(__loongarch__)
    143 #   define ZYAN_LOONGARCH
    144 #elif defined(__powerpc64__)
    145 #   define ZYAN_PPC64
    146 #elif defined(__powerpc__)
    147 #   define ZYAN_PPC
    148 #elif defined(__riscv) && __riscv_xlen == 64
    149 #   define ZYAN_RISCV64
    150 #else
    151 #   error "Unsupported architecture detected"
    152 #endif
    153 
    154 /* ============================================================================================== */
    155 /* Debug/Release detection                                                                        */
    156 /* ============================================================================================== */
    157 
    158 #if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
    159 #   ifdef _DEBUG
    160 #       define ZYAN_DEBUG
    161 #   else
    162 #       define ZYAN_RELEASE
    163 #   endif
    164 #elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
    165 #   ifdef NDEBUG
    166 #       define ZYAN_RELEASE
    167 #   else
    168 #       define ZYAN_DEBUG
    169 #   endif
    170 #else
    171 #   define ZYAN_RELEASE
    172 #endif
    173 
    174 /* ============================================================================================== */
    175 /* Deprecation hint                                                                               */
    176 /* ============================================================================================== */
    177 
    178 #if defined(ZYAN_GCC) || defined(ZYAN_CLANG)
    179 #   define ZYAN_DEPRECATED __attribute__((__deprecated__))
    180 #elif defined(ZYAN_MSVC)
    181 #   define ZYAN_DEPRECATED __declspec(deprecated)
    182 #else
    183 #   define ZYAN_DEPRECATED
    184 #endif
    185 
    186 /* ============================================================================================== */
    187 /* Generic DLL import/export helpers                                                              */
    188 /* ============================================================================================== */
    189 
    190 #if defined(ZYAN_MSVC)
    191 #   define ZYAN_DLLEXPORT __declspec(dllexport)
    192 #   define ZYAN_DLLIMPORT __declspec(dllimport)
    193 #else
    194 #   define ZYAN_DLLEXPORT
    195 #   define ZYAN_DLLIMPORT
    196 #endif
    197 
    198 /* ============================================================================================== */
    199 /* Zycore dll{export,import}                                                                      */
    200 /* ============================================================================================== */
    201 
    202 // This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To
    203 // simplify builds without CMake, we define these things manually instead of relying on CMake
    204 // to generate the header.
    205 //
    206 // For static builds, our CMakeList will define `ZYCORE_STATIC_BUILD`. For shared library builds,
    207 // our CMake will define `ZYCORE_SHOULD_EXPORT` depending on whether the target is being imported or
    208 // exported. If CMake isn't used, users can manually define these to fit their use-case.
    209 
    210 // Backward compatibility: CMake would previously generate these variables names. However, because
    211 // they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For
    212 // backward compatibility for users that don't use CMake and previously manually defined these, we
    213 // translate the old defines here and print a warning.
    214 #if defined(ZYCORE_STATIC_DEFINE)
    215 #   pragma message("ZYCORE_STATIC_DEFINE was renamed to ZYCORE_STATIC_BUILD.")
    216 #   define ZYCORE_STATIC_BUILD
    217 #endif
    218 #if defined(Zycore_EXPORTS)
    219 #   pragma message("Zycore_EXPORTS was renamed to ZYCORE_SHOULD_EXPORT.")
    220 #   define ZYCORE_SHOULD_EXPORT
    221 #endif
    222 
    223 /**
    224 * Symbol is exported in shared library builds.
    225 */
    226 #if defined(ZYCORE_STATIC_BUILD)
    227 #   define ZYCORE_EXPORT
    228 #else
    229 #   if defined(ZYCORE_SHOULD_EXPORT)
    230 #       define ZYCORE_EXPORT ZYAN_DLLEXPORT
    231 #   else
    232 #       define ZYCORE_EXPORT ZYAN_DLLIMPORT
    233 #   endif
    234 #endif
    235 
    236 /**
    237 * Symbol is not exported and for internal use only.
    238 */
    239 #define ZYCORE_NO_EXPORT
    240 
    241 /* ============================================================================================== */
    242 /* Misc compatibility macros                                                                      */
    243 /* ============================================================================================== */
    244 
    245 #if defined(ZYAN_CLANG)
    246 #   define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
    247 #else
    248 #   define ZYAN_NO_SANITIZE(what)
    249 #endif
    250 
    251 #if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
    252 #   define ZYAN_INLINE __inline
    253 #else
    254 #   define ZYAN_INLINE static inline
    255 #endif
    256 
    257 #if defined(ZYAN_MSVC)
    258 #   define ZYAN_NOINLINE __declspec(noinline)
    259 #elif defined(ZYAN_GCC) || defined(ZYAN_CLANG)
    260 #   define ZYAN_NOINLINE __attribute__((noinline))
    261 #else
    262 #   define ZYAN_NOINLINE
    263 #endif
    264 
    265 /* ============================================================================================== */
    266 /* Debugging and optimization macros                                                              */
    267 /* ============================================================================================== */
    268 
    269 /**
    270 * Runtime debug assertion.
    271 */
    272 #if defined(ZYAN_NO_LIBC)
    273 #   define ZYAN_ASSERT(condition) (void)(condition)
    274 #elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
    275 #   include <wdm.h>
    276 #   define ZYAN_ASSERT(condition) NT_ASSERT(condition)
    277 #else
    278 #   include <assert.h>
    279 #   define ZYAN_ASSERT(condition) assert(condition)
    280 #endif
    281 
    282 /**
    283 * Compiler-time assertion.
    284 */
    285 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
    286 #   define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
    287 #elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
    288      (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
    289      (defined (_MSC_VER) && (_MSC_VER >= 1800))
    290 #   define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
    291 #else
    292 #   define ZYAN_STATIC_ASSERT(x) \
    293        typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
    294 #endif
    295 
    296 /**
    297 * Marks the current code path as unreachable.
    298 */
    299 #if defined(ZYAN_RELEASE)
    300 #   if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
    301 #       if __has_builtin(__builtin_unreachable)
    302 #           define ZYAN_UNREACHABLE __builtin_unreachable()
    303 #       else
    304 #           define ZYAN_UNREACHABLE for(;;)
    305 #       endif
    306 #   elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
    307 #       define ZYAN_UNREACHABLE __builtin_unreachable()
    308 #   elif defined(ZYAN_ICC)
    309 #       ifdef ZYAN_WINDOWS
    310 #           include <stdlib.h> // "missing return statement" workaround
    311 #           define ZYAN_UNREACHABLE __assume(0); (void)abort()
    312 #       else
    313 #           define ZYAN_UNREACHABLE __builtin_unreachable()
    314 #       endif
    315 #   elif defined(ZYAN_MSVC)
    316 #       define ZYAN_UNREACHABLE __assume(0)
    317 #   else
    318 #       define ZYAN_UNREACHABLE for(;;)
    319 #   endif
    320 #elif defined(ZYAN_NO_LIBC)
    321 #   define ZYAN_UNREACHABLE for(;;)
    322 #elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
    323 #   define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
    324 #else
    325 #   include <stdlib.h>
    326 #   define ZYAN_UNREACHABLE { assert(0); abort(); }
    327 #endif
    328 
    329 /* ============================================================================================== */
    330 /* Utils                                                                                          */
    331 /* ============================================================================================== */
    332 
    333 /* ---------------------------------------------------------------------------------------------- */
    334 /* General purpose                                                                                */
    335 /* ---------------------------------------------------------------------------------------------- */
    336 
    337 /**
    338 * Marks the specified parameter as unused.
    339 *
    340 * @param   x   The name of the unused parameter.
    341 */
    342 #define ZYAN_UNUSED(x) (void)(x)
    343 
    344 /**
    345 * Intentional fallthrough.
    346 */
    347 #if defined(ZYAN_GCC) && __GNUC__ >= 7
    348 #   define ZYAN_FALLTHROUGH ; __attribute__((__fallthrough__))
    349 #else
    350 #   define ZYAN_FALLTHROUGH
    351 #endif
    352 
    353 /**
    354 * Declares a bitfield.
    355 *
    356 * @param   x   The size (in bits) of the bitfield.
    357 */
    358 #define ZYAN_BITFIELD(x) : x
    359 
    360 /**
    361 * Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`).
    362 */
    363 #define ZYAN_REQUIRES_LIBC
    364 
    365 /**
    366 * Decorator for `printf`-style functions.
    367 *
    368 * @param   format_index    The 1-based index of the format string parameter.
    369 * @param   first_to_check  The 1-based index of the format arguments parameter.
    370 */
    371 #if defined(__RESHARPER__)
    372 #   define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
    373        [[gnu::format(printf, format_index, first_to_check)]]
    374 #elif defined(ZYAN_GCC)
    375 #   define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
    376        __attribute__((format(printf, format_index, first_to_check)))
    377 #else
    378 #   define ZYAN_PRINTF_ATTR(format_index, first_to_check)
    379 #endif
    380 
    381 /**
    382 * Decorator for `wprintf`-style functions.
    383 *
    384 * @param   format_index    The 1-based index of the format string parameter.
    385 * @param   first_to_check  The 1-based index of the format arguments parameter.
    386 */
    387 #if defined(__RESHARPER__)
    388 #   define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
    389        [[rscpp::format(wprintf, format_index, first_to_check)]]
    390 #else
    391 #   define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
    392 #endif
    393 
    394 /* ---------------------------------------------------------------------------------------------- */
    395 /* Arrays                                                                                         */
    396 /* ---------------------------------------------------------------------------------------------- */
    397 
    398 /**
    399 * Returns the length (number of elements) of an array.
    400 *
    401 * @param   a   The name of the array.
    402 *
    403 * @return  The number of elements of the given array.
    404 */
    405 #define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
    406 
    407 /* ---------------------------------------------------------------------------------------------- */
    408 /* Arithmetic                                                                                     */
    409 /* ---------------------------------------------------------------------------------------------- */
    410 
    411 /**
    412 * Returns the smaller value of `a` or `b`.
    413 *
    414 * @param   a   The first value.
    415 * @param   b   The second value.
    416 *
    417 * @return  The smaller value of `a` or `b`.
    418 */
    419 #define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
    420 
    421 /**
    422 * Returns the bigger value of `a` or `b`.
    423 *
    424 * @param   a   The first value.
    425 * @param   b   The second value.
    426 *
    427 * @return  The bigger value of `a` or `b`.
    428 */
    429 #define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
    430 
    431 /**
    432 * Returns the absolute value of `a`.
    433 *
    434 * @param   a   The value.
    435 *
    436 * @return  The absolute value of `a`.
    437 */
    438 #define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
    439 
    440 /**
    441 * Checks, if the given value is a power of 2.
    442 *
    443 * @param   x   The value.
    444 *
    445 * @return  `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not.
    446 *
    447 * Note that this macro always returns `ZYAN_TRUE` for `x == 0`.
    448 */
    449 #define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
    450 
    451 /**
    452 * Checks, if the given value is properly aligned.
    453 *
    454 * Note that this macro only works for powers of 2.
    455 */
    456 #define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
    457 
    458 /**
    459 * Aligns the value to the nearest given alignment boundary (by rounding it up).
    460 *
    461 * @param   x       The value.
    462 * @param   align   The desired alignment.
    463 *
    464 * @return  The aligned value.
    465 *
    466 * Note that this macro only works for powers of 2.
    467 */
    468 #define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
    469 
    470 /**
    471 * Aligns the value to the nearest given alignment boundary (by rounding it down).
    472 *
    473 * @param   x       The value.
    474 * @param   align   The desired alignment.
    475 *
    476 * @return  The aligned value.
    477 *
    478 * Note that this macro only works for powers of 2.
    479 */
    480 #define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
    481 
    482 /**
    483 * Divide the 64bit integer value by the given divisor.
    484 *
    485 * @param   n       Variable containing the dividend that will be updated with the result of the
    486 *                  division.
    487 * @param   divisor The divisor.
    488 */
    489 #if defined(ZYAN_LINUX) && defined(ZYAN_KERNEL)
    490 #   include <asm/div64.h> /* do_div */
    491 #   define ZYAN_DIV64(n, divisor) do_div(n, divisor)
    492 #else
    493 #   define ZYAN_DIV64(n, divisor) (n /= divisor)
    494 #endif
    495 
    496 /* ---------------------------------------------------------------------------------------------- */
    497 /* Bit operations                                                                                 */
    498 /* ---------------------------------------------------------------------------------------------- */
    499 
    500 /*
    501 * Checks, if the bit at index `b` is required to present the ordinal value `n`.
    502 *
    503 * @param   n   The ordinal value.
    504 * @param   b   The bit index.
    505 *
    506 * @return  `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
    507 *          `ZYAN_FALSE`, if not.
    508 *
    509 * Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
    510 */
    511 #define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
    512 
    513 /*
    514 * Returns the number of bits required to represent the ordinal value `n`.
    515 *
    516 * @param   n   The ordinal value.
    517 *
    518 * @return  The number of bits required to represent the ordinal value `n`.
    519 *
    520 * Note that this macro returns `0` for `n == 0`.
    521 */
    522 #define ZYAN_BITS_TO_REPRESENT(n) \
    523    ( \
    524        ZYAN_NEEDS_BIT(n,  0) + ZYAN_NEEDS_BIT(n,  1) + \
    525        ZYAN_NEEDS_BIT(n,  2) + ZYAN_NEEDS_BIT(n,  3) + \
    526        ZYAN_NEEDS_BIT(n,  4) + ZYAN_NEEDS_BIT(n,  5) + \
    527        ZYAN_NEEDS_BIT(n,  6) + ZYAN_NEEDS_BIT(n,  7) + \
    528        ZYAN_NEEDS_BIT(n,  8) + ZYAN_NEEDS_BIT(n,  9) + \
    529        ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
    530        ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
    531        ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
    532        ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
    533        ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
    534        ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
    535        ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
    536        ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
    537        ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
    538        ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
    539        ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31)   \
    540    )
    541 
    542 /* ---------------------------------------------------------------------------------------------- */
    543 
    544 /* ============================================================================================== */
    545 
    546 #endif /* ZYCORE_DEFINES_H */