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