• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_BASE_BIT_HELPER_H
17 #define ECMASCRIPT_BASE_BIT_HELPER_H
18 
19 #include <cstdint>
20 #include <cstring>
21 #include <limits>
22 #include <type_traits>
23 
24 namespace panda::ecmascript::base {
25 constexpr uint64_t pureNaN = 0x7FF8ULL << 48U; // Be sure return the NaN that is safe.
26 template <class S, class R>
27 union Data {
28     S src;
29     R dst;
30 };
31 
32 bool CheckBufferBounds(void* addr, void* buffer, size_t bufferSize, const char* name);
33 
34 template <typename T>
ReadBuffer(void ** buffer,size_t offset)35 inline T ReadBuffer(void **buffer, size_t offset)
36 {
37     T result = *(reinterpret_cast<T *>(*buffer));
38     *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + offset);
39     return result;
40 }
41 
42 template <typename T>
ReadBuffer(void ** buffer)43 inline T ReadBuffer(void **buffer)
44 {
45     T result = *(reinterpret_cast<T *>(*buffer));
46     *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + result.offset_);
47     return result;
48 }
49 
ReadBuffer(void ** buffer)50 inline char *ReadBuffer(void **buffer)
51 {
52     auto result = reinterpret_cast<char *>(*buffer);
53     *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + strlen(result) + 1);
54     return result;
55 }
56 
57 template <typename T>
ReadBufferInSize(void ** buffer)58 inline T *ReadBufferInSize(void **buffer)
59 {
60     T *result = reinterpret_cast<T *>(*buffer);
61     *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + result->Size());
62     return result;
63 }
64 
65 template <typename T>
CountLeadingZeros(T value)66 inline constexpr uint32_t CountLeadingZeros(T value)
67 {
68     constexpr size_t RADIX = 2;
69     static_assert(std::is_integral<T>::value, "T must be integral");
70     static_assert(std::is_unsigned<T>::value, "T must be unsigned");
71     static_assert(std::numeric_limits<T>::radix == RADIX, "Unexpected radix!");
72     static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)");
73     if (value == 0) {
74         return sizeof(T) * 8; // 8: Each byte has 8 bits
75     }
76     if (sizeof(T) == sizeof(uint64_t)) {
77         return __builtin_clzll(static_cast<uint64_t>(value));
78     }
79     // 32 : 32 mean the bits of type T is less than 32
80     return __builtin_clz(static_cast<uint32_t>(value)) - (32 - std::numeric_limits<T>::digits);
81 }
82 
CountLeadingZeros32(uint32_t value)83 inline constexpr uint32_t CountLeadingZeros32(uint32_t value)
84 {
85     return CountLeadingZeros(value);
86 }
87 
CountLeadingZeros64(uint64_t value)88 inline constexpr uint32_t CountLeadingZeros64(uint64_t value)
89 {
90     return CountLeadingZeros(value);
91 }
92 
CountLeadingOnes32(uint32_t value)93 inline constexpr uint32_t CountLeadingOnes32(uint32_t value)
94 {
95     return CountLeadingZeros(~value);
96 }
97 
CountLeadingOnes64(uint64_t value)98 inline constexpr uint32_t CountLeadingOnes64(uint64_t value)
99 {
100     return CountLeadingZeros(~value);
101 }
102 
103 template <typename T>
CountTrailingZeros(T value)104 inline constexpr uint32_t CountTrailingZeros(T value)
105 {
106     constexpr size_t RADIX = 2;
107     static_assert(std::is_integral<T>::value, "T must be integral");
108     static_assert(std::is_unsigned<T>::value, "T must be unsigned");
109     static_assert(std::numeric_limits<T>::radix == RADIX, "Unexpected radix!");
110     static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)");
111     if (value == 0) {
112         return sizeof(T) * 8; // 8: Each byte has 8 bits
113     }
114     if (sizeof(T) == sizeof(uint64_t)) {
115         return __builtin_ctzll(static_cast<uint64_t>(value));
116     }
117     return __builtin_ctz(static_cast<uint32_t>(value));
118 }
119 
CountTrailingZeros32(uint32_t value)120 inline constexpr unsigned CountTrailingZeros32(uint32_t value)
121 {
122     return CountTrailingZeros(value);
123 }
124 
CountTrailingZeros64(uint64_t value)125 inline constexpr unsigned CountTrailingZeros64(uint64_t value)
126 {
127     return CountTrailingZeros(value);
128 }
129 
CountTrailingOnes32(uint32_t value)130 inline constexpr unsigned CountTrailingOnes32(uint32_t value)
131 {
132     return CountTrailingZeros(~value);
133 }
134 
CountTrailingOnes64(uint64_t value)135 inline constexpr unsigned CountTrailingOnes64(uint64_t value)
136 {
137     return CountTrailingZeros(~value);
138 }
139 
140 /// isMask_64 - This function returns true if the argument is a non-empty
141 /// sequence of ones starting at the least significant bit with the remainder
142 /// zero (64 bit version).
IsMask_64(uint64_t Value)143 constexpr inline bool IsMask_64(uint64_t Value)
144 {
145     return Value && ((Value + 1) & Value) == 0;
146 }
147 
148 /// isShiftedMask_64 - This function returns true if the argument contains a
149 /// non-empty sequence of ones with the remainder zero (64 bit version.)
IsShiftedMask_64(uint64_t Value)150 constexpr inline bool IsShiftedMask_64(uint64_t Value)
151 {
152     return Value && IsMask_64((Value - 1) | Value);
153 }
154 
155 template <typename T>
RoundUp(T x,size_t n)156 constexpr T RoundUp(T x, size_t n)
157 {
158     static_assert(std::is_integral<T>::value, "T must be integral");
159     return (static_cast<size_t>(x) + n - 1U) & (-n);
160 }
161 
162 template <class To, class From>
bit_cast(const From & src)163 inline To bit_cast(const From &src) noexcept  // NOLINT(readability-identifier-naming)
164 {
165     static_assert(sizeof(To) == sizeof(From), "size of the types must be equal");
166     // The use of security functions 'memcpy_s' here will have a greater impact on performance
167     Data<From, To> data;
168     data.src = src;
169     return data.dst;
170 }
171 
172 template <typename T>
BitNumbers()173 inline constexpr uint32_t BitNumbers()
174 {
175     constexpr int BIT_NUMBER_OF_CHAR = 8;
176     return sizeof(T) * BIT_NUMBER_OF_CHAR;
177 }
178 }  // panda::ecmascript::base
179 #endif
180