Raven Core  3.0.0
P2P Digital Currency
utilstrencodings.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Copyright (c) 2017-2019 The Raven 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 
9 #include "tinyformat.h"
10 
11 #include <cstdlib>
12 #include <cstring>
13 #include <errno.h>
14 #include <limits>
15 
16 static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
17 
18 static const std::string SAFE_CHARS[] =
19 {
20  CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
21  CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
22  CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
23 };
24 
25 std::string SanitizeString(const std::string& str, int rule)
26 {
27  std::string strResult;
28  for (std::string::size_type i = 0; i < str.size(); i++)
29  {
30  if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
31  strResult.push_back(str[i]);
32  }
33  return strResult;
34 }
35 
36 const signed char p_util_hexdigit[256] =
37 { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
38  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
39  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
40  0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
41  -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
42  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-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,-1,-1,-1,-1,-1,-1,-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 
54 signed char HexDigit(char c)
55 {
56  return p_util_hexdigit[(unsigned char)c];
57 }
58 
59 bool IsHex(const std::string& str)
60 {
61  for(std::string::const_iterator it(str.begin()); it != str.end(); ++it)
62  {
63  if (HexDigit(*it) < 0)
64  return false;
65  }
66  return (str.size() > 0) && (str.size()%2 == 0);
67 }
68 
69 bool IsHexNumber(const std::string& str)
70 {
71  size_t starting_location = 0;
72  if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
73  starting_location = 2;
74  }
75  for (auto c : str.substr(starting_location)) {
76  if (HexDigit(c) < 0) return false;
77  }
78  // Return false for empty string or "0x".
79  return (str.size() > starting_location);
80 }
81 
82 std::vector<unsigned char> ParseHex(const char* psz)
83 {
84  // convert hex dump to vector
85  std::vector<unsigned char> vch;
86  while (true)
87  {
88  while (isspace(*psz))
89  psz++;
90  signed char c = HexDigit(*psz++);
91  if (c == (signed char)-1)
92  break;
93  unsigned char n = (c << 4);
94  c = HexDigit(*psz++);
95  if (c == (signed char)-1)
96  break;
97  n |= c;
98  vch.push_back(n);
99  }
100  return vch;
101 }
102 
103 std::vector<unsigned char> ParseHex(const std::string& str)
104 {
105  return ParseHex(str.c_str());
106 }
107 
108 void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
109  size_t colon = in.find_last_of(':');
110  // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
111  bool fHaveColon = colon != in.npos;
112  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
113  bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
114  if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
115  int32_t n;
116  if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
117  in = in.substr(0, colon);
118  portOut = n;
119  }
120  }
121  if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
122  hostOut = in.substr(1, in.size()-2);
123  else
124  hostOut = in;
125 }
126 
127 std::string EncodeBase64(const unsigned char* pch, size_t len)
128 {
129  static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
130 
131  std::string strRet = "";
132  strRet.reserve((len+2)/3*4);
133 
134  int mode=0, left=0;
135  const unsigned char *pchEnd = pch+len;
136 
137  while (pch<pchEnd)
138  {
139  int enc = *(pch++);
140  switch (mode)
141  {
142  case 0: // we have no bits
143  strRet += pbase64[enc >> 2];
144  left = (enc & 3) << 4;
145  mode = 1;
146  break;
147 
148  case 1: // we have two bits
149  strRet += pbase64[left | (enc >> 4)];
150  left = (enc & 15) << 2;
151  mode = 2;
152  break;
153 
154  case 2: // we have four bits
155  strRet += pbase64[left | (enc >> 6)];
156  strRet += pbase64[enc & 63];
157  mode = 0;
158  break;
159  }
160  }
161 
162  if (mode)
163  {
164  strRet += pbase64[left];
165  strRet += '=';
166  if (mode == 1)
167  strRet += '=';
168  }
169 
170  return strRet;
171 }
172 
173 std::string EncodeBase64(const std::string& str)
174 {
175  return EncodeBase64((const unsigned char*)str.c_str(), str.size());
176 }
177 
178 std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
179 {
180  static const int decode64_table[256] =
181  {
182  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
183  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
184  -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
185  -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
186  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
187  29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
188  49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
189  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
190  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
191  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
192  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
193  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
194  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
195  };
196 
197  if (pfInvalid)
198  *pfInvalid = false;
199 
200  std::vector<unsigned char> vchRet;
201  vchRet.reserve(strlen(p)*3/4);
202 
203  int mode = 0;
204  int left = 0;
205 
206  while (1)
207  {
208  int dec = decode64_table[(unsigned char)*p];
209  if (dec == -1) break;
210  p++;
211  switch (mode)
212  {
213  case 0: // we have no bits and get 6
214  left = dec;
215  mode = 1;
216  break;
217 
218  case 1: // we have 6 bits and keep 4
219  vchRet.push_back((left<<2) | (dec>>4));
220  left = dec & 15;
221  mode = 2;
222  break;
223 
224  case 2: // we have 4 bits and get 6, we keep 2
225  vchRet.push_back((left<<4) | (dec>>2));
226  left = dec & 3;
227  mode = 3;
228  break;
229 
230  case 3: // we have 2 bits and get 6
231  vchRet.push_back((left<<6) | dec);
232  mode = 0;
233  break;
234  }
235  }
236 
237  if (pfInvalid)
238  switch (mode)
239  {
240  case 0: // 4n base64 characters processed: ok
241  break;
242 
243  case 1: // 4n+1 base64 character processed: impossible
244  *pfInvalid = true;
245  break;
246 
247  case 2: // 4n+2 base64 characters processed: require '=='
248  if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1)
249  *pfInvalid = true;
250  break;
251 
252  case 3: // 4n+3 base64 characters processed: require '='
253  if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1)
254  *pfInvalid = true;
255  break;
256  }
257 
258  return vchRet;
259 }
260 
261 std::string DecodeBase64(const std::string& str)
262 {
263  std::vector<unsigned char> vchRet = DecodeBase64(str.c_str());
264  return std::string((const char*)vchRet.data(), vchRet.size());
265 }
266 
267 std::string EncodeBase32(const unsigned char* pch, size_t len)
268 {
269  static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
270 
271  std::string strRet="";
272  strRet.reserve((len+4)/5*8);
273 
274  int mode=0, left=0;
275  const unsigned char *pchEnd = pch+len;
276 
277  while (pch<pchEnd)
278  {
279  int enc = *(pch++);
280  switch (mode)
281  {
282  case 0: // we have no bits
283  strRet += pbase32[enc >> 3];
284  left = (enc & 7) << 2;
285  mode = 1;
286  break;
287 
288  case 1: // we have three bits
289  strRet += pbase32[left | (enc >> 6)];
290  strRet += pbase32[(enc >> 1) & 31];
291  left = (enc & 1) << 4;
292  mode = 2;
293  break;
294 
295  case 2: // we have one bit
296  strRet += pbase32[left | (enc >> 4)];
297  left = (enc & 15) << 1;
298  mode = 3;
299  break;
300 
301  case 3: // we have four bits
302  strRet += pbase32[left | (enc >> 7)];
303  strRet += pbase32[(enc >> 2) & 31];
304  left = (enc & 3) << 3;
305  mode = 4;
306  break;
307 
308  case 4: // we have two bits
309  strRet += pbase32[left | (enc >> 5)];
310  strRet += pbase32[enc & 31];
311  mode = 0;
312  }
313  }
314 
315  static const int nPadding[5] = {0, 6, 4, 3, 1};
316  if (mode)
317  {
318  strRet += pbase32[left];
319  for (int n=0; n<nPadding[mode]; n++)
320  strRet += '=';
321  }
322 
323  return strRet;
324 }
325 
326 std::string EncodeBase32(const std::string& str)
327 {
328  return EncodeBase32((const unsigned char*)str.c_str(), str.size());
329 }
330 
331 std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
332 {
333  static const int decode32_table[256] =
334  {
335  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
336  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
337  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
338  -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
339  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
340  3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
341  23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
342  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
343  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
344  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
345  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
346  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
347  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
348  };
349 
350  if (pfInvalid)
351  *pfInvalid = false;
352 
353  std::vector<unsigned char> vchRet;
354  vchRet.reserve((strlen(p))*5/8);
355 
356  int mode = 0;
357  int left = 0;
358 
359  while (1)
360  {
361  int dec = decode32_table[(unsigned char)*p];
362  if (dec == -1) break;
363  p++;
364  switch (mode)
365  {
366  case 0: // we have no bits and get 5
367  left = dec;
368  mode = 1;
369  break;
370 
371  case 1: // we have 5 bits and keep 2
372  vchRet.push_back((left<<3) | (dec>>2));
373  left = dec & 3;
374  mode = 2;
375  break;
376 
377  case 2: // we have 2 bits and keep 7
378  left = left << 5 | dec;
379  mode = 3;
380  break;
381 
382  case 3: // we have 7 bits and keep 4
383  vchRet.push_back((left<<1) | (dec>>4));
384  left = dec & 15;
385  mode = 4;
386  break;
387 
388  case 4: // we have 4 bits, and keep 1
389  vchRet.push_back((left<<4) | (dec>>1));
390  left = dec & 1;
391  mode = 5;
392  break;
393 
394  case 5: // we have 1 bit, and keep 6
395  left = left << 5 | dec;
396  mode = 6;
397  break;
398 
399  case 6: // we have 6 bits, and keep 3
400  vchRet.push_back((left<<2) | (dec>>3));
401  left = dec & 7;
402  mode = 7;
403  break;
404 
405  case 7: // we have 3 bits, and keep 0
406  vchRet.push_back((left<<5) | dec);
407  mode = 0;
408  break;
409  }
410  }
411 
412  if (pfInvalid)
413  switch (mode)
414  {
415  case 0: // 8n base32 characters processed: ok
416  break;
417 
418  case 1: // 8n+1 base32 characters processed: impossible
419  case 3: // +3
420  case 6: // +6
421  *pfInvalid = true;
422  break;
423 
424  case 2: // 8n+2 base32 characters processed: require '======'
425  if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(unsigned char)p[6]] != -1)
426  *pfInvalid = true;
427  break;
428 
429  case 4: // 8n+4 base32 characters processed: require '===='
430  if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(unsigned char)p[4]] != -1)
431  *pfInvalid = true;
432  break;
433 
434  case 5: // 8n+5 base32 characters processed: require '==='
435  if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(unsigned char)p[3]] != -1)
436  *pfInvalid = true;
437  break;
438 
439  case 7: // 8n+7 base32 characters processed: require '='
440  if (left || p[0] != '=' || decode32_table[(unsigned char)p[1]] != -1)
441  *pfInvalid = true;
442  break;
443  }
444 
445  return vchRet;
446 }
447 
448 std::string DecodeBase32(const std::string& str)
449 {
450  std::vector<unsigned char> vchRet = DecodeBase32(str.c_str());
451  return std::string((const char*)vchRet.data(), vchRet.size());
452 }
453 
454 static bool ParsePrechecks(const std::string& str)
455 {
456  if (str.empty()) // No empty string allowed
457  return false;
458  if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
459  return false;
460  if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
461  return false;
462  return true;
463 }
464 
465 bool ParseInt32(const std::string& str, int32_t *out)
466 {
467  if (!ParsePrechecks(str))
468  return false;
469  char *endp = nullptr;
470  errno = 0; // strtol will not set errno if valid
471  long int n = strtol(str.c_str(), &endp, 10);
472  if(out) *out = (int32_t)n;
473  // Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow
474  // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
475  // platforms the size of these types may be different.
476  return endp && *endp == 0 && !errno &&
477  n >= std::numeric_limits<int32_t>::min() &&
478  n <= std::numeric_limits<int32_t>::max();
479 }
480 
481 bool ParseInt64(const std::string& str, int64_t *out)
482 {
483  if (!ParsePrechecks(str))
484  return false;
485  char *endp = nullptr;
486  errno = 0; // strtoll will not set errno if valid
487  long long int n = strtoll(str.c_str(), &endp, 10);
488  if(out) *out = (int64_t)n;
489  // Note that strtoll returns a *long long int*, so even if strtol doesn't report an over/underflow
490  // we still have to check that the returned value is within the range of an *int64_t*.
491  return endp && *endp == 0 && !errno &&
492  n >= std::numeric_limits<int64_t>::min() &&
493  n <= std::numeric_limits<int64_t>::max();
494 }
495 
496 bool ParseUInt32(const std::string& str, uint32_t *out)
497 {
498  if (!ParsePrechecks(str))
499  return false;
500  if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoul accepts these by default if they fit in the range
501  return false;
502  char *endp = nullptr;
503  errno = 0; // strtoul will not set errno if valid
504  unsigned long int n = strtoul(str.c_str(), &endp, 10);
505  if(out) *out = (uint32_t)n;
506  // Note that strtoul returns a *unsigned long int*, so even if it doesn't report an over/underflow
507  // we still have to check that the returned value is within the range of an *uint32_t*. On 64-bit
508  // platforms the size of these types may be different.
509  return endp && *endp == 0 && !errno &&
510  n <= std::numeric_limits<uint32_t>::max();
511 }
512 
513 bool ParseUInt64(const std::string& str, uint64_t *out)
514 {
515  if (!ParsePrechecks(str))
516  return false;
517  if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoull accepts these by default if they fit in the range
518  return false;
519  char *endp = nullptr;
520  errno = 0; // strtoull will not set errno if valid
521  unsigned long long int n = strtoull(str.c_str(), &endp, 10);
522  if(out) *out = (uint64_t)n;
523  // Note that strtoull returns a *unsigned long long int*, so even if it doesn't report an over/underflow
524  // we still have to check that the returned value is within the range of an *uint64_t*.
525  return endp && *endp == 0 && !errno &&
526  n <= std::numeric_limits<uint64_t>::max();
527 }
528 
529 
530 bool ParseDouble(const std::string& str, double *out)
531 {
532  if (!ParsePrechecks(str))
533  return false;
534  if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
535  return false;
536  std::istringstream text(str);
537  text.imbue(std::locale::classic());
538  double result;
539  text >> result;
540  if(out) *out = result;
541  return text.eof() && !text.fail();
542 }
543 
544 std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
545 {
546  std::stringstream out;
547  size_t ptr = 0;
548  size_t indented = 0;
549  while (ptr < in.size())
550  {
551  size_t lineend = in.find_first_of('\n', ptr);
552  if (lineend == std::string::npos) {
553  lineend = in.size();
554  }
555  const size_t linelen = lineend - ptr;
556  const size_t rem_width = width - indented;
557  if (linelen <= rem_width) {
558  out << in.substr(ptr, linelen + 1);
559  ptr = lineend + 1;
560  indented = 0;
561  } else {
562  size_t finalspace = in.find_last_of(" \n", ptr + rem_width);
563  if (finalspace == std::string::npos || finalspace < ptr) {
564  // No place to break; just include the entire word and move on
565  finalspace = in.find_first_of("\n ", ptr);
566  if (finalspace == std::string::npos) {
567  // End of the string, just add it and break
568  out << in.substr(ptr);
569  break;
570  }
571  }
572  out << in.substr(ptr, finalspace - ptr) << "\n";
573  if (in[finalspace] == '\n') {
574  indented = 0;
575  } else if (indent) {
576  out << std::string(indent, ' ');
577  indented = indent;
578  }
579  ptr = finalspace + 1;
580  }
581  }
582  return out.str();
583 }
584 
585 std::string i64tostr(int64_t n)
586 {
587  return strprintf("%d", n);
588 }
589 
590 std::string itostr(int n)
591 {
592  return strprintf("%d", n);
593 }
594 
595 int64_t atoi64(const char* psz)
596 {
597 #ifdef _MSC_VER
598  return _atoi64(psz);
599 #else
600  return strtoll(psz, nullptr, 10);
601 #endif
602 }
603 
604 int64_t atoi64(const std::string& str)
605 {
606 #ifdef _MSC_VER
607  return _atoi64(str.c_str());
608 #else
609  return strtoll(str.c_str(), nullptr, 10);
610 #endif
611 }
612 
613 int atoi(const std::string& str)
614 {
615  return atoi(str.c_str());
616 }
617 
626 static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL;
627 
629 static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros)
630 {
631  if(ch == '0')
632  ++mantissa_tzeros;
633  else {
634  for (int i=0; i<=mantissa_tzeros; ++i) {
635  if (mantissa > (UPPER_BOUND / 10LL))
636  return false; /* overflow */
637  mantissa *= 10;
638  }
639  mantissa += ch - '0';
640  mantissa_tzeros = 0;
641  }
642  return true;
643 }
644 
645 bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
646 {
647  int64_t mantissa = 0;
648  int64_t exponent = 0;
649  int mantissa_tzeros = 0;
650  bool mantissa_sign = false;
651  bool exponent_sign = false;
652  int ptr = 0;
653  int end = val.size();
654  int point_ofs = 0;
655 
656  if (ptr < end && val[ptr] == '-') {
657  mantissa_sign = true;
658  ++ptr;
659  }
660  if (ptr < end)
661  {
662  if (val[ptr] == '0') {
663  /* pass single 0 */
664  ++ptr;
665  } else if (val[ptr] >= '1' && val[ptr] <= '9') {
666  while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') {
667  if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
668  return false; /* overflow */
669  ++ptr;
670  }
671  } else return false; /* missing expected digit */
672  } else return false; /* empty string or loose '-' */
673  if (ptr < end && val[ptr] == '.')
674  {
675  ++ptr;
676  if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9')
677  {
678  while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') {
679  if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
680  return false; /* overflow */
681  ++ptr;
682  ++point_ofs;
683  }
684  } else return false; /* missing expected digit */
685  }
686  if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
687  {
688  ++ptr;
689  if (ptr < end && val[ptr] == '+')
690  ++ptr;
691  else if (ptr < end && val[ptr] == '-') {
692  exponent_sign = true;
693  ++ptr;
694  }
695  if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') {
696  while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') {
697  if (exponent > (UPPER_BOUND / 10LL))
698  return false; /* overflow */
699  exponent = exponent * 10 + val[ptr] - '0';
700  ++ptr;
701  }
702  } else return false; /* missing expected digit */
703  }
704  if (ptr != end)
705  return false; /* trailing garbage */
706 
707  /* finalize exponent */
708  if (exponent_sign)
709  exponent = -exponent;
710  exponent = exponent - point_ofs + mantissa_tzeros;
711 
712  /* finalize mantissa */
713  if (mantissa_sign)
714  mantissa = -mantissa;
715 
716  /* convert to one 64-bit fixed-point value */
717  exponent += decimals;
718  if (exponent < 0)
719  return false; /* cannot represent values smaller than 10^-decimals */
720  if (exponent >= 18)
721  return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
722 
723  for (int i=0; i < exponent; ++i) {
724  if (mantissa > (420000000000000000LL) || mantissa < -(UPPER_BOUND / 10LL))
725  return false; /* overflow */
726  mantissa *= 10;
727  }
728  if (mantissa > 4200000000000000000LL || mantissa < -UPPER_BOUND)
729  return false; /* overflow */
730 
731  if (amount_out)
732  *amount_out = mantissa;
733 
734  return true;
735 }
736 
bool IsHexNumber(const std::string &str)
Return true if the string is a hex number, optionally prefixed with "0x".
std::vector< unsigned char > DecodeBase64(const char *p, bool *pfInvalid)
#define strprintf
Definition: tinyformat.h:1054
bool ParseDouble(const std::string &str, double *out)
Convert string to double with strict parse error feedback.
bool ParseUInt64(const std::string &str, uint64_t *out)
Convert decimal string to unsigned 64-bit integer with strict parse error feedback.
bool ParseInt64(const std::string &str, int64_t *out)
Convert string to signed 64-bit integer with strict parse error feedback.
const signed char p_util_hexdigit[256]
bool ParseInt32(const std::string &str, int32_t *out)
Convert string to signed 32-bit integer with strict parse error feedback.
std::vector< unsigned char > DecodeBase32(const char *p, bool *pfInvalid)
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
bool IsHex(const std::string &str)
std::string FormatParagraph(const std::string &in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line...
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
bool ParseUInt32(const std::string &str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
int64_t atoi64(const char *psz)
std::string i64tostr(int64_t n)
std::string EncodeBase32(const unsigned char *pch, size_t len)
signed char HexDigit(char c)
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
std::string itostr(int n)
int atoi(const std::string &str)
std::string EncodeBase64(const unsigned char *pch, size_t len)
std::vector< unsigned char > ParseHex(const char *psz)