bitcoin_string/strencodings.rs
1/*!
2 | Utilities for converting data from/to
3 | strings.
4 |
5 */
6
7crate::ix!();
8
9pub trait ToUpper {
10 fn to_upper(&self) -> Self;
11}
12
13pub trait ToLower {
14 fn to_lower(&self) -> Self;
15}
16
17//-------------------------------------------[.cpp/bitcoin/src/util/strencodings.h]
18
19/**
20 | Used by SanitizeString()
21 |
22 */
23pub enum SafeChars
24{
25 /**
26 | The full set of allowed chars
27 |
28 */
29 SAFE_CHARS_DEFAULT,
30
31 /**
32 | BIP-0014 subset
33 |
34 */
35 SAFE_CHARS_UA_COMMENT,
36
37 /**
38 | Chars allowed in filenames
39 |
40 */
41 SAFE_CHARS_FILENAME,
42
43 /**
44 | Chars allowed in URIs (RFC 3986)
45 |
46 */
47 SAFE_CHARS_URI,
48}
49
50/**
51 | LocaleIndependentAtoi is provided for backwards
52 | compatibility reasons.
53 |
54 | New code should use ToIntegral or the ParseInt*
55 | functions which provide parse error feedback.
56 |
57 | The goal of LocaleIndependentAtoi is to
58 | replicate the exact defined behaviour of atoi
59 | and atoi64 as they behave under the "C" locale.
60 */
61pub fn locale_independent_atoi<T>(str_: &str) -> T {
62
63 todo!();
64 /*
65 const_assert(std::is_integral<T>::value);
66 T result;
67 // Emulate atoi(...) handling of white space and leading +/-.
68 std::string s = TrimString(str);
69 if (!s.empty() && s[0] == '+') {
70 if (s.length() >= 2 && s[1] == '-') {
71 return 0;
72 }
73 s = s.substr(1);
74 }
75 auto [_, error_condition] = std::from_chars(s.data(), s.data() + s.size(), result);
76 if (error_condition != std::errc{}) {
77 return 0;
78 }
79 return result;
80 */
81}
82
83/**
84 | Tests if the given character is a decimal
85 | digit.
86 |
87 | -----------
88 | @param[in] c
89 |
90 | character to test
91 |
92 | -----------
93 | @return
94 |
95 | true if the argument is a decimal digit;
96 | otherwise false.
97 |
98 */
99pub fn is_digit(c: u8) -> bool {
100
101 todo!();
102 /*
103 return c >= '0' && c <= '9';
104 */
105}
106
107/**
108 | Tests if the given character is a whitespace
109 | character. The whitespace characters
110 | are:
111 |
112 | space,
113 | form-feed ('\f'),
114 | newline ('\n'),
115 | carriage return ('\r'),
116 | horizontal tab ('\t'),
117 | and vertical tab ('\v').
118 |
119 | This function is locale independent.
120 | Under the C locale this function gives
121 | the same result as std::isspace.
122 |
123 | -----------
124 | @param[in] c
125 |
126 | character to test
127 |
128 | -----------
129 | @return
130 |
131 | true if the argument is a whitespace
132 | character; otherwise false
133 |
134 */
135#[inline] pub fn is_space(c: u8) -> bool {
136
137 todo!();
138 /*
139 return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
140 */
141}
142
143/**
144 | Convert string to integral type T. Leading
145 | whitespace, a leading +, or any trailing
146 | character fail the parsing.
147 |
148 | The required format expressed as regex
149 | is `-?[0-9]+`. The minus sign is only
150 | permitted for signed integer types.
151 |
152 | -----------
153 | @return
154 |
155 | std::nullopt if the entire string could
156 | not be parsed, or if the parsed value
157 | is not in the range representable by
158 | the type T.
159 |
160 */
161pub fn to_integral<T>(str_: &str) -> Option<T> {
162
163 todo!();
164 /*
165 const_assert(std::is_integral<T>::value);
166 T result;
167 const auto [first_nonmatching, error_condition] = std::from_chars(str.data(), str.data() + str.size(), result);
168 if (first_nonmatching != str.data() + str.size() || error_condition != std::errc{}) {
169 return std::nullopt;
170 }
171 return result;
172 */
173}
174
175/**
176 | Timing-attack-resistant comparison.
177 |
178 | Takes time proportional to length of
179 | first argument.
180 |
181 */
182pub fn timing_resistant_equal<T>(a: &T, b: &T) -> bool {
183
184 todo!();
185 /*
186 if (b.size() == 0) return a.size() == 0;
187 size_t accumulator = a.size() ^ b.size();
188 for (size_t i = 0; i < a.size(); i++)
189 accumulator |= a[i] ^ b[i%b.size()];
190 return accumulator == 0;
191 */
192}
193
194/**
195 | Convert from one power-of-2 number
196 | base to another.
197 |
198 */
199pub fn convert_bits<O, I, const frombits: i32, const tobits: i32, const pad: bool>(
200 outfn: &O,
201 it: I,
202 end: I) -> bool {
203
204 todo!();
205 /*
206 size_t acc = 0;
207 size_t bits = 0;
208 constexpr size_t maxv = (1 << tobits) - 1;
209 constexpr size_t max_acc = (1 << (frombits + tobits - 1)) - 1;
210 while (it != end) {
211 acc = ((acc << frombits) | *it) & max_acc;
212 bits += frombits;
213 while (bits >= tobits) {
214 bits -= tobits;
215 outfn((acc >> bits) & maxv);
216 }
217 ++it;
218 }
219 if (pad) {
220 if (bits) outfn((acc << (tobits - bits)) & maxv);
221 } else if (bits >= frombits || ((acc << (tobits - bits)) & maxv)) {
222 return false;
223 }
224 return true;
225 */
226}
227
228impl ToLower for u8 {
229
230 /**
231 | Converts the given character to its
232 | lowercase equivalent.
233 |
234 | This function is locale independent.
235 | It only converts uppercase characters
236 | in the standard 7-bit ASCII range.
237 |
238 | This is a feature, not a limitation.
239 |
240 | -----------
241 | @param[in] c
242 |
243 | the character to convert to lowercase.
244 |
245 | -----------
246 | @return
247 |
248 | the lowercase equivalent of c; or the
249 | argument if no conversion is possible.
250 |
251 */
252 fn to_lower(&self) -> u8 {
253
254 todo!();
255 /*
256 return (c >= 'A' && c <= 'Z' ? (c - 'A') + 'a' : c);
257 */
258 }
259}
260
261/**
262 | Converts the given character to its
263 | uppercase equivalent.
264 |
265 | This function is locale independent.
266 | It only converts lowercase characters
267 | in the standard 7-bit ASCII range.
268 |
269 | This is a feature, not a limitation.
270 |
271 | -----------
272 | @param[in] c
273 |
274 | the character to convert to uppercase.
275 |
276 | -----------
277 | @return
278 |
279 | the uppercase equivalent of c; or the
280 | argument if no conversion is possible.
281 |
282 */
283impl ToUpper for u8 {
284
285 fn to_upper(&self) -> u8 {
286
287 todo!();
288 /*
289 return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c);
290 */
291 }
292}
293
294//-------------------------------------------[.cpp/bitcoin/src/util/strencodings.cpp]
295
296pub const CHARS_ALPHA_NUM: &'static str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
297
298lazy_static!{
299 static ref SAFE_CHARS: Box<[String]> =
300 Box::new([
301 CHARS_ALPHA_NUM.to_owned() + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
302 CHARS_ALPHA_NUM.to_owned() + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
303 CHARS_ALPHA_NUM.to_owned() + ".-_", // SAFE_CHARS_FILENAME
304 CHARS_ALPHA_NUM.to_owned() + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI
305 ]);
306}
307
308/**
309 | Remove unsafe chars. Safe chars chosen
310 | to allow simple messages/URLs/email
311 | addresses, but avoid anything even
312 | possibly remotely dangerous like &
313 | or >
314 |
315 | -----------
316 | @param[in] str
317 |
318 | The string to sanitize
319 | ----------
320 | @param[in] rule
321 |
322 | The set of safe chars to choose (default:
323 | least restrictive)
324 |
325 | -----------
326 | @return
327 |
328 | A new string without unsafe chars
329 |
330 */
331pub fn sanitize_string(
332 str_: &str,
333 rule: Option<i32>) -> String {
334
335 let rule: i32 = rule.unwrap_or(SafeChars::SAFE_CHARS_DEFAULT as i32);
336
337 todo!();
338 /*
339 std::string strResult;
340 for (std::string::size_type i = 0; i < str.size(); i++)
341 {
342 if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
343 strResult.push_back(str[i]);
344 }
345 return strResult;
346 */
347}
348
349pub const util_hexdigit: [i8; 256] = [
350 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
351 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
352 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
353 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
354 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
355 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
356 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
357 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
358 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
359 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
360 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
361 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
362 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
363 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
364 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
365 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
366];
367
368pub fn hex_digit(c: u8) -> i8 {
369
370 todo!();
371 /*
372 return p_util_hexdigit[(unsigned char)c];
373 */
374}
375
376/**
377 | Returns true if each character in str
378 | is a hex character, and has an even number
379 | of hex digits.
380 |
381 */
382pub fn is_hex(str_: &str) -> bool {
383
384 todo!();
385 /*
386 for(std::string::const_iterator it(str.begin()); it != str.end(); ++it)
387 {
388 if (HexDigit(*it) < 0)
389 return false;
390 }
391 return (str.size() > 0) && (str.size()%2 == 0);
392 */
393}
394
395/**
396 | Return true if the string is a hex number,
397 | optionally prefixed with "0x"
398 |
399 */
400pub fn is_hex_number(str_: &str) -> bool {
401
402 todo!();
403 /*
404 size_t starting_location = 0;
405 if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
406 starting_location = 2;
407 }
408 for (const char c : str.substr(starting_location)) {
409 if (HexDigit(c) < 0) return false;
410 }
411 // Return false for empty string or "0x".
412 return (str.size() > starting_location);
413 */
414}
415
416pub fn parse_hex(psz: &str) -> Vec<u8> {
417
418 todo!();
419 /*
420 // convert hex dump to vector
421 std::vector<unsigned char> vch;
422 while (true)
423 {
424 while (IsSpace(*psz))
425 psz++;
426 signed char c = HexDigit(*psz++);
427 if (c == (signed char)-1)
428 break;
429 unsigned char n = (c << 4);
430 c = HexDigit(*psz++);
431 if (c == (signed char)-1)
432 break;
433 n |= c;
434 vch.push_back(n);
435 }
436 return vch;
437 */
438}
439
440pub fn encode_base64_bytes(input: &[u8]) -> String {
441
442 todo!();
443 /*
444 static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
445
446 std::string str;
447 str.reserve(((input.size() + 2) / 3) * 4);
448 ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, input.begin(), input.end());
449 while (str.size() % 4) str += '=';
450 return str;
451 */
452}
453
454pub fn encode_base64(str_: &String) -> String {
455
456 todo!();
457 /*
458 return EncodeBase64(MakeUCharSpan(str));
459 */
460}
461
462pub fn decode_base64_bytes(
463 p: *const u8,
464 pf_invalid: Option<*mut bool>) -> Vec<u8> {
465
466 todo!();
467 /*
468 static const int decode64_table[256] =
469 {
470 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
471 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
472 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
473 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
474 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
475 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
476 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
477 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
478 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
479 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
480 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
481 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
482 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
483 };
484
485 const char* e = p;
486 std::vector<uint8_t> val;
487 val.reserve(strlen(p));
488 while (*p != 0) {
489 int x = decode64_table[(unsigned char)*p];
490 if (x == -1) break;
491 val.push_back(x);
492 ++p;
493 }
494
495 std::vector<unsigned char> ret;
496 ret.reserve((val.size() * 3) / 4);
497 bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
498
499 const char* q = p;
500 while (valid && *p != 0) {
501 if (*p != '=') {
502 valid = false;
503 break;
504 }
505 ++p;
506 }
507 valid = valid && (p - e) % 4 == 0 && p - q < 4;
508 if (pf_invalid) *pf_invalid = !valid;
509
510 return ret;
511 */
512}
513
514pub fn decode_base64(
515 str_: &str,
516 pf_invalid: Option<&mut bool>) -> String {
517
518 todo!();
519 /*
520 if (!ValidAsCString(str)) {
521 if (pf_invalid) {
522 *pf_invalid = true;
523 }
524 return {};
525 }
526 std::vector<unsigned char> vchRet = DecodeBase64(str.c_str(), pf_invalid);
527 return std::string((const char*)vchRet.data(), vchRet.size());
528 */
529}
530
531/**
532 | Base32 encode.
533 |
534 | If `pad` is true, then the output will
535 | be padded with '=' so that its length
536 | is a multiple of 8.
537 |
538 */
539pub fn encode_base32_bytes(
540 input: &[u8],
541 pad: Option<bool>) -> String {
542 let pad: bool = pad.unwrap_or(true);
543
544 todo!();
545 /*
546 static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
547
548 std::string str;
549 str.reserve(((input.size() + 4) / 5) * 8);
550 ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, input.begin(), input.end());
551 if (pad) {
552 while (str.size() % 8) {
553 str += '=';
554 }
555 }
556 return str;
557 */
558}
559
560/**
561 | Base32 encode.
562 |
563 | If `pad` is true, then the output will
564 | be padded with '=' so that its length
565 | is a multiple of 8.
566 |
567 */
568pub fn encode_base32(
569 str_: &[u8],
570 pad: Option<bool>) -> String {
571 let pad: bool = pad.unwrap_or(true);
572
573 todo!();
574 /*
575 return EncodeBase32(MakeUCharSpan(str), pad);
576 */
577}
578
579pub fn decode_base32_bytes(
580 p: *const u8,
581 pf_invalid: Option<*mut bool>) -> Vec<u8> {
582
583 todo!();
584 /*
585 static const int decode32_table[256] =
586 {
587 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
588 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
589 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
590 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
591 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
592 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
593 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
594 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
595 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
596 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
597 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
598 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
599 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
600 };
601
602 const char* e = p;
603 std::vector<uint8_t> val;
604 val.reserve(strlen(p));
605 while (*p != 0) {
606 int x = decode32_table[(unsigned char)*p];
607 if (x == -1) break;
608 val.push_back(x);
609 ++p;
610 }
611
612 std::vector<unsigned char> ret;
613 ret.reserve((val.size() * 5) / 8);
614 bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
615
616 const char* q = p;
617 while (valid && *p != 0) {
618 if (*p != '=') {
619 valid = false;
620 break;
621 }
622 ++p;
623 }
624 valid = valid && (p - e) % 8 == 0 && p - q < 8;
625 if (pf_invalid) *pf_invalid = !valid;
626
627 return ret;
628 */
629}
630
631pub fn decode_base32(
632 str_: &str,
633 pf_invalid: Option<*mut bool>) -> String {
634
635 todo!();
636 /*
637 if (!ValidAsCString(str)) {
638 if (pf_invalid) {
639 *pf_invalid = true;
640 }
641 return {};
642 }
643 std::vector<unsigned char> vchRet = DecodeBase32(str.c_str(), pf_invalid);
644 return std::string((const char*)vchRet.data(), vchRet.size());
645 */
646}
647
648pub fn parse_integral<T>(
649 str_: &String,
650 out: *mut T) -> bool {
651
652 todo!();
653 /*
654 const_assert(std::is_integral<T>::value);
655 // Replicate the exact behavior of strtol/strtoll/strtoul/strtoull when
656 // handling leading +/- for backwards compatibility.
657 if (str.length() >= 2 && str[0] == '+' && str[1] == '-') {
658 return false;
659 }
660 const std::optional<T> opt_int = ToIntegral<T>((!str.empty() && str[0] == '+') ? str.substr(1) : str);
661 if (!opt_int) {
662 return false;
663 }
664 if (out != nullptr) {
665 *out = *opt_int;
666 }
667 return true;
668 */
669}
670
671/**
672 | Convert string to signed 32-bit integer
673 | with strict parse error feedback.
674 |
675 |
676 | -----------
677 | @return
678 |
679 | true if the entire string could be parsed
680 | as valid integer, false if not the entire
681 | string could be parsed or when overflow
682 | or underflow occurred.
683 |
684 */
685pub fn parse_int32(
686 str_: &String,
687 out: *mut i32) -> bool {
688
689 todo!();
690 /*
691 return ParseIntegral<int32_t>(str, out);
692 */
693}
694
695/**
696 | Convert string to signed 64-bit integer
697 | with strict parse error feedback.
698 |
699 | -----------
700 | @return
701 |
702 | true if the entire string could be parsed
703 | as valid integer, false if not the entire
704 | string could be parsed or when overflow
705 | or underflow occurred.
706 |
707 */
708pub fn parse_int64(
709 str_: &String,
710 out: *mut i64) -> bool {
711
712 todo!();
713 /*
714 return ParseIntegral<int64_t>(str, out);
715 */
716}
717
718/**
719 | Convert decimal string to unsigned
720 | 8-bit integer with strict parse error
721 | feedback.
722 |
723 | -----------
724 | @return
725 |
726 | true if the entire string could be parsed
727 | as valid integer, false if not the entire
728 | string could be parsed or when overflow
729 | or underflow occurred.
730 |
731 */
732pub fn parse_uint8(
733 str_: &str,
734 out: *mut u8) -> bool {
735
736 todo!();
737 /*
738 return ParseIntegral<uint8_t>(str, out);
739 */
740}
741
742/**
743 | Convert decimal string to unsigned
744 | 16-bit integer with strict parse error
745 | feedback.
746 |
747 | -----------
748 | @return
749 |
750 | true if the entire string could be parsed
751 | as valid integer, false if the entire
752 | string could not be parsed or if overflow
753 | or underflow occurred.
754 |
755 */
756pub fn parse_uint16(
757 str_: &str,
758 out: *mut u16) -> bool {
759
760 todo!();
761 /*
762 return ParseIntegral<uint16_t>(str, out);
763 */
764}
765
766/**
767 | Convert decimal string to unsigned
768 | 32-bit integer with strict parse error
769 | feedback.
770 |
771 | -----------
772 | @return
773 |
774 | true if the entire string could be parsed
775 | as valid integer, false if not the entire
776 | string could be parsed or when overflow
777 | or underflow occurred.
778 |
779 */
780pub fn parse_uint32(
781 str_: &str,
782 out: *mut u32) -> bool {
783
784 todo!();
785 /*
786 return ParseIntegral<uint32_t>(str, out);
787 */
788}
789
790/**
791 | Convert decimal string to unsigned
792 | 64-bit integer with strict parse error
793 | feedback.
794 |
795 |
796 | -----------
797 | @return
798 |
799 | true if the entire string could be parsed
800 | as valid integer, false if not the entire
801 | string could be parsed or when overflow
802 | or underflow occurred.
803 |
804 */
805pub fn parse_uint64(
806 str_: &str,
807 out: *mut u64) -> bool {
808
809 todo!();
810 /*
811 return ParseIntegral<uint64_t>(str, out);
812 */
813}
814
815/**
816 | Upper bound for mantissa.
817 |
818 | 10^18-1 is the largest arbitrary decimal that
819 | will fit in a signed 64-bit integer.
820 |
821 | Larger integers cannot consist of arbitrary
822 | combinations of 0-9:
823 |
824 | 999999999999999999 1^18-1
825 | 9223372036854775807 (1<<63)-1 (max int64_t)
826 | 9999999999999999999 1^19-1 (would overflow)
827 */
828pub const UPPER_BOUND: i64 = 1000000000000000000 - 1;
829
830/**
831 | Helper function for ParseFixedPoint
832 |
833 */
834#[inline] pub fn process_mantissa_digit(
835 ch: u8,
836 mantissa: &mut i64,
837 mantissa_tzeros: &mut i32) -> bool {
838
839 todo!();
840 /*
841 if(ch == '0')
842 ++mantissa_tzeros;
843 else {
844 for (int i=0; i<=mantissa_tzeros; ++i) {
845 if (mantissa > (UPPER_BOUND / 10LL))
846 return false; /* overflow */
847 mantissa *= 10;
848 }
849 mantissa += ch - '0';
850 mantissa_tzeros = 0;
851 }
852 return true;
853 */
854}
855
856/**
857 | Parse number as fixed point according
858 | to JSON number syntax.
859 |
860 | See https://json.org/number.gif
861 |
862 | -----------
863 | @note
864 |
865 | The result must be in the range (-10^18,10^18),
866 | otherwise an overflow error will trigger.
867 |
868 | -----------
869 | @return
870 |
871 | true on success, false on error.
872 |
873 */
874pub fn parse_fixed_point(
875 val: &str,
876 decimals: i32,
877 amount_out: *mut i64) -> bool {
878
879 todo!();
880 /*
881 int64_t mantissa = 0;
882 int64_t exponent = 0;
883 int mantissa_tzeros = 0;
884 bool mantissa_sign = false;
885 bool exponent_sign = false;
886 int ptr = 0;
887 int end = val.size();
888 int point_ofs = 0;
889
890 if (ptr < end && val[ptr] == '-') {
891 mantissa_sign = true;
892 ++ptr;
893 }
894 if (ptr < end)
895 {
896 if (val[ptr] == '0') {
897 /* pass single 0 */
898 ++ptr;
899 } else if (val[ptr] >= '1' && val[ptr] <= '9') {
900 while (ptr < end && IsDigit(val[ptr])) {
901 if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
902 return false; /* overflow */
903 ++ptr;
904 }
905 } else return false; /* missing expected digit */
906 } else return false; /* empty string or loose '-' */
907 if (ptr < end && val[ptr] == '.')
908 {
909 ++ptr;
910 if (ptr < end && IsDigit(val[ptr]))
911 {
912 while (ptr < end && IsDigit(val[ptr])) {
913 if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
914 return false; /* overflow */
915 ++ptr;
916 ++point_ofs;
917 }
918 } else return false; /* missing expected digit */
919 }
920 if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
921 {
922 ++ptr;
923 if (ptr < end && val[ptr] == '+')
924 ++ptr;
925 else if (ptr < end && val[ptr] == '-') {
926 exponent_sign = true;
927 ++ptr;
928 }
929 if (ptr < end && IsDigit(val[ptr])) {
930 while (ptr < end && IsDigit(val[ptr])) {
931 if (exponent > (UPPER_BOUND / 10LL))
932 return false; /* overflow */
933 exponent = exponent * 10 + val[ptr] - '0';
934 ++ptr;
935 }
936 } else return false; /* missing expected digit */
937 }
938 if (ptr != end)
939 return false; /* trailing garbage */
940
941 /* finalize exponent */
942 if (exponent_sign)
943 exponent = -exponent;
944 exponent = exponent - point_ofs + mantissa_tzeros;
945
946 /* finalize mantissa */
947 if (mantissa_sign)
948 mantissa = -mantissa;
949
950 /* convert to one 64-bit fixed-point value */
951 exponent += decimals;
952 if (exponent < 0)
953 return false; /* cannot represent values smaller than 10^-decimals */
954 if (exponent >= 18)
955 return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
956
957 for (int i=0; i < exponent; ++i) {
958 if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL))
959 return false; /* overflow */
960 mantissa *= 10;
961 }
962 if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND)
963 return false; /* overflow */
964
965 if (amount_out)
966 *amount_out = mantissa;
967
968 return true;
969 */
970}
971
972impl ToLower for String {
973
974 /**
975 | Returns the lowercase equivalent of
976 | the given string.
977 |
978 | This function is locale independent.
979 | It only converts uppercase characters
980 | in the standard 7-bit ASCII range.
981 |
982 | This is a feature, not a limitation.
983 |
984 | -----------
985 | @param[in] str
986 |
987 | the string to convert to lowercase.
988 |
989 | -----------
990 | @return
991 |
992 | lowercased equivalent of str
993 |
994 */
995 fn to_lower(&self) -> String {
996
997 todo!();
998 /*
999 std::string r;
1000 for (auto ch : str) r += ToLower((unsigned char)ch);
1001 return r;
1002 */
1003 }
1004}
1005
1006/**
1007 | Returns the uppercase equivalent of
1008 | the given string.
1009 |
1010 | This function is locale independent.
1011 | It only converts lowercase characters
1012 | in the standard 7-bit ASCII range.
1013 |
1014 | This is a feature, not a limitation.
1015 |
1016 | -----------
1017 | @param[in] str
1018 |
1019 | the string to convert to uppercase.
1020 |
1021 | -----------
1022 | @return
1023 |
1024 | UPPERCASED EQUIVALENT OF str
1025 |
1026 */
1027impl ToUpper for String {
1028 fn to_upper(&self) -> String {
1029
1030 todo!();
1031 /*
1032 std::string r;
1033 for (auto ch : str) r += ToUpper((unsigned char)ch);
1034 return r;
1035 */
1036 }
1037}
1038
1039/**
1040 | Capitalizes the first character of
1041 | the given string.
1042 |
1043 | This function is locale independent.
1044 | It only converts lowercase characters
1045 | in the standard 7-bit ASCII range.
1046 |
1047 | This is a feature, not a limitation.
1048 |
1049 | -----------
1050 | @param[in] str
1051 |
1052 | the string to capitalize.
1053 |
1054 | -----------
1055 | @return
1056 |
1057 | string with the first letter capitalized.
1058 |
1059 */
1060pub fn capitalize(str_: &str) -> String {
1061
1062 todo!();
1063 /*
1064 if (str.empty()) return str;
1065 str[0] = ToUpper(str.front());
1066 return str;
1067 */
1068}
1069
1070/**
1071 | Convert a span of bytes to a lower-case
1072 | hexadecimal string.
1073 |
1074 */
1075pub fn hex_str(s: &[u8]) -> String {
1076
1077 todo!();
1078 /*
1079 std::string rv(s.size() * 2, '\0');
1080 static constexpr char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
1081 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
1082 auto it = rv.begin();
1083 for (uint8_t v : s) {
1084 *it++ = hexmap[v >> 4];
1085 *it++ = hexmap[v & 15];
1086 }
1087 assert(it == rv.end());
1088 return rv;
1089 */
1090}