utils/bits.h: Add macros for swapping endianness in place.
[mLib] / utils / bits.h
index 4279170..3b12f96 100644 (file)
@@ -314,6 +314,103 @@ typedef unsigned char octet, uint8;
    } while (0)
 #endif
 
+/* --- Endianness swapping --- */
+
+#ifndef ENDSWAP8
+#  define ENDSWAP8(x) U8(x)
+#endif
+#ifndef ENDSWAP16
+#  define ENDSWAP16(x)                                                 \
+       ((((uint16)(x) >> 8)&0xff) |                                    \
+        (((uint16)(x)&0xff) << 8))
+#endif
+#ifndef ENDSWAP24
+#  define ENDSWAP24(x)                                                 \
+       ((((uint24)(x) >> 16)&0xff) |                                   \
+        ((uint24)(x)&0xff00) |                                         \
+        ((uint24)((x)&0xff) << 16))
+#endif
+#ifndef ENDSWAP32
+#  define ENDSWAP32(x)                                                 \
+       (ENDSWAP16(((uint32)(x) >> 16)&0xffff) |                        \
+        ((uint32)ENDSWAP16((x)&0xffff) << 16))
+#endif
+#if defined(HAVE_UINT64) && !defined(ENDSWAP64)
+#  define ENDSWAP64(x)                                                 \
+       (ENDSWAP32(((uint64)(x) >> 32)&0xffffffff) |                    \
+        ((uint64)ENDSWAP32((x)&0xffffffff) << 32))
+#endif
+#ifdef HAVE_UINT64
+#  define ENDSWAP64_(z, x)                                             \
+       ((z).i = ENDSWAP64((x).i))
+#else
+#  define ENDSWAP64_(z, x)                                             \
+       ((z).lo = ENDSWAP32((x).hi),                                    \
+        (z).hi = ENDSWAP32((x).lo))
+#endif
+
+#define MLIB_LITTLE_ENDIAN 1234
+#define MLIB_BIG_ENDIAN 4321
+#if defined(__ORDER_LITTLE_ENDIAN__) &&                                        \
+    __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define MLIB_BYTE_ORDER MLIB_LITTLE_ENDIAN
+#elif defined(__ORDER_BIG_ENDIAN__) &&                                 \
+      __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  define MLIB_BYTE_ORDER MLIB_BIG_ENDIAN
+#endif
+
+#if MLIB_BYTE_ORDER == MLIB_LITTLE_ENDIAN
+#  define HTOL16(x) (x)
+#  define LTOH16(x) (x)
+#  define HTOB16(x) ENDSWAP16(x)
+#  define BTOH16(x) ENDSWAP16(x)
+#  define HTOL24(x) (x)
+#  define LTOH24(x) (x)
+#  define HTOB24(x) ENDSWAP24(x)
+#  define BTOH24(x) ENDSWAP24(x)
+#  define HTOL32(x) (x)
+#  define LTOH32(x) (x)
+#  define HTOB32(x) ENDSWAP32(x)
+#  define BTOH32(x) ENDSWAP32(x)
+#  ifdef HAVE_UINT64
+#    define HTOL64(x) (x)
+#    define LTOH64(x) (x)
+#    define HTOB64(x) ENDSWAP64(x)
+#    define BTOH64(x) ENDSWAP64(x)
+#  endif
+#  define HTOL64_(z, x) ASSIGN64(z, x)
+#  define LTOH64_(z, x) ASSIGN64(z, x)
+#  define HTOB64_(z, x) ENDSWAP64_(z, x)
+#  define BTOH64_(z, x) ENDSWAP64_(z, x)
+#elif MLIB_BYTE_ORDER == MLIB_BIG_ENDIAN
+#  define HTOL16(x) ENDSWAP16(x)
+#  define LTOH16(x) ENDSWAP16(x)
+#  define HTOB16(x) (x)
+#  define BTOH16(x) (x)
+#  define HTOL24(x) ENDSWAP24(x)
+#  define LTOH24(x) ENDSWAP24(x)
+#  define HTOB24(x) (x)
+#  define BTOH24(x) (x)
+#  define HTOL32(x) ENDSWAP32(x)
+#  define LTOH32(x) ENDSWAP32(x)
+#  define HTOB32(x) (x)
+#  define BTOH32(x) (x)
+#  ifdef HAVE_UINT64
+#    define HTOL64(x) ENDSWAP64(x)
+#    define LTOH64(x) ENDSWAP64(x)
+#    define HTOB64(x) (x)
+#    define BTOH64(x) (x)
+#    define HTOL64_(z, x) ENDSWAP64_(z, x)
+#    define LTOH64_(z, x) ENDSWAP64_(z, x)
+#    define HTOB64_(z, x) ((z).i = (x).i)
+#    define BTOH64_(z, x) ((z).i = (x).i)
+#  endif
+#  define HTOL64_(z, x) ENDSWAP64_(z, x)
+#  define LTOH64_(z, x) ENDSWAP64_(z, x)
+#  define HTOB64_(z, x) ASSIGN64(z, x)
+#  define BTOH64_(z, x) ASSIGN64(z, x)
+#endif
+
 /* --- Storage and retrieval --- */
 
 #define GETBYTE(p, o) (((octet *)(p))[o] & MASK8)