• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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