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