Merge pull request #1253 from ltrk2/bugfix/hashing-on-big-endian

Make hashes identical between LE and BE platforms

GitOrigin-RevId: 26b3b238fe96d51f0bcd4b083bd7a62e57dab2a4
Change-Id: Id179e6ba97a9f36ede71be9a70896945e1e563cd
diff --git a/lib/README.md b/lib/README.md
index a86cd0d..0932b07 100644
--- a/lib/README.md
+++ b/lib/README.md
@@ -108,6 +108,12 @@
   Remove support of dynamic memory allocation.
   For more details, see description of this macro in `lib/lz4.c`.
 
+- `LZ4_STATIC_LINKING_ONLY_ENDIANNESS_INDEPENDENT_OUTPUT` : experimental feature aimed at producing the same
+  compressed output on platforms of different endianness (i.e. little-endian and big-endian).
+  Output on little-endian platforms shall remain unchanged, while big-endian platforms will start producing
+  the same output as little-endian ones. This isn't expected to impact backward- and forward-compatibility
+  in any way.
+
 - `LZ4_FREESTANDING` : by setting this build macro to 1,
   LZ4/HC removes dependencies on the C standard library,
   including allocation functions and `memmove()`, `memcpy()`, and `memset()`.
diff --git a/lib/lz4.c b/lib/lz4.c
index 77cecc5..b235d1d 100644
--- a/lib/lz4.c
+++ b/lib/lz4.c
@@ -434,6 +434,18 @@
     }
 }
 
+#ifdef LZ4_STATIC_LINKING_ONLY_ENDIANNESS_INDEPENDENT_OUTPUT
+static U32 LZ4_readLE32(const void* memPtr)
+{
+    if (LZ4_isLittleEndian()) {
+        return LZ4_read32(memPtr);
+    } else {
+        const BYTE* p = (const BYTE*)memPtr;
+        return (U32)p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24);
+    }
+}
+#endif
+
 static void LZ4_writeLE16(void* memPtr, U16 value)
 {
     if (LZ4_isLittleEndian()) {
@@ -782,7 +794,12 @@
 LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType)
 {
     if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType);
+
+#ifdef LZ4_STATIC_LINKING_ONLY_ENDIANNESS_INDEPENDENT_OUTPUT
+    return LZ4_hash4(LZ4_readLE32(p), tableType);
+#else
     return LZ4_hash4(LZ4_read32(p), tableType);
+#endif
 }
 
 LZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType)