Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
2021-12-30 19:36:57 +02:00
|
|
|
// Copyright (c) 2009-2021 The Bitcoin Core developers
|
2014-11-17 11:04:01 +08:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
2018-10-22 15:51:11 -07:00
|
|
|
#include <util/strencodings.h>
|
2019-12-11 11:00:52 +00:00
|
|
|
#include <util/string.h>
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
|
2017-11-10 13:57:53 +13:00
|
|
|
#include <tinyformat.h>
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
|
2018-08-28 18:42:27 +02:00
|
|
|
#include <algorithm>
|
util: optimizes HexStr
In my benchmark, this rewrite improves runtime 27% (g++) to 46% (clang++) for the benchmark `HexStrBench`:
g++ 11.2.0
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.94 | 1,061,381,310.36 | 0.7% | 12.00 | 3.01 | 3.990 | 1.00 | 0.0% | 0.01 | `HexStrBench` master
| 0.68 | 1,465,366,544.25 | 1.7% | 6.00 | 2.16 | 2.778 | 1.00 | 0.0% | 0.01 | `HexStrBench` branch
clang++ 13.0.1
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.80 | 1,244,713,415.92 | 0.9% | 10.00 | 2.56 | 3.913 | 0.50 | 0.0% | 0.01 | `HexStrBench` master
| 0.43 | 2,324,188,940.72 | 0.2% | 4.00 | 1.37 | 2.914 | 0.25 | 0.0% | 0.01 | `HexStrBench` branch
Note that the idea for this change comes from denis2342 in PR 23364. This is a rewrite so no unaligned accesses occur.
Also, the lookup table is now calculated at compile time, which hopefully makes the code a bit easier to review.
2022-03-23 07:08:32 +01:00
|
|
|
#include <array>
|
2014-10-10 13:24:12 -04:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
2021-11-17 12:47:30 +02:00
|
|
|
#include <limits>
|
2021-09-18 04:30:30 +00:00
|
|
|
#include <optional>
|
2014-09-14 12:43:56 +02:00
|
|
|
|
2017-01-27 10:34:06 +09:00
|
|
|
static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
|
2017-01-27 10:34:06 +09:00
|
|
|
static const std::string SAFE_CHARS[] =
|
2015-09-09 14:24:56 +02:00
|
|
|
{
|
2015-09-23 12:06:00 +02:00
|
|
|
CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
|
2017-01-08 20:41:30 +00:00
|
|
|
CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
|
|
|
|
CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
|
2018-11-01 17:03:32 +01:00
|
|
|
CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI
|
2015-09-09 14:24:56 +02:00
|
|
|
};
|
|
|
|
|
2022-04-04 11:23:03 -04:00
|
|
|
std::string SanitizeString(std::string_view str, int rule)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
2022-04-04 11:23:03 -04:00
|
|
|
std::string result;
|
|
|
|
for (char c : str) {
|
|
|
|
if (SAFE_CHARS[rule].find(c) != std::string::npos) {
|
|
|
|
result.push_back(c);
|
|
|
|
}
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
2022-04-04 11:23:03 -04:00
|
|
|
return result;
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const signed char p_util_hexdigit[256] =
|
|
|
|
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
|
|
|
|
|
|
|
|
signed char HexDigit(char c)
|
|
|
|
{
|
|
|
|
return p_util_hexdigit[(unsigned char)c];
|
|
|
|
}
|
|
|
|
|
2022-04-04 11:12:04 -04:00
|
|
|
bool IsHex(std::string_view str)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
2022-04-04 11:12:04 -04:00
|
|
|
for (char c : str) {
|
|
|
|
if (HexDigit(c) < 0) return false;
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
return (str.size() > 0) && (str.size()%2 == 0);
|
|
|
|
}
|
|
|
|
|
2022-04-04 11:20:10 -04:00
|
|
|
bool IsHexNumber(std::string_view str)
|
2017-05-07 14:10:19 -04:00
|
|
|
{
|
2022-04-04 11:20:10 -04:00
|
|
|
if (str.substr(0, 2) == "0x") str.remove_prefix(2);
|
|
|
|
for (char c : str) {
|
2017-05-07 14:10:19 -04:00
|
|
|
if (HexDigit(c) < 0) return false;
|
|
|
|
}
|
|
|
|
// Return false for empty string or "0x".
|
2022-04-04 11:20:10 -04:00
|
|
|
return str.size() > 0;
|
2017-05-07 14:10:19 -04:00
|
|
|
}
|
|
|
|
|
2022-04-04 11:08:08 -04:00
|
|
|
std::vector<unsigned char> ParseHex(std::string_view str)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
|
|
|
// convert hex dump to vector
|
2017-01-27 10:34:06 +09:00
|
|
|
std::vector<unsigned char> vch;
|
2022-04-04 11:08:08 -04:00
|
|
|
auto it = str.begin();
|
|
|
|
while (it != str.end() && it + 1 != str.end()) {
|
|
|
|
if (IsSpace(*it)) {
|
|
|
|
++it;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto c1 = HexDigit(*(it++));
|
|
|
|
auto c2 = HexDigit(*(it++));
|
|
|
|
if (c1 < 0 || c2 < 0) break;
|
|
|
|
vch.push_back(uint8_t(c1 << 4) | c2);
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
return vch;
|
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
void SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut)
|
2021-03-01 21:35:28 +01:00
|
|
|
{
|
2017-07-12 16:55:28 -04:00
|
|
|
size_t colon = in.find_last_of(':');
|
|
|
|
// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
|
|
|
|
bool fHaveColon = colon != in.npos;
|
2021-03-06 21:17:50 +01:00
|
|
|
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
|
2022-02-09 13:26:38 +01:00
|
|
|
bool fMultiColon{fHaveColon && colon != 0 && (in.find_last_of(':', colon - 1) != in.npos)};
|
2021-03-06 21:17:50 +01:00
|
|
|
if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) {
|
2021-03-02 22:37:50 +01:00
|
|
|
uint16_t n;
|
|
|
|
if (ParseUInt16(in.substr(colon + 1), &n)) {
|
2017-07-12 16:55:28 -04:00
|
|
|
in = in.substr(0, colon);
|
|
|
|
portOut = n;
|
|
|
|
}
|
|
|
|
}
|
2021-03-06 21:17:50 +01:00
|
|
|
if (in.size() > 0 && in[0] == '[' && in[in.size() - 1] == ']') {
|
|
|
|
hostOut = in.substr(1, in.size() - 2);
|
|
|
|
} else {
|
2017-07-12 16:55:28 -04:00
|
|
|
hostOut = in;
|
2021-03-06 21:17:50 +01:00
|
|
|
}
|
2017-07-12 16:55:28 -04:00
|
|
|
}
|
|
|
|
|
2020-08-07 20:25:42 +02:00
|
|
|
std::string EncodeBase64(Span<const unsigned char> input)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
|
|
|
static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
|
|
|
2017-11-07 14:24:30 -08:00
|
|
|
std::string str;
|
2020-08-07 20:25:42 +02:00
|
|
|
str.reserve(((input.size() + 2) / 3) * 4);
|
|
|
|
ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, input.begin(), input.end());
|
2017-11-07 14:24:30 -08:00
|
|
|
while (str.size() % 4) str += '=';
|
|
|
|
return str;
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
|
2022-04-04 14:10:10 -04:00
|
|
|
std::optional<std::vector<unsigned char>> DecodeBase64(std::string_view str)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
2021-12-13 10:05:32 +01:00
|
|
|
static const int8_t decode64_table[256]{
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
|
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
|
|
|
|
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
|
|
|
49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
|
|
|
};
|
|
|
|
|
2022-04-04 14:10:10 -04:00
|
|
|
if (str.size() % 4 != 0) return {};
|
|
|
|
/* One or two = characters at the end are permitted. */
|
|
|
|
if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
|
|
|
|
if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
|
2017-11-07 14:24:30 -08:00
|
|
|
std::vector<unsigned char> ret;
|
2022-04-04 14:10:10 -04:00
|
|
|
ret.reserve((str.size() * 3) / 4);
|
|
|
|
bool valid = ConvertBits<6, 8, false>(
|
|
|
|
[&](unsigned char c) { ret.push_back(c); },
|
|
|
|
str.begin(), str.end(),
|
|
|
|
[](char c) { return decode64_table[uint8_t(c)]; }
|
|
|
|
);
|
2022-04-04 13:52:06 -04:00
|
|
|
if (!valid) return {};
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
|
2017-11-07 14:24:30 -08:00
|
|
|
return ret;
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
|
2020-08-27 11:03:21 +02:00
|
|
|
std::string EncodeBase32(Span<const unsigned char> input, bool pad)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
|
|
|
static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
|
|
|
|
|
2017-11-07 14:24:30 -08:00
|
|
|
std::string str;
|
2020-08-07 19:55:51 +02:00
|
|
|
str.reserve(((input.size() + 4) / 5) * 8);
|
|
|
|
ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, input.begin(), input.end());
|
2020-08-27 11:03:21 +02:00
|
|
|
if (pad) {
|
|
|
|
while (str.size() % 8) {
|
|
|
|
str += '=';
|
|
|
|
}
|
|
|
|
}
|
2017-11-07 14:24:30 -08:00
|
|
|
return str;
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
std::string EncodeBase32(std::string_view str, bool pad)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
2020-08-27 11:03:21 +02:00
|
|
|
return EncodeBase32(MakeUCharSpan(str), pad);
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
|
2022-04-04 14:10:10 -04:00
|
|
|
std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
2021-12-13 10:05:32 +01:00
|
|
|
static const int8_t decode32_table[256]{
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
|
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
|
|
|
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
|
|
|
23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
|
|
|
};
|
|
|
|
|
2022-04-04 14:10:10 -04:00
|
|
|
if (str.size() % 8 != 0) return {};
|
|
|
|
/* 1, 3, 4, or 6 padding '=' suffix characters are permitted. */
|
|
|
|
if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
|
|
|
|
if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2);
|
|
|
|
if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
|
|
|
|
if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2);
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
|
2017-11-07 14:24:30 -08:00
|
|
|
std::vector<unsigned char> ret;
|
2022-04-04 14:10:10 -04:00
|
|
|
ret.reserve((str.size() * 5) / 8);
|
|
|
|
bool valid = ConvertBits<5, 8, false>(
|
|
|
|
[&](unsigned char c) { ret.push_back(c); },
|
|
|
|
str.begin(), str.end(),
|
|
|
|
[](char c) { return decode32_table[uint8_t(c)]; }
|
|
|
|
);
|
2017-11-07 14:24:30 -08:00
|
|
|
|
2022-04-04 13:52:06 -04:00
|
|
|
if (!valid) return {};
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
|
2017-11-07 14:24:30 -08:00
|
|
|
return ret;
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
|
2021-09-18 04:30:30 +00:00
|
|
|
namespace {
|
|
|
|
template <typename T>
|
2022-04-04 15:05:47 -04:00
|
|
|
bool ParseIntegral(std::string_view str, T* out)
|
2021-09-18 04:30:30 +00:00
|
|
|
{
|
|
|
|
static_assert(std::is_integral<T>::value);
|
|
|
|
// Replicate the exact behavior of strtol/strtoll/strtoul/strtoull when
|
|
|
|
// handling leading +/- for backwards compatibility.
|
|
|
|
if (str.length() >= 2 && str[0] == '+' && str[1] == '-') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const std::optional<T> opt_int = ToIntegral<T>((!str.empty() && str[0] == '+') ? str.substr(1) : str);
|
|
|
|
if (!opt_int) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (out != nullptr) {
|
|
|
|
*out = *opt_int;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}; // namespace
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
bool ParseInt32(std::string_view str, int32_t* out)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
2021-09-18 04:30:30 +00:00
|
|
|
return ParseIntegral<int32_t>(str, out);
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
bool ParseInt64(std::string_view str, int64_t* out)
|
2015-06-04 12:03:09 +02:00
|
|
|
{
|
2021-09-18 04:30:30 +00:00
|
|
|
return ParseIntegral<int64_t>(str, out);
|
2015-06-04 12:03:09 +02:00
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
bool ParseUInt8(std::string_view str, uint8_t* out)
|
2020-08-24 21:34:26 +02:00
|
|
|
{
|
2021-09-18 04:30:30 +00:00
|
|
|
return ParseIntegral<uint8_t>(str, out);
|
2020-08-24 21:34:26 +02:00
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
bool ParseUInt16(std::string_view str, uint16_t* out)
|
2021-03-02 22:37:50 +01:00
|
|
|
{
|
2021-09-18 04:30:30 +00:00
|
|
|
return ParseIntegral<uint16_t>(str, out);
|
2021-03-02 22:37:50 +01:00
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
bool ParseUInt32(std::string_view str, uint32_t* out)
|
2016-06-08 10:23:25 +02:00
|
|
|
{
|
2021-09-18 04:30:30 +00:00
|
|
|
return ParseIntegral<uint32_t>(str, out);
|
2016-06-08 10:23:25 +02:00
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
bool ParseUInt64(std::string_view str, uint64_t* out)
|
2016-06-08 10:23:25 +02:00
|
|
|
{
|
2021-09-18 04:30:30 +00:00
|
|
|
return ParseIntegral<uint64_t>(str, out);
|
2016-06-08 10:23:25 +02:00
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
std::string FormatParagraph(std::string_view in, size_t width, size_t indent)
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
2022-02-09 14:38:56 +01:00
|
|
|
assert(width >= indent);
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
std::stringstream out;
|
|
|
|
size_t ptr = 0;
|
2016-02-03 05:16:49 +00:00
|
|
|
size_t indented = 0;
|
|
|
|
while (ptr < in.size())
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
{
|
2016-02-03 05:16:49 +00:00
|
|
|
size_t lineend = in.find_first_of('\n', ptr);
|
|
|
|
if (lineend == std::string::npos) {
|
|
|
|
lineend = in.size();
|
|
|
|
}
|
|
|
|
const size_t linelen = lineend - ptr;
|
|
|
|
const size_t rem_width = width - indented;
|
|
|
|
if (linelen <= rem_width) {
|
|
|
|
out << in.substr(ptr, linelen + 1);
|
|
|
|
ptr = lineend + 1;
|
|
|
|
indented = 0;
|
|
|
|
} else {
|
|
|
|
size_t finalspace = in.find_last_of(" \n", ptr + rem_width);
|
|
|
|
if (finalspace == std::string::npos || finalspace < ptr) {
|
|
|
|
// No place to break; just include the entire word and move on
|
|
|
|
finalspace = in.find_first_of("\n ", ptr);
|
|
|
|
if (finalspace == std::string::npos) {
|
|
|
|
// End of the string, just add it and break
|
|
|
|
out << in.substr(ptr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out << in.substr(ptr, finalspace - ptr) << "\n";
|
|
|
|
if (in[finalspace] == '\n') {
|
|
|
|
indented = 0;
|
|
|
|
} else if (indent) {
|
|
|
|
out << std::string(indent, ' ');
|
|
|
|
indented = indent;
|
|
|
|
}
|
|
|
|
ptr = finalspace + 1;
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return out.str();
|
|
|
|
}
|
|
|
|
|
2015-07-06 10:49:24 +02:00
|
|
|
/** Upper bound for mantissa.
|
|
|
|
* 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer.
|
|
|
|
* Larger integers cannot consist of arbitrary combinations of 0-9:
|
|
|
|
*
|
|
|
|
* 999999999999999999 1^18-1
|
|
|
|
* 9223372036854775807 (1<<63)-1 (max int64_t)
|
|
|
|
* 9999999999999999999 1^19-1 (would overflow)
|
|
|
|
*/
|
|
|
|
static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL;
|
|
|
|
|
|
|
|
/** Helper function for ParseFixedPoint */
|
|
|
|
static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros)
|
|
|
|
{
|
|
|
|
if(ch == '0')
|
|
|
|
++mantissa_tzeros;
|
|
|
|
else {
|
|
|
|
for (int i=0; i<=mantissa_tzeros; ++i) {
|
|
|
|
if (mantissa > (UPPER_BOUND / 10LL))
|
|
|
|
return false; /* overflow */
|
|
|
|
mantissa *= 10;
|
|
|
|
}
|
|
|
|
mantissa += ch - '0';
|
|
|
|
mantissa_tzeros = 0;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
bool ParseFixedPoint(std::string_view val, int decimals, int64_t *amount_out)
|
2015-07-06 10:49:24 +02:00
|
|
|
{
|
|
|
|
int64_t mantissa = 0;
|
|
|
|
int64_t exponent = 0;
|
|
|
|
int mantissa_tzeros = 0;
|
|
|
|
bool mantissa_sign = false;
|
|
|
|
bool exponent_sign = false;
|
|
|
|
int ptr = 0;
|
|
|
|
int end = val.size();
|
|
|
|
int point_ofs = 0;
|
|
|
|
|
|
|
|
if (ptr < end && val[ptr] == '-') {
|
|
|
|
mantissa_sign = true;
|
|
|
|
++ptr;
|
|
|
|
}
|
|
|
|
if (ptr < end)
|
|
|
|
{
|
|
|
|
if (val[ptr] == '0') {
|
|
|
|
/* pass single 0 */
|
|
|
|
++ptr;
|
|
|
|
} else if (val[ptr] >= '1' && val[ptr] <= '9') {
|
2018-07-22 21:34:45 +02:00
|
|
|
while (ptr < end && IsDigit(val[ptr])) {
|
2015-07-06 10:49:24 +02:00
|
|
|
if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
|
|
|
|
return false; /* overflow */
|
|
|
|
++ptr;
|
|
|
|
}
|
|
|
|
} else return false; /* missing expected digit */
|
|
|
|
} else return false; /* empty string or loose '-' */
|
|
|
|
if (ptr < end && val[ptr] == '.')
|
|
|
|
{
|
|
|
|
++ptr;
|
2018-07-22 21:34:45 +02:00
|
|
|
if (ptr < end && IsDigit(val[ptr]))
|
2015-07-06 10:49:24 +02:00
|
|
|
{
|
2018-07-22 21:34:45 +02:00
|
|
|
while (ptr < end && IsDigit(val[ptr])) {
|
2015-07-06 10:49:24 +02:00
|
|
|
if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
|
|
|
|
return false; /* overflow */
|
|
|
|
++ptr;
|
|
|
|
++point_ofs;
|
|
|
|
}
|
|
|
|
} else return false; /* missing expected digit */
|
|
|
|
}
|
|
|
|
if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
|
|
|
|
{
|
|
|
|
++ptr;
|
|
|
|
if (ptr < end && val[ptr] == '+')
|
|
|
|
++ptr;
|
|
|
|
else if (ptr < end && val[ptr] == '-') {
|
|
|
|
exponent_sign = true;
|
|
|
|
++ptr;
|
|
|
|
}
|
2018-07-22 21:34:45 +02:00
|
|
|
if (ptr < end && IsDigit(val[ptr])) {
|
|
|
|
while (ptr < end && IsDigit(val[ptr])) {
|
2015-07-06 10:49:24 +02:00
|
|
|
if (exponent > (UPPER_BOUND / 10LL))
|
|
|
|
return false; /* overflow */
|
|
|
|
exponent = exponent * 10 + val[ptr] - '0';
|
|
|
|
++ptr;
|
|
|
|
}
|
|
|
|
} else return false; /* missing expected digit */
|
|
|
|
}
|
|
|
|
if (ptr != end)
|
|
|
|
return false; /* trailing garbage */
|
|
|
|
|
|
|
|
/* finalize exponent */
|
|
|
|
if (exponent_sign)
|
|
|
|
exponent = -exponent;
|
|
|
|
exponent = exponent - point_ofs + mantissa_tzeros;
|
|
|
|
|
|
|
|
/* finalize mantissa */
|
|
|
|
if (mantissa_sign)
|
|
|
|
mantissa = -mantissa;
|
|
|
|
|
|
|
|
/* convert to one 64-bit fixed-point value */
|
|
|
|
exponent += decimals;
|
|
|
|
if (exponent < 0)
|
|
|
|
return false; /* cannot represent values smaller than 10^-decimals */
|
|
|
|
if (exponent >= 18)
|
|
|
|
return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
|
|
|
|
|
|
|
|
for (int i=0; i < exponent; ++i) {
|
|
|
|
if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL))
|
|
|
|
return false; /* overflow */
|
|
|
|
mantissa *= 10;
|
|
|
|
}
|
|
|
|
if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND)
|
|
|
|
return false; /* overflow */
|
|
|
|
|
|
|
|
if (amount_out)
|
|
|
|
*amount_out = mantissa;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
std::string ToLower(std::string_view str)
|
2018-08-28 18:42:27 +02:00
|
|
|
{
|
2019-08-07 13:42:54 +09:00
|
|
|
std::string r;
|
2021-12-13 10:04:50 +01:00
|
|
|
for (auto ch : str) r += ToLower(ch);
|
2019-08-07 13:42:54 +09:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
std::string ToUpper(std::string_view str)
|
2019-08-07 13:42:54 +09:00
|
|
|
{
|
|
|
|
std::string r;
|
2021-12-13 10:04:50 +01:00
|
|
|
for (auto ch : str) r += ToUpper(ch);
|
2019-08-07 13:42:54 +09:00
|
|
|
return r;
|
2018-08-28 18:42:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string Capitalize(std::string str)
|
|
|
|
{
|
|
|
|
if (str.empty()) return str;
|
|
|
|
str[0] = ToUpper(str.front());
|
|
|
|
return str;
|
|
|
|
}
|
2020-06-24 17:26:47 +02:00
|
|
|
|
util: optimizes HexStr
In my benchmark, this rewrite improves runtime 27% (g++) to 46% (clang++) for the benchmark `HexStrBench`:
g++ 11.2.0
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.94 | 1,061,381,310.36 | 0.7% | 12.00 | 3.01 | 3.990 | 1.00 | 0.0% | 0.01 | `HexStrBench` master
| 0.68 | 1,465,366,544.25 | 1.7% | 6.00 | 2.16 | 2.778 | 1.00 | 0.0% | 0.01 | `HexStrBench` branch
clang++ 13.0.1
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.80 | 1,244,713,415.92 | 0.9% | 10.00 | 2.56 | 3.913 | 0.50 | 0.0% | 0.01 | `HexStrBench` master
| 0.43 | 2,324,188,940.72 | 0.2% | 4.00 | 1.37 | 2.914 | 0.25 | 0.0% | 0.01 | `HexStrBench` branch
Note that the idea for this change comes from denis2342 in PR 23364. This is a rewrite so no unaligned accesses occur.
Also, the lookup table is now calculated at compile time, which hopefully makes the code a bit easier to review.
2022-03-23 07:08:32 +01:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
using ByteAsHex = std::array<char, 2>;
|
|
|
|
|
|
|
|
constexpr std::array<ByteAsHex, 256> CreateByteToHexMap()
|
|
|
|
{
|
|
|
|
constexpr char hexmap[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
|
|
|
|
|
|
|
std::array<ByteAsHex, 256> byte_to_hex{};
|
|
|
|
for (size_t i = 0; i < byte_to_hex.size(); ++i) {
|
|
|
|
byte_to_hex[i][0] = hexmap[i >> 4];
|
|
|
|
byte_to_hex[i][1] = hexmap[i & 15];
|
|
|
|
}
|
|
|
|
return byte_to_hex;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2020-06-24 17:26:47 +02:00
|
|
|
std::string HexStr(const Span<const uint8_t> s)
|
|
|
|
{
|
2021-02-14 12:10:15 +01:00
|
|
|
std::string rv(s.size() * 2, '\0');
|
util: optimizes HexStr
In my benchmark, this rewrite improves runtime 27% (g++) to 46% (clang++) for the benchmark `HexStrBench`:
g++ 11.2.0
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.94 | 1,061,381,310.36 | 0.7% | 12.00 | 3.01 | 3.990 | 1.00 | 0.0% | 0.01 | `HexStrBench` master
| 0.68 | 1,465,366,544.25 | 1.7% | 6.00 | 2.16 | 2.778 | 1.00 | 0.0% | 0.01 | `HexStrBench` branch
clang++ 13.0.1
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.80 | 1,244,713,415.92 | 0.9% | 10.00 | 2.56 | 3.913 | 0.50 | 0.0% | 0.01 | `HexStrBench` master
| 0.43 | 2,324,188,940.72 | 0.2% | 4.00 | 1.37 | 2.914 | 0.25 | 0.0% | 0.01 | `HexStrBench` branch
Note that the idea for this change comes from denis2342 in PR 23364. This is a rewrite so no unaligned accesses occur.
Also, the lookup table is now calculated at compile time, which hopefully makes the code a bit easier to review.
2022-03-23 07:08:32 +01:00
|
|
|
static constexpr auto byte_to_hex = CreateByteToHexMap();
|
|
|
|
static_assert(sizeof(byte_to_hex) == 512);
|
|
|
|
|
|
|
|
char* it = rv.data();
|
2021-02-14 12:10:15 +01:00
|
|
|
for (uint8_t v : s) {
|
util: optimizes HexStr
In my benchmark, this rewrite improves runtime 27% (g++) to 46% (clang++) for the benchmark `HexStrBench`:
g++ 11.2.0
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.94 | 1,061,381,310.36 | 0.7% | 12.00 | 3.01 | 3.990 | 1.00 | 0.0% | 0.01 | `HexStrBench` master
| 0.68 | 1,465,366,544.25 | 1.7% | 6.00 | 2.16 | 2.778 | 1.00 | 0.0% | 0.01 | `HexStrBench` branch
clang++ 13.0.1
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.80 | 1,244,713,415.92 | 0.9% | 10.00 | 2.56 | 3.913 | 0.50 | 0.0% | 0.01 | `HexStrBench` master
| 0.43 | 2,324,188,940.72 | 0.2% | 4.00 | 1.37 | 2.914 | 0.25 | 0.0% | 0.01 | `HexStrBench` branch
Note that the idea for this change comes from denis2342 in PR 23364. This is a rewrite so no unaligned accesses occur.
Also, the lookup table is now calculated at compile time, which hopefully makes the code a bit easier to review.
2022-03-23 07:08:32 +01:00
|
|
|
std::memcpy(it, byte_to_hex[v].data(), 2);
|
|
|
|
it += 2;
|
2020-06-24 17:26:47 +02:00
|
|
|
}
|
util: optimizes HexStr
In my benchmark, this rewrite improves runtime 27% (g++) to 46% (clang++) for the benchmark `HexStrBench`:
g++ 11.2.0
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.94 | 1,061,381,310.36 | 0.7% | 12.00 | 3.01 | 3.990 | 1.00 | 0.0% | 0.01 | `HexStrBench` master
| 0.68 | 1,465,366,544.25 | 1.7% | 6.00 | 2.16 | 2.778 | 1.00 | 0.0% | 0.01 | `HexStrBench` branch
clang++ 13.0.1
| ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 0.80 | 1,244,713,415.92 | 0.9% | 10.00 | 2.56 | 3.913 | 0.50 | 0.0% | 0.01 | `HexStrBench` master
| 0.43 | 2,324,188,940.72 | 0.2% | 4.00 | 1.37 | 2.914 | 0.25 | 0.0% | 0.01 | `HexStrBench` branch
Note that the idea for this change comes from denis2342 in PR 23364. This is a rewrite so no unaligned accesses occur.
Also, the lookup table is now calculated at compile time, which hopefully makes the code a bit easier to review.
2022-03-23 07:08:32 +01:00
|
|
|
|
|
|
|
assert(it == rv.data() + rv.size());
|
2020-06-24 17:26:47 +02:00
|
|
|
return rv;
|
|
|
|
}
|
2021-11-17 12:47:30 +02:00
|
|
|
|
2022-04-04 15:05:47 -04:00
|
|
|
std::optional<uint64_t> ParseByteUnits(std::string_view str, ByteUnit default_multiplier)
|
2021-11-17 12:47:30 +02:00
|
|
|
{
|
|
|
|
if (str.empty()) {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
auto multiplier = default_multiplier;
|
|
|
|
char unit = str.back();
|
|
|
|
switch (unit) {
|
|
|
|
case 'k':
|
|
|
|
multiplier = ByteUnit::k;
|
|
|
|
break;
|
|
|
|
case 'K':
|
|
|
|
multiplier = ByteUnit::K;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
multiplier = ByteUnit::m;
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
multiplier = ByteUnit::M;
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
multiplier = ByteUnit::g;
|
|
|
|
break;
|
|
|
|
case 'G':
|
|
|
|
multiplier = ByteUnit::G;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
multiplier = ByteUnit::t;
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
|
|
multiplier = ByteUnit::T;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
unit = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t unit_amount = static_cast<uint64_t>(multiplier);
|
|
|
|
auto parsed_num = ToIntegral<uint64_t>(unit ? str.substr(0, str.size() - 1) : str);
|
|
|
|
if (!parsed_num || parsed_num > std::numeric_limits<uint64_t>::max() / unit_amount) { // check overflow
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
return *parsed_num * unit_amount;
|
|
|
|
}
|