]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - util.c
Implemented roboust compile-time endianess check.
[xonotic/gmqcc.git] / util.c
diff --git a/util.c b/util.c
index 03cf40efda956590f2c8c97a0c545b3e6e4e1c1f..d277ae45b8df865eaa3e9182d9ade2abbef168ac 100644 (file)
--- a/util.c
+++ b/util.c
@@ -283,61 +283,76 @@ void util_endianswap(void *m, int s, int l) {
 }
 #endif
 
-static void util_swap16(uint16_t *d, size_t l) {
-    while (l--) {
-        d[l] = (d[l] << 8) | (d[l] >> 8);
+/*
+ * only required if big endian .. otherwise no need to swap
+ * data.
+ */   
+#if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_BIG
+    static void util_swap16(uint16_t *d, size_t l) {
+        while (l--) {
+            d[l] = (d[l] << 8) | (d[l] >> 8);
+        }
     }
-}
 
-static void util_swap32(uint32_t *d, size_t l) {
-    while (l--) {
-        uint32_t v;
-        v = ((d[l] << 8) & 0xFF00FF00) | ((d[l] >> 8) & 0x00FF00FF);
-        d[l] = (v << 16) | (v >> 16);
+    static void util_swap32(uint32_t *d, size_t l) {
+        while (l--) {
+            uint32_t v;
+            v = ((d[l] << 8) & 0xFF00FF00) | ((d[l] >> 8) & 0x00FF00FF);
+            d[l] = (v << 16) | (v >> 16);
+        }
     }
-}
 
-/* Some strange system doesn't like constants that big, AND doesn't recognize an ULL suffix
- * so let's go the safe way
- */
-static void util_swap64(uint32_t *d, size_t l) {
-    /*
-    while (l--) {
-        uint64_t v;
-        v = ((d[l] << 8) & 0xFF00FF00FF00FF00) | ((d[l] >> 8) & 0x00FF00FF00FF00FF);
-        v = ((v << 16) & 0xFFFF0000FFFF0000) | ((v >> 16) & 0x0000FFFF0000FFFF);
-        d[l] = (v << 32) | (v >> 32);
-    }
-    */
-    size_t i;
-    for (i = 0; i < l; i += 2) {
-        uint32_t v1 = d[i];
-        d[i] = d[i+1];
-        d[i+1] = v1;
-        util_swap32(d+i, 2);
+    /* Some strange system doesn't like constants that big, AND doesn't recognize an ULL suffix
+     * so let's go the safe way
+     */
+    static void util_swap64(uint32_t *d, size_t l) {
+        /*
+        while (l--) {
+            uint64_t v;
+            v = ((d[l] << 8) & 0xFF00FF00FF00FF00) | ((d[l] >> 8) & 0x00FF00FF00FF00FF);
+            v = ((v << 16) & 0xFFFF0000FFFF0000) | ((v >> 16) & 0x0000FFFF0000FFFF);
+            d[l] = (v << 32) | (v >> 32);
+        }
+        */
+        size_t i;
+        for (i = 0; i < l; i += 2) {
+            uint32_t v1 = d[i];
+            d[i] = d[i+1];
+            d[i+1] = v1;
+            util_swap32(d+i, 2);
+        }
     }
-}
+#endif
 
 void util_endianswap(void *_data, size_t length, unsigned int typesize) {
-    /* I'm guessing there's no GOOD way to do this at compile time:
-     * FIXME:
-     */
+#   if PLATFORM_BYTE_ORDER == -1 /* runtime check */
     if (*((char*)&typesize))
         return;
-    if (typesize == 1)
-        return;
-    if (typesize == 2) {
-        util_swap16((uint16_t*)_data, length>>1);
-        return;
-    }
-    if (typesize == 4) {
-        util_swap32((uint32_t*)_data, length>>2);
-        return;
-    }
-    if (typesize == 4) {
-        util_swap64((uint32_t*)_data, length>>3);
+#else
+    /* prevent unused warnings */
+    (void) _data;
+    (void) length;
+    (void) typesize;
+
+#   if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_LITTLE
         return;
-    }
+#   else
+        switch (typesize) {
+            case 1: return;
+            case 2:
+                util_swap16((uint16_t*)_data, length>>1);
+                return;
+            case 4:
+                util_swap32((uint32_t*)_data, length>>2);
+                return;
+            case 8:
+                util_swap64((uint32_t*)_data, length>>3);
+                return;
+
+            default: abort(); /* please blow the fuck up! */
+        }
+#   endif
+#endif
 }
 
 /*