1 /*
2 * Copyright (c) 2021-2024 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 PANDA_ASSEMBLER_UTILS_NUMBERS_UTILS_H
17 #define PANDA_ASSEMBLER_UTILS_NUMBERS_UTILS_H
18
19 namespace ark::pandasm {
20
21 constexpr size_t HEX_BASE = 16;
22
23 constexpr size_t DEC_BASE = 10;
24
25 constexpr size_t OCT_BASE = 8;
26
27 constexpr size_t BIN_BASE = 2;
28
29 constexpr size_t MAX_DWORD = 65536;
30
ValidateXToken(std::string_view token,size_t shift)31 inline bool ValidateXToken(std::string_view token, size_t shift)
32 {
33 token.remove_prefix(shift);
34
35 for (auto i : token) {
36 if (!((i >= '0' && i <= '9') || (i >= 'A' && i <= 'F') || (i >= 'a' && i <= 'f'))) {
37 return false;
38 }
39 }
40
41 return true;
42 }
43
ValidateBToken(std::string_view token,size_t shift)44 inline bool ValidateBToken(std::string_view token, size_t shift)
45 {
46 token.remove_prefix(shift);
47 if (token.empty()) {
48 return false;
49 }
50 for (auto i : token) {
51 if (!(i == '0' || i == '1')) {
52 return false;
53 }
54 }
55
56 return true;
57 }
58
ValidateZeroToTenToken(std::string_view token)59 inline bool ValidateZeroToTenToken(std::string_view token)
60 {
61 token.remove_prefix(1);
62
63 for (auto i : token) {
64 if (!(i >= '0' && i <= '7')) {
65 return false;
66 }
67 }
68
69 return true;
70 }
71
ValidateInteger(std::string_view p)72 inline bool ValidateInteger(std::string_view p)
73 {
74 constexpr size_t GENERAL_SHIFT = 2;
75
76 std::string_view token = p;
77
78 if (token.back() == '-' || token.back() == '+' || token.back() == 'x' || token == ".") {
79 return false;
80 }
81
82 if (token[0] == '-' || token[0] == '+') {
83 token.remove_prefix(1);
84 }
85
86 if (token[0] == '0' && token.size() > 1 && token.find('.') == std::string::npos) {
87 if (token[1] == 'x') {
88 return ValidateXToken(token, GENERAL_SHIFT);
89 }
90
91 if (token[1] == 'b') {
92 return ValidateBToken(token, GENERAL_SHIFT);
93 }
94
95 if (token[1] >= '0' && token[1] <= '9' && token.find('e') == std::string::npos) {
96 return ValidateZeroToTenToken(token);
97 }
98 }
99
100 for (auto i : token) {
101 if (!(i >= '0' && i <= '9')) {
102 return false;
103 }
104 }
105
106 return true;
107 }
108
IntegerNumber(std::string_view p)109 inline int64_t IntegerNumber(std::string_view p)
110 {
111 constexpr size_t GENERAL_SHIFT = 2;
112
113 // expects a valid number
114 if (p.size() == 1) {
115 return p[0] - '0';
116 }
117
118 size_t minusShift = 0;
119 if (p[0] == '-') {
120 minusShift++;
121 }
122
123 if (p.size() == GENERAL_SHIFT && minusShift != 0) {
124 return -1 * (p[1] - '0');
125 }
126
127 if (p[minusShift + 1] == 'b') {
128 p.remove_prefix(GENERAL_SHIFT + minusShift);
129 return std::strtoull(p.data(), nullptr, BIN_BASE) * (minusShift == 0 ? 1 : -1);
130 }
131
132 if (p[minusShift + 1] == 'x') {
133 return std::strtoull(p.data(), nullptr, HEX_BASE);
134 }
135
136 if (p[minusShift] == '0') {
137 return std::strtoull(p.data(), nullptr, OCT_BASE);
138 }
139
140 return std::strtoull(p.data(), nullptr, DEC_BASE);
141 }
142
ValidateFloat(std::string_view p)143 inline bool ValidateFloat(std::string_view p)
144 {
145 std::string_view token = p;
146
147 if (ValidateInteger(token)) {
148 return true;
149 }
150
151 if (token[0] == '-' || token[0] == '+') {
152 token.remove_prefix(1);
153 }
154
155 bool dot = false;
156 bool exp = false;
157 bool nowexp = false;
158
159 for (auto i : token) {
160 if (nowexp && (i == '-' || i == '+')) {
161 nowexp = false;
162 continue;
163 }
164
165 if (nowexp) {
166 nowexp = false;
167 }
168
169 if (i == '.' && !exp && !dot) {
170 dot = true;
171 } else if (!exp && i == 'e') {
172 nowexp = true;
173 exp = true;
174 } else if (!(i >= '0' && i <= '9')) {
175 return false;
176 }
177 }
178
179 return !nowexp;
180 }
181
FloatNumber(std::string_view p,bool is64bit)182 inline double FloatNumber(std::string_view p, bool is64bit)
183 {
184 constexpr size_t GENERAL_SHIFT = 2;
185 // expects a valid number
186 if (p.size() > GENERAL_SHIFT && p.substr(0, GENERAL_SHIFT) == "0x") { // hex literal
187 char *end = nullptr;
188 if (is64bit) {
189 return bit_cast<double>(strtoull(p.data(), &end, 0));
190 }
191 return bit_cast<float>(static_cast<uint32_t>(strtoull(p.data(), &end, 0)));
192 }
193 return std::strtold(std::string(p.data(), p.length()).c_str(), nullptr);
194 }
195
ToNumber(std::string_view p)196 inline size_t ToNumber(std::string_view p)
197 {
198 size_t sum = 0;
199
200 for (char i : p) {
201 if (isdigit(i) != 0) {
202 sum = sum * DEC_BASE + static_cast<size_t>(i - '0');
203 } else {
204 return MAX_DWORD;
205 }
206 }
207
208 return sum;
209 }
210
211 } // namespace ark::pandasm
212
213 #endif // PANDA_ASSEMBLER_UTILS_NUMBERS_UTILS_H
214