aboutsummaryrefslogtreecommitdiffhomepage
path: root/externals/zycore/include/Zycore/Defines.h
diff options
context:
space:
mode:
Diffstat (limited to 'externals/zycore/include/Zycore/Defines.h')
-rw-r--r--externals/zycore/include/Zycore/Defines.h443
1 files changed, 443 insertions, 0 deletions
diff --git a/externals/zycore/include/Zycore/Defines.h b/externals/zycore/include/Zycore/Defines.h
new file mode 100644
index 00000000..65afbaa3
--- /dev/null
+++ b/externals/zycore/include/Zycore/Defines.h
@@ -0,0 +1,443 @@
+/***************************************************************************************************
+
+ Zyan Core Library (Zycore-C)
+
+ Original Author : Florian Bernd, Joel Hoener
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+
+***************************************************************************************************/
+
+/**
+ * @file
+ * General helper and platform detection macros.
+ */
+
+#ifndef ZYCORE_DEFINES_H
+#define ZYCORE_DEFINES_H
+
+/* ============================================================================================== */
+/* Meta macros */
+/* ============================================================================================== */
+
+/**
+ * Concatenates two values using the stringify operator (`##`).
+ *
+ * @param x The first value.
+ * @param y The second value.
+ *
+ * @return The combined string of the given values.
+ */
+#define ZYAN_MACRO_CONCAT(x, y) x ## y
+
+/**
+ * Concatenates two values using the stringify operator (`##`) and expands the value to
+ * be used in another macro.
+ *
+ * @param x The first value.
+ * @param y The second value.
+ *
+ * @return The combined string of the given values.
+ */
+#define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
+
+/* ============================================================================================== */
+/* Compiler detection */
+/* ============================================================================================== */
+
+#if defined(__clang__)
+# define ZYAN_CLANG
+# define ZYAN_GNUC
+#elif defined(__ICC) || defined(__INTEL_COMPILER)
+# define ZYAN_ICC
+#elif defined(__GNUC__) || defined(__GNUG__)
+# define ZYAN_GCC
+# define ZYAN_GNUC
+#elif defined(_MSC_VER)
+# define ZYAN_MSVC
+#elif defined(__BORLANDC__)
+# define ZYAN_BORLAND
+#else
+# define ZYAN_UNKNOWN_COMPILER
+#endif
+
+/* ============================================================================================== */
+/* Platform detection */
+/* ============================================================================================== */
+
+#if defined(_WIN32)
+# define ZYAN_WINDOWS
+#elif defined(__EMSCRIPTEN__)
+# define ZYAN_EMSCRIPTEN
+#elif defined(__APPLE__)
+# define ZYAN_APPLE
+# define ZYAN_POSIX
+#elif defined(__linux)
+# define ZYAN_LINUX
+# define ZYAN_POSIX
+#elif defined(__FreeBSD__)
+# define ZYAN_FREEBSD
+# define ZYAN_POSIX
+#elif defined(sun) || defined(__sun)
+# define ZYAN_SOLARIS
+# define ZYAN_POSIX
+#elif defined(__unix)
+# define ZYAN_UNIX
+# define ZYAN_POSIX
+#elif defined(__posix)
+# define ZYAN_POSIX
+#else
+# define ZYAN_UNKNOWN_PLATFORM
+#endif
+
+/* ============================================================================================== */
+/* Kernel mode detection */
+/* ============================================================================================== */
+
+#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
+ (defined(ZYAN_APPLE) && defined(KERNEL)) || \
+ (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
+ (defined(__FreeBSD_kernel__))
+# define ZYAN_KERNEL
+#else
+# define ZYAN_USER
+#endif
+
+/* ============================================================================================== */
+/* Architecture detection */
+/* ============================================================================================== */
+
+#if defined(_M_AMD64) || defined(__x86_64__)
+# define ZYAN_X64
+#elif defined(_M_IX86) || defined(__i386__)
+# define ZYAN_X86
+#elif defined(_M_ARM64) || defined(__aarch64__)
+# define ZYAN_AARCH64
+#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
+# define ZYAN_ARM
+#elif defined(__EMSCRIPTEN__)
+ // Nothing to do, `ZYAN_EMSCRIPTEN` is both platform and arch macro for this one.
+#else
+# error "Unsupported architecture detected"
+#endif
+
+/* ============================================================================================== */
+/* Debug/Release detection */
+/* ============================================================================================== */
+
+#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
+# ifdef _DEBUG
+# define ZYAN_DEBUG
+# else
+# define ZYAN_RELEASE
+# endif
+#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
+# ifdef NDEBUG
+# define ZYAN_RELEASE
+# else
+# define ZYAN_DEBUG
+# endif
+#else
+# define ZYAN_RELEASE
+#endif
+
+/* ============================================================================================== */
+/* Misc compatibility macros */
+/* ============================================================================================== */
+
+#if defined(ZYAN_CLANG)
+# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
+#else
+# define ZYAN_NO_SANITIZE(what)
+#endif
+
+#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
+# define ZYAN_INLINE __inline
+#else
+# define ZYAN_INLINE static inline
+#endif
+
+/* ============================================================================================== */
+/* Debugging and optimization macros */
+/* ============================================================================================== */
+
+/**
+ * Runtime debug assertion.
+ */
+#if defined(ZYAN_NO_LIBC)
+# define ZYAN_ASSERT(condition) (void)(condition)
+#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
+# include <wdm.h>
+# define ZYAN_ASSERT(condition) NT_ASSERT(condition)
+#else
+# include <assert.h>
+# define ZYAN_ASSERT(condition) assert(condition)
+#endif
+
+/**
+ * Compiler-time assertion.
+ */
+#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
+# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
+#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
+ (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
+ (defined (_MSC_VER) && (_MSC_VER >= 1800))
+# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
+#else
+# define ZYAN_STATIC_ASSERT(x) \
+ typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
+#endif
+
+/**
+ * Marks the current code path as unreachable.
+ */
+#if defined(ZYAN_RELEASE)
+# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
+# if __has_builtin(__builtin_unreachable)
+# define ZYAN_UNREACHABLE __builtin_unreachable()
+# else
+# define ZYAN_UNREACHABLE for(;;)
+# endif
+# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
+# define ZYAN_UNREACHABLE __builtin_unreachable()
+# elif defined(ZYAN_ICC)
+# ifdef ZYAN_WINDOWS
+# include <stdlib.h> // "missing return statement" workaround
+# define ZYAN_UNREACHABLE __assume(0); (void)abort()
+# else
+# define ZYAN_UNREACHABLE __builtin_unreachable()
+# endif
+# elif defined(ZYAN_MSVC)
+# define ZYAN_UNREACHABLE __assume(0)
+# else
+# define ZYAN_UNREACHABLE for(;;)
+# endif
+#elif defined(ZYAN_NO_LIBC)
+# define ZYAN_UNREACHABLE for(;;)
+#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
+# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
+#else
+# include <stdlib.h>
+# define ZYAN_UNREACHABLE { assert(0); abort(); }
+#endif
+
+/* ============================================================================================== */
+/* Utils */
+/* ============================================================================================== */
+
+/* ---------------------------------------------------------------------------------------------- */
+/* General purpose */
+/* ---------------------------------------------------------------------------------------------- */
+
+/**
+ * Marks the specified parameter as unused.
+ *
+ * @param x The name of the unused parameter.
+ */
+#define ZYAN_UNUSED(x) (void)(x)
+
+/**
+ * Intentional fallthrough.
+ */
+#if defined(ZYAN_GCC) && __GNUC__ >= 7
+# define ZYAN_FALLTHROUGH __attribute__((fallthrough))
+#else
+# define ZYAN_FALLTHROUGH
+#endif
+
+/**
+ * Declares a bitfield.
+ *
+ * @param x The size (in bits) of the bitfield.
+ */
+#define ZYAN_BITFIELD(x) : x
+
+/**
+ * Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`).
+ */
+#define ZYAN_REQUIRES_LIBC
+
+/**
+ * Decorator for `printf`-style functions.
+ *
+ * @param format_index The 1-based index of the format string parameter.
+ * @param first_to_check The 1-based index of the format arguments parameter.
+ */
+#if defined(__RESHARPER__)
+# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
+ [[gnu::format(printf, format_index, first_to_check)]]
+#elif defined(ZYAN_GCC)
+# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
+ __attribute__((format(printf, format_index, first_to_check)))
+#else
+# define ZYAN_PRINTF_ATTR(format_index, first_to_check)
+#endif
+
+/**
+ * Decorator for `wprintf`-style functions.
+ *
+ * @param format_index The 1-based index of the format string parameter.
+ * @param first_to_check The 1-based index of the format arguments parameter.
+ */
+#if defined(__RESHARPER__)
+# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
+ [[rscpp::format(wprintf, format_index, first_to_check)]]
+#else
+# define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
+#endif
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Arrays */
+/* ---------------------------------------------------------------------------------------------- */
+
+/**
+ * Returns the length (number of elements) of an array.
+ *
+ * @param a The name of the array.
+ *
+ * @return The number of elements of the given array.
+ */
+#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Arithmetic */
+/* ---------------------------------------------------------------------------------------------- */
+
+/**
+ * Returns the smaller value of `a` or `b`.
+ *
+ * @param a The first value.
+ * @param b The second value.
+ *
+ * @return The smaller value of `a` or `b`.
+ */
+#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/**
+ * Returns the bigger value of `a` or `b`.
+ *
+ * @param a The first value.
+ * @param b The second value.
+ *
+ * @return The bigger value of `a` or `b`.
+ */
+#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+/**
+ * Returns the absolute value of `a`.
+ *
+ * @param a The value.
+ *
+ * @return The absolute value of `a`.
+ */
+#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
+
+/**
+ * Checks, if the given value is a power of 2.
+ *
+ * @param x The value.
+ *
+ * @return `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not.
+ *
+ * Note that this macro always returns `ZYAN_TRUE` for `x == 0`.
+ */
+#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
+
+/**
+ * Checks, if the given value is properly aligned.
+ *
+ * Note that this macro only works for powers of 2.
+ */
+#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
+
+/**
+ * Aligns the value to the nearest given alignment boundary (by rounding it up).
+ *
+ * @param x The value.
+ * @param align The desired alignment.
+ *
+ * @return The aligned value.
+ *
+ * Note that this macro only works for powers of 2.
+ */
+#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
+
+/**
+ * Aligns the value to the nearest given alignment boundary (by rounding it down).
+ *
+ * @param x The value.
+ * @param align The desired alignment.
+ *
+ * @return The aligned value.
+ *
+ * Note that this macro only works for powers of 2.
+ */
+#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Bit operations */
+/* ---------------------------------------------------------------------------------------------- */
+
+/*
+ * Checks, if the bit at index `b` is required to present the ordinal value `n`.
+ *
+ * @param n The ordinal value.
+ * @param b The bit index.
+ *
+ * @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
+ * `ZYAN_FALSE`, if not.
+ *
+ * Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
+ */
+#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
+
+/*
+ * Returns the number of bits required to represent the ordinal value `n`.
+ *
+ * @param n The ordinal value.
+ *
+ * @return The number of bits required to represent the ordinal value `n`.
+ *
+ * Note that this macro returns `0` for `n == 0`.
+ */
+#define ZYAN_BITS_TO_REPRESENT(n) \
+ ( \
+ ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \
+ ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \
+ ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \
+ ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \
+ ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \
+ ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
+ ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
+ ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
+ ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
+ ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
+ ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
+ ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
+ ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
+ ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
+ ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
+ ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \
+ )
+
+/* ---------------------------------------------------------------------------------------------- */
+
+/* ============================================================================================== */
+
+#endif /* ZYCORE_DEFINES_H */