• 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 template <typename T>
ReadBuffer(void ** buffer,size_t offset)33 inline T ReadBuffer(void **buffer, size_t offset)
34 {
35     T result = *(reinterpret_cast<T *>(*buffer));
36     *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + offset);
37     return result;
38 }
39 
40 template <typename T>
ReadBuffer(void ** buffer)41 inline T ReadBuffer(void **buffer)
42 {
43     T result = *(reinterpret_cast<T *>(*buffer));
44     *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + result.offset_);
45     return result;
46 }
47 
ReadBuffer(void ** buffer)48 inline char *ReadBuffer(void **buffer)
49 {
50     auto result = reinterpret_cast<char *>(*buffer);
51     *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + strlen(result) + 1);
52     return result;
53 }
54 
55 template <typename T>
ReadBufferInSize(void ** buffer)56 inline T *ReadBufferInSize(void **buffer)
57 {
58     T *result = reinterpret_cast<T *>(*buffer);
59     *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + result->Size());
60     return result;
61 }
62 
63 template <typename T>
CountLeadingZeros(T value)64 inline constexpr uint32_t CountLeadingZeros(T value)
65 {
66     constexpr size_t RADIX = 2;
67     static_assert(std::is_integral<T>::value, "T must be integral");
68     static_assert(std::is_unsigned<T>::value, "T must be unsigned");
69     static_assert(std::numeric_limits<T>::radix == RADIX, "Unexpected radix!");
70     static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)");
71     if (value == 0) {
72         return sizeof(T) * 8; // 8 : 8 bits
73     }
74     if (sizeof(T) == sizeof(uint64_t)) {
75         return __builtin_clzll(static_cast<uint64_t>(value));
76     }
77     // 32 : 32 mean the bits of type T is less than 32
78     return __builtin_clz(static_cast<uint32_t>(value)) - (32 - std::numeric_limits<T>::digits);
79 }
80 
CountLeadingZeros32(uint32_t value)81 inline constexpr uint32_t CountLeadingZeros32(uint32_t value)
82 {
83     return CountLeadingZeros(value);
84 }
85 
CountLeadingZeros64(uint64_t value)86 inline constexpr uint32_t CountLeadingZeros64(uint64_t value)
87 {
88     return CountLeadingZeros(value);
89 }
90 
CountLeadingOnes32(uint32_t value)91 inline constexpr uint32_t CountLeadingOnes32(uint32_t value)
92 {
93     return CountLeadingZeros(~value);
94 }
95 
CountLeadingOnes64(uint64_t value)96 inline constexpr uint32_t CountLeadingOnes64(uint64_t value)
97 {
98     return CountLeadingZeros(~value);
99 }
100 
101 template <typename T>
CountTrailingZeros(T value)102 inline constexpr uint32_t CountTrailingZeros(T value)
103 {
104     constexpr size_t RADIX = 2;
105     static_assert(std::is_integral<T>::value, "T must be integral");
106     static_assert(std::is_unsigned<T>::value, "T must be unsigned");
107     static_assert(std::numeric_limits<T>::radix == RADIX, "Unexpected radix!");
108     static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)");
109     if (value == 0) {
110         return sizeof(T) * 8; // 8 : 8 bits
111     }
112     if (sizeof(T) == sizeof(uint64_t)) {
113         return __builtin_ctzll(static_cast<uint64_t>(value));
114     }
115     return __builtin_ctz(static_cast<uint32_t>(value));
116 }
117 
CountTrailingZeros32(uint32_t value)118 inline constexpr unsigned CountTrailingZeros32(uint32_t value)
119 {
120     return CountTrailingZeros(value);
121 }
122 
CountTrailingZeros64(uint64_t value)123 inline constexpr unsigned CountTrailingZeros64(uint64_t value)
124 {
125     return CountTrailingZeros(value);
126 }
127 
CountTrailingOnes32(uint32_t value)128 inline constexpr unsigned CountTrailingOnes32(uint32_t value)
129 {
130     return CountTrailingZeros(~value);
131 }
132 
CountTrailingOnes64(uint64_t value)133 inline constexpr unsigned CountTrailingOnes64(uint64_t value)
134 {
135     return CountTrailingZeros(~value);
136 }
137 
138 /// isMask_64 - This function returns true if the argument is a non-empty
139 /// sequence of ones starting at the least significant bit with the remainder
140 /// zero (64 bit version).
IsMask_64(uint64_t Value)141 constexpr inline bool IsMask_64(uint64_t Value)
142 {
143     return Value && ((Value + 1) & Value) == 0;
144 }
145 
146 /// isShiftedMask_64 - This function returns true if the argument contains a
147 /// non-empty sequence of ones with the remainder zero (64 bit version.)
IsShiftedMask_64(uint64_t Value)148 constexpr inline bool IsShiftedMask_64(uint64_t Value)
149 {
150     return Value && IsMask_64((Value - 1) | Value);
151 }
152 
153 template <typename T>
RoundUp(T x,size_t n)154 constexpr T RoundUp(T x, size_t n)
155 {
156     static_assert(std::is_integral<T>::value, "T must be integral");
157     return (static_cast<size_t>(x) + n - 1U) & (-n);
158 }
159 
160 template <class To, class From>
bit_cast(const From & src)161 inline To bit_cast(const From &src) noexcept  // NOLINT(readability-identifier-naming)
162 {
163     static_assert(sizeof(To) == sizeof(From), "size of the types must be equal");
164     // The use of security functions 'memcpy_s' here will have a greater impact on performance
165     Data<From, To> data;
166     data.src = src;
167     return data.dst;
168 }
169 
170 template <typename T>
BitNumbers()171 inline constexpr uint32_t BitNumbers()
172 {
173     constexpr int BIT_NUMBER_OF_CHAR = 8;
174     return sizeof(T) * BIT_NUMBER_OF_CHAR;
175 }
176 }  // panda::ecmascript::base
177 #endif
178