LCOV - code coverage report
Current view: top level - src/util - strencodings.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 335 339 98.8 %
Date: 2020-09-26 01:30:44 Functions: 38 38 100.0 %

          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 : }

Generated by: LCOV version 1.15