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