LCOV - code coverage report
Current view: top level - src/util - strencodings.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 442 448 98.7 %
Date: 2021-06-29 14:35:33 Functions: 36 36 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: 282 310 91.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                 :     461822 : {
#      29                 :     461822 :     std::string strResult;
#      30         [ +  + ]:    3818737 :     for (std::string::size_type i = 0; i < str.size(); i++)
#      31                 :    3356915 :     {
#      32         [ +  + ]:    3356915 :         if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
#      33                 :    3356776 :             strResult.push_back(str[i]);
#      34                 :    3356915 :     }
#      35                 :     461822 :     return strResult;
#      36                 :     461822 : }
#      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                 :  537819135 : {
#      58                 :  537819135 :     return p_util_hexdigit[(unsigned char)c];
#      59                 :  537819135 : }
#      60                 :            : 
#      61                 :            : bool IsHex(const std::string& str)
#      62                 :      49391 : {
#      63         [ +  + ]:  260747419 :     for(std::string::const_iterator it(str.begin()); it != str.end(); ++it)
#      64                 :  260698611 :     {
#      65         [ +  + ]:  260698611 :         if (HexDigit(*it) < 0)
#      66                 :        583 :             return false;
#      67                 :  260698611 :     }
#      68 [ +  + ][ +  + ]:      49391 :     return (str.size() > 0) && (str.size()%2 == 0);
#      69                 :      49391 : }
#      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                 :         41 :     return (str.size() > starting_location);
#      82                 :         41 : }
#      83                 :            : 
#      84                 :            : std::vector<unsigned char> ParseHex(const char* psz)
#      85                 :      43160 : {
#      86                 :            :     // convert hex dump to vector
#      87                 :      43160 :     std::vector<unsigned char> vch;
#      88                 :  130796461 :     while (true)
#      89                 :  130796461 :     {
#      90         [ +  + ]:  130796505 :         while (IsSpace(*psz))
#      91                 :         44 :             psz++;
#      92                 :  130796461 :         signed char c = HexDigit(*psz++);
#      93         [ +  + ]:  130796461 :         if (c == (signed char)-1)
#      94                 :      43156 :             break;
#      95                 :  130753305 :         unsigned char n = (c << 4);
#      96                 :  130753305 :         c = HexDigit(*psz++);
#      97         [ +  + ]:  130753305 :         if (c == (signed char)-1)
#      98                 :          4 :             break;
#      99                 :  130753301 :         n |= c;
#     100                 :  130753301 :         vch.push_back(n);
#     101                 :  130753301 :     }
#     102                 :      43160 :     return vch;
#     103                 :      43160 : }
#     104                 :            : 
#     105                 :            : std::vector<unsigned char> ParseHex(const std::string& str)
#     106                 :      32555 : {
#     107                 :      32555 :     return ParseHex(str.c_str());
#     108                 :      32555 : }
#     109                 :            : 
#     110                 :            : void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut)
#     111                 :     348869 : {
#     112                 :     348869 :     size_t colon = in.find_last_of(':');
#     113                 :            :     // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
#     114                 :     348869 :     bool fHaveColon = colon != in.npos;
#     115 [ +  + ][ +  + ]:     348869 :     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
#                 [ +  + ]
#     116 [ +  + ][ +  + ]:     348869 :     bool fMultiColon = fHaveColon && (in.find_last_of(':', colon - 1) != in.npos);
#     117 [ +  + ][ +  + ]:     348869 :     if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) {
#         [ +  + ][ +  + ]
#     118                 :        429 :         uint16_t n;
#     119         [ +  - ]:        429 :         if (ParseUInt16(in.substr(colon + 1), &n)) {
#     120                 :        429 :             in = in.substr(0, colon);
#     121                 :        429 :             portOut = n;
#     122                 :        429 :         }
#     123                 :        429 :     }
#     124 [ +  + ][ +  + ]:     348869 :     if (in.size() > 0 && in[0] == '[' && in[in.size() - 1] == ']') {
#                 [ +  - ]
#     125                 :         27 :         hostOut = in.substr(1, in.size() - 2);
#     126                 :     348842 :     } else {
#     127                 :     348842 :         hostOut = in;
#     128                 :     348842 :     }
#     129                 :     348869 : }
#     130                 :            : 
#     131                 :            : std::string EncodeBase64(Span<const unsigned char> input)
#     132                 :       1210 : {
#     133                 :       1210 :     static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#     134                 :            : 
#     135                 :       1210 :     std::string str;
#     136                 :       1210 :     str.reserve(((input.size() + 2) / 3) * 4);
#     137                 :     708517 :     ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, input.begin(), input.end());
#     138         [ +  + ]:       1733 :     while (str.size() % 4) str += '=';
#     139                 :       1210 :     return str;
#     140                 :       1210 : }
#     141                 :            : 
#     142                 :            : std::string EncodeBase64(const std::string& str)
#     143                 :       1050 : {
#     144                 :       1050 :     return EncodeBase64(MakeUCharSpan(str));
#     145                 :       1050 : }
#     146                 :            : 
#     147                 :            : std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
#     148                 :     111793 : {
#     149                 :     111793 :     static const int decode64_table[256] =
#     150                 :     111793 :     {
#     151                 :     111793 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     152                 :     111793 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     153                 :     111793 :         -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
#     154                 :     111793 :         -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
#     155                 :     111793 :         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
#     156                 :     111793 :         29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
#     157                 :     111793 :         49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     158                 :     111793 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     159                 :     111793 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     160                 :     111793 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     161                 :     111793 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     162                 :     111793 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     163                 :     111793 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
#     164                 :     111793 :     };
#     165                 :            : 
#     166                 :     111793 :     const char* e = p;
#     167                 :     111793 :     std::vector<uint8_t> val;
#     168                 :     111793 :     val.reserve(strlen(p));
#     169         [ +  + ]:   11808068 :     while (*p != 0) {
#     170                 :   11696644 :         int x = decode64_table[(unsigned char)*p];
#     171         [ +  + ]:   11696644 :         if (x == -1) break;
#     172                 :   11696275 :         val.push_back(x);
#     173                 :   11696275 :         ++p;
#     174                 :   11696275 :     }
#     175                 :            : 
#     176                 :     111793 :     std::vector<unsigned char> ret;
#     177                 :     111793 :     ret.reserve((val.size() * 3) / 4);
#     178                 :    8772065 :     bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
#     179                 :            : 
#     180                 :     111793 :     const char* q = p;
#     181 [ +  + ][ +  + ]:     112354 :     while (valid && *p != 0) {
#     182         [ +  + ]:        563 :         if (*p != '=') {
#     183                 :          2 :             valid = false;
#     184                 :          2 :             break;
#     185                 :          2 :         }
#     186                 :        561 :         ++p;
#     187                 :        561 :     }
#     188 [ +  + ][ +  + ]:     111793 :     valid = valid && (p - e) % 4 == 0 && p - q < 4;
#                 [ +  - ]
#     189         [ +  + ]:     111793 :     if (pf_invalid) *pf_invalid = !valid;
#     190                 :            : 
#     191                 :     111793 :     return ret;
#     192                 :     111793 : }
#     193                 :            : 
#     194                 :            : std::string DecodeBase64(const std::string& str, bool* pf_invalid)
#     195                 :     111781 : {
#     196         [ +  + ]:     111781 :     if (!ValidAsCString(str)) {
#     197         [ +  - ]:          6 :         if (pf_invalid) {
#     198                 :          6 :             *pf_invalid = true;
#     199                 :          6 :         }
#     200                 :          6 :         return {};
#     201                 :          6 :     }
#     202                 :     111775 :     std::vector<unsigned char> vchRet = DecodeBase64(str.c_str(), pf_invalid);
#     203                 :     111775 :     return std::string((const char*)vchRet.data(), vchRet.size());
#     204                 :     111775 : }
#     205                 :            : 
#     206                 :            : std::string EncodeBase32(Span<const unsigned char> input, bool pad)
#     207                 :        270 : {
#     208                 :        270 :     static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
#     209                 :            : 
#     210                 :        270 :     std::string str;
#     211                 :        270 :     str.reserve(((input.size() + 4) / 5) * 8);
#     212                 :      12308 :     ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, input.begin(), input.end());
#     213         [ +  + ]:        270 :     if (pad) {
#     214         [ +  + ]:         79 :         while (str.size() % 8) {
#     215                 :         40 :             str += '=';
#     216                 :         40 :         }
#     217                 :         39 :     }
#     218                 :        270 :     return str;
#     219                 :        270 : }
#     220                 :            : 
#     221                 :            : std::string EncodeBase32(const std::string& str, bool pad)
#     222                 :         28 : {
#     223                 :         28 :     return EncodeBase32(MakeUCharSpan(str), pad);
#     224                 :         28 : }
#     225                 :            : 
#     226                 :            : std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
#     227                 :         75 : {
#     228                 :         75 :     static const int decode32_table[256] =
#     229                 :         75 :     {
#     230                 :         75 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     231                 :         75 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     232                 :         75 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
#     233                 :         75 :         -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
#     234                 :         75 :         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1,  0,  1,  2,
#     235                 :         75 :          3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
#     236                 :         75 :         23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     237                 :         75 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     238                 :         75 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     239                 :         75 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     240                 :         75 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     241                 :         75 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#     242                 :         75 :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
#     243                 :         75 :     };
#     244                 :            : 
#     245                 :         75 :     const char* e = p;
#     246                 :         75 :     std::vector<uint8_t> val;
#     247                 :         75 :     val.reserve(strlen(p));
#     248         [ +  + ]:       2571 :     while (*p != 0) {
#     249                 :       2530 :         int x = decode32_table[(unsigned char)*p];
#     250         [ +  + ]:       2530 :         if (x == -1) break;
#     251                 :       2496 :         val.push_back(x);
#     252                 :       2496 :         ++p;
#     253                 :       2496 :     }
#     254                 :            : 
#     255                 :         75 :     std::vector<unsigned char> ret;
#     256                 :         75 :     ret.reserve((val.size() * 5) / 8);
#     257                 :       1544 :     bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
#     258                 :            : 
#     259                 :         75 :     const char* q = p;
#     260 [ +  + ][ +  + ]:        195 :     while (valid && *p != 0) {
#     261         [ -  + ]:        120 :         if (*p != '=') {
#     262                 :          0 :             valid = false;
#     263                 :          0 :             break;
#     264                 :          0 :         }
#     265                 :        120 :         ++p;
#     266                 :        120 :     }
#     267 [ +  + ][ +  - ]:         75 :     valid = valid && (p - e) % 8 == 0 && p - q < 8;
#                 [ +  - ]
#     268         [ +  + ]:         75 :     if (pf_invalid) *pf_invalid = !valid;
#     269                 :            : 
#     270                 :         75 :     return ret;
#     271                 :         75 : }
#     272                 :            : 
#     273                 :            : std::string DecodeBase32(const std::string& str, bool* pf_invalid)
#     274                 :         22 : {
#     275         [ +  + ]:         22 :     if (!ValidAsCString(str)) {
#     276         [ +  - ]:          4 :         if (pf_invalid) {
#     277                 :          4 :             *pf_invalid = true;
#     278                 :          4 :         }
#     279                 :          4 :         return {};
#     280                 :          4 :     }
#     281                 :         18 :     std::vector<unsigned char> vchRet = DecodeBase32(str.c_str(), pf_invalid);
#     282                 :         18 :     return std::string((const char*)vchRet.data(), vchRet.size());
#     283                 :         18 : }
#     284                 :            : 
#     285                 :            : [[nodiscard]] static bool ParsePrechecks(const std::string& str)
#     286                 :       9960 : {
#     287         [ +  + ]:       9960 :     if (str.empty()) // No empty string allowed
#     288                 :         20 :         return false;
#     289 [ +  - ][ +  + ]:       9940 :     if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size()-1]))) // No padding allowed
#                 [ +  + ]
#     290                 :         36 :         return false;
#     291         [ +  + ]:       9904 :     if (!ValidAsCString(str)) // No embedded NUL characters allowed
#     292                 :         14 :         return false;
#     293                 :       9890 :     return true;
#     294                 :       9890 : }
#     295                 :            : 
#     296                 :            : bool ParseInt32(const std::string& str, int32_t *out)
#     297                 :        105 : {
#     298         [ +  + ]:        105 :     if (!ParsePrechecks(str))
#     299                 :          9 :         return false;
#     300                 :         96 :     char *endp = nullptr;
#     301                 :         96 :     errno = 0; // strtol will not set errno if valid
#     302                 :         96 :     long int n = strtol(str.c_str(), &endp, 10);
#     303         [ +  + ]:         96 :     if(out) *out = (int32_t)n;
#     304                 :            :     // Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow
#     305                 :            :     // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
#     306                 :            :     // platforms the size of these types may be different.
#     307 [ +  - ][ +  + ]:         96 :     return endp && *endp == 0 && !errno &&
#                 [ +  + ]
#     308         [ +  + ]:         96 :         n >= std::numeric_limits<int32_t>::min() &&
#     309         [ +  + ]:         96 :         n <= std::numeric_limits<int32_t>::max();
#     310                 :         96 : }
#     311                 :            : 
#     312                 :            : bool ParseInt64(const std::string& str, int64_t *out)
#     313                 :         46 : {
#     314         [ +  + ]:         46 :     if (!ParsePrechecks(str))
#     315                 :          8 :         return false;
#     316                 :         38 :     char *endp = nullptr;
#     317                 :         38 :     errno = 0; // strtoll will not set errno if valid
#     318                 :         38 :     long long int n = strtoll(str.c_str(), &endp, 10);
#     319         [ +  + ]:         38 :     if(out) *out = (int64_t)n;
#     320                 :            :     // Note that strtoll returns a *long long int*, so even if strtol doesn't report an over/underflow
#     321                 :            :     // we still have to check that the returned value is within the range of an *int64_t*.
#     322 [ +  - ][ +  + ]:         38 :     return endp && *endp == 0 && !errno &&
#                 [ +  + ]
#     323         [ +  - ]:         38 :         n >= std::numeric_limits<int64_t>::min() &&
#     324         [ +  - ]:         38 :         n <= std::numeric_limits<int64_t>::max();
#     325                 :         38 : }
#     326                 :            : 
#     327                 :            : bool ParseUInt8(const std::string& str, uint8_t *out)
#     328                 :        214 : {
#     329                 :        214 :     uint32_t u32;
#     330 [ +  + ][ +  + ]:        214 :     if (!ParseUInt32(str, &u32) || u32 > std::numeric_limits<uint8_t>::max()) {
#     331                 :        130 :         return false;
#     332                 :        130 :     }
#     333         [ +  + ]:         84 :     if (out != nullptr) {
#     334                 :         82 :         *out = static_cast<uint8_t>(u32);
#     335                 :         82 :     }
#     336                 :         84 :     return true;
#     337                 :         84 : }
#     338                 :            : 
#     339                 :            : bool ParseUInt16(const std::string& str, uint16_t* out)
#     340                 :        483 : {
#     341                 :        483 :     uint32_t u32;
#     342 [ +  + ][ +  + ]:        483 :     if (!ParseUInt32(str, &u32) || u32 > std::numeric_limits<uint16_t>::max()) {
#     343                 :         38 :         return false;
#     344                 :         38 :     }
#     345         [ +  + ]:        445 :     if (out != nullptr) {
#     346                 :        443 :         *out = static_cast<uint16_t>(u32);
#     347                 :        443 :     }
#     348                 :        445 :     return true;
#     349                 :        445 : }
#     350                 :            : 
#     351                 :            : bool ParseUInt32(const std::string& str, uint32_t *out)
#     352                 :       9729 : {
#     353         [ +  + ]:       9729 :     if (!ParsePrechecks(str))
#     354                 :         35 :         return false;
#     355 [ +  - ][ +  + ]:       9694 :     if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoul accepts these by default if they fit in the range
#     356                 :         46 :         return false;
#     357                 :       9648 :     char *endp = nullptr;
#     358                 :       9648 :     errno = 0; // strtoul will not set errno if valid
#     359                 :       9648 :     unsigned long int n = strtoul(str.c_str(), &endp, 10);
#     360         [ +  + ]:       9648 :     if(out) *out = (uint32_t)n;
#     361                 :            :     // Note that strtoul returns a *unsigned long int*, so even if it doesn't report an over/underflow
#     362                 :            :     // we still have to check that the returned value is within the range of an *uint32_t*. On 64-bit
#     363                 :            :     // platforms the size of these types may be different.
#     364 [ +  - ][ +  + ]:       9648 :     return endp && *endp == 0 && !errno &&
#                 [ +  + ]
#     365         [ +  + ]:       9648 :         n <= std::numeric_limits<uint32_t>::max();
#     366                 :       9648 : }
#     367                 :            : 
#     368                 :            : bool ParseUInt64(const std::string& str, uint64_t *out)
#     369                 :         44 : {
#     370         [ +  + ]:         44 :     if (!ParsePrechecks(str))
#     371                 :         10 :         return false;
#     372 [ +  - ][ +  + ]:         34 :     if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoull accepts these by default if they fit in the range
#     373                 :         10 :         return false;
#     374                 :         24 :     char *endp = nullptr;
#     375                 :         24 :     errno = 0; // strtoull will not set errno if valid
#     376                 :         24 :     unsigned long long int n = strtoull(str.c_str(), &endp, 10);
#     377         [ +  + ]:         24 :     if(out) *out = (uint64_t)n;
#     378                 :            :     // Note that strtoull returns a *unsigned long long int*, so even if it doesn't report an over/underflow
#     379                 :            :     // we still have to check that the returned value is within the range of an *uint64_t*.
#     380 [ +  - ][ +  + ]:         24 :     return endp && *endp == 0 && !errno &&
#                 [ +  + ]
#     381         [ +  - ]:         24 :         n <= std::numeric_limits<uint64_t>::max();
#     382                 :         24 : }
#     383                 :            : 
#     384                 :            : 
#     385                 :            : bool ParseDouble(const std::string& str, double *out)
#     386                 :         36 : {
#     387         [ +  + ]:         36 :     if (!ParsePrechecks(str))
#     388                 :          8 :         return false;
#     389 [ +  + ][ +  + ]:         28 :     if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
#                 [ +  + ]
#     390                 :          2 :         return false;
#     391                 :         26 :     std::istringstream text(str);
#     392                 :         26 :     text.imbue(std::locale::classic());
#     393                 :         26 :     double result;
#     394                 :         26 :     text >> result;
#     395         [ +  + ]:         26 :     if(out) *out = result;
#     396 [ +  - ][ +  + ]:         26 :     return text.eof() && !text.fail();
#     397                 :         26 : }
#     398                 :            : 
#     399                 :            : std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
#     400                 :        155 : {
#     401                 :        155 :     std::stringstream out;
#     402                 :        155 :     size_t ptr = 0;
#     403                 :        155 :     size_t indented = 0;
#     404         [ +  + ]:        544 :     while (ptr < in.size())
#     405                 :        391 :     {
#     406                 :        391 :         size_t lineend = in.find_first_of('\n', ptr);
#     407         [ +  + ]:        391 :         if (lineend == std::string::npos) {
#     408                 :        366 :             lineend = in.size();
#     409                 :        366 :         }
#     410                 :        391 :         const size_t linelen = lineend - ptr;
#     411                 :        391 :         const size_t rem_width = width - indented;
#     412         [ +  + ]:        391 :         if (linelen <= rem_width) {
#     413                 :        169 :             out << in.substr(ptr, linelen + 1);
#     414                 :        169 :             ptr = lineend + 1;
#     415                 :        169 :             indented = 0;
#     416                 :        222 :         } else {
#     417                 :        222 :             size_t finalspace = in.find_last_of(" \n", ptr + rem_width);
#     418 [ +  + ][ +  + ]:        222 :             if (finalspace == std::string::npos || finalspace < ptr) {
#     419                 :            :                 // No place to break; just include the entire word and move on
#     420                 :          8 :                 finalspace = in.find_first_of("\n ", ptr);
#     421         [ +  + ]:          8 :                 if (finalspace == std::string::npos) {
#     422                 :            :                     // End of the string, just add it and break
#     423                 :          2 :                     out << in.substr(ptr);
#     424                 :          2 :                     break;
#     425                 :          2 :                 }
#     426                 :        220 :             }
#     427                 :        220 :             out << in.substr(ptr, finalspace - ptr) << "\n";
#     428         [ +  + ]:        220 :             if (in[finalspace] == '\n') {
#     429                 :          2 :                 indented = 0;
#     430         [ +  + ]:        218 :             } else if (indent) {
#     431                 :        200 :                 out << std::string(indent, ' ');
#     432                 :        200 :                 indented = indent;
#     433                 :        200 :             }
#     434                 :        220 :             ptr = finalspace + 1;
#     435                 :        220 :         }
#     436                 :        391 :     }
#     437                 :        155 :     return out.str();
#     438                 :        155 : }
#     439                 :            : 
#     440                 :            : int64_t atoi64(const std::string& str)
#     441                 :      88689 : {
#     442                 :            : #ifdef _MSC_VER
#     443                 :            :     return _atoi64(str.c_str());
#     444                 :            : #else
#     445                 :      88689 :     return strtoll(str.c_str(), nullptr, 10);
#     446                 :      88689 : #endif
#     447                 :      88689 : }
#     448                 :            : 
#     449                 :            : int atoi(const std::string& str)
#     450                 :     136227 : {
#     451                 :     136227 :     return atoi(str.c_str());
#     452                 :     136227 : }
#     453                 :            : 
#     454                 :            : /** Upper bound for mantissa.
#     455                 :            :  * 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer.
#     456                 :            :  * Larger integers cannot consist of arbitrary combinations of 0-9:
#     457                 :            :  *
#     458                 :            :  *   999999999999999999  1^18-1
#     459                 :            :  *  9223372036854775807  (1<<63)-1  (max int64_t)
#     460                 :            :  *  9999999999999999999  1^19-1     (would overflow)
#     461                 :            :  */
#     462                 :            : static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL;
#     463                 :            : 
#     464                 :            : /** Helper function for ParseFixedPoint */
#     465                 :            : static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros)
#     466                 :      82611 : {
#     467         [ +  + ]:      82611 :     if(ch == '0')
#     468                 :      21732 :         ++mantissa_tzeros;
#     469                 :      60879 :     else {
#     470         [ +  + ]:     136248 :         for (int i=0; i<=mantissa_tzeros; ++i) {
#     471         [ +  + ]:      75410 :             if (mantissa > (UPPER_BOUND / 10LL))
#     472                 :         41 :                 return false; /* overflow */
#     473                 :      75369 :             mantissa *= 10;
#     474                 :      75369 :         }
#     475                 :      60879 :         mantissa += ch - '0';
#     476                 :      60838 :         mantissa_tzeros = 0;
#     477                 :      60838 :     }
#     478                 :      82611 :     return true;
#     479                 :      82611 : }
#     480                 :            : 
#     481                 :            : bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
#     482                 :      29822 : {
#     483                 :      29822 :     int64_t mantissa = 0;
#     484                 :      29822 :     int64_t exponent = 0;
#     485                 :      29822 :     int mantissa_tzeros = 0;
#     486                 :      29822 :     bool mantissa_sign = false;
#     487                 :      29822 :     bool exponent_sign = false;
#     488                 :      29822 :     int ptr = 0;
#     489                 :      29822 :     int end = val.size();
#     490                 :      29822 :     int point_ofs = 0;
#     491                 :            : 
#     492 [ +  + ][ +  + ]:      29822 :     if (ptr < end && val[ptr] == '-') {
#     493                 :         55 :         mantissa_sign = true;
#     494                 :         55 :         ++ptr;
#     495                 :         55 :     }
#     496         [ +  + ]:      29822 :     if (ptr < end)
#     497                 :      29801 :     {
#     498         [ +  + ]:      29801 :         if (val[ptr] == '0') {
#     499                 :            :             /* pass single 0 */
#     500                 :      22406 :             ++ptr;
#     501 [ +  + ][ +  + ]:      22406 :         } else if (val[ptr] >= '1' && val[ptr] <= '9') {
#     502 [ +  + ][ +  + ]:      17390 :             while (ptr < end && IsDigit(val[ptr])) {
#     503         [ -  + ]:      10005 :                 if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
#     504                 :          0 :                     return false; /* overflow */
#     505                 :      10005 :                 ++ptr;
#     506                 :      10005 :             }
#     507                 :       7385 :         } else return false; /* missing expected digit */
#     508                 :         21 :     } else return false; /* empty string or loose '-' */
#     509 [ +  + ][ +  + ]:      29791 :     if (ptr < end && val[ptr] == '.')
#     510                 :      17210 :     {
#     511                 :      17210 :         ++ptr;
#     512 [ +  + ][ +  - ]:      17210 :         if (ptr < end && IsDigit(val[ptr]))
#     513                 :      17208 :         {
#     514 [ +  + ][ +  + ]:      89773 :             while (ptr < end && IsDigit(val[ptr])) {
#     515         [ +  + ]:      72606 :                 if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
#     516                 :         41 :                     return false; /* overflow */
#     517                 :      72565 :                 ++ptr;
#     518                 :      72565 :                 ++point_ofs;
#     519                 :      72565 :             }
#     520                 :      17208 :         } else return false; /* missing expected digit */
#     521                 :      29748 :     }
#     522 [ +  + ][ +  + ]:      29748 :     if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
#                 [ +  + ]
#     523                 :       4099 :     {
#     524                 :       4099 :         ++ptr;
#     525 [ +  + ][ +  + ]:       4099 :         if (ptr < end && val[ptr] == '+')
#     526                 :          8 :             ++ptr;
#     527 [ +  + ][ +  + ]:       4091 :         else if (ptr < end && val[ptr] == '-') {
#     528                 :       4083 :             exponent_sign = true;
#     529                 :       4083 :             ++ptr;
#     530                 :       4083 :         }
#     531 [ +  + ][ +  - ]:       4099 :         if (ptr < end && IsDigit(val[ptr])) {
#     532 [ +  + ][ +  - ]:      12263 :             while (ptr < end && IsDigit(val[ptr])) {
#     533         [ -  + ]:       8168 :                 if (exponent > (UPPER_BOUND / 10LL))
#     534                 :          0 :                     return false; /* overflow */
#     535                 :       8168 :                 exponent = exponent * 10 + val[ptr] - '0';
#     536                 :       8168 :                 ++ptr;
#     537                 :       8168 :             }
#     538                 :       4095 :         } else return false; /* missing expected digit */
#     539                 :      29744 :     }
#     540         [ +  + ]:      29744 :     if (ptr != end)
#     541                 :          8 :         return false; /* trailing garbage */
#     542                 :            : 
#     543                 :            :     /* finalize exponent */
#     544         [ +  + ]:      29736 :     if (exponent_sign)
#     545                 :       4081 :         exponent = -exponent;
#     546                 :      29736 :     exponent = exponent - point_ofs + mantissa_tzeros;
#     547                 :            : 
#     548                 :            :     /* finalize mantissa */
#     549         [ +  + ]:      29736 :     if (mantissa_sign)
#     550                 :         35 :         mantissa = -mantissa;
#     551                 :            : 
#     552                 :            :     /* convert to one 64-bit fixed-point value */
#     553                 :      29736 :     exponent += decimals;
#     554         [ +  + ]:      29736 :     if (exponent < 0)
#     555                 :        175 :         return false; /* cannot represent values smaller than 10^-decimals */
#     556         [ +  + ]:      29561 :     if (exponent >= 18)
#     557                 :          8 :         return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
#     558                 :            : 
#     559         [ +  + ]:     181060 :     for (int i=0; i < exponent; ++i) {
#     560 [ +  + ][ -  + ]:     151526 :         if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL))
#     561                 :         19 :             return false; /* overflow */
#     562                 :     151507 :         mantissa *= 10;
#     563                 :     151507 :     }
#     564 [ -  + ][ -  + ]:      29553 :     if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND)
#     565                 :          0 :         return false; /* overflow */
#     566                 :            : 
#     567         [ +  - ]:      29534 :     if (amount_out)
#     568                 :      29534 :         *amount_out = mantissa;
#     569                 :            : 
#     570                 :      29534 :     return true;
#     571                 :      29534 : }
#     572                 :            : 
#     573                 :            : std::string ToLower(const std::string& str)
#     574                 :         57 : {
#     575                 :         57 :     std::string r;
#     576         [ +  + ]:        404 :     for (auto ch : str) r += ToLower((unsigned char)ch);
#     577                 :         57 :     return r;
#     578                 :         57 : }
#     579                 :            : 
#     580                 :            : std::string ToUpper(const std::string& str)
#     581                 :        479 : {
#     582                 :        479 :     std::string r;
#     583         [ +  + ]:       3901 :     for (auto ch : str) r += ToUpper((unsigned char)ch);
#     584                 :        479 :     return r;
#     585                 :        479 : }
#     586                 :            : 
#     587                 :            : std::string Capitalize(std::string str)
#     588                 :         35 : {
#     589         [ +  + ]:         35 :     if (str.empty()) return str;
#     590                 :         33 :     str[0] = ToUpper(str.front());
#     591                 :         33 :     return str;
#     592                 :         33 : }
#     593                 :            : 
#     594                 :            : std::string HexStr(const Span<const uint8_t> s)
#     595                 :    6105590 : {
#     596                 :    6105590 :     std::string rv(s.size() * 2, '\0');
#     597                 :    6105590 :     static constexpr char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
#     598                 :    6105590 :                                          '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
#     599                 :    6105590 :     auto it = rv.begin();
#     600         [ +  + ]:  211728211 :     for (uint8_t v : s) {
#     601                 :  211728211 :         *it++ = hexmap[v >> 4];
#     602                 :  211728211 :         *it++ = hexmap[v & 15];
#     603                 :  211728211 :     }
#     604                 :    6105590 :     assert(it == rv.end());
#     605                 :    6105590 :     return rv;
#     606                 :    6105590 : }

Generated by: LCOV version 1.14