From 530b764953debdd04ddb6a0e3337c7fccbb2c9a5 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Fri, 21 Apr 2023 12:38:45 +0200 Subject: [PATCH] Fix IBM --- base/base/unaligned.h | 105 +++++++++++------- programs/copier/Internals.h | 1 - programs/copier/TaskTable.cpp | 2 + src/Access/ReplicatedAccessStorage.cpp | 2 +- src/Backups/BackupCoordinationRemote.cpp | 2 +- src/Backups/RestoreCoordinationRemote.cpp | 3 +- src/Backups/RestorerFromBackup.cpp | 2 +- src/Common/HashTable/Hash.h | 4 +- src/Common/SipHash.h | 20 ++-- src/Common/ZooKeeper/ZooKeeperIO.cpp | 77 +------------ src/Common/ZooKeeper/ZooKeeperIO.h | 34 +++--- src/Compression/CompressedReadBufferBase.cpp | 14 ++- src/Compression/CompressedWriteBuffer.cpp | 33 +++--- .../CompressionCodecDoubleDelta.cpp | 24 ++-- src/Compression/CompressionCodecGorilla.cpp | 16 +-- src/Compression/CompressionCodecT64.cpp | 2 +- src/Compression/ICompressionCodec.cpp | 8 +- .../tests/gtest_compressionCodec.cpp | 12 +- src/Coordination/FourLetterCommand.cpp | 6 +- src/Functions/FunctionsCodingIP.cpp | 9 +- src/IO/BitHelpers.h | 12 +- src/IO/ReadHelpers.h | 44 +++++--- src/IO/WriteHelpers.h | 44 +++++--- src/Storages/StorageGenerateRandom.cpp | 2 +- 24 files changed, 231 insertions(+), 247 deletions(-) diff --git a/base/base/unaligned.h b/base/base/unaligned.h index fcaaa38f2fe..3ab25c803bb 100644 --- a/base/base/unaligned.h +++ b/base/base/unaligned.h @@ -5,44 +5,6 @@ #include -inline void reverseMemcpy(void * dst, const void * src, size_t size) -{ - uint8_t * uint_dst = reinterpret_cast(dst); - const uint8_t * uint_src = reinterpret_cast(src); - - uint_dst += size; - while (size) - { - --uint_dst; - *uint_dst = *uint_src; - ++uint_src; - --size; - } -} - -template -inline T unalignedLoadLE(const void * address) -{ - T res {}; - if constexpr (std::endian::native == std::endian::little) - memcpy(&res, address, sizeof(res)); - else - reverseMemcpy(&res, address, sizeof(res)); - return res; -} - - -template -inline void unalignedStoreLE(void * address, - const typename std::enable_if::type & src) -{ - static_assert(std::is_trivially_copyable_v); - if constexpr (std::endian::native == std::endian::little) - memcpy(address, &src, sizeof(src)); - else - reverseMemcpy(address, &src, sizeof(src)); -} - template inline T unalignedLoad(const void * address) { @@ -62,3 +24,70 @@ inline void unalignedStore(void * address, static_assert(std::is_trivially_copyable_v); memcpy(address, &src, sizeof(src)); } + + +inline void reverseMemcpy(void * dst, const void * src, size_t size) +{ + uint8_t * uint_dst = reinterpret_cast(dst); + const uint8_t * uint_src = reinterpret_cast(src); + + uint_dst += size; + while (size) + { + --uint_dst; + *uint_dst = *uint_src; + ++uint_src; + --size; + } +} + +template +inline T unalignedLoadEndian(const void * address) +{ + T res {}; + if constexpr (std::endian::native == endian) + memcpy(&res, address, sizeof(res)); + else + reverseMemcpy(&res, address, sizeof(res)); + return res; +} + + +template +inline void unalignedStoreEndian(void * address, T & src) +{ + static_assert(std::is_trivially_copyable_v); + if constexpr (std::endian::native == endian) + memcpy(address, &src, sizeof(src)); + else + reverseMemcpy(address, &src, sizeof(src)); +} + + +template +inline T unalignedLoadLittleEndian(const void * address) +{ + return unalignedLoadEndian(address); +} + + +template +inline void unalignedStoreLittleEndian(void * address, + const typename std::enable_if::type & src) +{ + unalignedStoreEndian(address, src); +} + +template +inline T unalignedLoadBigEndian(const void * address) +{ + return unalignedLoadEndian(address); +} + + +template +inline void unalignedStoreBigEndian(void * address, + const typename std::enable_if::type & src) +{ + unalignedStoreEndian(address, src); +} diff --git a/programs/copier/Internals.h b/programs/copier/Internals.h index b3c9936cd33..48f4b0fab09 100644 --- a/programs/copier/Internals.h +++ b/programs/copier/Internals.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/programs/copier/TaskTable.cpp b/programs/copier/TaskTable.cpp index 451a33a1c02..d055ceb4c7b 100644 --- a/programs/copier/TaskTable.cpp +++ b/programs/copier/TaskTable.cpp @@ -4,9 +4,11 @@ #include "TaskCluster.h" #include +#include #include + namespace DB { namespace ErrorCodes diff --git a/src/Access/ReplicatedAccessStorage.cpp b/src/Access/ReplicatedAccessStorage.cpp index f34e6728ab3..7a608c298b1 100644 --- a/src/Access/ReplicatedAccessStorage.cpp +++ b/src/Access/ReplicatedAccessStorage.cpp @@ -14,9 +14,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/Backups/BackupCoordinationRemote.cpp b/src/Backups/BackupCoordinationRemote.cpp index 8e6b5db91b1..91a7444c746 100644 --- a/src/Backups/BackupCoordinationRemote.cpp +++ b/src/Backups/BackupCoordinationRemote.cpp @@ -5,9 +5,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/Backups/RestoreCoordinationRemote.cpp b/src/Backups/RestoreCoordinationRemote.cpp index cc03f0c4a2a..b2da013220d 100644 --- a/src/Backups/RestoreCoordinationRemote.cpp +++ b/src/Backups/RestoreCoordinationRemote.cpp @@ -1,10 +1,11 @@ #include #include #include +#include #include #include #include -#include "Backups/BackupCoordinationStageSync.h" + namespace DB { diff --git a/src/Backups/RestorerFromBackup.cpp b/src/Backups/RestorerFromBackup.cpp index 77f7512e0d1..7981cc2f19f 100644 --- a/src/Backups/RestorerFromBackup.cpp +++ b/src/Backups/RestorerFromBackup.cpp @@ -19,8 +19,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/Common/HashTable/Hash.h b/src/Common/HashTable/Hash.h index efdc43917da..c6b867b256d 100644 --- a/src/Common/HashTable/Hash.h +++ b/src/Common/HashTable/Hash.h @@ -221,7 +221,7 @@ inline UInt32 updateWeakHash32(const DB::UInt8 * pos, size_t size, DB::UInt32 up const auto * end = pos + size; while (pos + 8 <= end) { - auto word = unalignedLoadLE(pos); + auto word = unalignedLoadLittleEndian(pos); updated_value = static_cast(intHashCRC32(word, updated_value)); pos += 8; @@ -233,7 +233,7 @@ inline UInt32 updateWeakHash32(const DB::UInt8 * pos, size_t size, DB::UInt32 up /// Lets' assume the string was 'abcdefghXYZ', so it's tail is 'XYZ'. DB::UInt8 tail_size = end - pos; /// Load tailing 8 bytes. Word is 'defghXYZ'. - auto word = unalignedLoadLE(end - 8); + auto word = unalignedLoadLittleEndian(end - 8); /// Prepare mask which will set other 5 bytes to 0. It is 0xFFFFFFFFFFFFFFFF << 5 = 0xFFFFFF0000000000. /// word & mask = '\0\0\0\0\0XYZ' (bytes are reversed because of little ending) word &= (~UInt64(0)) << DB::UInt8(8 * (8 - tail_size)); diff --git a/src/Common/SipHash.h b/src/Common/SipHash.h index 8f2a5e1a48f..9e6479d81c1 100644 --- a/src/Common/SipHash.h +++ b/src/Common/SipHash.h @@ -13,6 +13,7 @@ * (~ 700 MB/sec, 15 million strings per second) */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include + namespace DB { namespace ErrorCodes @@ -29,15 +31,13 @@ namespace ErrorCodes } } -#define ROTL(x, b) static_cast(((x) << (b)) | ((x) >> (64 - (b)))) - #define SIPROUND \ do \ { \ - v0 += v1; v1 = ROTL(v1, 13); v1 ^= v0; v0 = ROTL(v0, 32); \ - v2 += v3; v3 = ROTL(v3, 16); v3 ^= v2; \ - v0 += v3; v3 = ROTL(v3, 21); v3 ^= v0; \ - v2 += v1; v1 = ROTL(v1, 17); v1 ^= v2; v2 = ROTL(v2, 32); \ + v0 += v1; v1 = std::rotl(v1, 13); v1 ^= v0; v0 = std::rotl(v0, 32); \ + v2 += v3; v3 = std::rotl(v3, 16); v3 ^= v2; \ + v0 += v3; v3 = std::rotl(v3, 21); v3 ^= v0; \ + v2 += v1; v1 = std::rotl(v1, 17); v1 ^= v2; v2 = std::rotl(v2, 32); \ } while(0) /// Define macro CURRENT_BYTES_IDX for building index used in current_bytes array @@ -136,7 +136,7 @@ public: while (data + 8 <= end) { - current_word = unalignedLoadLE(data); + current_word = unalignedLoadLittleEndian(data); v3 ^= current_word; SIPROUND; @@ -242,14 +242,16 @@ public: SIPROUND; SIPROUND; auto hi = v0 ^ v1 ^ v2 ^ v3; + if constexpr (std::endian::native == std::endian::big) { - lo = __builtin_bswap64(lo); - hi = __builtin_bswap64(hi); + lo = std::byteswap(lo); + hi = std::byteswap(hi); auto tmp = hi; hi = lo; lo = tmp; } + UInt128 res = hi; res <<= 64; res |= lo; diff --git a/src/Common/ZooKeeper/ZooKeeperIO.cpp b/src/Common/ZooKeeper/ZooKeeperIO.cpp index 3bfa5585d87..2911d511254 100644 --- a/src/Common/ZooKeeper/ZooKeeperIO.cpp +++ b/src/Common/ZooKeeper/ZooKeeperIO.cpp @@ -1,48 +1,14 @@ #include + namespace Coordination { -void write(size_t x, WriteBuffer & out) -{ - x = __builtin_bswap64(x); - writeBinary(x, out); -} - -#ifdef OS_DARWIN -void write(uint64_t x, WriteBuffer & out) -{ - x = __builtin_bswap64(x); - writeBinary(x, out); -} -#endif - -void write(int64_t x, WriteBuffer & out) -{ - x = __builtin_bswap64(x); - writeBinary(x, out); -} -void write(int32_t x, WriteBuffer & out) -{ - x = __builtin_bswap32(x); - writeBinary(x, out); -} - -void write(uint8_t x, WriteBuffer & out) -{ - writeBinary(x, out); -} - void write(OpNum x, WriteBuffer & out) { write(static_cast(x), out); } -void write(bool x, WriteBuffer & out) -{ - writeBinary(x, out); -} - void write(const std::string & s, WriteBuffer & out) { write(static_cast(s.size()), out); @@ -76,37 +42,6 @@ void write(const Error & x, WriteBuffer & out) write(static_cast(x), out); } -#ifdef OS_DARWIN -void read(uint64_t & x, ReadBuffer & in) -{ - readBinary(x, in); - x = __builtin_bswap64(x); -} -#endif - -void read(size_t & x, ReadBuffer & in) -{ - readBinary(x, in); - x = __builtin_bswap64(x); -} - -void read(int64_t & x, ReadBuffer & in) -{ - readBinary(x, in); - x = __builtin_bswap64(x); -} - -void read(uint8_t & x, ReadBuffer & in) -{ - readBinary(x, in); -} - -void read(int32_t & x, ReadBuffer & in) -{ - readBinary(x, in); - x = __builtin_bswap32(x); -} - void read(OpNum & x, ReadBuffer & in) { int32_t raw_op_num; @@ -114,16 +49,6 @@ void read(OpNum & x, ReadBuffer & in) x = getOpNum(raw_op_num); } -void read(bool & x, ReadBuffer & in) -{ - readBinary(x, in); -} - -void read(int8_t & x, ReadBuffer & in) -{ - readBinary(x, in); -} - void read(std::string & s, ReadBuffer & in) { int32_t size = 0; diff --git a/src/Common/ZooKeeper/ZooKeeperIO.h b/src/Common/ZooKeeper/ZooKeeperIO.h index 2c5fdd5d8a3..81b56a02e27 100644 --- a/src/Common/ZooKeeper/ZooKeeperIO.h +++ b/src/Common/ZooKeeper/ZooKeeperIO.h @@ -1,4 +1,5 @@ #pragma once + #include #include #include @@ -8,23 +9,20 @@ #include #include + namespace Coordination { using namespace DB; -void write(size_t x, WriteBuffer & out); +template +requires is_arithmetic_v +void write(T x, WriteBuffer & out) +{ + writeBinaryBigEndian(x, out); +} -/// uint64_t != size_t on darwin -#ifdef OS_DARWIN -void write(uint64_t x, WriteBuffer & out); -#endif - -void write(int64_t x, WriteBuffer & out); -void write(int32_t x, WriteBuffer & out); -void write(uint8_t x, WriteBuffer & out); void write(OpNum x, WriteBuffer & out); -void write(bool x, WriteBuffer & out); void write(const std::string & s, WriteBuffer & out); void write(const ACL & acl, WriteBuffer & out); void write(const Stat & stat, WriteBuffer & out); @@ -45,16 +43,14 @@ void write(const std::vector & arr, WriteBuffer & out) write(elem, out); } -void read(size_t & x, ReadBuffer & in); -#ifdef OS_DARWIN -void read(uint64_t & x, ReadBuffer & in); -#endif -void read(int64_t & x, ReadBuffer & in); -void read(int32_t & x, ReadBuffer & in); -void read(uint8_t & x, ReadBuffer & in); +template +requires is_arithmetic_v +void read(T & x, ReadBuffer & in) +{ + readBinaryBigEndian(x, in); +} + void read(OpNum & x, ReadBuffer & in); -void read(bool & x, ReadBuffer & in); -void read(int8_t & x, ReadBuffer & in); void read(std::string & s, ReadBuffer & in); void read(ACL & acl, ReadBuffer & in); void read(Stat & stat, ReadBuffer & in); diff --git a/src/Compression/CompressedReadBufferBase.cpp b/src/Compression/CompressedReadBufferBase.cpp index 3111f649b26..278210d770a 100644 --- a/src/Compression/CompressedReadBufferBase.cpp +++ b/src/Compression/CompressedReadBufferBase.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -191,7 +192,11 @@ size_t CompressedReadBufferBase::readCompressedData(size_t & size_decompressed, if (!disable_checksum) { - Checksum & checksum = *reinterpret_cast(own_compressed_buffer.data()); + Checksum checksum; + ReadBufferFromMemory checksum_in(own_compressed_buffer.data(), sizeof(checksum)); + readBinaryLittleEndian(checksum.first, checksum_in); + readBinaryLittleEndian(checksum.second, checksum_in); + validateChecksum(compressed_buffer, size_compressed_without_checksum, checksum); } @@ -231,7 +236,11 @@ size_t CompressedReadBufferBase::readCompressedDataBlockForAsynchronous(size_t & if (!disable_checksum) { - Checksum & checksum = *reinterpret_cast(own_compressed_buffer.data()); + Checksum checksum; + ReadBufferFromMemory checksum_in(own_compressed_buffer.data(), sizeof(checksum)); + readBinaryLittleEndian(checksum.first, checksum_in); + readBinaryLittleEndian(checksum.second, checksum_in); + validateChecksum(compressed_buffer, size_compressed_without_checksum, checksum); } @@ -319,5 +328,4 @@ CompressedReadBufferBase::CompressedReadBufferBase(ReadBuffer * in, bool allow_d CompressedReadBufferBase::~CompressedReadBufferBase() = default; /// Proper destruction of unique_ptr of forward-declared type. - } diff --git a/src/Compression/CompressedWriteBuffer.cpp b/src/Compression/CompressedWriteBuffer.cpp index 82beeea37cd..cb2ee1140d0 100644 --- a/src/Compression/CompressedWriteBuffer.cpp +++ b/src/Compression/CompressedWriteBuffer.cpp @@ -5,19 +5,15 @@ #include #include +#include + #include -#include "CompressedWriteBuffer.h" +#include namespace DB { -namespace ErrorCodes -{ -} - -static constexpr auto CHECKSUM_SIZE{sizeof(CityHash_v1_0_2::uint128)}; - void CompressedWriteBuffer::nextImpl() { if (!offset()) @@ -29,21 +25,23 @@ void CompressedWriteBuffer::nextImpl() /** During compression we need buffer with capacity >= compressed_reserve_size + CHECKSUM_SIZE. * - * If output buffer has necessary capacity, we can compress data directly in output buffer. + * If output buffer has necessary capacity, we can compress data directly into the output buffer. * Then we can write checksum at the output buffer begin. * - * If output buffer does not have necessary capacity. Compress data in temporary buffer. - * Then we can write checksum and temporary buffer in output buffer. + * If output buffer does not have necessary capacity. Compress data into a temporary buffer. + * Then we can write checksum and copy the temporary buffer into the output buffer. */ - if (out.available() >= compressed_reserve_size + CHECKSUM_SIZE) + if (out.available() >= compressed_reserve_size + sizeof(CityHash_v1_0_2::uint128)) { - char * out_checksum_ptr = out.position(); - char * out_compressed_ptr = out.position() + CHECKSUM_SIZE; + char * out_compressed_ptr = out.position() + sizeof(CityHash_v1_0_2::uint128); UInt32 compressed_size = codec->compress(working_buffer.begin(), decompressed_size, out_compressed_ptr); CityHash_v1_0_2::uint128 checksum = CityHash_v1_0_2::CityHash128(out_compressed_ptr, compressed_size); - memcpy(out_checksum_ptr, reinterpret_cast(&checksum), CHECKSUM_SIZE); - out.position() += CHECKSUM_SIZE + compressed_size; + + writeBinaryLittleEndian(checksum.first, out); + writeBinaryLittleEndian(checksum.second, out); + + out.position() += compressed_size; } else { @@ -51,7 +49,10 @@ void CompressedWriteBuffer::nextImpl() UInt32 compressed_size = codec->compress(working_buffer.begin(), decompressed_size, compressed_buffer.data()); CityHash_v1_0_2::uint128 checksum = CityHash_v1_0_2::CityHash128(compressed_buffer.data(), compressed_size); - out.write(reinterpret_cast(&checksum), CHECKSUM_SIZE); + + writeBinaryLittleEndian(checksum.first, out); + writeBinaryLittleEndian(checksum.second, out); + out.write(compressed_buffer.data(), compressed_size); } } diff --git a/src/Compression/CompressionCodecDoubleDelta.cpp b/src/Compression/CompressionCodecDoubleDelta.cpp index 40271726697..8e9a90cf416 100644 --- a/src/Compression/CompressionCodecDoubleDelta.cpp +++ b/src/Compression/CompressionCodecDoubleDelta.cpp @@ -293,7 +293,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) const char * dest_start = dest; const UInt32 items_count = source_size / sizeof(ValueType); - unalignedStoreLE(dest, items_count); + unalignedStoreLittleEndian(dest, items_count); dest += sizeof(items_count); ValueType prev_value{}; @@ -301,8 +301,8 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) if (source < source_end) { - prev_value = unalignedLoadLE(source); - unalignedStoreLE(dest, prev_value); + prev_value = unalignedLoadLittleEndian(source); + unalignedStoreLittleEndian(dest, prev_value); source += sizeof(prev_value); dest += sizeof(prev_value); @@ -310,10 +310,10 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) if (source < source_end) { - const ValueType curr_value = unalignedLoadLE(source); + const ValueType curr_value = unalignedLoadLittleEndian(source); prev_delta = curr_value - prev_value; - unalignedStoreLE(dest, prev_delta); + unalignedStoreLittleEndian(dest, prev_delta); source += sizeof(curr_value); dest += sizeof(prev_delta); @@ -325,7 +325,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) int item = 2; for (; source < source_end; source += sizeof(ValueType), ++item) { - const ValueType curr_value = unalignedLoadLE(source); + const ValueType curr_value = unalignedLoadLittleEndian(source); const UnsignedDeltaType delta = curr_value - prev_value; const UnsignedDeltaType double_delta = delta - prev_delta; @@ -369,7 +369,7 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest, if (source + sizeof(UInt32) > source_end) return; - const UInt32 items_count = unalignedLoadLE(source); + const UInt32 items_count = unalignedLoadLittleEndian(source); source += sizeof(items_count); ValueType prev_value{}; @@ -379,10 +379,10 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest, if (source + sizeof(ValueType) > source_end || items_count < 1) return; - prev_value = unalignedLoadLE(source); + prev_value = unalignedLoadLittleEndian(source); if (dest + sizeof(prev_value) > output_end) throw Exception(ErrorCodes::CANNOT_DECOMPRESS, "Cannot decompress the data"); - unalignedStoreLE(dest, prev_value); + unalignedStoreLittleEndian(dest, prev_value); source += sizeof(prev_value); dest += sizeof(prev_value); @@ -391,11 +391,11 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest, if (source + sizeof(UnsignedDeltaType) > source_end || items_count < 2) return; - prev_delta = unalignedLoadLE(source); + prev_delta = unalignedLoadLittleEndian(source); prev_value = prev_value + static_cast(prev_delta); if (dest + sizeof(prev_value) > output_end) throw Exception(ErrorCodes::CANNOT_DECOMPRESS, "Cannot decompress the data"); - unalignedStoreLE(dest, prev_value); + unalignedStoreLittleEndian(dest, prev_value); source += sizeof(prev_delta); dest += sizeof(prev_value); @@ -428,7 +428,7 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest, const ValueType curr_value = prev_value + delta; if (dest + sizeof(curr_value) > output_end) throw Exception(ErrorCodes::CANNOT_DECOMPRESS, "Cannot decompress the data"); - unalignedStoreLE(dest, curr_value); + unalignedStoreLittleEndian(dest, curr_value); dest += sizeof(curr_value); prev_delta = curr_value - prev_value; diff --git a/src/Compression/CompressionCodecGorilla.cpp b/src/Compression/CompressionCodecGorilla.cpp index 2c6f862d38b..aca68fab9ac 100644 --- a/src/Compression/CompressionCodecGorilla.cpp +++ b/src/Compression/CompressionCodecGorilla.cpp @@ -205,7 +205,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest, const UInt32 items_count = source_size / sizeof(T); - unalignedStoreLE(dest, items_count); + unalignedStoreLittleEndian(dest, items_count); dest += sizeof(items_count); T prev_value = 0; @@ -214,8 +214,8 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest, if (source < source_end) { - prev_value = unalignedLoadLE(source); - unalignedStoreLE(dest, prev_value); + prev_value = unalignedLoadLittleEndian(source); + unalignedStoreLittleEndian(dest, prev_value); source += sizeof(prev_value); dest += sizeof(prev_value); @@ -229,7 +229,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest, while (source < source_end) { - const T curr_value = unalignedLoadLE(source); + const T curr_value = unalignedLoadLittleEndian(source); source += sizeof(curr_value); const auto xored_data = curr_value ^ prev_value; @@ -271,7 +271,7 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest) if (source + sizeof(UInt32) > source_end) return; - const UInt32 items_count = unalignedLoadLE(source); + const UInt32 items_count = unalignedLoadLittleEndian(source); source += sizeof(items_count); T prev_value = 0; @@ -280,8 +280,8 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest) if (source + sizeof(T) > source_end || items_count < 1) return; - prev_value = unalignedLoadLE(source); - unalignedStoreLE(dest, prev_value); + prev_value = unalignedLoadLittleEndian(source); + unalignedStoreLittleEndian(dest, prev_value); source += sizeof(prev_value); dest += sizeof(prev_value); @@ -326,7 +326,7 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest) } // else: 0b0 prefix - use prev_value - unalignedStoreLE(dest, curr_value); + unalignedStoreLittleEndian(dest, curr_value); dest += sizeof(curr_value); prev_xored_info = curr_xored_info; diff --git a/src/Compression/CompressionCodecT64.cpp b/src/Compression/CompressionCodecT64.cpp index 1f8331c8a5f..d5bace020be 100644 --- a/src/Compression/CompressionCodecT64.cpp +++ b/src/Compression/CompressionCodecT64.cpp @@ -326,7 +326,7 @@ void load(const char * src, T * buf, UInt32 tail = 64) /// as little-endian types on big-endian machine (s390x, etc). for (UInt32 i = 0; i < tail; ++i) { - buf[i] = unalignedLoadLE(src + i * sizeof(T)); + buf[i] = unalignedLoadLittleEndian(src + i * sizeof(T)); } } } diff --git a/src/Compression/ICompressionCodec.cpp b/src/Compression/ICompressionCodec.cpp index d6beaba7e0a..a8257c4331f 100644 --- a/src/Compression/ICompressionCodec.cpp +++ b/src/Compression/ICompressionCodec.cpp @@ -86,8 +86,8 @@ UInt32 ICompressionCodec::compress(const char * source, UInt32 source_size, char UInt8 header_size = getHeaderSize(); /// Write data from header_size UInt32 compressed_bytes_written = doCompressData(source, source_size, &dest[header_size]); - unalignedStoreLE(&dest[1], compressed_bytes_written + header_size); - unalignedStoreLE(&dest[5], source_size); + unalignedStoreLittleEndian(&dest[1], compressed_bytes_written + header_size); + unalignedStoreLittleEndian(&dest[5], source_size); return header_size + compressed_bytes_written; } @@ -114,7 +114,7 @@ UInt32 ICompressionCodec::decompress(const char * source, UInt32 source_size, ch UInt32 ICompressionCodec::readCompressedBlockSize(const char * source) { - UInt32 compressed_block_size = unalignedLoadLE(&source[1]); + UInt32 compressed_block_size = unalignedLoadLittleEndian(&source[1]); if (compressed_block_size == 0) throw Exception(ErrorCodes::CORRUPTED_DATA, "Can't decompress data: header is corrupt with compressed block size 0"); return compressed_block_size; @@ -123,7 +123,7 @@ UInt32 ICompressionCodec::readCompressedBlockSize(const char * source) UInt32 ICompressionCodec::readDecompressedBlockSize(const char * source) { - UInt32 decompressed_block_size = unalignedLoadLE(&source[5]); + UInt32 decompressed_block_size = unalignedLoadLittleEndian(&source[5]); if (decompressed_block_size == 0) throw Exception(ErrorCodes::CORRUPTED_DATA, "Can't decompress data: header is corrupt with decompressed block size 0"); return decompressed_block_size; diff --git a/src/Compression/tests/gtest_compressionCodec.cpp b/src/Compression/tests/gtest_compressionCodec.cpp index 3bf225fccc3..fa89e2da645 100644 --- a/src/Compression/tests/gtest_compressionCodec.cpp +++ b/src/Compression/tests/gtest_compressionCodec.cpp @@ -172,7 +172,7 @@ private: throw std::runtime_error("No more data to read"); } - current_value = unalignedLoadLE(data); + current_value = unalignedLoadLittleEndian(data); data = reinterpret_cast(data) + sizeof(T); } }; @@ -368,7 +368,7 @@ CodecTestSequence makeSeq(Args && ... args) char * write_pos = data.data(); for (const auto & v : vals) { - unalignedStoreLE(write_pos, v); + unalignedStoreLittleEndian(write_pos, v); write_pos += sizeof(v); } @@ -390,7 +390,7 @@ CodecTestSequence generateSeq(Generator gen, const char* gen_name, B Begin = 0, { const T v = static_cast(gen(i)); - unalignedStoreLE(write_pos, v); + unalignedStoreLittleEndian(write_pos, v); write_pos += sizeof(v); } @@ -1297,9 +1297,9 @@ TEST(LZ4Test, DecompressMalformedInput) DB::Memory<> memory; memory.resize(ICompressionCodec::getHeaderSize() + uncompressed_size + LZ4::ADDITIONAL_BYTES_AT_END_OF_BUFFER); - unalignedStoreLE(memory.data(), static_cast(CompressionMethodByte::LZ4)); - unalignedStoreLE(&memory[1], source_size); - unalignedStoreLE(&memory[5], uncompressed_size); + unalignedStoreLittleEndian(memory.data(), static_cast(CompressionMethodByte::LZ4)); + unalignedStoreLittleEndian(&memory[1], source_size); + unalignedStoreLittleEndian(&memory[5], uncompressed_size); auto codec = CompressionCodecFactory::instance().get("LZ4", {}); ASSERT_THROW(codec->decompress(source, source_size, memory.data()), Exception); diff --git a/src/Coordination/FourLetterCommand.cpp b/src/Coordination/FourLetterCommand.cpp index 8a7fdb82fb7..7077e792fd8 100644 --- a/src/Coordination/FourLetterCommand.cpp +++ b/src/Coordination/FourLetterCommand.cpp @@ -14,6 +14,8 @@ #include #include +#include + namespace DB { @@ -34,7 +36,7 @@ int32_t IFourLetterCommand::code() String IFourLetterCommand::toName(int32_t code) { - int reverted_code = __builtin_bswap32(code); + int reverted_code = std::byteswap(code); return String(reinterpret_cast(&reverted_code), 4); } @@ -42,7 +44,7 @@ int32_t IFourLetterCommand::toCode(const String & name) { int32_t res = *reinterpret_cast(name.data()); /// keep consistent with Coordination::read method by changing big endian to little endian. - return __builtin_bswap32(res); + return std::byteswap(res); } IFourLetterCommand::~IFourLetterCommand() = default; diff --git a/src/Functions/FunctionsCodingIP.cpp b/src/Functions/FunctionsCodingIP.cpp index f10ea24f4a6..8279aa490db 100644 --- a/src/Functions/FunctionsCodingIP.cpp +++ b/src/Functions/FunctionsCodingIP.cpp @@ -245,8 +245,8 @@ public: private: static bool isIPv4Mapped(const UInt8 * address) { - return (unalignedLoadLE(address) == 0) && - ((unalignedLoadLE(address + 8) & 0x00000000FFFFFFFFull) == 0x00000000FFFF0000ull); + return (unalignedLoadLittleEndian(address) == 0) && + ((unalignedLoadLittleEndian(address + 8) & 0x00000000FFFFFFFFull) == 0x00000000FFFF0000ull); } static void cutAddress(const unsigned char * address, char *& dst, UInt8 zeroed_tail_bytes_count) @@ -576,10 +576,11 @@ private: static void mapIPv4ToIPv6(UInt32 in, UInt8 * buf) { unalignedStore(buf, 0); + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - unalignedStoreLE(buf + 8, 0x00000000FFFF0000ull | (static_cast(ntohl(in)) << 32)); + unalignedStoreLittleEndian(buf + 8, 0x00000000FFFF0000ull | (static_cast(ntohl(in)) << 32)); #else - unalignedStoreLE(buf + 8, 0x00000000FFFF0000ull | (static_cast(__builtin_bswap32(ntohl(in))) << 32)); + unalignedStoreLittleEndian(buf + 8, 0x00000000FFFF0000ull | (static_cast(in)) << 32)); #endif } }; diff --git a/src/IO/BitHelpers.h b/src/IO/BitHelpers.h index 34173ccd8f9..2ca36c16c9b 100644 --- a/src/IO/BitHelpers.h +++ b/src/IO/BitHelpers.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -139,7 +140,7 @@ private: source_current += bytes_to_read; if constexpr (std::endian::native == std::endian::little) - tmp_buffer = __builtin_bswap64(tmp_buffer); + tmp_buffer = std::byteswap(tmp_buffer); bits_buffer |= BufferType(tmp_buffer) << ((sizeof(BufferType) - sizeof(tmp_buffer)) * 8 - bits_count); bits_count += static_cast(bytes_to_read) * 8; @@ -220,12 +221,9 @@ private: "Can not write past end of buffer. Space available {} bytes, required to write {} bytes.", available, to_write); } - UInt64 tmp_buffer = 0; - if constexpr (std::endian::native == std::endian::little) - tmp_buffer = __builtin_bswap64(static_cast(bits_buffer >> (sizeof(bits_buffer) - sizeof(UInt64)) * 8)); - else - tmp_buffer = static_cast(bits_buffer >> (sizeof(bits_buffer) - sizeof(UInt64)) * 8); - memcpy(dest_current, &tmp_buffer, to_write); + UInt64 tmp_buffer = static_cast(bits_buffer >> (sizeof(bits_buffer) - sizeof(UInt64)) * 8); + + unalignedStoreBigEndian(dest_current, tmp_buffer); dest_current += to_write; bits_buffer <<= to_write * 8; diff --git a/src/IO/ReadHelpers.h b/src/IO/ReadHelpers.h index 0b0a0640cb1..f0d2304f12b 100644 --- a/src/IO/ReadHelpers.h +++ b/src/IO/ReadHelpers.h @@ -1116,33 +1116,41 @@ inline void readBinary(Decimal256 & x, ReadBuffer & buf) { readPODBinary(x.value inline void readBinary(LocalDate & x, ReadBuffer & buf) { readPODBinary(x, buf); } -template +template requires is_arithmetic_v && (sizeof(T) <= 8) -inline void readBinaryBigEndian(T & x, ReadBuffer & buf) /// Assuming little endian architecture. +inline void readBinaryEndian(T & x, ReadBuffer & buf) { readPODBinary(x, buf); - if constexpr (std::endian::native == std::endian::little) + if constexpr (std::endian::native != endian) + std::byteswap(x); +} + +template +requires is_big_int_v +inline void readBinaryEndian(T & x, ReadBuffer & buf) +{ + if constexpr (std::endian::native == endian) { - if constexpr (sizeof(x) == 1) - return; - else if constexpr (sizeof(x) == 2) - x = __builtin_bswap16(x); - else if constexpr (sizeof(x) == 4) - x = __builtin_bswap32(x); - else if constexpr (sizeof(x) == 8) - x = __builtin_bswap64(x); + for (size_t i = 0; i != std::size(x.items); ++i) + readBinaryEndian(x.items[i], buf); + } + else + { + for (ssize_t i = std::size(x.items) - 1; i >= 0; --i) + readBinaryEndian(x.items[i], buf); } } template -requires is_big_int_v -inline void readBinaryBigEndian(T & x, ReadBuffer & buf) /// Assuming little endian architecture. +inline void readBinaryLittleEndian(T & x, ReadBuffer & buf) { - for (size_t i = 0; i != std::size(x.items); ++i) - { - auto & item = x.items[(std::endian::native == std::endian::little) ? std::size(x.items) - i - 1 : i]; - readBinaryBigEndian(item, buf); - } + readBinaryEndian(x, buf); +} + +template +inline void readBinaryBigEndian(T & x, ReadBuffer & buf) +{ + readBinaryEndian(x, buf); } diff --git a/src/IO/WriteHelpers.h b/src/IO/WriteHelpers.h index e08e451e0a7..8656ee8e098 100644 --- a/src/IO/WriteHelpers.h +++ b/src/IO/WriteHelpers.h @@ -1172,33 +1172,45 @@ inline void writeNullTerminatedString(const String & s, WriteBuffer & buffer) buffer.write(s.c_str(), s.size() + 1); } -template + +template requires is_arithmetic_v && (sizeof(T) <= 8) -inline void writeBinaryBigEndian(T x, WriteBuffer & buf) /// Assuming little endian architecture. +inline void writeBinaryEndian(T x, WriteBuffer & buf) { - if constexpr (std::endian::native == std::endian::little) - { - if constexpr (sizeof(x) == 2) - x = __builtin_bswap16(x); - else if constexpr (sizeof(x) == 4) - x = __builtin_bswap32(x); - else if constexpr (sizeof(x) == 8) - x = __builtin_bswap64(x); - } + if constexpr (std::endian::native != endian) + std::byteswap(x); writePODBinary(x, buf); } -template +template requires is_big_int_v -inline void writeBinaryBigEndian(const T & x, WriteBuffer & buf) /// Assuming little endian architecture. +inline void writeBinaryEndian(const T & x, WriteBuffer & buf) { - for (size_t i = 0; i != std::size(x.items); ++i) + if constexpr (std::endian::native == endian) { - const auto & item = x.items[(std::endian::native == std::endian::little) ? std::size(x.items) - i - 1 : i]; - writeBinaryBigEndian(item, buf); + for (size_t i = 0; i != std::size(x.items); ++i) + writeBinaryEndian(x.items[i], buf); + } + else + { + for (ssize_t i = std::size(x.items) - 1; i >= 0; --i) + writeBinaryEndian(x.items[i], buf); } } +template +inline void writeBinaryLittleEndian(T x, WriteBuffer & buf) +{ + writeBinaryEndian(x, buf); +} + +template +inline void writeBinaryBigEndian(T x, WriteBuffer & buf) +{ + writeBinaryEndian(x, buf); +} + + struct PcgSerializer { static void serializePcg32(const pcg32_fast & rng, WriteBuffer & buf) diff --git a/src/Storages/StorageGenerateRandom.cpp b/src/Storages/StorageGenerateRandom.cpp index fc642eb7cc3..567c674ded9 100644 --- a/src/Storages/StorageGenerateRandom.cpp +++ b/src/Storages/StorageGenerateRandom.cpp @@ -60,7 +60,7 @@ void fillBufferWithRandomData(char * __restrict data, size_t limit, size_t size_ /// The loop can be further optimized. UInt64 number = rng(); #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - unalignedStoreLE(data, number); + unalignedStoreLittleEndian(data, number); #else unalignedStore(data, number); #endif