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