blob: 48b1ad771c3ba1ae09af05b910151c1be97d0de6 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#pragma once
#include "olap/uint24.h"
#include "vec/common/unaligned.h"
#include "vec/core/extended_types.h"
namespace doris {
#include "common/compile_check_begin.h"
inline uint64_t gbswap_64(uint64_t host_int) {
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__APPLE__)
// Adapted from /usr/include/byteswap.h. Not available on Mac.
if (__builtin_constant_p(host_int)) {
return __bswap_constant_64(host_int);
} else {
uint64_t result;
__asm__("bswap %0" : "=r"(result) : "0"(host_int));
return result;
}
#elif defined(bswap_64)
return bswap_64(host_int);
#else
return static_cast<uint64_t>(bswap_32(static_cast<uint32_t>(host_int >> 32))) |
(static_cast<uint64_t>(bswap_32(static_cast<uint32_t>(host_int))) << 32);
#endif // bswap_64
}
inline unsigned __int128 gbswap_128(unsigned __int128 host_int) {
return static_cast<unsigned __int128>(bswap_64(static_cast<uint64_t>(host_int >> 64))) |
(static_cast<unsigned __int128>(bswap_64(static_cast<uint64_t>(host_int))) << 64);
}
inline wide::UInt256 gbswap_256(wide::UInt256 host_int) {
wide::UInt256 result {gbswap_64(host_int.items[3]), gbswap_64(host_int.items[2]),
gbswap_64(host_int.items[1]), gbswap_64(host_int.items[0])};
return result;
}
// Swap bytes of a 24-bit value.
inline uint32_t bswap_24(uint32_t x) {
return uint32_t((x & 0x0000ffULL) << 16) | ((x & 0x00ff00ULL)) | ((x & 0xff0000ULL) >> 16);
}
// use std::byteswap after doris enable cpp23
template <typename T>
T byte_swap(T x) {
if constexpr (sizeof(T) == sizeof(wide::Int256)) {
return gbswap_256(x);
} else if constexpr (sizeof(T) == sizeof(__int128)) {
return gbswap_128(x);
} else if constexpr (sizeof(T) == sizeof(int64_t)) {
return bswap_64(x);
} else if constexpr (sizeof(T) == sizeof(int32_t)) {
return bswap_32(x);
} else if constexpr (sizeof(T) == sizeof(doris::uint24_t)) {
return bswap_24(x);
} else if constexpr (sizeof(T) == sizeof(int16_t)) {
return bswap_16(x);
} else {
static_assert(sizeof(T) == 1, "Unsupported type size for byte_swap");
return x; // No byte swap needed for unsupported types
}
}
template <std::endian target, typename T>
T to_endian(T value) {
if constexpr (std::endian::native == target) {
return value; // No swap needed
} else {
static_assert(std::endian::native == std::endian::big ||
std::endian::native == std::endian::little,
"Unsupported endianness");
return byte_swap(value);
}
}
// Utilities to convert numbers between the current hosts's native byte
// order and little-endian byte order
//
// Load/Store methods are alignment safe
class LittleEndian {
public:
// Functions to do unaligned loads and stores in little-endian order.
static uint16_t Load16(const void* p) {
return to_endian<std::endian::little>(unaligned_load<uint16_t>(p));
}
static void Store16(void* p, uint16_t v) {
unaligned_store<uint16_t>(p, to_endian<std::endian::little>(v));
}
static uint32_t Load32(const void* p) {
return to_endian<std::endian::little>(unaligned_load<uint32_t>(p));
}
static void Store32(void* p, uint32_t v) {
unaligned_store<uint32_t>(p, to_endian<std::endian::little>(v));
}
static uint64_t Load64(const void* p) {
return to_endian<std::endian::little>(unaligned_load<uint64_t>(p));
}
static void Store64(void* p, uint64_t v) {
unaligned_store<uint64_t>(p, to_endian<std::endian::little>(v));
}
};
// Utilities to convert numbers between the current hosts's native byte
// order and big-endian byte order (same as network byte order)
//
// Load/Store methods are alignment safe
class BigEndian {
public:
// Functions to do unaligned loads and stores in little-endian order.
static uint16_t Load16(const void* p) {
return to_endian<std::endian::big>(unaligned_load<uint16_t>(p));
}
static void Store16(void* p, uint16_t v) {
unaligned_store<uint16_t>(p, to_endian<std::endian::big>(v));
}
static uint32_t Load32(const void* p) {
return to_endian<std::endian::big>(unaligned_load<uint32_t>(p));
}
static void Store32(void* p, uint32_t v) {
unaligned_store<uint32_t>(p, to_endian<std::endian::big>(v));
}
static uint64_t Load64(const void* p) {
return to_endian<std::endian::big>(unaligned_load<uint64_t>(p));
}
static void Store64(void* p, uint64_t v) {
unaligned_store<uint64_t>(p, to_endian<std::endian::big>(v));
}
}; // BigEndian
#include "common/compile_check_end.h"
} // namespace doris