Repository: zyantific/zycore-c
Pull request #87: Big endian support
Author: login: mappzor
Created: 2025-05-18T00:26:39Z | Merged: 2025-05-18T20:07:50Z

Related to [#567](https://github.com/zyantific/zydis/issues/567)


Diff:
diff --git a/include/Zycore/Defines.h b/include/Zycore/Defines.h
index 847700b..0b385af 100644
--- a/include/Zycore/Defines.h
+++ b/include/Zycore/Defines.h
@@ -57,6 +57,32 @@
  */
 #define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
 
+/**
+ * Checks if a header can be included.
+ *
+ * @param name  Header file name.
+ *
+ * @return      True if header exists, false if it doesn't or it's not possible to check.
+ */
+#if defined(__has_include)
+#   define ZYAN_HAS_INCLUDE(name) __has_include(name)
+#else
+#   define ZYAN_HAS_INCLUDE(name) 0
+#endif
+
+/**
+ * Checks if a symbol is a recognized built-in function.
+ *
+ * @param symbol  Function name.
+ *
+ * @return        True if symbol is known, false otherwise.
+ */
+#if defined(__has_builtin)
+#   define ZYAN_HAS_BUILTIN(symbol) __has_builtin(symbol)
+#else
+#   define ZYAN_HAS_BUILTIN(symbol) 0
+#endif
+
 /* ============================================================================================== */
 /* Compiler detection                                                                             */
 /* ============================================================================================== */
@@ -152,12 +178,54 @@
 #   define ZYAN_PPC64
 #elif defined(__powerpc__)
 #   define ZYAN_PPC
-#elif defined(__riscv) && __riscv_xlen == 64
-#   define ZYAN_RISCV64
+#elif defined(__riscv) || defined(__riscv__)
+#   if __riscv_xlen == 64
+#       define ZYAN_RISCV64
+#   else
+#       define ZYAN_RISCV32
+#   endif
+#elif defined(__arc__)
+#   define ZYAN_ARC
+#elif defined(__s390x__)
+#   define ZYAN_S390
+#elif defined(__sparc__)
+#   define ZYAN_SPARC
+#elif defined(__mips__)
+#   define ZYAN_MIPS
 #else
 #   error "Unsupported architecture detected"
 #endif
 
+/* ============================================================================================== */
+/* Endianness detection                                                                           */
+/* ============================================================================================== */
+
+#define ZYAN_LITTLE_ENDIAN 0
+#define ZYAN_BIG_ENDIAN 1
+
+#if !defined(ZYAN_NO_LIBC) && ZYAN_HAS_INCLUDE(<stdbit.h>)
+#   include <stdbit.h>
+#   if __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_LITTLE__
+#       define ZYAN_ENDIAN ZYAN_LITTLE_ENDIAN
+#   elif __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__
+#       define ZYAN_ENDIAN ZYAN_BIG_ENDIAN
+#   else
+#       error "Unsupported endianness"
+#   endif
+#elif defined(__BYTE_ORDER__)
+#   if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#       define ZYAN_ENDIAN ZYAN_LITTLE_ENDIAN
+#   elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#       define ZYAN_ENDIAN ZYAN_BIG_ENDIAN
+#   else
+#       error "Unsupported endianness"
+#   endif
+#elif defined(ZYAN_S390) || defined(ZYAN_SPARC) || defined(ZYAN_MIPS)
+#   define ZYAN_ENDIAN ZYAN_BIG_ENDIAN
+#else
+#   define ZYAN_ENDIAN ZYAN_LITTLE_ENDIAN
+#endif
+
 /* ============================================================================================== */
 /* Debug/Release detection                                                                        */
 /* ============================================================================================== */
@@ -264,8 +332,8 @@
 #   define ZYAN_NO_SANITIZE(what)
 #endif
 
-#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
-#   define ZYAN_INLINE __inline
+#if defined(ZYAN_BORLAND)
+#   define ZYAN_INLINE static __inline
 #else
 #   define ZYAN_INLINE static inline
 #endif
@@ -507,9 +575,9 @@
  */
 #if defined(ZYAN_LINUX) && defined(ZYAN_KERNEL)
 #   include <asm/div64.h> /* do_div */
-#   define ZYAN_DIV64(n, divisor) do_div(n, divisor)
+#   define ZYAN_DIV64(n, divisor) do_div((n), (divisor))
 #else
-#   define ZYAN_DIV64(n, divisor) (n /= divisor)
+#   define ZYAN_DIV64(n, divisor) ((n) /= (divisor))
 #endif
 
 /* ---------------------------------------------------------------------------------------------- */
diff --git a/include/Zycore/Internal/AtomicMSVC.h b/include/Zycore/Internal/AtomicMSVC.h
index f4dc1e6..705bdb6 100644
--- a/include/Zycore/Internal/AtomicMSVC.h
+++ b/include/Zycore/Internal/AtomicMSVC.h
@@ -48,36 +48,36 @@ extern "C" {
 
 #if defined(ZYAN_X86)
 
-static ZYAN_INLINE ZyanUPointer ZyanAtomicCompareExchange(ZyanAtomicPointer* destination,
+ZYAN_INLINE ZyanUPointer ZyanAtomicCompareExchange(ZyanAtomicPointer* destination,
     ZyanUPointer comparand, ZyanUPointer value)
 {
     return (ZyanUPointer)ZyanAtomicCompareExchange32((ZyanAtomic32*)destination, comparand, value);
 }
 
-static ZYAN_INLINE ZyanUPointer ZyanAtomicIncrement(ZyanAtomicPointer* destination)
+ZYAN_INLINE ZyanUPointer ZyanAtomicIncrement(ZyanAtomicPointer* destination)
 {
     return (ZyanUPointer)ZyanAtomicIncrement32((ZyanAtomic32*)destination);
 }
 
-static ZYAN_INLINE ZyanUPointer ZyanAtomicDecrement(ZyanAtomicPointer* destination)
+ZYAN_INLINE ZyanUPointer ZyanAtomicDecrement(ZyanAtomicPointer* destination)
 {
     return (ZyanUPointer)ZyanAtomicDecrement32((ZyanAtomic32*)destination);
 }
 
 #elif defined(ZYAN_X64)
 
-static ZYAN_INLINE ZyanUPointer ZyanAtomicCompareExchange(ZyanAtomicPointer* destination,
+ZYAN_INLINE ZyanUPointer ZyanAtomicCompareExchange(ZyanAtomicPointer* destination,
     ZyanUPointer comparand, ZyanUPointer value)
 {
     return (ZyanUPointer)ZyanAtomicCompareExchange64((ZyanAtomic64*)destination, comparand, value);
 }
 
-static ZYAN_INLINE ZyanUPointer ZyanAtomicIncrement(ZyanAtomicPointer* destination)
+ZYAN_INLINE ZyanUPointer ZyanAtomicIncrement(ZyanAtomicPointer* destination)
 {
     return (ZyanUPointer)ZyanAtomicIncrement64((ZyanAtomic64*)destination);
 }
 
-static ZYAN_INLINE ZyanUPointer ZyanAtomicDecrement(ZyanAtomicPointer* destination)
+ZYAN_INLINE ZyanUPointer ZyanAtomicDecrement(ZyanAtomicPointer* destination)
 {
     return (ZyanUPointer)ZyanAtomicDecrement64((ZyanAtomic64*)destination);
 }
@@ -90,19 +90,19 @@ static ZYAN_INLINE ZyanUPointer ZyanAtomicDecrement(ZyanAtomicPointer* destinati
 /* 32-bit                                                                                         */
 /* ---------------------------------------------------------------------------------------------- */
 
-static ZYAN_INLINE ZyanU32 ZyanAtomicCompareExchange32(ZyanAtomic32* destination,
+ZYAN_INLINE ZyanU32 ZyanAtomicCompareExchange32(ZyanAtomic32* destination,
     ZyanU32 comparand, ZyanU32 value)
 {
     return (ZyanU32)(_InterlockedCompareExchange((volatile LONG*)&(destination->value),
         (LONG)value, (LONG)comparand));
 }
 
-static ZYAN_INLINE ZyanU32 ZyanAtomicIncrement32(ZyanAtomic32* destination)
+ZYAN_INLINE ZyanU32 ZyanAtomicIncrement32(ZyanAtomic32* destination)
 {
     return (ZyanU32)(_InterlockedIncrement((volatile LONG*)&(destination->value)));
 }
 
-static ZYAN_INLINE ZyanU32 ZyanAtomicDecrement32(ZyanAtomic32* destination)
+ZYAN_INLINE ZyanU32 ZyanAtomicDecrement32(ZyanAtomic32* destination)
 {
     return (ZyanU32)(_InterlockedDecrement((volatile LONG*)&(destination->value)));
 }
@@ -111,19 +111,19 @@ static ZYAN_INLINE ZyanU32 ZyanAtomicDecrement32(ZyanAtomic32* destination)
 /* 64-bit                                                                                         */
 /* ---------------------------------------------------------------------------------------------- */
 
-static ZYAN_INLINE ZyanU64 ZyanAtomicCompareExchange64(ZyanAtomic64* destination,
+ZYAN_INLINE ZyanU64 ZyanAtomicCompareExchange64(ZyanAtomic64* destination,
     ZyanU64 comparand, ZyanU64 value)
 {
     return (ZyanU64)(_InterlockedCompareExchange64((volatile LONG64*)&(destination->value),
         (LONG64)value, (LONG64)comparand));
 }
 
-static ZYAN_INLINE ZyanU64 ZyanAtomicIncrement64(ZyanAtomic64* destination)
+ZYAN_INLINE ZyanU64 ZyanAtomicIncrement64(ZyanAtomic64* destination)
 {
     return (ZyanU64)(_InterlockedIncrement64((volatile LONG64*)&(destination->value)));
 }
 
-static ZYAN_INLINE ZyanU64 ZyanAtomicDecrement64(ZyanAtomic64* destination)
+ZYAN_INLINE ZyanU64 ZyanAtomicDecrement64(ZyanAtomic64* destination)
 {
     return (ZyanU64)(_InterlockedDecrement64((volatile LONG64*)&(destination->value)));
 }
diff --git a/include/Zycore/Types.h b/include/Zycore/Types.h
index 9690a95..3b0523b 100644
--- a/include/Zycore/Types.h
+++ b/include/Zycore/Types.h
@@ -333,6 +333,86 @@ typedef char* ZyanCharPointer;
  */
 typedef const char* ZyanConstCharPointer;
 
+/* ============================================================================================== */
+/* Type conversion utils                                                                          */
+/* ============================================================================================== */
+
+/**
+ * Collection of functions for swapping byte order in 16/32/64-bit values respectively.
+ *
+ * @param   x       16/32/64-bit value.
+ *
+ * @return  16/32/64-bit value with byte order swapped.
+ */
+#if defined(ZYAN_MSVC)
+#   if defined(ZYAN_NO_LIBC)
+#       if defined(__cplusplus)
+        extern "C" {
+#       endif
+            unsigned short __cdecl _byteswap_ushort(unsigned short);
+            unsigned long  __cdecl _byteswap_ulong(unsigned long);
+            unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64);
+#       if defined(__cplusplus)
+        }
+#       endif
+#   elif defined(ZYAN_KERNEL)
+#       include <wdm.h>
+#   else
+#       include <stdlib.h>
+#   endif
+
+#   define ZYAN_BYTESWAP16(x) _byteswap_ushort((x))
+#   define ZYAN_BYTESWAP32(x) _byteswap_ulong((x))
+#   define ZYAN_BYTESWAP64(x) _byteswap_uint64((x))
+#elif ZYAN_HAS_BUILTIN(__builtin_bswap16) && \
+      ZYAN_HAS_BUILTIN(__builtin_bswap32) && \
+      ZYAN_HAS_BUILTIN(__builtin_bswap64)
+#   define ZYAN_BYTESWAP16(x) __builtin_bswap16((x))
+#   define ZYAN_BYTESWAP32(x) __builtin_bswap32((x))
+#   define ZYAN_BYTESWAP64(x) __builtin_bswap64((x))
+#else
+ZYAN_INLINE ZyanU16 ZYAN_BYTESWAP16(ZyanU16 x)
+{
+    return (((x >> 8) & 0xFFU) | ((x & 0xFFU) << 8));
+}
+
+ZYAN_INLINE ZyanU32 ZYAN_BYTESWAP32(ZyanU32 x)
+{
+    return (((x & 0xFF000000U) >> 24) |
+            ((x & 0x00FF0000U) >> 8 ) |
+            ((x & 0x0000FF00U) << 8 ) |
+            ((x & 0x000000FFU) << 24));
+}
+
+ZYAN_INLINE ZyanU64 ZYAN_BYTESWAP64(ZyanU64 x)
+{
+    return (((x & 0xFF00000000000000ULL) >> 56) |
+            ((x & 0x00FF000000000000ULL) >> 40) |
+            ((x & 0x0000FF0000000000ULL) >> 24) |
+            ((x & 0x000000FF00000000ULL) >> 8 ) |
+            ((x & 0x00000000FF000000ULL) << 8 ) |
+            ((x & 0x0000000000FF0000ULL) << 24) |
+            ((x & 0x000000000000FF00ULL) << 40) |
+            ((x & 0x00000000000000FFULL) << 56));
+}
+#endif
+
+/**
+ * Collection of functions for converting 16/32/64-bit variables from little endian to native endian
+ * of the current platform.
+ *
+ * @param   x       16/32/64-bit variable.
+ */
+#if ZYAN_ENDIAN == ZYAN_LITTLE_ENDIAN
+#   define ZYAN_LE16_TO_NATIVE(x)
+#   define ZYAN_LE32_TO_NATIVE(x)
+#   define ZYAN_LE64_TO_NATIVE(x)
+#else
+#   define ZYAN_LE16_TO_NATIVE(x) (x) = ZYAN_BYTESWAP16((x))
+#   define ZYAN_LE32_TO_NATIVE(x) (x) = ZYAN_BYTESWAP32((x))
+#   define ZYAN_LE64_TO_NATIVE(x) (x) = ZYAN_BYTESWAP64((x))
+#endif
+
 /* ---------------------------------------------------------------------------------------------- */
 
 /* ============================================================================================== */


Reviews:
user: login: mappzor
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T00:34:14Z
user: login: athre0z
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-18T10:20:31Z
user: login: mappzor
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T16:21:04Z
user: login: mappzor
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T16:22:30Z
user: login: athre0z
body: LGTM, thank you!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-18T17:15:38Z
user: login: athre0z
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-18T17:16:39Z
user: login: flobernd
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-18T20:07:40Z

Review comments:
diff_hunk: @@ -264,8 +332,8 @@
 #   define ZYAN_NO_SANITIZE(what)
 #endif
 
-#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
-#   define ZYAN_INLINE __inline
+#if defined(ZYAN_BORLAND)
+#   define ZYAN_INLINE static __inline
path: include/Zycore/Defines.h
user: login: mappzor
body: Old version resulted in storage class inconsistency between different compilers.
created_at: 2025-05-18T00:27:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,12 +178,54 @@
 #   define ZYAN_PPC64
 #elif defined(__powerpc__)
 #   define ZYAN_PPC
-#elif defined(__riscv) && __riscv_xlen == 64
-#   define ZYAN_RISCV64
+#elif defined(__riscv) || defined(__riscv__)
+#   if __riscv_xlen == 64
+#       define ZYAN_RISCV64
+#   else
+#       define ZYAN_RISCV32
+#   endif
+#elif defined(__arc__)
+#   define ZYAN_ARC
+#elif defined(__s390x__)
+#   define ZYAN_S390
+#elif defined(__sparc__)
+#   define ZYAN_SPARC
+#elif defined(__mips__)
+#   define ZYAN_MIPS
 #else
 #   error "Unsupported architecture detected"
 #endif
 
+/* ============================================================================================== */
+/* Endianness detection                                                                           */
+/* ============================================================================================== */
+
+#define ZYAN_LITTLE_ENDIAN 0
+#define ZYAN_BIG_ENDIAN 1
+
+#if !defined(ZYAN_NO_LIBC) && ZYAN_HAS_INCLUDE(<stdbit.h>)
path: include/Zycore/Defines.h
user: login: mappzor
body: One would think that using `__STDC_VERSION__` to check for C23 would be enough but it's not. MSVC support for C23 library features is abysmal and on *nix `-march` doesn't tell you anything about glibc that will be used.
created_at: 2025-05-18T00:31:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -333,6 +333,84 @@ typedef char* ZyanCharPointer;
  */
 typedef const char* ZyanConstCharPointer;
 
+/* ============================================================================================== */
+/* Type conversion utils                                                                          */
path: include/Zycore/Types.h
user: login: mappzor
body: Perhaps this is not a perfect place but it's the best one from existing ones. Fallback functions require types to be properly defined so `Defines.h` is not an option.

If we don't want it here I can move this and other utilities from `Defines.h` to a new header file (`Utils.h`? `Arithmetic.h`?).
created_at: 2025-05-18T00:33:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -333,6 +333,84 @@ typedef char* ZyanCharPointer;
  */
 typedef const char* ZyanConstCharPointer;
 
+/* ============================================================================================== */
+/* Type conversion utils                                                                          */
+/* ============================================================================================== */
+
+/**
+ * Collection of functions for swapping byte order in 16/32/64-bit values respectively.
+ *
+ * @param   x       16/32/64-bit value.
+ *
+ * @return  16/32/64-bit value with byte order swapped.
+ */
+#if defined(ZYAN_MSVC)
+#   if defined(ZYAN_NO_LIBC)
+#ifdef __cplusplus
+extern "C" {
+#endif
path: include/Zycore/Types.h
user: login: athre0z
body: Nit: let's consistently also indent this and use `#if defined(..)`. Same for the `}` a few lines below.
created_at: 2025-05-18T10:15:12Z
author_association: MEMBER
diff_hunk: @@ -333,6 +333,84 @@ typedef char* ZyanCharPointer;
  */
 typedef const char* ZyanConstCharPointer;
 
+/* ============================================================================================== */
+/* Type conversion utils                                                                          */
path: include/Zycore/Types.h
user: login: athre0z
body: I think this is fine as-is. :)
created_at: 2025-05-18T10:15:48Z
author_association: MEMBER
diff_hunk: @@ -57,6 +57,32 @@
  */
 #define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
 
+/**
+ * Checks if a header can be included.
+ *
+ * @param name  Header file name.
+ *
+ * @return      True if header exists, false if it doesn't or it's not possible to check.
+ */
+#if defined(__has_include)
+#   define ZYAN_HAS_INCLUDE(name) __has_include(name)
path: include/Zycore/Defines.h
user: login: athre0z
body: TIL `__has_include` exists!
created_at: 2025-05-18T10:16:17Z
author_association: MEMBER
diff_hunk: @@ -333,6 +333,84 @@ typedef char* ZyanCharPointer;
  */
 typedef const char* ZyanConstCharPointer;
 
+/* ============================================================================================== */
+/* Type conversion utils                                                                          */
+/* ============================================================================================== */
+
+/**
+ * Collection of functions for swapping byte order in 16/32/64-bit values respectively.
+ *
+ * @param   x       16/32/64-bit value.
+ *
+ * @return  16/32/64-bit value with byte order swapped.
+ */
+#if defined(ZYAN_MSVC)
+#   if defined(ZYAN_NO_LIBC)
+#ifdef __cplusplus
+extern "C" {
+#endif
+    unsigned short __cdecl _byteswap_ushort(unsigned short);
+    unsigned long  __cdecl _byteswap_ulong(unsigned long);
+    unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64);
+#ifdef __cplusplus
+}
+#endif
+#   elif defined(ZYAN_KERNEL)
+#       include <wdm.h>
+#   else
+#       include <stdlib.h>
+#   endif
+
+#   define ZYAN_BYTESWAP16(x) _byteswap_ushort((x))
+#   define ZYAN_BYTESWAP32(x) _byteswap_ulong((x))
+#   define ZYAN_BYTESWAP64(x) _byteswap_uint64((x))
+#elif ZYAN_HAS_BUILTIN(__builtin_bswap64)
path: include/Zycore/Types.h
user: login: athre0z
body: Let's check presence of all the `__builtin` variants here. It's possible to disable builtins individually with some compiler flag that I forgot. I had to occasionally use this in build systems to work around bugs in upstream libraries (`glibc` specifically).
created_at: 2025-05-18T10:19:47Z
author_association: MEMBER
diff_hunk: @@ -333,6 +333,84 @@ typedef char* ZyanCharPointer;
  */
 typedef const char* ZyanConstCharPointer;
 
+/* ============================================================================================== */
+/* Type conversion utils                                                                          */
+/* ============================================================================================== */
+
+/**
+ * Collection of functions for swapping byte order in 16/32/64-bit values respectively.
+ *
+ * @param   x       16/32/64-bit value.
+ *
+ * @return  16/32/64-bit value with byte order swapped.
+ */
+#if defined(ZYAN_MSVC)
+#   if defined(ZYAN_NO_LIBC)
+#ifdef __cplusplus
+extern "C" {
+#endif
path: include/Zycore/Types.h
user: login: mappzor
body: I always struggle to decide how to mix preprocessor and code indentation levels. In fixed version I went with "code starts at last preprocessor level".
created_at: 2025-05-18T16:21:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -57,6 +57,32 @@
  */
 #define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
 
+/**
+ * Checks if a header can be included.
+ *
+ * @param name  Header file name.
+ *
+ * @return      True if header exists, false if it doesn't or it's not possible to check.
+ */
+#if defined(__has_include)
+#   define ZYAN_HAS_INCLUDE(name) __has_include(name)
path: include/Zycore/Defines.h
user: login: mappzor
body: And it works even on msvc :grinning:
created_at: 2025-05-18T16:22:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -333,6 +333,84 @@ typedef char* ZyanCharPointer;
  */
 typedef const char* ZyanConstCharPointer;
 
+/* ============================================================================================== */
+/* Type conversion utils                                                                          */
+/* ============================================================================================== */
+
+/**
+ * Collection of functions for swapping byte order in 16/32/64-bit values respectively.
+ *
+ * @param   x       16/32/64-bit value.
+ *
+ * @return  16/32/64-bit value with byte order swapped.
+ */
+#if defined(ZYAN_MSVC)
+#   if defined(ZYAN_NO_LIBC)
+#ifdef __cplusplus
+extern "C" {
+#endif
path: include/Zycore/Types.h
user: login: athre0z
body: Haha, I'm also not sure if we have a consistent convention for that across the codebase. 
created_at: 2025-05-18T17:16:39Z
author_association: MEMBER

PR comments:
user: login: flobernd
created_at: 2025-05-18T20:07:30Z
body: Just found some time to check this. Thank you @mappzor , very good work as usual. LGTM!
author_association: MEMBER
user: login: flobernd
created_at: 2025-05-18T20:16:35Z
body: We might have to check these ones (and the equivalent duplicates in `zydis`) with BE:
https://github.com/zyantific/zycore-c/blob/master/src/Format.c#L86

The added architectures might mess with the hardcoded condition (I guess we finally need a proper `ZYAN_32BIT/ZYAN_64BIT` define).
author_association: MEMBER
user: login: mochaaP
created_at: 2025-09-27T19:54:58Z
body: Tests failed on s390x: (???)

```
[==========] Running 21 tests from 3 test suites.
[----------] Global test environment set-up.
[----------] 5 tests from VectorTest
[ RUN      ] VectorTest.InitBasic
[       OK ] VectorTest.InitBasic (0 ms)
[ RUN      ] VectorTest.InitAdvanced
[       OK ] VectorTest.InitAdvanced (0 ms)
[ RUN      ] VectorTest.InitCustomBuffer
[       OK ] VectorTest.InitCustomBuffer (0 ms)
[ RUN      ] VectorTest.Destructor
../tests/Vector.cpp:220: Failure
Expected equality of these values:
  buffer[i]
    Which is: 0
  element
    Which is: 1

[  FAILED  ] VectorTest.Destructor (0 ms)
[ RUN      ] VectorTest.TestGrowingAndShrinking
[       OK ] VectorTest.TestGrowingAndShrinking (0 ms)
[----------] 5 tests from VectorTest (0 ms total)

[----------] 12 tests from Param/VectorTestFilled
[ RUN      ] Param/VectorTestFilled.ElementAccess/0
[       OK ] Param/VectorTestFilled.ElementAccess/0 (0 ms)
[ RUN      ] Param/VectorTestFilled.ElementAccess/1
[       OK ] Param/VectorTestFilled.ElementAccess/1 (0 ms)
[ RUN      ] Param/VectorTestFilled.PushPop/0
[       OK ] Param/VectorTestFilled.PushPop/0 (0 ms)
[ RUN      ] Param/VectorTestFilled.PushPop/1
[       OK ] Param/VectorTestFilled.PushPop/1 (0 ms)
[ RUN      ] Param/VectorTestFilled.Insert/0
[       OK ] Param/VectorTestFilled.Insert/0 (0 ms)
[ RUN      ] Param/VectorTestFilled.Insert/1
[       OK ] Param/VectorTestFilled.Insert/1 (0 ms)
[ RUN      ] Param/VectorTestFilled.Delete/0
[       OK ] Param/VectorTestFilled.Delete/0 (0 ms)
[ RUN      ] Param/VectorTestFilled.Delete/1
[       OK ] Param/VectorTestFilled.Delete/1 (0 ms)
[ RUN      ] Param/VectorTestFilled.Find/0
[       OK ] Param/VectorTestFilled.Find/0 (0 ms)
[ RUN      ] Param/VectorTestFilled.Find/1
[       OK ] Param/VectorTestFilled.Find/1 (0 ms)
[ RUN      ] Param/VectorTestFilled.SwapElements/0
[       OK ] Param/VectorTestFilled.SwapElements/0 (0 ms)
[ RUN      ] Param/VectorTestFilled.SwapElements/1
[       OK ] Param/VectorTestFilled.SwapElements/1 (0 ms)
[----------] 12 tests from Param/VectorTestFilled (0 ms total)

[----------] 4 tests from Param/VectorTestBase
[ RUN      ] Param/VectorTestBase.BinarySearch/0
[       OK ] Param/VectorTestBase.BinarySearch/0 (0 ms)
[ RUN      ] Param/VectorTestBase.BinarySearch/1
[       OK ] Param/VectorTestBase.BinarySearch/1 (0 ms)
[ RUN      ] Param/VectorTestBase.Emplace/0
[       OK ] Param/VectorTestBase.Emplace/0 (0 ms)
[ RUN      ] Param/VectorTestBase.Emplace/1
[       OK ] Param/VectorTestBase.Emplace/1 (0 ms)
[----------] 4 tests from Param/VectorTestBase (0 ms total)

[----------] Global test environment tear-down
[==========] 21 tests from 3 test suites ran. (0 ms total)
[  PASSED  ] 20 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] VectorTest.Destructor

 1 FAILED TEST
```
author_association: CONTRIBUTOR
user: login: mochaaP
created_at: 2025-09-28T02:02:29Z
body: Why is there a `+ 0` here?

https://github.com/zyantific/zycore-c/blob/master/tests/Vector.cpp#L218

This causes the element to be promoted to int - and thus fails on big-endian platforms.
author_association: CONTRIBUTOR