blob: 575ed41e41e5b2bcedf3eb6dc868b4d2d9c38667 [file]
/*
* 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.
*/
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
// Adapted from RocksDB
// https://github.com/facebook/rocksdb/blob/main/util/math.h
#pragma once
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <limits>
#include <type_traits>
namespace paimon {
template <typename To, typename From>
constexpr bool InRange(From value) {
static_assert(std::is_integral_v<To> && std::is_integral_v<From>,
"InRange only supports integral types");
if constexpr (std::is_signed_v<From> && std::is_unsigned_v<To>) {
if (value < 0) {
return false;
}
using CompareType = std::common_type_t<std::make_unsigned_t<From>, To>;
return static_cast<CompareType>(value) <=
static_cast<CompareType>(std::numeric_limits<To>::max());
} else if constexpr (std::is_unsigned_v<From> && std::is_signed_v<To>) {
using CompareType = std::common_type_t<From, std::make_unsigned_t<To>>;
return static_cast<CompareType>(value) <=
static_cast<CompareType>(std::numeric_limits<To>::max());
} else {
using CompareType = std::common_type_t<To, From>;
const auto numeric_value = static_cast<CompareType>(value);
const auto min_value = static_cast<CompareType>(std::numeric_limits<To>::min());
const auto max_value = static_cast<CompareType>(std::numeric_limits<To>::max());
return numeric_value >= min_value && numeric_value <= max_value;
}
}
// Swaps between big and little endian. Can be used in combination with the
// little-endian encoding/decoding functions in coding_lean.h and coding.h to
// encode/decode big endian.
template <typename T>
inline T EndianSwapValue(T v) {
static_assert(std::is_standard_layout_v<T> && std::is_trivially_copyable_v<T>,
"Type must be standard-layout and trivially copyable (e.g., integral or "
"floating-point types).");
if constexpr (sizeof(T) == 1) {
return v;
} else if constexpr (std::is_same_v<T, float> || // NOLINT(readability/braces)
std::is_same_v<T, double> || std::is_integral_v<T>) {
using UintType = std::conditional_t<
sizeof(T) == 2, uint16_t,
std::conditional_t<sizeof(T) == 4, uint32_t,
std::conditional_t<sizeof(T) == 8, uint64_t, void>>>;
static_assert(!std::is_same_v<UintType, void>,
"Unsupported size: only 2-byte, 4-byte, and 8-byte types are supported.");
UintType int_repr;
std::memcpy(&int_repr, &v, sizeof(T));
#ifdef _MSC_VER
if constexpr (sizeof(T) == 2) {
int_repr = _byteswap_ushort(static_cast<uint16_t>(int_repr));
} else if constexpr (sizeof(T) == 4) {
int_repr = _byteswap_ulong(static_cast<uint32_t>(int_repr));
} else if constexpr (sizeof(T) == 8) {
int_repr = _byteswap_uint64(static_cast<uint64_t>(int_repr));
}
#else
if constexpr (sizeof(T) == 2) {
int_repr = __builtin_bswap16(static_cast<uint16_t>(int_repr));
} else if constexpr (sizeof(T) == 4) {
int_repr = __builtin_bswap32(static_cast<uint32_t>(int_repr));
} else if constexpr (sizeof(T) == 8) {
int_repr = __builtin_bswap64(static_cast<uint64_t>(int_repr));
}
#endif
T result;
std::memcpy(&result, &int_repr, sizeof(T));
return result;
} else {
// Fallback for unsupported sizes (e.g., 16-bit integers on some platforms)
T ret_val{};
for (std::size_t i = 0; i < sizeof(T); ++i) {
reinterpret_cast<unsigned char*>(&ret_val)[sizeof(T) - 1 - i] =
reinterpret_cast<unsigned char*>(&v)[i];
}
return ret_val;
}
}
} // namespace paimon