Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2020 The Bitcoin Core developers
3 : // Distributed under the MIT software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include <util/strencodings.h>
7 : #include <util/string.h>
8 :
9 : #include <tinyformat.h>
10 :
11 : #include <algorithm>
12 : #include <cstdlib>
13 : #include <cstring>
14 : #include <errno.h>
15 : #include <limits>
16 :
17 1150 : static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
18 :
19 1150 : static const std::string SAFE_CHARS[] =
20 1150 : {
21 1150 : CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
22 1150 : CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
23 1150 : CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
24 5750 : CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI
25 : };
26 :
27 341379 : std::string SanitizeString(const std::string& str, int rule)
28 : {
29 341379 : std::string strResult;
30 2692058 : for (std::string::size_type i = 0; i < str.size(); i++)
31 : {
32 2350676 : if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
33 2350617 : strResult.push_back(str[i]);
34 : }
35 : return strResult;
36 341379 : }
37 :
38 : const signed char p_util_hexdigit[256] =
39 : { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
40 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
41 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
42 : 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
43 : -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
44 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
45 : -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
46 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
47 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
48 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
49 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
50 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
51 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
52 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
53 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
54 : -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
55 :
56 175709990 : signed char HexDigit(char c)
57 : {
58 175709990 : return p_util_hexdigit[(unsigned char)c];
59 : }
60 :
61 36518 : bool IsHex(const std::string& str)
62 : {
63 83224940 : for(std::string::const_iterator it(str.begin()); it != str.end(); ++it)
64 : {
65 83188422 : if (HexDigit(*it) < 0)
66 327 : return false;
67 : }
68 36191 : return (str.size() > 0) && (str.size()%2 == 0);
69 36518 : }
70 :
71 41 : bool IsHexNumber(const std::string& str)
72 : {
73 : size_t starting_location = 0;
74 41 : if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
75 : starting_location = 2;
76 21 : }
77 279 : for (const char c : str.substr(starting_location)) {
78 238 : if (HexDigit(c) < 0) return false;
79 222 : }
80 : // Return false for empty string or "0x".
81 25 : return (str.size() > starting_location);
82 41 : }
83 :
84 22965 : std::vector<unsigned char> ParseHex(const char* psz)
85 : {
86 : // convert hex dump to vector
87 22965 : std::vector<unsigned char> vch;
88 22965 : while (true)
89 : {
90 41454853 : while (IsSpace(*psz))
91 44 : psz++;
92 41454809 : signed char c = HexDigit(*psz++);
93 41454809 : if (c == (signed char)-1)
94 22963 : break;
95 41431846 : unsigned char n = (c << 4);
96 41431846 : c = HexDigit(*psz++);
97 41431846 : if (c == (signed char)-1)
98 2 : break;
99 41431844 : n |= c;
100 41431844 : vch.push_back(n);
101 41431846 : }
102 : return vch;
103 22965 : }
104 :
105 18383 : std::vector<unsigned char> ParseHex(const std::string& str)
106 : {
107 18383 : return ParseHex(str.c_str());
108 : }
109 :
110 245020 : void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
111 245020 : size_t colon = in.find_last_of(':');
112 : // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
113 245020 : bool fHaveColon = colon != in.npos;
114 245020 : bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
115 245020 : bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
116 245020 : if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
117 278 : int32_t n;
118 278 : if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
119 278 : in = in.substr(0, colon);
120 278 : portOut = n;
121 278 : }
122 278 : }
123 245020 : if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
124 11 : hostOut = in.substr(1, in.size()-2);
125 : else
126 245009 : hostOut = in;
127 245020 : }
128 :
129 742 : std::string EncodeBase64(Span<const unsigned char> input)
130 : {
131 : static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
132 :
133 742 : std::string str;
134 742 : str.reserve(((input.size() + 2) / 3) * 4);
135 419163 : ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, input.begin(), input.end());
136 1069 : while (str.size() % 4) str += '=';
137 : return str;
138 742 : }
139 :
140 632 : std::string EncodeBase64(const std::string& str)
141 : {
142 632 : return EncodeBase64(MakeUCharSpan(str));
143 : }
144 :
145 79397 : std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
146 : {
147 : static const int decode64_table[256] =
148 : {
149 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
150 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
151 : -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
152 : -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
153 : 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
154 : 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
155 : 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
156 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
157 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
158 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
159 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
160 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
161 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
162 : };
163 :
164 : const char* e = p;
165 79397 : std::vector<uint8_t> val;
166 79397 : val.reserve(strlen(p));
167 8381689 : while (*p != 0) {
168 8302537 : int x = decode64_table[(unsigned char)*p];
169 8302537 : if (x == -1) break;
170 8302292 : val.push_back(x);
171 8302292 : ++p;
172 8302292 : }
173 :
174 79397 : std::vector<unsigned char> ret;
175 79397 : ret.reserve((val.size() * 3) / 4);
176 6306023 : bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
177 :
178 : const char* q = p;
179 79765 : while (valid && *p != 0) {
180 371 : if (*p != '=') {
181 : valid = false;
182 3 : break;
183 : }
184 368 : ++p;
185 : }
186 79397 : valid = valid && (p - e) % 4 == 0 && p - q < 4;
187 79397 : if (pf_invalid) *pf_invalid = !valid;
188 :
189 : return ret;
190 79397 : }
191 :
192 79381 : std::string DecodeBase64(const std::string& str, bool* pf_invalid)
193 : {
194 79381 : if (!ValidAsCString(str)) {
195 1 : if (pf_invalid) {
196 1 : *pf_invalid = true;
197 1 : }
198 1 : return {};
199 : }
200 79380 : std::vector<unsigned char> vchRet = DecodeBase64(str.c_str(), pf_invalid);
201 79380 : return std::string((const char*)vchRet.data(), vchRet.size());
202 79381 : }
203 :
204 13 : std::string EncodeBase32(Span<const unsigned char> input)
205 : {
206 : static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
207 :
208 13 : std::string str;
209 13 : str.reserve(((input.size() + 4) / 5) * 8);
210 145 : ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, input.begin(), input.end());
211 33 : while (str.size() % 8) str += '=';
212 : return str;
213 13 : }
214 :
215 7 : std::string EncodeBase32(const std::string& str)
216 : {
217 7 : return EncodeBase32(MakeUCharSpan(str));
218 : }
219 :
220 17 : std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
221 : {
222 : static const int decode32_table[256] =
223 : {
224 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
225 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
227 : -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
228 : 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
229 : 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
230 : 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
231 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
232 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
233 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
234 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
235 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
236 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
237 : };
238 :
239 : const char* e = p;
240 17 : std::vector<uint8_t> val;
241 17 : val.reserve(strlen(p));
242 195 : while (*p != 0) {
243 183 : int x = decode32_table[(unsigned char)*p];
244 183 : if (x == -1) break;
245 178 : val.push_back(x);
246 178 : ++p;
247 178 : }
248 :
249 17 : std::vector<unsigned char> ret;
250 17 : ret.reserve((val.size() * 5) / 8);
251 126 : bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
252 :
253 : const char* q = p;
254 37 : while (valid && *p != 0) {
255 20 : if (*p != '=') {
256 : valid = false;
257 0 : break;
258 : }
259 20 : ++p;
260 : }
261 17 : valid = valid && (p - e) % 8 == 0 && p - q < 8;
262 17 : if (pf_invalid) *pf_invalid = !valid;
263 :
264 : return ret;
265 17 : }
266 :
267 11 : std::string DecodeBase32(const std::string& str, bool* pf_invalid)
268 : {
269 11 : if (!ValidAsCString(str)) {
270 1 : if (pf_invalid) {
271 1 : *pf_invalid = true;
272 1 : }
273 1 : return {};
274 : }
275 10 : std::vector<unsigned char> vchRet = DecodeBase32(str.c_str(), pf_invalid);
276 10 : return std::string((const char*)vchRet.data(), vchRet.size());
277 11 : }
278 :
279 4340 : NODISCARD static bool ParsePrechecks(const std::string& str)
280 : {
281 4340 : if (str.empty()) // No empty string allowed
282 16 : return false;
283 4324 : if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size()-1]))) // No padding allowed
284 24 : return false;
285 4300 : if (!ValidAsCString(str)) // No embedded NUL characters allowed
286 10 : return false;
287 4290 : return true;
288 4340 : }
289 :
290 368 : bool ParseInt32(const std::string& str, int32_t *out)
291 : {
292 368 : if (!ParsePrechecks(str))
293 9 : return false;
294 359 : char *endp = nullptr;
295 359 : errno = 0; // strtol will not set errno if valid
296 359 : long int n = strtol(str.c_str(), &endp, 10);
297 359 : if(out) *out = (int32_t)n;
298 : // Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow
299 : // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
300 : // platforms the size of these types may be different.
301 359 : return endp && *endp == 0 && !errno &&
302 346 : n >= std::numeric_limits<int32_t>::min() &&
303 344 : n <= std::numeric_limits<int32_t>::max();
304 368 : }
305 :
306 105 : bool ParseInt64(const std::string& str, int64_t *out)
307 : {
308 105 : if (!ParsePrechecks(str))
309 8 : return false;
310 97 : char *endp = nullptr;
311 97 : errno = 0; // strtoll will not set errno if valid
312 97 : long long int n = strtoll(str.c_str(), &endp, 10);
313 97 : if(out) *out = (int64_t)n;
314 : // Note that strtoll returns a *long long int*, so even if strtol doesn't report an over/underflow
315 : // we still have to check that the returned value is within the range of an *int64_t*.
316 97 : return endp && *endp == 0 && !errno &&
317 77 : n >= std::numeric_limits<int64_t>::min() &&
318 77 : n <= std::numeric_limits<int64_t>::max();
319 105 : }
320 :
321 83 : bool ParseUInt8(const std::string& str, uint8_t *out)
322 : {
323 83 : uint32_t u32;
324 83 : if (!ParseUInt32(str, &u32) || u32 > std::numeric_limits<uint8_t>::max()) {
325 46 : return false;
326 : }
327 37 : if (out != nullptr) {
328 37 : *out = static_cast<uint8_t>(u32);
329 37 : }
330 37 : return true;
331 83 : }
332 :
333 3787 : bool ParseUInt32(const std::string& str, uint32_t *out)
334 : {
335 3787 : if (!ParsePrechecks(str))
336 15 : return false;
337 3772 : if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoul accepts these by default if they fit in the range
338 8 : return false;
339 3764 : char *endp = nullptr;
340 3764 : errno = 0; // strtoul will not set errno if valid
341 3764 : unsigned long int n = strtoul(str.c_str(), &endp, 10);
342 3764 : if(out) *out = (uint32_t)n;
343 : // Note that strtoul returns a *unsigned long int*, so even if it doesn't report an over/underflow
344 : // we still have to check that the returned value is within the range of an *uint32_t*. On 64-bit
345 : // platforms the size of these types may be different.
346 3764 : return endp && *endp == 0 && !errno &&
347 3706 : n <= std::numeric_limits<uint32_t>::max();
348 3787 : }
349 :
350 44 : bool ParseUInt64(const std::string& str, uint64_t *out)
351 : {
352 44 : if (!ParsePrechecks(str))
353 10 : return false;
354 34 : if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoull accepts these by default if they fit in the range
355 10 : return false;
356 24 : char *endp = nullptr;
357 24 : errno = 0; // strtoull will not set errno if valid
358 24 : unsigned long long int n = strtoull(str.c_str(), &endp, 10);
359 24 : if(out) *out = (uint64_t)n;
360 : // Note that strtoull returns a *unsigned long long int*, so even if it doesn't report an over/underflow
361 : // we still have to check that the returned value is within the range of an *uint64_t*.
362 24 : return endp && *endp == 0 && !errno &&
363 16 : n <= std::numeric_limits<uint64_t>::max();
364 44 : }
365 :
366 :
367 36 : bool ParseDouble(const std::string& str, double *out)
368 : {
369 36 : if (!ParsePrechecks(str))
370 8 : return false;
371 28 : if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
372 2 : return false;
373 26 : std::istringstream text(str);
374 26 : text.imbue(std::locale::classic());
375 26 : double result;
376 26 : text >> result;
377 26 : if(out) *out = result;
378 26 : return text.eof() && !text.fail();
379 36 : }
380 :
381 153 : std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
382 : {
383 153 : std::stringstream out;
384 : size_t ptr = 0;
385 : size_t indented = 0;
386 505 : while (ptr < in.size())
387 : {
388 354 : size_t lineend = in.find_first_of('\n', ptr);
389 354 : if (lineend == std::string::npos) {
390 329 : lineend = in.size();
391 329 : }
392 354 : const size_t linelen = lineend - ptr;
393 354 : const size_t rem_width = width - indented;
394 354 : if (linelen <= rem_width) {
395 167 : out << in.substr(ptr, linelen + 1);
396 167 : ptr = lineend + 1;
397 : indented = 0;
398 167 : } else {
399 187 : size_t finalspace = in.find_last_of(" \n", ptr + rem_width);
400 187 : if (finalspace == std::string::npos || finalspace < ptr) {
401 : // No place to break; just include the entire word and move on
402 8 : finalspace = in.find_first_of("\n ", ptr);
403 8 : if (finalspace == std::string::npos) {
404 : // End of the string, just add it and break
405 2 : out << in.substr(ptr);
406 2 : break;
407 : }
408 : }
409 185 : out << in.substr(ptr, finalspace - ptr) << "\n";
410 185 : if (in[finalspace] == '\n') {
411 : indented = 0;
412 185 : } else if (indent) {
413 165 : out << std::string(indent, ' ');
414 : indented = indent;
415 165 : }
416 185 : ptr = finalspace + 1;
417 185 : }
418 352 : }
419 153 : return out.str();
420 153 : }
421 :
422 48813 : int64_t atoi64(const std::string& str)
423 : {
424 : #ifdef _MSC_VER
425 : return _atoi64(str.c_str());
426 : #else
427 48813 : return strtoll(str.c_str(), nullptr, 10);
428 : #endif
429 : }
430 :
431 67521 : int atoi(const std::string& str)
432 : {
433 67521 : return atoi(str.c_str());
434 : }
435 :
436 : /** Upper bound for mantissa.
437 : * 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer.
438 : * Larger integers cannot consist of arbitrary combinations of 0-9:
439 : *
440 : * 999999999999999999 1^18-1
441 : * 9223372036854775807 (1<<63)-1 (max int64_t)
442 : * 9999999999999999999 1^19-1 (would overflow)
443 : */
444 : static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL;
445 :
446 : /** Helper function for ParseFixedPoint */
447 68435 : static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros)
448 : {
449 68435 : if(ch == '0')
450 18613 : ++mantissa_tzeros;
451 : else {
452 112658 : for (int i=0; i<=mantissa_tzeros; ++i) {
453 62857 : if (mantissa > (UPPER_BOUND / 10LL))
454 21 : return false; /* overflow */
455 62836 : mantissa *= 10;
456 : }
457 49801 : mantissa += ch - '0';
458 49801 : mantissa_tzeros = 0;
459 : }
460 68414 : return true;
461 68435 : }
462 :
463 19034 : bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
464 : {
465 19034 : int64_t mantissa = 0;
466 18994 : int64_t exponent = 0;
467 19034 : int mantissa_tzeros = 0;
468 : bool mantissa_sign = false;
469 18994 : bool exponent_sign = false;
470 : int ptr = 0;
471 19034 : int end = val.size();
472 18998 : int point_ofs = 0;
473 :
474 19034 : if (ptr < end && val[ptr] == '-') {
475 : mantissa_sign = true;
476 : ++ptr;
477 44 : }
478 19034 : if (ptr < end)
479 : {
480 19030 : if (val[ptr] == '0') {
481 : /* pass single 0 */
482 15019 : ++ptr;
483 19030 : } else if (val[ptr] >= '1' && val[ptr] <= '9') {
484 9963 : while (ptr < end && IsDigit(val[ptr])) {
485 5961 : if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
486 0 : return false; /* overflow */
487 5961 : ++ptr;
488 : }
489 9 : } else return false; /* missing expected digit */
490 4 : } else return false; /* empty string or loose '-' */
491 19021 : if (ptr < end && val[ptr] == '.')
492 : {
493 11293 : ++ptr;
494 11293 : if (ptr < end && IsDigit(val[ptr]))
495 : {
496 73744 : while (ptr < end && IsDigit(val[ptr])) {
497 62474 : if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
498 21 : return false; /* overflow */
499 62453 : ++ptr;
500 62453 : ++point_ofs;
501 : }
502 2 : } else return false; /* missing expected digit */
503 : }
504 18998 : if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
505 : {
506 2036 : ++ptr;
507 2036 : if (ptr < end && val[ptr] == '+')
508 4 : ++ptr;
509 2032 : else if (ptr < end && val[ptr] == '-') {
510 : exponent_sign = true;
511 2026 : ++ptr;
512 2026 : }
513 2036 : if (ptr < end && IsDigit(val[ptr])) {
514 6082 : while (ptr < end && IsDigit(val[ptr])) {
515 4050 : if (exponent > (UPPER_BOUND / 10LL))
516 0 : return false; /* overflow */
517 4050 : exponent = exponent * 10 + val[ptr] - '0';
518 4050 : ++ptr;
519 : }
520 4 : } else return false; /* missing expected digit */
521 : }
522 18994 : if (ptr != end)
523 8 : return false; /* trailing garbage */
524 :
525 : /* finalize exponent */
526 18986 : if (exponent_sign)
527 2024 : exponent = -exponent;
528 18986 : exponent = exponent - point_ofs + mantissa_tzeros;
529 :
530 : /* finalize mantissa */
531 18986 : if (mantissa_sign)
532 24 : mantissa = -mantissa;
533 :
534 : /* convert to one 64-bit fixed-point value */
535 18986 : exponent += decimals;
536 18986 : if (exponent < 0)
537 9 : return false; /* cannot represent values smaller than 10^-decimals */
538 18977 : if (exponent >= 18)
539 6 : return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
540 :
541 104050 : for (int i=0; i < exponent; ++i) {
542 85080 : if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL))
543 1 : return false; /* overflow */
544 85079 : mantissa *= 10;
545 : }
546 18970 : if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND)
547 0 : return false; /* overflow */
548 :
549 18970 : if (amount_out)
550 18970 : *amount_out = mantissa;
551 :
552 18970 : return true;
553 19034 : }
554 :
555 15 : std::string ToLower(const std::string& str)
556 : {
557 15 : std::string r;
558 60 : for (auto ch : str) r += ToLower((unsigned char)ch);
559 : return r;
560 15 : }
561 :
562 158 : std::string ToUpper(const std::string& str)
563 : {
564 158 : std::string r;
565 1290 : for (auto ch : str) r += ToUpper((unsigned char)ch);
566 : return r;
567 158 : }
568 :
569 30 : std::string Capitalize(std::string str)
570 : {
571 30 : if (str.empty()) return str;
572 28 : str[0] = ToUpper(str.front());
573 28 : return str;
574 30 : }
575 :
576 6926612 : std::string HexStr(const Span<const uint8_t> s)
577 : {
578 6926612 : std::string rv;
579 : static constexpr char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
580 : '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
581 6926612 : rv.reserve(s.size() * 2);
582 262943029 : for (uint8_t v: s) {
583 256016522 : rv.push_back(hexmap[v >> 4]);
584 256016414 : rv.push_back(hexmap[v & 15]);
585 : }
586 : return rv;
587 6926636 : }
|