Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin developers
3 : // Copyright (c) 2016-2022 The PIVX Core developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 :
7 : #include "utilstrencodings.h"
8 : #include "util/string.h"
9 :
10 : #include "tinyformat.h"
11 :
12 : #include <algorithm>
13 : #include <cstdlib>
14 : #include <cstring>
15 : #include <errno.h>
16 : #include <limits>
17 : #include <regex>
18 :
19 :
20 :
21 : static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
22 :
23 : static const std::string SAFE_CHARS[] =
24 : {
25 : CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
26 : CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
27 : CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
28 : };
29 :
30 995764 : std::string SanitizeString(const std::string& str, int rule)
31 : {
32 995764 : std::string strResult;
33 8691110 : for (std::string::size_type i = 0; i < str.size(); i++)
34 : {
35 7695350 : if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
36 7695330 : strResult.push_back(str[i]);
37 : }
38 995764 : return strResult;
39 : }
40 :
41 50 : bool validateURL(const std::string& strURL)
42 : {
43 50 : std::string strErr;
44 50 : return validateURL(strURL, strErr);
45 : }
46 :
47 99 : bool validateURL(const std::string& strURL, std::string& strErr, unsigned int maxSize)
48 : {
49 : // Check URL size
50 99 : if (strURL.size() > maxSize) {
51 1 : strErr = strprintf("Invalid URL: %d exceeds limit of %d characters.", strURL.size(), maxSize);
52 1 : return false;
53 : }
54 :
55 : // Validate URL
56 98 : std::regex url_regex(R"(^(https?)://[^\s/$.?#][^\s]*[^\s/.]\.[^\s/.][^\s]*[^\s.]$)");
57 98 : if (!std::regex_match(strURL, url_regex)) {
58 98 : strErr = "Invalid URL";
59 : return false;
60 : }
61 :
62 : return true;
63 : }
64 :
65 : const signed char p_util_hexdigit[256] =
66 : {
67 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
68 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
69 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
70 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
71 : -1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1,
72 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
73 : -1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
76 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
77 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
78 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
79 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
80 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
81 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
82 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
83 : };
84 :
85 353157770 : signed char HexDigit(char c)
86 : {
87 353157770 : return p_util_hexdigit[(unsigned char)c];
88 : }
89 :
90 220275 : bool IsHex(const std::string& str)
91 : {
92 163474409 : for (std::string::const_iterator it(str.begin()); it != str.end(); ++it) {
93 163253911 : if (HexDigit(*it) < 0)
94 11 : return false;
95 : }
96 220264 : return (str.size() > 0) && (str.size() % 2 == 0);
97 : }
98 :
99 216487 : std::vector<unsigned char> ParseHex(const char* psz)
100 : {
101 : // convert hex dump to vector
102 216487 : std::vector<unsigned char> vch;
103 163618878 : while (true) {
104 81917832 : while (isspace(*psz))
105 8 : psz++;
106 81917824 : signed char c = HexDigit(*psz++);
107 81917824 : if (c == (signed char)-1)
108 : break;
109 81701346 : unsigned char n = (c << 4);
110 81701346 : c = HexDigit(*psz++);
111 81701346 : if (c == (signed char)-1)
112 : break;
113 81701346 : n |= c;
114 81701346 : vch.push_back(n);
115 81701346 : }
116 216487 : return vch;
117 : }
118 :
119 215305 : std::vector<unsigned char> ParseHex(const std::string& str)
120 : {
121 215305 : return ParseHex(str.c_str());
122 : }
123 :
124 35 : std::string EncodeBase64(Span<const unsigned char> input)
125 : {
126 35 : static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
127 :
128 35 : std::string str;
129 35 : str.reserve(((input.size() + 2) / 3) * 4);
130 2540 : ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, input.begin(), input.end());
131 66 : while (str.size() % 4) str += '=';
132 35 : return str;
133 : }
134 :
135 10 : std::string EncodeBase64(const std::string& str)
136 : {
137 10 : return EncodeBase64(MakeUCharSpan(str));
138 : }
139 :
140 298191 : std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
141 : {
142 298191 : static const int decode64_table[256] =
143 : {
144 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
145 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
146 : -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
147 : -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
148 : 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
149 : 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
150 : 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
151 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
152 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
153 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
154 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
155 : -1, -1, -1, -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
157 : };
158 :
159 298191 : const char* e = p;
160 298191 : std::vector<uint8_t> val;
161 298191 : val.reserve(strlen(p));
162 30115137 : while (*p != 0) {
163 29817034 : int x = decode64_table[(unsigned char)*p];
164 29817034 : if (x == -1) break;
165 29816930 : val.push_back(x);
166 29816930 : ++p;
167 : }
168 :
169 298191 : std::vector<unsigned char> ret;
170 298191 : ret.reserve((val.size() * 3) / 4);
171 22660928 : bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
172 :
173 298191 : const char* q = p;
174 298235 : while (valid && *p != 0) {
175 44 : if (*p != '=') {
176 : valid = false;
177 : break;
178 : }
179 44 : ++p;
180 : }
181 298191 : valid = valid && (p - e) % 4 == 0 && p - q < 4;
182 298191 : if (pfInvalid) *pfInvalid = !valid;
183 :
184 596381 : return ret;
185 : }
186 :
187 298173 : std::string DecodeBase64(const std::string& str)
188 : {
189 298173 : std::vector<unsigned char> vchRet = DecodeBase64(str.c_str());
190 894518 : return std::string((const char*)vchRet.data(), vchRet.size());
191 : }
192 :
193 25 : std::string EncodeBase32(Span<const unsigned char> input, bool pad)
194 : {
195 25 : static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
196 :
197 25 : std::string str;
198 25 : str.reserve(((input.size() + 4) / 5) * 8);
199 389 : ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, input.begin(), input.end());
200 25 : if (pad) {
201 37 : while (str.size() % 8) {
202 37 : str += '=';
203 : }
204 : }
205 25 : return str;
206 : }
207 :
208 14 : std::string EncodeBase32(const std::string& str, bool pad)
209 : {
210 14 : return EncodeBase32(MakeUCharSpan(str), pad);
211 : }
212 :
213 :
214 24 : std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
215 : {
216 24 : static const int decode32_table[256] =
217 : {
218 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
219 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
220 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
221 : -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
222 : 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
223 : 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
224 : 23, 24, 25, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
227 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
228 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
229 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
230 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
231 : };
232 :
233 24 : const char* e = p;
234 24 : std::vector<uint8_t> val;
235 24 : val.reserve(strlen(p));
236 510 : while (*p != 0) {
237 492 : int x = decode32_table[(unsigned char)*p];
238 492 : if (x == -1) break;
239 486 : val.push_back(x);
240 486 : ++p;
241 : }
242 :
243 24 : std::vector<unsigned char> ret;
244 24 : ret.reserve((val.size() * 5) / 8);
245 326 : bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
246 :
247 24 : const char* q = p;
248 44 : while (valid && *p != 0) {
249 20 : if (*p != '=') {
250 : valid = false;
251 : break;
252 : }
253 20 : ++p;
254 : }
255 24 : valid = valid && (p - e) % 8 == 0 && p - q < 8;
256 24 : if (pfInvalid) *pfInvalid = !valid;
257 :
258 47 : return ret;
259 : }
260 :
261 7 : std::string DecodeBase32(const std::string& str)
262 : {
263 7 : std::vector<unsigned char> vchRet = DecodeBase32(str.c_str());
264 20 : return std::string((const char*)vchRet.data(), vchRet.size());
265 : }
266 :
267 2701 : static bool ParsePrechecks(const std::string& str)
268 : {
269 2701 : if (str.empty()) // No empty string allowed
270 : return false;
271 2695 : if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
272 : return false;
273 2683 : if (!ValidAsCString(str)) // No embedded NUL characters allowed
274 6 : return false;
275 : return true;
276 : }
277 :
278 2406 : bool ParseInt32(const std::string& str, int32_t *out)
279 : {
280 2406 : if (!ParsePrechecks(str))
281 : return false;
282 2398 : char *endp = nullptr;
283 2398 : errno = 0; // strtol will not set errno if valid
284 2398 : long int n = strtol(str.c_str(), &endp, 10);
285 2398 : if(out) *out = (int32_t)n;
286 : // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
287 : // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
288 : // platforms the size of these types may be different.
289 2398 : return endp && *endp == 0 && !errno &&
290 4784 : n >= std::numeric_limits<int32_t>::min() &&
291 : n <= std::numeric_limits<int32_t>::max();
292 : }
293 :
294 52 : bool ParseInt64(const std::string& str, int64_t *out)
295 : {
296 52 : if (!ParsePrechecks(str))
297 : return false;
298 44 : char *endp = nullptr;
299 44 : errno = 0; // strtoll will not set errno if valid
300 44 : long long int n = strtoll(str.c_str(), &endp, 10);
301 44 : if(out) *out = (int64_t)n;
302 : // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow
303 : // we still have to check that the returned value is within the range of an *int64_t*.
304 44 : return endp && *endp == 0 && !errno &&
305 : n >= std::numeric_limits<int64_t>::min() &&
306 : n <= std::numeric_limits<int64_t>::max();
307 : }
308 :
309 81 : bool ParseUInt8(const std::string& str, uint8_t *out)
310 : {
311 81 : uint32_t u32;
312 81 : if (!ParseUInt32(str, &u32) || u32 > std::numeric_limits<uint8_t>::max()) {
313 : return false;
314 : }
315 35 : if (out != nullptr) {
316 35 : *out = static_cast<uint8_t>(u32);
317 : }
318 : return true;
319 : }
320 :
321 146 : bool ParseUInt32(const std::string& str, uint32_t *out)
322 : {
323 146 : if (!ParsePrechecks(str))
324 : return false;
325 146 : if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoul accepts these by default if they fit in the range
326 : return false;
327 144 : char *endp = nullptr;
328 144 : errno = 0; // strtoul will not set errno if valid
329 144 : unsigned long int n = strtoul(str.c_str(), &endp, 10);
330 144 : if(out) *out = (uint32_t)n;
331 : // Note that strtoul returns a *unsigned long int*, so even if it doesn't report an over/underflow
332 : // we still have to check that the returned value is within the range of an *uint32_t*. On 64-bit
333 : // platforms the size of these types may be different.
334 144 : return endp && *endp == 0 && !errno &&
335 : n <= std::numeric_limits<uint32_t>::max();
336 : }
337 :
338 97 : bool ParseDouble(const std::string& str, double *out)
339 : {
340 97 : if (!ParsePrechecks(str))
341 : return false;
342 89 : if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
343 : return false;
344 174 : std::istringstream text(str);
345 87 : text.imbue(std::locale::classic());
346 87 : double result;
347 87 : text >> result;
348 87 : if(out) *out = result;
349 87 : return text.eof() && !text.fail();
350 : }
351 :
352 141 : std::string FormatParagraph(const std::string in, size_t width, size_t indent)
353 : {
354 141 : std::stringstream out;
355 : size_t col = 0;
356 : size_t ptr = 0;
357 1718 : while (ptr < in.size()) {
358 : // Find beginning of next word
359 1579 : ptr = in.find_first_not_of(' ', ptr);
360 1579 : if (ptr == std::string::npos)
361 : break;
362 : // Find end of next word
363 1577 : size_t endword = in.find_first_of(' ', ptr);
364 1577 : if (endword == std::string::npos)
365 137 : endword = in.size();
366 : // Add newline and indentation if this wraps over the allowed width
367 1577 : if (col > 0) {
368 1438 : if ((col + endword - ptr) > width) {
369 75 : out << '\n';
370 545 : for (size_t i = 0; i < indent; ++i)
371 470 : out << ' ';
372 : col = 0;
373 : } else
374 1363 : out << ' ';
375 : }
376 : // Append word
377 3154 : out << in.substr(ptr, endword - ptr);
378 1577 : col += endword - ptr + 1;
379 1577 : ptr = endword;
380 : }
381 141 : return out.str();
382 : }
383 :
384 336571 : std::string i64tostr(int64_t n)
385 : {
386 336571 : return strprintf("%d", n);
387 : }
388 :
389 0 : std::string itostr(int n)
390 : {
391 0 : return strprintf("%d", n);
392 : }
393 :
394 6763 : int64_t atoi64(const char* psz)
395 : {
396 : #ifdef _MSC_VER
397 : return _atoi64(psz);
398 : #else
399 6763 : return strtoll(psz, nullptr, 10);
400 : #endif
401 : }
402 :
403 24132 : int64_t atoi64(const std::string& str)
404 : {
405 : #ifdef _MSC_VER
406 : return _atoi64(str.c_str());
407 : #else
408 24132 : return strtoll(str.c_str(), nullptr, 10);
409 : #endif
410 : }
411 :
412 3774 : int atoi(const std::string& str)
413 : {
414 3774 : return atoi(str.c_str());
415 : }
416 :
417 :
418 : /** Upper bound for mantissa.
419 : * 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer.
420 : * Larger integers cannot consist of arbitrary combinations of 0-9:
421 : *
422 : * 999999999999999999 1^18-1
423 : * 9223372036854775807 (1<<63)-1 (max int64_t)
424 : * 9999999999999999999 1^19-1 (would overflow)
425 : */
426 : static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL;
427 :
428 : /** Helper function for ParseFixedPoint */
429 54443 : static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros)
430 : {
431 54443 : if(ch == '0')
432 9373 : ++mantissa_tzeros;
433 : else {
434 90785 : for (int i=0; i<=mantissa_tzeros; ++i) {
435 45736 : if (mantissa > (UPPER_BOUND / 10LL))
436 : return false; /* overflow */
437 45715 : mantissa *= 10;
438 : }
439 45049 : mantissa += ch - '0';
440 45049 : mantissa_tzeros = 0;
441 : }
442 : return true;
443 : }
444 :
445 8073 : bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
446 : {
447 8073 : int64_t mantissa = 0;
448 8073 : int64_t exponent = 0;
449 8073 : int mantissa_tzeros = 0;
450 8073 : bool mantissa_sign = false;
451 8073 : bool exponent_sign = false;
452 8073 : int ptr = 0;
453 8073 : int end = val.size();
454 8073 : int point_ofs = 0;
455 :
456 8073 : if (ptr < end && val[ptr] == '-') {
457 : mantissa_sign = true;
458 : ++ptr;
459 : }
460 8073 : if (ptr < end)
461 : {
462 8069 : if (val[ptr] == '0') {
463 : /* pass single 0 */
464 377 : ++ptr;
465 7692 : } else if (val[ptr] >= '1' && val[ptr] <= '9') {
466 18022 : while (ptr < end && IsDigit(val[ptr])) {
467 20676 : if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
468 : return false; /* overflow */
469 10338 : ++ptr;
470 : }
471 : } else return false; /* missing expected digit */
472 : } else return false; /* empty string or loose '-' */
473 8061 : if (ptr < end && val[ptr] == '.')
474 : {
475 7760 : ++ptr;
476 7760 : if (ptr < end && IsDigit(val[ptr]))
477 : {
478 51842 : while (ptr < end && IsDigit(val[ptr])) {
479 88210 : if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
480 : return false; /* overflow */
481 44084 : ++ptr;
482 44084 : ++point_ofs;
483 : }
484 : } else return false; /* missing expected digit */
485 : }
486 8038 : if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
487 : {
488 20 : ++ptr;
489 20 : if (ptr < end && val[ptr] == '+')
490 3 : ++ptr;
491 17 : else if (ptr < end && val[ptr] == '-') {
492 11 : exponent_sign = true;
493 11 : ++ptr;
494 : }
495 20 : if (ptr < end && IsDigit(val[ptr])) {
496 37 : while (ptr < end && IsDigit(val[ptr])) {
497 21 : if (exponent > (UPPER_BOUND / 10LL))
498 : return false; /* overflow */
499 21 : exponent = exponent * 10 + val[ptr] - '0';
500 21 : ++ptr;
501 : }
502 : } else return false; /* missing expected digit */
503 : }
504 8034 : if (ptr != end)
505 : return false; /* trailing garbage */
506 :
507 : /* finalize exponent */
508 8028 : if (exponent_sign)
509 9 : exponent = -exponent;
510 8028 : exponent = exponent - point_ofs + mantissa_tzeros;
511 :
512 : /* finalize mantissa */
513 8028 : if (mantissa_sign)
514 13 : mantissa = -mantissa;
515 :
516 : /* convert to one 64-bit fixed-point value */
517 8028 : exponent += decimals;
518 8028 : if (exponent < 0)
519 : return false; /* cannot represent values smaller than 10^-decimals */
520 8019 : if (exponent >= 18)
521 : return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
522 :
523 36967 : for (int i=0; i < exponent; ++i) {
524 28955 : if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL))
525 : return false; /* overflow */
526 28954 : mantissa *= 10;
527 : }
528 8012 : if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND)
529 : return false; /* overflow */
530 :
531 8012 : if (amount_out)
532 8012 : *amount_out = mantissa;
533 :
534 : return true;
535 : }
536 :
537 23 : void Downcase(std::string& str)
538 : {
539 114 : std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c){return ToLower(c);});
540 23 : }
541 :
542 0 : std::string ToLower(const std::string& str)
543 : {
544 0 : std::string r;
545 0 : for (auto ch : str) r += ToLower((unsigned char)ch);
546 0 : return r;
547 : }
548 :
549 6 : std::string ToUpper(const std::string& str)
550 : {
551 6 : std::string r;
552 24 : for (auto ch : str) r += ToUpper((unsigned char)ch);
553 6 : return r;
554 : }
555 :
556 6 : std::string Capitalize(std::string str)
557 : {
558 6 : if (str.empty()) return str;
559 4 : str[0] = ToUpper(str.front());
560 2 : return str;
561 : }
562 :
563 9445754 : std::string HexStr(const Span<const uint8_t> s)
564 : {
565 9445754 : std::string rv;
566 9445754 : static constexpr char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
567 : '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
568 9445754 : rv.reserve(s.size() * 2);
569 398835627 : for (uint8_t v: s) {
570 389390303 : rv.push_back(hexmap[v >> 4]);
571 389390303 : rv.push_back(hexmap[v & 15]);
572 : }
573 9445754 : return rv;
574 : }
575 :
576 : // Based on http://www.zedwood.com/article/cpp-is-valid-utf8-string-function
577 3 : bool IsValidUTF8(const std::string& str)
578 : {
579 3 : const unsigned int strLen = str.length();
580 3 : int c,n;
581 141 : for (unsigned i = 0; i < strLen; i++) {
582 138 : c = (unsigned char) str[i];
583 138 : if (0x00 <= c && c <= 0x7f) n=0; // 0bbbbbbb (ASCII)
584 6 : else if ((c & 0xE0) == 0xC0) n=1; // 110bbbbb
585 6 : else if ( c == 0xED && i < (strLen - 1) && ((unsigned char)str[i+1] & 0xA0) == 0xA0)
586 : return false; //U+d800 to U+dfff
587 6 : else if ((c & 0xF0) == 0xE0) n=2; // 1110bbbb
588 0 : else if ((c & 0xF8) == 0xF0) n=3; // 11110bbb
589 : else return false;
590 150 : for (int j=0; j < n && i < strLen; j++) { // n bytes matching 10bbbbbb follow ?
591 12 : if ((++i == strLen) || (( (unsigned char)str[i] & 0xC0) != 0x80))
592 : return false;
593 : }
594 : }
595 : return true;
596 : }
597 :
|