/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed 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. */ #ifndef ECMASCRIPT_BASE_BIT_HELPER_H #define ECMASCRIPT_BASE_BIT_HELPER_H #include #include #include #include namespace panda::ecmascript::base { constexpr uint64_t pureNaN = 0x7FF8ULL << 48U; // Be sure return the NaN that is safe. template union Data { S src; R dst; }; bool CheckBufferBounds(void* addr, void* buffer, size_t bufferSize, const char* name); template inline T ReadBuffer(void **buffer, size_t offset) { T result = *(reinterpret_cast(*buffer)); *buffer = reinterpret_cast(reinterpret_cast(*buffer) + offset); return result; } template inline T ReadBuffer(void **buffer) { T result = *(reinterpret_cast(*buffer)); *buffer = reinterpret_cast(reinterpret_cast(*buffer) + result.offset_); return result; } inline char *ReadBuffer(void **buffer) { auto result = reinterpret_cast(*buffer); *buffer = reinterpret_cast(reinterpret_cast(*buffer) + strlen(result) + 1); return result; } template inline T *ReadBufferInSize(void **buffer) { T *result = reinterpret_cast(*buffer); *buffer = reinterpret_cast(reinterpret_cast(*buffer) + result->Size()); return result; } template inline constexpr uint32_t CountLeadingZeros(T value) { constexpr size_t RADIX = 2; static_assert(std::is_integral::value, "T must be integral"); static_assert(std::is_unsigned::value, "T must be unsigned"); static_assert(std::numeric_limits::radix == RADIX, "Unexpected radix!"); static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)"); if (value == 0) { return sizeof(T) * 8; // 8: Each byte has 8 bits } if (sizeof(T) == sizeof(uint64_t)) { return __builtin_clzll(static_cast(value)); } // 32 : 32 mean the bits of type T is less than 32 return __builtin_clz(static_cast(value)) - (32 - std::numeric_limits::digits); } inline constexpr uint32_t CountLeadingZeros32(uint32_t value) { return CountLeadingZeros(value); } inline constexpr uint32_t CountLeadingZeros64(uint64_t value) { return CountLeadingZeros(value); } inline constexpr uint32_t CountLeadingOnes32(uint32_t value) { return CountLeadingZeros(~value); } inline constexpr uint32_t CountLeadingOnes64(uint64_t value) { return CountLeadingZeros(~value); } template inline constexpr uint32_t CountTrailingZeros(T value) { constexpr size_t RADIX = 2; static_assert(std::is_integral::value, "T must be integral"); static_assert(std::is_unsigned::value, "T must be unsigned"); static_assert(std::numeric_limits::radix == RADIX, "Unexpected radix!"); static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)"); if (value == 0) { return sizeof(T) * 8; // 8: Each byte has 8 bits } if (sizeof(T) == sizeof(uint64_t)) { return __builtin_ctzll(static_cast(value)); } return __builtin_ctz(static_cast(value)); } inline constexpr unsigned CountTrailingZeros32(uint32_t value) { return CountTrailingZeros(value); } inline constexpr unsigned CountTrailingZeros64(uint64_t value) { return CountTrailingZeros(value); } inline constexpr unsigned CountTrailingOnes32(uint32_t value) { return CountTrailingZeros(~value); } inline constexpr unsigned CountTrailingOnes64(uint64_t value) { return CountTrailingZeros(~value); } /// isMask_64 - This function returns true if the argument is a non-empty /// sequence of ones starting at the least significant bit with the remainder /// zero (64 bit version). constexpr inline bool IsMask_64(uint64_t Value) { return Value && ((Value + 1) & Value) == 0; } /// isShiftedMask_64 - This function returns true if the argument contains a /// non-empty sequence of ones with the remainder zero (64 bit version.) constexpr inline bool IsShiftedMask_64(uint64_t Value) { return Value && IsMask_64((Value - 1) | Value); } template constexpr T RoundUp(T x, size_t n) { static_assert(std::is_integral::value, "T must be integral"); return (static_cast(x) + n - 1U) & (-n); } template inline To bit_cast(const From &src) noexcept // NOLINT(readability-identifier-naming) { static_assert(sizeof(To) == sizeof(From), "size of the types must be equal"); // The use of security functions 'memcpy_s' here will have a greater impact on performance Data data; data.src = src; return data.dst; } template inline constexpr uint32_t BitNumbers() { constexpr int BIT_NUMBER_OF_CHAR = 8; return sizeof(T) * BIT_NUMBER_OF_CHAR; } } // panda::ecmascript::base #endif