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