LCOV - code coverage report
Current view: top level - src/util - strencodings.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 447 453 98.7 %
Date: 2020-09-17 15:21:04 Functions: 35 35 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 0 0 -

           Branch data     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                 :            : static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
#      18                 :            : 
#      19                 :            : static const std::string SAFE_CHARS[] =
#      20                 :            : {
#      21                 :            :     CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
#      22                 :            :     CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
#      23                 :            :     CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
#      24                 :            :     CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI
#      25                 :            : };
#      26                 :            : 
#      27                 :            : std::string SanitizeString(const std::string& str, int rule)
#      28                 :     331925 : {
#      29                 :     331925 :     std::string strResult;
#      30                 :    2613740 :     for (std::string::size_type i = 0; i < str.size(); i++)
#      31                 :    2281815 :     {
#      32                 :    2281815 :         if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
#      33                 :    2281755 :             strResult.push_back(str[i]);
#      34                 :    2281815 :     }
#      35                 :     331925 :     return strResult;
#      36                 :     331925 : }
#      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                 :            : signed char HexDigit(char c)
#      57                 :  179020242 : {
#      58                 :  179020242 :     return p_util_hexdigit[(unsigned char)c];
#      59                 :  179020242 : }
#      60                 :            : 
#      61                 :            : bool IsHex(const std::string& str)
#      62                 :      38412 : {
#      63                 :   83114904 :     for(std::string::const_iterator it(str.begin()); it != str.end(); ++it)
#      64                 :   83076930 :     {
#      65                 :   83076930 :         if (HexDigit(*it) < 0)
#      66                 :        438 :             return false;
#      67                 :   83076930 :     }
#      68                 :      37974 :     return (str.size() > 0) && (str.size()%2 == 0);
#      69                 :      38412 : }
#      70                 :            : 
#      71                 :            : bool IsHexNumber(const std::string& str)
#      72                 :         41 : {
#      73                 :         41 :     size_t starting_location = 0;
#      74                 :         41 :     if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
#      75                 :         21 :         starting_location = 2;
#      76                 :         21 :     }
#      77                 :        238 :     for (const char c : str.substr(starting_location)) {
#      78                 :        238 :         if (HexDigit(c) < 0) return false;
#      79                 :        238 :     }
#      80                 :            :     // Return false for empty string or "0x".
#      81                 :         25 :     return (str.size() > starting_location);
#      82                 :         41 : }
#      83                 :            : 
#      84                 :            : std::vector<unsigned char> ParseHex(const char* psz)
#      85                 :      28706 : {
#      86                 :            :     // convert hex dump to vector
#      87                 :      28706 :     std::vector<unsigned char> vch;
#      88                 :   41695187 :     while (true)
#      89                 :   41695187 :     {
#      90                 :   41695231 :         while (IsSpace(*psz))
#      91                 :         44 :             psz++;
#      92                 :   41695187 :         signed char c = HexDigit(*psz++);
#      93                 :   41695187 :         if (c == (signed char)-1)
#      94                 :      28702 :             break;
#      95                 :   41666485 :         unsigned char n = (c << 4);
#      96                 :   41666485 :         c = HexDigit(*psz++);
#      97                 :   41666485 :         if (c == (signed char)-1)
#      98                 :          4 :             break;
#      99                 :   41666481 :         n |= c;
#     100                 :   41666481 :         vch.push_back(n);
#     101                 :   41666481 :     }
#     102                 :      28706 :     return vch;
#     103                 :      28706 : }
#     104                 :            : 
#     105                 :            : std::vector<unsigned char> ParseHex(const std::string& str)
#     106                 :      22510 : {
#     107                 :      22510 :     return ParseHex(str.c_str());
#     108                 :      22510 : }
#     109                 :            : 
#     110                 :     238558 : void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
#     111                 :     238558 :     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                 :     238558 :     bool fHaveColon = colon != in.npos;
#     114                 :     238558 :     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                 :     238558 :     bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
#     116                 :     238558 :     if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
#     117                 :        299 :         int32_t n;
#     118                 :        299 :         if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
#     119                 :        299 :             in = in.substr(0, colon);
#     120                 :        299 :             portOut = n;
#     121                 :        299 :         }
#     122                 :        299 :     }
#     123                 :     238558 :     if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
#     124                 :         22 :         hostOut = in.substr(1, in.size()-2);
#     125                 :     238536 :     else
#     126                 :     238536 :         hostOut = in;
#     127                 :     238558 : }
#     128                 :            : 
#     129                 :            : std::string EncodeBase64(Span<const unsigned char> input)
#     130                 :        720 : {
#     131                 :        720 :     static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#     132                 :        720 : 
#     133                 :        720 :     std::string str;
#     134                 :        720 :     str.reserve(((input.size() + 2) / 3) * 4);
#     135                 :     403547 :     ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, input.begin(), input.end());
#     136                 :       1021 :     while (str.size() % 4) str += '=';
#     137                 :        720 :     return str;
#     138                 :        720 : }
#     139                 :            : 
#     140                 :            : std::string EncodeBase64(const std::string& str)
#     141                 :        610 : {
#     142                 :        610 :     return EncodeBase64(MakeUCharSpan(str));
#     143                 :        610 : }
#     144                 :            : 
#     145                 :            : std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
#     146                 :      75025 : {
#     147                 :      75025 :     static const int decode64_table[256] =
#     148                 :      75025 :     {
#     149                 :      75025 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     150                 :      75025 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     151                 :      75025 :         -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
#     152                 :      75025 :         -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
#     153                 :      75025 :         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
#     154                 :      75025 :         29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
#     155                 :      75025 :         49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     156                 :      75025 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     157                 :      75025 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     158                 :      75025 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     159                 :      75025 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     160                 :      75025 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     161                 :      75025 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
#     162                 :      75025 :     };
#     163                 :      75025 : 
#     164                 :      75025 :     const char* e = p;
#     165                 :      75025 :     std::vector<uint8_t> val;
#     166                 :      75025 :     val.reserve(strlen(p));
#     167                 :    7936736 :     while (*p != 0) {
#     168                 :    7861956 :         int x = decode64_table[(unsigned char)*p];
#     169                 :    7861956 :         if (x == -1) break;
#     170                 :    7861711 :         val.push_back(x);
#     171                 :    7861711 :         ++p;
#     172                 :    7861711 :     }
#     173                 :      75025 : 
#     174                 :      75025 :     std::vector<unsigned char> ret;
#     175                 :      75025 :     ret.reserve((val.size() * 3) / 4);
#     176                 :    5896190 :     bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
#     177                 :      75025 : 
#     178                 :      75025 :     const char* q = p;
#     179                 :      75393 :     while (valid && *p != 0) {
#     180                 :        372 :         if (*p != '=') {
#     181                 :          4 :             valid = false;
#     182                 :          4 :             break;
#     183                 :          4 :         }
#     184                 :        368 :         ++p;
#     185                 :        368 :     }
#     186                 :      75025 :     valid = valid && (p - e) % 4 == 0 && p - q < 4;
#     187                 :      75025 :     if (pf_invalid) *pf_invalid = !valid;
#     188                 :      75025 : 
#     189                 :      75025 :     return ret;
#     190                 :      75025 : }
#     191                 :            : 
#     192                 :            : std::string DecodeBase64(const std::string& str, bool* pf_invalid)
#     193                 :      75010 : {
#     194                 :      75010 :     if (!ValidAsCString(str)) {
#     195                 :          2 :         if (pf_invalid) {
#     196                 :          2 :             *pf_invalid = true;
#     197                 :          2 :         }
#     198                 :          2 :         return {};
#     199                 :          2 :     }
#     200                 :      75008 :     std::vector<unsigned char> vchRet = DecodeBase64(str.c_str(), pf_invalid);
#     201                 :      75008 :     return std::string((const char*)vchRet.data(), vchRet.size());
#     202                 :      75008 : }
#     203                 :            : 
#     204                 :            : std::string EncodeBase32(Span<const unsigned char> input, bool pad)
#     205                 :         33 : {
#     206                 :         33 :     static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
#     207                 :         33 : 
#     208                 :         33 :     std::string str;
#     209                 :         33 :     str.reserve(((input.size() + 4) / 5) * 8);
#     210                 :        608 :     ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, input.begin(), input.end());
#     211                 :         33 :     if (pad) {
#     212                 :         71 :         while (str.size() % 8) {
#     213                 :         40 :             str += '=';
#     214                 :         40 :         }
#     215                 :         31 :     }
#     216                 :         33 :     return str;
#     217                 :         33 : }
#     218                 :            : 
#     219                 :            : std::string EncodeBase32(const std::string& str, bool pad)
#     220                 :         14 : {
#     221                 :         14 :     return EncodeBase32(MakeUCharSpan(str), pad);
#     222                 :         14 : }
#     223                 :            : 
#     224                 :            : std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
#     225                 :         49 : {
#     226                 :         49 :     static const int decode32_table[256] =
#     227                 :         49 :     {
#     228                 :         49 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     229                 :         49 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     230                 :         49 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
#     231                 :         49 :         -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
#     232                 :         49 :         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1,  0,  1,  2,
#     233                 :         49 :          3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
#     234                 :         49 :         23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     235                 :         49 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     236                 :         49 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     237                 :         49 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     238                 :         49 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     239                 :         49 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     240                 :         49 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
#     241                 :         49 :     };
#     242                 :         49 : 
#     243                 :         49 :     const char* e = p;
#     244                 :         49 :     std::vector<uint8_t> val;
#     245                 :         49 :     val.reserve(strlen(p));
#     246                 :       1001 :     while (*p != 0) {
#     247                 :        964 :         int x = decode32_table[(unsigned char)*p];
#     248                 :        964 :         if (x == -1) break;
#     249                 :        952 :         val.push_back(x);
#     250                 :        952 :         ++p;
#     251                 :        952 :     }
#     252                 :         49 : 
#     253                 :         49 :     std::vector<unsigned char> ret;
#     254                 :         49 :     ret.reserve((val.size() * 5) / 8);
#     255                 :        590 :     bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
#     256                 :         49 : 
#     257                 :         49 :     const char* q = p;
#     258                 :         89 :     while (valid && *p != 0) {
#     259                 :         40 :         if (*p != '=') {
#     260                 :          0 :             valid = false;
#     261                 :          0 :             break;
#     262                 :          0 :         }
#     263                 :         40 :         ++p;
#     264                 :         40 :     }
#     265                 :         49 :     valid = valid && (p - e) % 8 == 0 && p - q < 8;
#     266                 :         49 :     if (pf_invalid) *pf_invalid = !valid;
#     267                 :         49 : 
#     268                 :         49 :     return ret;
#     269                 :         49 : }
#     270                 :            : 
#     271                 :            : std::string DecodeBase32(const std::string& str, bool* pf_invalid)
#     272                 :         22 : {
#     273                 :         22 :     if (!ValidAsCString(str)) {
#     274                 :          2 :         if (pf_invalid) {
#     275                 :          2 :             *pf_invalid = true;
#     276                 :          2 :         }
#     277                 :          2 :         return {};
#     278                 :          2 :     }
#     279                 :         20 :     std::vector<unsigned char> vchRet = DecodeBase32(str.c_str(), pf_invalid);
#     280                 :         20 :     return std::string((const char*)vchRet.data(), vchRet.size());
#     281                 :         20 : }
#     282                 :            : 
#     283                 :            : NODISCARD static bool ParsePrechecks(const std::string& str)
#     284                 :       4624 : {
#     285                 :       4624 :     if (str.empty()) // No empty string allowed
#     286                 :         16 :         return false;
#     287                 :       4608 :     if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size()-1]))) // No padding allowed
#     288                 :         24 :         return false;
#     289                 :       4584 :     if (!ValidAsCString(str)) // No embedded NUL characters allowed
#     290                 :         10 :         return false;
#     291                 :       4574 :     return true;
#     292                 :       4574 : }
#     293                 :            : 
#     294                 :            : bool ParseInt32(const std::string& str, int32_t *out)
#     295                 :        389 : {
#     296                 :        389 :     if (!ParsePrechecks(str))
#     297                 :          9 :         return false;
#     298                 :        380 :     char *endp = nullptr;
#     299                 :        380 :     errno = 0; // strtol will not set errno if valid
#     300                 :        380 :     long int n = strtol(str.c_str(), &endp, 10);
#     301                 :        380 :     if(out) *out = (int32_t)n;
#     302                 :            :     // Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow
#     303                 :            :     // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
#     304                 :            :     // platforms the size of these types may be different.
#     305                 :        380 :     return endp && *endp == 0 && !errno &&
#     306                 :        367 :         n >= std::numeric_limits<int32_t>::min() &&
#     307                 :        365 :         n <= std::numeric_limits<int32_t>::max();
#     308                 :        380 : }
#     309                 :            : 
#     310                 :            : bool ParseInt64(const std::string& str, int64_t *out)
#     311                 :         40 : {
#     312                 :         40 :     if (!ParsePrechecks(str))
#     313                 :          8 :         return false;
#     314                 :         32 :     char *endp = nullptr;
#     315                 :         32 :     errno = 0; // strtoll will not set errno if valid
#     316                 :         32 :     long long int n = strtoll(str.c_str(), &endp, 10);
#     317                 :         32 :     if(out) *out = (int64_t)n;
#     318                 :            :     // Note that strtoll returns a *long long int*, so even if strtol doesn't report an over/underflow
#     319                 :            :     // we still have to check that the returned value is within the range of an *int64_t*.
#     320                 :         32 :     return endp && *endp == 0 && !errno &&
#     321                 :         18 :         n >= std::numeric_limits<int64_t>::min() &&
#     322                 :         18 :         n <= std::numeric_limits<int64_t>::max();
#     323                 :         32 : }
#     324                 :            : 
#     325                 :            : bool ParseUInt8(const std::string& str, uint8_t *out)
#     326                 :        160 : {
#     327                 :        160 :     uint32_t u32;
#     328                 :        160 :     if (!ParseUInt32(str, &u32) || u32 > std::numeric_limits<uint8_t>::max()) {
#     329                 :         92 :         return false;
#     330                 :         92 :     }
#     331                 :         68 :     if (out != nullptr) {
#     332                 :         68 :         *out = static_cast<uint8_t>(u32);
#     333                 :         68 :     }
#     334                 :         68 :     return true;
#     335                 :         68 : }
#     336                 :            : 
#     337                 :            : bool ParseUInt32(const std::string& str, uint32_t *out)
#     338                 :       4115 : {
#     339                 :       4115 :     if (!ParsePrechecks(str))
#     340                 :         15 :         return false;
#     341                 :       4100 :     if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoul accepts these by default if they fit in the range
#     342                 :         10 :         return false;
#     343                 :       4090 :     char *endp = nullptr;
#     344                 :       4090 :     errno = 0; // strtoul will not set errno if valid
#     345                 :       4090 :     unsigned long int n = strtoul(str.c_str(), &endp, 10);
#     346                 :       4090 :     if(out) *out = (uint32_t)n;
#     347                 :            :     // Note that strtoul returns a *unsigned long int*, so even if it doesn't report an over/underflow
#     348                 :            :     // we still have to check that the returned value is within the range of an *uint32_t*. On 64-bit
#     349                 :            :     // platforms the size of these types may be different.
#     350                 :       4090 :     return endp && *endp == 0 && !errno &&
#     351                 :       3985 :         n <= std::numeric_limits<uint32_t>::max();
#     352                 :       4090 : }
#     353                 :            : 
#     354                 :            : bool ParseUInt64(const std::string& str, uint64_t *out)
#     355                 :         44 : {
#     356                 :         44 :     if (!ParsePrechecks(str))
#     357                 :         10 :         return false;
#     358                 :         34 :     if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoull accepts these by default if they fit in the range
#     359                 :         10 :         return false;
#     360                 :         24 :     char *endp = nullptr;
#     361                 :         24 :     errno = 0; // strtoull will not set errno if valid
#     362                 :         24 :     unsigned long long int n = strtoull(str.c_str(), &endp, 10);
#     363                 :         24 :     if(out) *out = (uint64_t)n;
#     364                 :            :     // Note that strtoull returns a *unsigned long long int*, so even if it doesn't report an over/underflow
#     365                 :            :     // we still have to check that the returned value is within the range of an *uint64_t*.
#     366                 :         24 :     return endp && *endp == 0 && !errno &&
#     367                 :         16 :         n <= std::numeric_limits<uint64_t>::max();
#     368                 :         24 : }
#     369                 :            : 
#     370                 :            : 
#     371                 :            : bool ParseDouble(const std::string& str, double *out)
#     372                 :         36 : {
#     373                 :         36 :     if (!ParsePrechecks(str))
#     374                 :          8 :         return false;
#     375                 :         28 :     if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
#     376                 :          2 :         return false;
#     377                 :         26 :     std::istringstream text(str);
#     378                 :         26 :     text.imbue(std::locale::classic());
#     379                 :         26 :     double result;
#     380                 :         26 :     text >> result;
#     381                 :         26 :     if(out) *out = result;
#     382                 :         26 :     return text.eof() && !text.fail();
#     383                 :         26 : }
#     384                 :            : 
#     385                 :            : std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
#     386                 :        152 : {
#     387                 :        152 :     std::stringstream out;
#     388                 :        152 :     size_t ptr = 0;
#     389                 :        152 :     size_t indented = 0;
#     390                 :        502 :     while (ptr < in.size())
#     391                 :        352 :     {
#     392                 :        352 :         size_t lineend = in.find_first_of('\n', ptr);
#     393                 :        352 :         if (lineend == std::string::npos) {
#     394                 :        327 :             lineend = in.size();
#     395                 :        327 :         }
#     396                 :        352 :         const size_t linelen = lineend - ptr;
#     397                 :        352 :         const size_t rem_width = width - indented;
#     398                 :        352 :         if (linelen <= rem_width) {
#     399                 :        166 :             out << in.substr(ptr, linelen + 1);
#     400                 :        166 :             ptr = lineend + 1;
#     401                 :        166 :             indented = 0;
#     402                 :        186 :         } else {
#     403                 :        186 :             size_t finalspace = in.find_last_of(" \n", ptr + rem_width);
#     404                 :        186 :             if (finalspace == std::string::npos || finalspace < ptr) {
#     405                 :            :                 // No place to break; just include the entire word and move on
#     406                 :          8 :                 finalspace = in.find_first_of("\n ", ptr);
#     407                 :          8 :                 if (finalspace == std::string::npos) {
#     408                 :            :                     // End of the string, just add it and break
#     409                 :          2 :                     out << in.substr(ptr);
#     410                 :          2 :                     break;
#     411                 :          2 :                 }
#     412                 :        184 :             }
#     413                 :        184 :             out << in.substr(ptr, finalspace - ptr) << "\n";
#     414                 :        184 :             if (in[finalspace] == '\n') {
#     415                 :          2 :                 indented = 0;
#     416                 :        182 :             } else if (indent) {
#     417                 :        164 :                 out << std::string(indent, ' ');
#     418                 :        164 :                 indented = indent;
#     419                 :        164 :             }
#     420                 :        184 :             ptr = finalspace + 1;
#     421                 :        184 :         }
#     422                 :        352 :     }
#     423                 :        152 :     return out.str();
#     424                 :        152 : }
#     425                 :            : 
#     426                 :            : int64_t atoi64(const std::string& str)
#     427                 :      53557 : {
#     428                 :            : #ifdef _MSC_VER
#     429                 :            :     return _atoi64(str.c_str());
#     430                 :            : #else
#     431                 :      53557 :     return strtoll(str.c_str(), nullptr, 10);
#     432                 :      53557 : #endif
#     433                 :      53557 : }
#     434                 :            : 
#     435                 :            : int atoi(const std::string& str)
#     436                 :      67739 : {
#     437                 :      67739 :     return atoi(str.c_str());
#     438                 :      67739 : }
#     439                 :            : 
#     440                 :            : /** Upper bound for mantissa.
#     441                 :            :  * 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer.
#     442                 :            :  * Larger integers cannot consist of arbitrary combinations of 0-9:
#     443                 :            :  *
#     444                 :            :  *   999999999999999999  1^18-1
#     445                 :            :  *  9223372036854775807  (1<<63)-1  (max int64_t)
#     446                 :            :  *  9999999999999999999  1^19-1     (would overflow)
#     447                 :            :  */
#     448                 :            : static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL;
#     449                 :            : 
#     450                 :            : /** Helper function for ParseFixedPoint */
#     451                 :            : static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros)
#     452                 :      67966 : {
#     453                 :      67966 :     if(ch == '0')
#     454                 :      19271 :         ++mantissa_tzeros;
#     455                 :      48695 :     else {
#     456                 :     110773 :         for (int i=0; i<=mantissa_tzeros; ++i) {
#     457                 :      62100 :             if (mantissa > (UPPER_BOUND / 10LL))
#     458                 :         22 :                 return false; /* overflow */
#     459                 :      62078 :             mantissa *= 10;
#     460                 :      62078 :         }
#     461                 :      48673 :         mantissa += ch - '0';
#     462                 :      48673 :         mantissa_tzeros = 0;
#     463                 :      48673 :     }
#     464                 :      67944 :     return true;
#     465                 :      67966 : }
#     466                 :            : 
#     467                 :            : bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
#     468                 :      18062 : {
#     469                 :      18062 :     int64_t mantissa = 0;
#     470                 :      18062 :     int64_t exponent = 0;
#     471                 :      18062 :     int mantissa_tzeros = 0;
#     472                 :      18062 :     bool mantissa_sign = false;
#     473                 :      18062 :     bool exponent_sign = false;
#     474                 :      18062 :     int ptr = 0;
#     475                 :      18062 :     int end = val.size();
#     476                 :      18062 :     int point_ofs = 0;
#     477                 :      18062 : 
#     478                 :      18062 :     if (ptr < end && val[ptr] == '-') {
#     479                 :         44 :         mantissa_sign = true;
#     480                 :         44 :         ++ptr;
#     481                 :         44 :     }
#     482                 :      18062 :     if (ptr < end)
#     483                 :      18058 :     {
#     484                 :      18058 :         if (val[ptr] == '0') {
#     485                 :            :             /* pass single 0 */
#     486                 :      14081 :             ++ptr;
#     487                 :       3977 :         } else if (val[ptr] >= '1' && val[ptr] <= '9') {
#     488                 :       9970 :             while (ptr < end && IsDigit(val[ptr])) {
#     489                 :       6002 :                 if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
#     490                 :          0 :                     return false; /* overflow */
#     491                 :       6002 :                 ++ptr;
#     492                 :       6002 :             }
#     493                 :          9 :         } else return false; /* missing expected digit */
#     494                 :          4 :     } else return false; /* empty string or loose '-' */
#     495                 :      18049 :     if (ptr < end && val[ptr] == '.')
#     496                 :      10544 :     {
#     497                 :      10544 :         ++ptr;
#     498                 :      10544 :         if (ptr < end && IsDigit(val[ptr]))
#     499                 :      10542 :         {
#     500                 :      72484 :             while (ptr < end && IsDigit(val[ptr])) {
#     501                 :      61964 :                 if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
#     502                 :         22 :                     return false; /* overflow */
#     503                 :      61942 :                 ++ptr;
#     504                 :      61942 :                 ++point_ofs;
#     505                 :      61942 :             }
#     506                 :          2 :         } else return false; /* missing expected digit */
#     507                 :      18025 :     }
#     508                 :      18025 :     if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
#     509                 :       2048 :     {
#     510                 :       2048 :         ++ptr;
#     511                 :       2048 :         if (ptr < end && val[ptr] == '+')
#     512                 :          8 :             ++ptr;
#     513                 :       2040 :         else if (ptr < end && val[ptr] == '-') {
#     514                 :       2032 :             exponent_sign = true;
#     515                 :       2032 :             ++ptr;
#     516                 :       2032 :         }
#     517                 :       2048 :         if (ptr < end && IsDigit(val[ptr])) {
#     518                 :       6111 :             while (ptr < end && IsDigit(val[ptr])) {
#     519                 :       4067 :                 if (exponent > (UPPER_BOUND / 10LL))
#     520                 :          0 :                     return false; /* overflow */
#     521                 :       4067 :                 exponent = exponent * 10 + val[ptr] - '0';
#     522                 :       4067 :                 ++ptr;
#     523                 :       4067 :             }
#     524                 :          4 :         } else return false; /* missing expected digit */
#     525                 :      18021 :     }
#     526                 :      18021 :     if (ptr != end)
#     527                 :          8 :         return false; /* trailing garbage */
#     528                 :      18013 : 
#     529                 :            :     /* finalize exponent */
#     530                 :      18013 :     if (exponent_sign)
#     531                 :       2030 :         exponent = -exponent;
#     532                 :      18013 :     exponent = exponent - point_ofs + mantissa_tzeros;
#     533                 :      18013 : 
#     534                 :            :     /* finalize mantissa */
#     535                 :      18013 :     if (mantissa_sign)
#     536                 :         24 :         mantissa = -mantissa;
#     537                 :      18013 : 
#     538                 :            :     /* convert to one 64-bit fixed-point value */
#     539                 :      18013 :     exponent += decimals;
#     540                 :      18013 :     if (exponent < 0)
#     541                 :         12 :         return false; /* cannot represent values smaller than 10^-decimals */
#     542                 :      18001 :     if (exponent >= 18)
#     543                 :          8 :         return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
#     544                 :      17993 : 
#     545                 :      96148 :     for (int i=0; i < exponent; ++i) {
#     546                 :      78157 :         if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL))
#     547                 :          2 :             return false; /* overflow */
#     548                 :      78155 :         mantissa *= 10;
#     549                 :      78155 :     }
#     550                 :      17991 :     if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND)
#     551                 :          0 :         return false; /* overflow */
#     552                 :      17991 : 
#     553                 :      17991 :     if (amount_out)
#     554                 :      17991 :         *amount_out = mantissa;
#     555                 :      17991 : 
#     556                 :      17991 :     return true;
#     557                 :      17991 : }
#     558                 :            : 
#     559                 :            : std::string ToLower(const std::string& str)
#     560                 :         27 : {
#     561                 :         27 :     std::string r;
#     562                 :         85 :     for (auto ch : str) r += ToLower((unsigned char)ch);
#     563                 :         27 :     return r;
#     564                 :         27 : }
#     565                 :            : 
#     566                 :            : std::string ToUpper(const std::string& str)
#     567                 :        129 : {
#     568                 :        129 :     std::string r;
#     569                 :        914 :     for (auto ch : str) r += ToUpper((unsigned char)ch);
#     570                 :        129 :     return r;
#     571                 :        129 : }
#     572                 :            : 
#     573                 :            : std::string Capitalize(std::string str)
#     574                 :         30 : {
#     575                 :         30 :     if (str.empty()) return str;
#     576                 :         28 :     str[0] = ToUpper(str.front());
#     577                 :         28 :     return str;
#     578                 :         28 : }
#     579                 :            : 
#     580                 :            : std::string HexStr(const Span<const uint8_t> s)
#     581                 :    5686763 : {
#     582                 :    5686763 :     std::string rv;
#     583                 :    5686763 :     static constexpr char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
#     584                 :    5686763 :                                          '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
#     585                 :    5686763 :     rv.reserve(s.size() * 2);
#     586                 :  197838963 :     for (uint8_t v: s) {
#     587                 :  197838963 :         rv.push_back(hexmap[v >> 4]);
#     588                 :  197838963 :         rv.push_back(hexmap[v & 15]);
#     589                 :  197838963 :     }
#     590                 :    5686763 :     return rv;
#     591                 :    5686763 : }

Generated by: LCOV version 1.14