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