mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-05-31 00:05:13 +02:00
scripted-diff: Move util files to separate directory.
-BEGIN VERIFY SCRIPT- mkdir -p src/util git mv src/util.h src/util/system.h git mv src/util.cpp src/util/system.cpp git mv src/utilmemory.h src/util/memory.h git mv src/utilmoneystr.h src/util/moneystr.h git mv src/utilmoneystr.cpp src/util/moneystr.cpp git mv src/utilstrencodings.h src/util/strencodings.h git mv src/utilstrencodings.cpp src/util/strencodings.cpp git mv src/utiltime.h src/util/time.h git mv src/utiltime.cpp src/util/time.cpp sed -i 's/<util\.h>/<util\/system\.h>/g' $(git ls-files 'src/*.h' 'src/*.cpp') sed -i 's/<utilmemory\.h>/<util\/memory\.h>/g' $(git ls-files 'src/*.h' 'src/*.cpp') sed -i 's/<utilmoneystr\.h>/<util\/moneystr\.h>/g' $(git ls-files 'src/*.h' 'src/*.cpp') sed -i 's/<utilstrencodings\.h>/<util\/strencodings\.h>/g' $(git ls-files 'src/*.h' 'src/*.cpp') sed -i 's/<utiltime\.h>/<util\/time\.h>/g' $(git ls-files 'src/*.h' 'src/*.cpp') sed -i 's/BITCOIN_UTIL_H/BITCOIN_UTIL_SYSTEM_H/g' src/util/system.h sed -i 's/BITCOIN_UTILMEMORY_H/BITCOIN_UTIL_MEMORY_H/g' src/util/memory.h sed -i 's/BITCOIN_UTILMONEYSTR_H/BITCOIN_UTIL_MONEYSTR_H/g' src/util/moneystr.h sed -i 's/BITCOIN_UTILSTRENCODINGS_H/BITCOIN_UTIL_STRENCODINGS_H/g' src/util/strencodings.h sed -i 's/BITCOIN_UTILTIME_H/BITCOIN_UTIL_TIME_H/g' src/util/time.h sed -i 's/ util\.\(h\|cpp\)/ util\/system\.\1/g' src/Makefile.am sed -i 's/utilmemory\.\(h\|cpp\)/util\/memory\.\1/g' src/Makefile.am sed -i 's/utilmoneystr\.\(h\|cpp\)/util\/moneystr\.\1/g' src/Makefile.am sed -i 's/utilstrencodings\.\(h\|cpp\)/util\/strencodings\.\1/g' src/Makefile.am sed -i 's/utiltime\.\(h\|cpp\)/util\/time\.\1/g' src/Makefile.am sed -i 's/-> util ->/-> util\/system ->/' test/lint/lint-circular-dependencies.sh sed -i 's/src\/util\.cpp/src\/util\/system\.cpp/g' test/lint/lint-format-strings.py test/lint/lint-locale-dependence.sh sed -i 's/src\/utilmoneystr\.cpp/src\/util\/moneystr\.cpp/g' test/lint/lint-locale-dependence.sh sed -i 's/src\/utilstrencodings\.\(h\|cpp\)/src\/util\/strencodings\.\1/g' test/lint/lint-locale-dependence.sh sed -i 's/src\\utilstrencodings\.cpp/src\\util\\strencodings\.cpp/' build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj -END VERIFY SCRIPT-
This commit is contained in:
19
src/util/memory.h
Normal file
19
src/util/memory.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_UTIL_MEMORY_H
|
||||
#define BITCOIN_UTIL_MEMORY_H
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
//! Substitute for C++14 std::make_unique.
|
||||
template <typename T, typename... Args>
|
||||
std::unique_ptr<T> MakeUnique(Args&&... args)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
#endif
|
||||
77
src/util/moneystr.cpp
Normal file
77
src/util/moneystr.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <util/moneystr.h>
|
||||
|
||||
#include <primitives/transaction.h>
|
||||
#include <tinyformat.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
std::string FormatMoney(const CAmount& n)
|
||||
{
|
||||
// Note: not using straight sprintf here because we do NOT want
|
||||
// localized number formatting.
|
||||
int64_t n_abs = (n > 0 ? n : -n);
|
||||
int64_t quotient = n_abs/COIN;
|
||||
int64_t remainder = n_abs%COIN;
|
||||
std::string str = strprintf("%d.%08d", quotient, remainder);
|
||||
|
||||
// Right-trim excess zeros before the decimal point:
|
||||
int nTrim = 0;
|
||||
for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
|
||||
++nTrim;
|
||||
if (nTrim)
|
||||
str.erase(str.size()-nTrim, nTrim);
|
||||
|
||||
if (n < 0)
|
||||
str.insert((unsigned int)0, 1, '-');
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
bool ParseMoney(const std::string& str, CAmount& nRet)
|
||||
{
|
||||
return ParseMoney(str.c_str(), nRet);
|
||||
}
|
||||
|
||||
bool ParseMoney(const char* pszIn, CAmount& nRet)
|
||||
{
|
||||
std::string strWhole;
|
||||
int64_t nUnits = 0;
|
||||
const char* p = pszIn;
|
||||
while (IsSpace(*p))
|
||||
p++;
|
||||
for (; *p; p++)
|
||||
{
|
||||
if (*p == '.')
|
||||
{
|
||||
p++;
|
||||
int64_t nMult = COIN / 10;
|
||||
while (isdigit(*p) && (nMult > 0))
|
||||
{
|
||||
nUnits += nMult * (*p++ - '0');
|
||||
nMult /= 10;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (IsSpace(*p))
|
||||
break;
|
||||
if (!isdigit(*p))
|
||||
return false;
|
||||
strWhole.insert(strWhole.end(), *p);
|
||||
}
|
||||
for (; *p; p++)
|
||||
if (!IsSpace(*p))
|
||||
return false;
|
||||
if (strWhole.size() > 10) // guard against 63 bit overflow
|
||||
return false;
|
||||
if (nUnits < 0 || nUnits > COIN)
|
||||
return false;
|
||||
int64_t nWhole = atoi64(strWhole);
|
||||
CAmount nValue = nWhole*COIN + nUnits;
|
||||
|
||||
nRet = nValue;
|
||||
return true;
|
||||
}
|
||||
24
src/util/moneystr.h
Normal file
24
src/util/moneystr.h
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
/**
|
||||
* Money parsing/formatting utilities.
|
||||
*/
|
||||
#ifndef BITCOIN_UTIL_MONEYSTR_H
|
||||
#define BITCOIN_UTIL_MONEYSTR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include <amount.h>
|
||||
|
||||
/* Do not use these functions to represent or parse monetary amounts to or from
|
||||
* JSON but use AmountFromValue and ValueFromAmount for that.
|
||||
*/
|
||||
std::string FormatMoney(const CAmount& n);
|
||||
bool ParseMoney(const std::string& str, CAmount& nRet);
|
||||
bool ParseMoney(const char* pszIn, CAmount& nRet);
|
||||
|
||||
#endif // BITCOIN_UTIL_MONEYSTR_H
|
||||
599
src/util/strencodings.cpp
Normal file
599
src/util/strencodings.cpp
Normal file
@@ -0,0 +1,599 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <tinyformat.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
#include <limits>
|
||||
|
||||
static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
|
||||
static const std::string SAFE_CHARS[] =
|
||||
{
|
||||
CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
|
||||
CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
|
||||
CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
|
||||
};
|
||||
|
||||
std::string SanitizeString(const std::string& str, int rule)
|
||||
{
|
||||
std::string strResult;
|
||||
for (std::string::size_type i = 0; i < str.size(); i++)
|
||||
{
|
||||
if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
|
||||
strResult.push_back(str[i]);
|
||||
}
|
||||
return strResult;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
bool IsHex(const std::string& str)
|
||||
{
|
||||
for(std::string::const_iterator it(str.begin()); it != str.end(); ++it)
|
||||
{
|
||||
if (HexDigit(*it) < 0)
|
||||
return false;
|
||||
}
|
||||
return (str.size() > 0) && (str.size()%2 == 0);
|
||||
}
|
||||
|
||||
bool IsHexNumber(const std::string& str)
|
||||
{
|
||||
size_t starting_location = 0;
|
||||
if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
|
||||
starting_location = 2;
|
||||
}
|
||||
for (const char c : str.substr(starting_location)) {
|
||||
if (HexDigit(c) < 0) return false;
|
||||
}
|
||||
// Return false for empty string or "0x".
|
||||
return (str.size() > starting_location);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> ParseHex(const char* psz)
|
||||
{
|
||||
// convert hex dump to vector
|
||||
std::vector<unsigned char> vch;
|
||||
while (true)
|
||||
{
|
||||
while (IsSpace(*psz))
|
||||
psz++;
|
||||
signed char c = HexDigit(*psz++);
|
||||
if (c == (signed char)-1)
|
||||
break;
|
||||
unsigned char n = (c << 4);
|
||||
c = HexDigit(*psz++);
|
||||
if (c == (signed char)-1)
|
||||
break;
|
||||
n |= c;
|
||||
vch.push_back(n);
|
||||
}
|
||||
return vch;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> ParseHex(const std::string& str)
|
||||
{
|
||||
return ParseHex(str.c_str());
|
||||
}
|
||||
|
||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
|
||||
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;
|
||||
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
|
||||
bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
|
||||
if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
|
||||
int32_t n;
|
||||
if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
|
||||
in = in.substr(0, colon);
|
||||
portOut = n;
|
||||
}
|
||||
}
|
||||
if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
|
||||
hostOut = in.substr(1, in.size()-2);
|
||||
else
|
||||
hostOut = in;
|
||||
}
|
||||
|
||||
std::string EncodeBase64(const unsigned char* pch, size_t len)
|
||||
{
|
||||
static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
std::string str;
|
||||
str.reserve(((len + 2) / 3) * 4);
|
||||
ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, pch, pch + len);
|
||||
while (str.size() % 4) str += '=';
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string EncodeBase64(const std::string& str)
|
||||
{
|
||||
return EncodeBase64((const unsigned char*)str.c_str(), str.size());
|
||||
}
|
||||
|
||||
std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
|
||||
{
|
||||
static const int decode64_table[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, 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
|
||||
};
|
||||
|
||||
const char* e = p;
|
||||
std::vector<uint8_t> val;
|
||||
val.reserve(strlen(p));
|
||||
while (*p != 0) {
|
||||
int x = decode64_table[(unsigned char)*p];
|
||||
if (x == -1) break;
|
||||
val.push_back(x);
|
||||
++p;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> ret;
|
||||
ret.reserve((val.size() * 3) / 4);
|
||||
bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
|
||||
|
||||
const char* q = p;
|
||||
while (valid && *p != 0) {
|
||||
if (*p != '=') {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
valid = valid && (p - e) % 4 == 0 && p - q < 4;
|
||||
if (pfInvalid) *pfInvalid = !valid;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string DecodeBase64(const std::string& str)
|
||||
{
|
||||
std::vector<unsigned char> vchRet = DecodeBase64(str.c_str());
|
||||
return std::string((const char*)vchRet.data(), vchRet.size());
|
||||
}
|
||||
|
||||
std::string EncodeBase32(const unsigned char* pch, size_t len)
|
||||
{
|
||||
static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
|
||||
|
||||
std::string str;
|
||||
str.reserve(((len + 4) / 5) * 8);
|
||||
ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, pch, pch + len);
|
||||
while (str.size() % 8) str += '=';
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string EncodeBase32(const std::string& str)
|
||||
{
|
||||
return EncodeBase32((const unsigned char*)str.c_str(), str.size());
|
||||
}
|
||||
|
||||
std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
|
||||
{
|
||||
static const int decode32_table[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, -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
|
||||
};
|
||||
|
||||
const char* e = p;
|
||||
std::vector<uint8_t> val;
|
||||
val.reserve(strlen(p));
|
||||
while (*p != 0) {
|
||||
int x = decode32_table[(unsigned char)*p];
|
||||
if (x == -1) break;
|
||||
val.push_back(x);
|
||||
++p;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> ret;
|
||||
ret.reserve((val.size() * 5) / 8);
|
||||
bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
|
||||
|
||||
const char* q = p;
|
||||
while (valid && *p != 0) {
|
||||
if (*p != '=') {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
valid = valid && (p - e) % 8 == 0 && p - q < 8;
|
||||
if (pfInvalid) *pfInvalid = !valid;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string DecodeBase32(const std::string& str)
|
||||
{
|
||||
std::vector<unsigned char> vchRet = DecodeBase32(str.c_str());
|
||||
return std::string((const char*)vchRet.data(), vchRet.size());
|
||||
}
|
||||
|
||||
static bool ParsePrechecks(const std::string& str)
|
||||
{
|
||||
if (str.empty()) // No empty string allowed
|
||||
return false;
|
||||
if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size()-1]))) // No padding allowed
|
||||
return false;
|
||||
if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseInt32(const std::string& str, int32_t *out)
|
||||
{
|
||||
if (!ParsePrechecks(str))
|
||||
return false;
|
||||
char *endp = nullptr;
|
||||
errno = 0; // strtol will not set errno if valid
|
||||
long int n = strtol(str.c_str(), &endp, 10);
|
||||
if(out) *out = (int32_t)n;
|
||||
// Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow
|
||||
// we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
|
||||
// platforms the size of these types may be different.
|
||||
return endp && *endp == 0 && !errno &&
|
||||
n >= std::numeric_limits<int32_t>::min() &&
|
||||
n <= std::numeric_limits<int32_t>::max();
|
||||
}
|
||||
|
||||
bool ParseInt64(const std::string& str, int64_t *out)
|
||||
{
|
||||
if (!ParsePrechecks(str))
|
||||
return false;
|
||||
char *endp = nullptr;
|
||||
errno = 0; // strtoll will not set errno if valid
|
||||
long long int n = strtoll(str.c_str(), &endp, 10);
|
||||
if(out) *out = (int64_t)n;
|
||||
// Note that strtoll returns a *long long int*, so even if strtol doesn't report an over/underflow
|
||||
// we still have to check that the returned value is within the range of an *int64_t*.
|
||||
return endp && *endp == 0 && !errno &&
|
||||
n >= std::numeric_limits<int64_t>::min() &&
|
||||
n <= std::numeric_limits<int64_t>::max();
|
||||
}
|
||||
|
||||
bool ParseUInt32(const std::string& str, uint32_t *out)
|
||||
{
|
||||
if (!ParsePrechecks(str))
|
||||
return false;
|
||||
if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoul accepts these by default if they fit in the range
|
||||
return false;
|
||||
char *endp = nullptr;
|
||||
errno = 0; // strtoul will not set errno if valid
|
||||
unsigned long int n = strtoul(str.c_str(), &endp, 10);
|
||||
if(out) *out = (uint32_t)n;
|
||||
// Note that strtoul returns a *unsigned long int*, so even if it doesn't report an over/underflow
|
||||
// we still have to check that the returned value is within the range of an *uint32_t*. On 64-bit
|
||||
// platforms the size of these types may be different.
|
||||
return endp && *endp == 0 && !errno &&
|
||||
n <= std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
|
||||
bool ParseUInt64(const std::string& str, uint64_t *out)
|
||||
{
|
||||
if (!ParsePrechecks(str))
|
||||
return false;
|
||||
if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoull accepts these by default if they fit in the range
|
||||
return false;
|
||||
char *endp = nullptr;
|
||||
errno = 0; // strtoull will not set errno if valid
|
||||
unsigned long long int n = strtoull(str.c_str(), &endp, 10);
|
||||
if(out) *out = (uint64_t)n;
|
||||
// Note that strtoull returns a *unsigned long long int*, so even if it doesn't report an over/underflow
|
||||
// we still have to check that the returned value is within the range of an *uint64_t*.
|
||||
return endp && *endp == 0 && !errno &&
|
||||
n <= std::numeric_limits<uint64_t>::max();
|
||||
}
|
||||
|
||||
|
||||
bool ParseDouble(const std::string& str, double *out)
|
||||
{
|
||||
if (!ParsePrechecks(str))
|
||||
return false;
|
||||
if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
|
||||
return false;
|
||||
std::istringstream text(str);
|
||||
text.imbue(std::locale::classic());
|
||||
double result;
|
||||
text >> result;
|
||||
if(out) *out = result;
|
||||
return text.eof() && !text.fail();
|
||||
}
|
||||
|
||||
std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
|
||||
{
|
||||
std::stringstream out;
|
||||
size_t ptr = 0;
|
||||
size_t indented = 0;
|
||||
while (ptr < in.size())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string i64tostr(int64_t n)
|
||||
{
|
||||
return strprintf("%d", n);
|
||||
}
|
||||
|
||||
std::string itostr(int n)
|
||||
{
|
||||
return strprintf("%d", n);
|
||||
}
|
||||
|
||||
int64_t atoi64(const char* psz)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _atoi64(psz);
|
||||
#else
|
||||
return strtoll(psz, nullptr, 10);
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t atoi64(const std::string& str)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _atoi64(str.c_str());
|
||||
#else
|
||||
return strtoll(str.c_str(), nullptr, 10);
|
||||
#endif
|
||||
}
|
||||
|
||||
int atoi(const std::string& str)
|
||||
{
|
||||
return atoi(str.c_str());
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
|
||||
{
|
||||
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') {
|
||||
while (ptr < end && IsDigit(val[ptr])) {
|
||||
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;
|
||||
if (ptr < end && IsDigit(val[ptr]))
|
||||
{
|
||||
while (ptr < end && IsDigit(val[ptr])) {
|
||||
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;
|
||||
}
|
||||
if (ptr < end && IsDigit(val[ptr])) {
|
||||
while (ptr < end && IsDigit(val[ptr])) {
|
||||
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;
|
||||
}
|
||||
|
||||
bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath)
|
||||
{
|
||||
std::stringstream ss(keypath_str);
|
||||
std::string item;
|
||||
bool first = true;
|
||||
while (std::getline(ss, item, '/')) {
|
||||
if (item.compare("m") == 0) {
|
||||
if (first) {
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Finds whether it is hardened
|
||||
uint32_t path = 0;
|
||||
size_t pos = item.find("'");
|
||||
if (pos != std::string::npos) {
|
||||
// The hardened tick can only be in the last index of the string
|
||||
if (pos != item.size() - 1) {
|
||||
return false;
|
||||
}
|
||||
path |= 0x80000000;
|
||||
item = item.substr(0, item.size() - 1); // Drop the last character which is the hardened tick
|
||||
}
|
||||
|
||||
// Ensure this is only numbers
|
||||
if (item.find_first_not_of( "0123456789" ) != std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
uint32_t number;
|
||||
if (!ParseUInt32(item, &number)) {
|
||||
return false;
|
||||
}
|
||||
path |= number;
|
||||
|
||||
keypath.push_back(path);
|
||||
first = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Downcase(std::string& str)
|
||||
{
|
||||
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c){return ToLower(c);});
|
||||
}
|
||||
|
||||
std::string Capitalize(std::string str)
|
||||
{
|
||||
if (str.empty()) return str;
|
||||
str[0] = ToUpper(str.front());
|
||||
return str;
|
||||
}
|
||||
248
src/util/strencodings.h
Normal file
248
src/util/strencodings.h
Normal file
@@ -0,0 +1,248 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
/**
|
||||
* Utilities for converting data from/to strings.
|
||||
*/
|
||||
#ifndef BITCOIN_UTIL_STRENCODINGS_H
|
||||
#define BITCOIN_UTIL_STRENCODINGS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define BEGIN(a) ((char*)&(a))
|
||||
#define END(a) ((char*)&((&(a))[1]))
|
||||
#define UBEGIN(a) ((unsigned char*)&(a))
|
||||
#define UEND(a) ((unsigned char*)&((&(a))[1]))
|
||||
#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
|
||||
|
||||
/** Used by SanitizeString() */
|
||||
enum SafeChars
|
||||
{
|
||||
SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
|
||||
SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
|
||||
SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove unsafe chars. Safe chars chosen to allow simple messages/URLs/email
|
||||
* addresses, but avoid anything even possibly remotely dangerous like & or >
|
||||
* @param[in] str The string to sanitize
|
||||
* @param[in] rule The set of safe chars to choose (default: least restrictive)
|
||||
* @return A new string without unsafe chars
|
||||
*/
|
||||
std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT);
|
||||
std::vector<unsigned char> ParseHex(const char* psz);
|
||||
std::vector<unsigned char> ParseHex(const std::string& str);
|
||||
signed char HexDigit(char c);
|
||||
/* Returns true if each character in str is a hex character, and has an even
|
||||
* number of hex digits.*/
|
||||
bool IsHex(const std::string& str);
|
||||
/**
|
||||
* Return true if the string is a hex number, optionally prefixed with "0x"
|
||||
*/
|
||||
bool IsHexNumber(const std::string& str);
|
||||
std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = nullptr);
|
||||
std::string DecodeBase64(const std::string& str);
|
||||
std::string EncodeBase64(const unsigned char* pch, size_t len);
|
||||
std::string EncodeBase64(const std::string& str);
|
||||
std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = nullptr);
|
||||
std::string DecodeBase32(const std::string& str);
|
||||
std::string EncodeBase32(const unsigned char* pch, size_t len);
|
||||
std::string EncodeBase32(const std::string& str);
|
||||
|
||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
|
||||
std::string i64tostr(int64_t n);
|
||||
std::string itostr(int n);
|
||||
int64_t atoi64(const char* psz);
|
||||
int64_t atoi64(const std::string& str);
|
||||
int atoi(const std::string& str);
|
||||
|
||||
/**
|
||||
* Tests if the given character is a decimal digit.
|
||||
* @param[in] c character to test
|
||||
* @return true if the argument is a decimal digit; otherwise false.
|
||||
*/
|
||||
constexpr bool IsDigit(char c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the given character is a whitespace character. The whitespace characters
|
||||
* are: space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal
|
||||
* tab ('\t'), and vertical tab ('\v').
|
||||
*
|
||||
* This function is locale independent. Under the C locale this function gives the
|
||||
* same result as std::isspace.
|
||||
*
|
||||
* @param[in] c character to test
|
||||
* @return true if the argument is a whitespace character; otherwise false
|
||||
*/
|
||||
constexpr inline bool IsSpace(char c) noexcept {
|
||||
return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string to signed 32-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
bool ParseInt32(const std::string& str, int32_t *out);
|
||||
|
||||
/**
|
||||
* Convert string to signed 64-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
bool ParseInt64(const std::string& str, int64_t *out);
|
||||
|
||||
/**
|
||||
* Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
bool ParseUInt32(const std::string& str, uint32_t *out);
|
||||
|
||||
/**
|
||||
* Convert decimal string to unsigned 64-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
bool ParseUInt64(const std::string& str, uint64_t *out);
|
||||
|
||||
/**
|
||||
* Convert string to double with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid double,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
bool ParseDouble(const std::string& str, double *out);
|
||||
|
||||
template<typename T>
|
||||
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
|
||||
{
|
||||
std::string rv;
|
||||
static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
rv.reserve((itend-itbegin)*3);
|
||||
for(T it = itbegin; it < itend; ++it)
|
||||
{
|
||||
unsigned char val = (unsigned char)(*it);
|
||||
if(fSpaces && it != itbegin)
|
||||
rv.push_back(' ');
|
||||
rv.push_back(hexmap[val>>4]);
|
||||
rv.push_back(hexmap[val&15]);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::string HexStr(const T& vch, bool fSpaces=false)
|
||||
{
|
||||
return HexStr(vch.begin(), vch.end(), fSpaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a paragraph of text to a fixed width, adding spaces for
|
||||
* indentation to any added line.
|
||||
*/
|
||||
std::string FormatParagraph(const std::string& in, size_t width = 79, size_t indent = 0);
|
||||
|
||||
/**
|
||||
* Timing-attack-resistant comparison.
|
||||
* Takes time proportional to length
|
||||
* of first argument.
|
||||
*/
|
||||
template <typename T>
|
||||
bool TimingResistantEqual(const T& a, const T& b)
|
||||
{
|
||||
if (b.size() == 0) return a.size() == 0;
|
||||
size_t accumulator = a.size() ^ b.size();
|
||||
for (size_t i = 0; i < a.size(); i++)
|
||||
accumulator |= a[i] ^ b[i%b.size()];
|
||||
return accumulator == 0;
|
||||
}
|
||||
|
||||
/** Parse number as fixed point according to JSON number syntax.
|
||||
* See http://json.org/number.gif
|
||||
* @returns true on success, false on error.
|
||||
* @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger.
|
||||
*/
|
||||
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out);
|
||||
|
||||
/** Convert from one power-of-2 number base to another. */
|
||||
template<int frombits, int tobits, bool pad, typename O, typename I>
|
||||
bool ConvertBits(const O& outfn, I it, I end) {
|
||||
size_t acc = 0;
|
||||
size_t bits = 0;
|
||||
constexpr size_t maxv = (1 << tobits) - 1;
|
||||
constexpr size_t max_acc = (1 << (frombits + tobits - 1)) - 1;
|
||||
while (it != end) {
|
||||
acc = ((acc << frombits) | *it) & max_acc;
|
||||
bits += frombits;
|
||||
while (bits >= tobits) {
|
||||
bits -= tobits;
|
||||
outfn((acc >> bits) & maxv);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
if (pad) {
|
||||
if (bits) outfn((acc << (tobits - bits)) & maxv);
|
||||
} else if (bits >= frombits || ((acc << (tobits - bits)) & maxv)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Parse an HD keypaths like "m/7/0'/2000". */
|
||||
bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath);
|
||||
|
||||
/**
|
||||
* Converts the given character to its lowercase equivalent.
|
||||
* This function is locale independent. It only converts uppercase
|
||||
* characters in the standard 7-bit ASCII range.
|
||||
* @param[in] c the character to convert to lowercase.
|
||||
* @return the lowercase equivalent of c; or the argument
|
||||
* if no conversion is possible.
|
||||
*/
|
||||
constexpr unsigned char ToLower(unsigned char c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z' ? (c - 'A') + 'a' : c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given string to its lowercase equivalent.
|
||||
* This function is locale independent. It only converts uppercase
|
||||
* characters in the standard 7-bit ASCII range.
|
||||
* @param[in,out] str the string to convert to lowercase.
|
||||
*/
|
||||
void Downcase(std::string& str);
|
||||
|
||||
/**
|
||||
* Converts the given character to its uppercase equivalent.
|
||||
* This function is locale independent. It only converts lowercase
|
||||
* characters in the standard 7-bit ASCII range.
|
||||
* @param[in] c the character to convert to uppercase.
|
||||
* @return the uppercase equivalent of c; or the argument
|
||||
* if no conversion is possible.
|
||||
*/
|
||||
constexpr unsigned char ToUpper(unsigned char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Capitalizes the first character of the given string.
|
||||
* This function is locale independent. It only capitalizes the
|
||||
* first character of the argument if it has an uppercase equivalent
|
||||
* in the standard 7-bit ASCII range.
|
||||
* @param[in] str the string to capitalize.
|
||||
* @return string with the first letter capitalized.
|
||||
*/
|
||||
std::string Capitalize(std::string str);
|
||||
|
||||
#endif // BITCOIN_UTIL_STRENCODINGS_H
|
||||
1299
src/util/system.cpp
Normal file
1299
src/util/system.cpp
Normal file
File diff suppressed because it is too large
Load Diff
382
src/util/system.h
Normal file
382
src/util/system.h
Normal file
@@ -0,0 +1,382 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
/**
|
||||
* Server/client environment: argument handling, config file parsing,
|
||||
* thread wrappers, startup time
|
||||
*/
|
||||
#ifndef BITCOIN_UTIL_SYSTEM_H
|
||||
#define BITCOIN_UTIL_SYSTEM_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config/bitcoin-config.h>
|
||||
#endif
|
||||
|
||||
#include <compat.h>
|
||||
#include <fs.h>
|
||||
#include <logging.h>
|
||||
#include <sync.h>
|
||||
#include <tinyformat.h>
|
||||
#include <util/memory.h>
|
||||
#include <util/time.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/thread/condition_variable.hpp> // for boost::thread_interrupted
|
||||
|
||||
// Application startup time (used for uptime calculation)
|
||||
int64_t GetStartupTime();
|
||||
|
||||
extern const char * const BITCOIN_CONF_FILENAME;
|
||||
extern const char * const BITCOIN_PID_FILENAME;
|
||||
|
||||
/** Translate a message to the native language of the user. */
|
||||
const extern std::function<std::string(const char*)> G_TRANSLATION_FUN;
|
||||
|
||||
/**
|
||||
* Translation function.
|
||||
* If no translation function is set, simply return the input.
|
||||
*/
|
||||
inline std::string _(const char* psz)
|
||||
{
|
||||
return G_TRANSLATION_FUN ? (G_TRANSLATION_FUN)(psz) : psz;
|
||||
}
|
||||
|
||||
void SetupEnvironment();
|
||||
bool SetupNetworking();
|
||||
|
||||
template<typename... Args>
|
||||
bool error(const char* fmt, const Args&... args)
|
||||
{
|
||||
LogPrintf("ERROR: %s\n", tfm::format(fmt, args...));
|
||||
return false;
|
||||
}
|
||||
|
||||
void PrintExceptionContinue(const std::exception *pex, const char* pszThread);
|
||||
bool FileCommit(FILE *file);
|
||||
bool TruncateFile(FILE *file, unsigned int length);
|
||||
int RaiseFileDescriptorLimit(int nMinFD);
|
||||
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
|
||||
bool RenameOver(fs::path src, fs::path dest);
|
||||
bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false);
|
||||
bool DirIsWritable(const fs::path& directory);
|
||||
|
||||
/** Release all directory locks. This is used for unit testing only, at runtime
|
||||
* the global destructor will take care of the locks.
|
||||
*/
|
||||
void ReleaseDirectoryLocks();
|
||||
|
||||
bool TryCreateDirectories(const fs::path& p);
|
||||
fs::path GetDefaultDataDir();
|
||||
const fs::path &GetBlocksDir(bool fNetSpecific = true);
|
||||
const fs::path &GetDataDir(bool fNetSpecific = true);
|
||||
void ClearDatadirCache();
|
||||
fs::path GetConfigFile(const std::string& confPath);
|
||||
#ifndef WIN32
|
||||
fs::path GetPidFile();
|
||||
void CreatePidFile(const fs::path &path, pid_t pid);
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
|
||||
#endif
|
||||
void runCommand(const std::string& strCommand);
|
||||
|
||||
/**
|
||||
* Most paths passed as configuration arguments are treated as relative to
|
||||
* the datadir if they are not absolute.
|
||||
*
|
||||
* @param path The path to be conditionally prefixed with datadir.
|
||||
* @param net_specific Forwarded to GetDataDir().
|
||||
* @return The normalized path.
|
||||
*/
|
||||
fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific = true);
|
||||
|
||||
inline bool IsSwitchChar(char c)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return c == '-' || c == '/';
|
||||
#else
|
||||
return c == '-';
|
||||
#endif
|
||||
}
|
||||
|
||||
enum class OptionsCategory {
|
||||
OPTIONS,
|
||||
CONNECTION,
|
||||
WALLET,
|
||||
WALLET_DEBUG_TEST,
|
||||
ZMQ,
|
||||
DEBUG_TEST,
|
||||
CHAINPARAMS,
|
||||
NODE_RELAY,
|
||||
BLOCK_CREATION,
|
||||
RPC,
|
||||
GUI,
|
||||
COMMANDS,
|
||||
REGISTER_COMMANDS,
|
||||
|
||||
HIDDEN // Always the last option to avoid printing these in the help
|
||||
};
|
||||
|
||||
class ArgsManager
|
||||
{
|
||||
protected:
|
||||
friend class ArgsManagerHelper;
|
||||
|
||||
struct Arg
|
||||
{
|
||||
std::string m_help_param;
|
||||
std::string m_help_text;
|
||||
bool m_debug_only;
|
||||
|
||||
Arg(const std::string& help_param, const std::string& help_text, bool debug_only) : m_help_param(help_param), m_help_text(help_text), m_debug_only(debug_only) {};
|
||||
};
|
||||
|
||||
mutable CCriticalSection cs_args;
|
||||
std::map<std::string, std::vector<std::string>> m_override_args GUARDED_BY(cs_args);
|
||||
std::map<std::string, std::vector<std::string>> m_config_args GUARDED_BY(cs_args);
|
||||
std::string m_network GUARDED_BY(cs_args);
|
||||
std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
|
||||
std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
|
||||
|
||||
bool ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys = false);
|
||||
|
||||
public:
|
||||
ArgsManager();
|
||||
|
||||
/**
|
||||
* Select the network in use
|
||||
*/
|
||||
void SelectConfigNetwork(const std::string& network);
|
||||
|
||||
bool ParseParameters(int argc, const char* const argv[], std::string& error);
|
||||
bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false);
|
||||
|
||||
/**
|
||||
* Log warnings for options in m_section_only_args when
|
||||
* they are specified in the default section but not overridden
|
||||
* on the command line or in a network-specific section in the
|
||||
* config file.
|
||||
*/
|
||||
void WarnForSectionOnlyArgs();
|
||||
|
||||
/**
|
||||
* Return a vector of strings of the given argument
|
||||
*
|
||||
* @param strArg Argument to get (e.g. "-foo")
|
||||
* @return command-line arguments
|
||||
*/
|
||||
std::vector<std::string> GetArgs(const std::string& strArg) const;
|
||||
|
||||
/**
|
||||
* Return true if the given argument has been manually set
|
||||
*
|
||||
* @param strArg Argument to get (e.g. "-foo")
|
||||
* @return true if the argument has been set
|
||||
*/
|
||||
bool IsArgSet(const std::string& strArg) const;
|
||||
|
||||
/**
|
||||
* Return true if the argument was originally passed as a negated option,
|
||||
* i.e. -nofoo.
|
||||
*
|
||||
* @param strArg Argument to get (e.g. "-foo")
|
||||
* @return true if the argument was passed negated
|
||||
*/
|
||||
bool IsArgNegated(const std::string& strArg) const;
|
||||
|
||||
/**
|
||||
* Return string argument or default value
|
||||
*
|
||||
* @param strArg Argument to get (e.g. "-foo")
|
||||
* @param strDefault (e.g. "1")
|
||||
* @return command-line argument or default value
|
||||
*/
|
||||
std::string GetArg(const std::string& strArg, const std::string& strDefault) const;
|
||||
|
||||
/**
|
||||
* Return integer argument or default value
|
||||
*
|
||||
* @param strArg Argument to get (e.g. "-foo")
|
||||
* @param nDefault (e.g. 1)
|
||||
* @return command-line argument (0 if invalid number) or default value
|
||||
*/
|
||||
int64_t GetArg(const std::string& strArg, int64_t nDefault) const;
|
||||
|
||||
/**
|
||||
* Return boolean argument or default value
|
||||
*
|
||||
* @param strArg Argument to get (e.g. "-foo")
|
||||
* @param fDefault (true or false)
|
||||
* @return command-line argument or default value
|
||||
*/
|
||||
bool GetBoolArg(const std::string& strArg, bool fDefault) const;
|
||||
|
||||
/**
|
||||
* Set an argument if it doesn't already have a value
|
||||
*
|
||||
* @param strArg Argument to set (e.g. "-foo")
|
||||
* @param strValue Value (e.g. "1")
|
||||
* @return true if argument gets set, false if it already had a value
|
||||
*/
|
||||
bool SoftSetArg(const std::string& strArg, const std::string& strValue);
|
||||
|
||||
/**
|
||||
* Set a boolean argument if it doesn't already have a value
|
||||
*
|
||||
* @param strArg Argument to set (e.g. "-foo")
|
||||
* @param fValue Value (e.g. false)
|
||||
* @return true if argument gets set, false if it already had a value
|
||||
*/
|
||||
bool SoftSetBoolArg(const std::string& strArg, bool fValue);
|
||||
|
||||
// Forces an arg setting. Called by SoftSetArg() if the arg hasn't already
|
||||
// been set. Also called directly in testing.
|
||||
void ForceSetArg(const std::string& strArg, const std::string& strValue);
|
||||
|
||||
/**
|
||||
* Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
|
||||
* @return CBaseChainParams::MAIN by default; raises runtime error if an invalid combination is given.
|
||||
*/
|
||||
std::string GetChainName() const;
|
||||
|
||||
/**
|
||||
* Add argument
|
||||
*/
|
||||
void AddArg(const std::string& name, const std::string& help, const bool debug_only, const OptionsCategory& cat);
|
||||
|
||||
/**
|
||||
* Add many hidden arguments
|
||||
*/
|
||||
void AddHiddenArgs(const std::vector<std::string>& args);
|
||||
|
||||
/**
|
||||
* Clear available arguments
|
||||
*/
|
||||
void ClearArgs() {
|
||||
LOCK(cs_args);
|
||||
m_available_args.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the help string
|
||||
*/
|
||||
std::string GetHelpMessage() const;
|
||||
|
||||
/**
|
||||
* Check whether we know of this arg
|
||||
*/
|
||||
bool IsArgKnown(const std::string& key) const;
|
||||
};
|
||||
|
||||
extern ArgsManager gArgs;
|
||||
|
||||
/**
|
||||
* @return true if help has been requested via a command-line arg
|
||||
*/
|
||||
bool HelpRequested(const ArgsManager& args);
|
||||
|
||||
/**
|
||||
* Format a string to be used as group of options in help messages
|
||||
*
|
||||
* @param message Group name (e.g. "RPC server options:")
|
||||
* @return the formatted string
|
||||
*/
|
||||
std::string HelpMessageGroup(const std::string& message);
|
||||
|
||||
/**
|
||||
* Format a string to be used as option description in help messages
|
||||
*
|
||||
* @param option Option message (e.g. "-rpcuser=<user>")
|
||||
* @param message Option description (e.g. "Username for JSON-RPC connections")
|
||||
* @return the formatted string
|
||||
*/
|
||||
std::string HelpMessageOpt(const std::string& option, const std::string& message);
|
||||
|
||||
/**
|
||||
* Return the number of cores available on the current system.
|
||||
* @note This does count virtual cores, such as those provided by HyperThreading.
|
||||
*/
|
||||
int GetNumCores();
|
||||
|
||||
void RenameThread(const char* name);
|
||||
|
||||
/**
|
||||
* .. and a wrapper that just calls func once
|
||||
*/
|
||||
template <typename Callable> void TraceThread(const char* name, Callable func)
|
||||
{
|
||||
std::string s = strprintf("bitcoin-%s", name);
|
||||
RenameThread(s.c_str());
|
||||
try
|
||||
{
|
||||
LogPrintf("%s thread start\n", name);
|
||||
func();
|
||||
LogPrintf("%s thread exit\n", name);
|
||||
}
|
||||
catch (const boost::thread_interrupted&)
|
||||
{
|
||||
LogPrintf("%s thread interrupt\n", name);
|
||||
throw;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
PrintExceptionContinue(&e, name);
|
||||
throw;
|
||||
}
|
||||
catch (...) {
|
||||
PrintExceptionContinue(nullptr, name);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
std::string CopyrightHolders(const std::string& strPrefix);
|
||||
|
||||
/**
|
||||
* On platforms that support it, tell the kernel the calling thread is
|
||||
* CPU-intensive and non-interactive. See SCHED_BATCH in sched(7) for details.
|
||||
*
|
||||
* @return The return value of sched_setschedule(), or 1 on systems without
|
||||
* sched_setschedule().
|
||||
*/
|
||||
int ScheduleBatchPriority();
|
||||
|
||||
namespace util {
|
||||
|
||||
//! Simplification of std insertion
|
||||
template <typename Tdst, typename Tsrc>
|
||||
inline void insert(Tdst& dst, const Tsrc& src) {
|
||||
dst.insert(dst.begin(), src.begin(), src.end());
|
||||
}
|
||||
template <typename TsetT, typename Tsrc>
|
||||
inline void insert(std::set<TsetT>& dst, const Tsrc& src) {
|
||||
dst.insert(src.begin(), src.end());
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
class WinCmdLineArgs
|
||||
{
|
||||
public:
|
||||
WinCmdLineArgs();
|
||||
~WinCmdLineArgs();
|
||||
std::pair<int, char**> get();
|
||||
|
||||
private:
|
||||
int argc;
|
||||
char** argv;
|
||||
std::vector<std::string> args;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace util
|
||||
|
||||
#endif // BITCOIN_UTIL_SYSTEM_H
|
||||
110
src/util/time.cpp
Normal file
110
src/util/time.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config/bitcoin-config.h>
|
||||
#endif
|
||||
|
||||
#include <util/time.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <ctime>
|
||||
#include <tinyformat.h>
|
||||
|
||||
static std::atomic<int64_t> nMockTime(0); //!< For unit testing
|
||||
|
||||
int64_t GetTime()
|
||||
{
|
||||
int64_t mocktime = nMockTime.load(std::memory_order_relaxed);
|
||||
if (mocktime) return mocktime;
|
||||
|
||||
time_t now = time(nullptr);
|
||||
assert(now > 0);
|
||||
return now;
|
||||
}
|
||||
|
||||
void SetMockTime(int64_t nMockTimeIn)
|
||||
{
|
||||
nMockTime.store(nMockTimeIn, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
int64_t GetMockTime()
|
||||
{
|
||||
return nMockTime.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
int64_t GetTimeMillis()
|
||||
{
|
||||
int64_t now = (boost::posix_time::microsec_clock::universal_time() -
|
||||
boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
|
||||
assert(now > 0);
|
||||
return now;
|
||||
}
|
||||
|
||||
int64_t GetTimeMicros()
|
||||
{
|
||||
int64_t now = (boost::posix_time::microsec_clock::universal_time() -
|
||||
boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
|
||||
assert(now > 0);
|
||||
return now;
|
||||
}
|
||||
|
||||
int64_t GetSystemTimeInSeconds()
|
||||
{
|
||||
return GetTimeMicros()/1000000;
|
||||
}
|
||||
|
||||
void MilliSleep(int64_t n)
|
||||
{
|
||||
|
||||
/**
|
||||
* Boost's sleep_for was uninterruptible when backed by nanosleep from 1.50
|
||||
* until fixed in 1.52. Use the deprecated sleep method for the broken case.
|
||||
* See: https://svn.boost.org/trac/boost/ticket/7238
|
||||
*/
|
||||
#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
|
||||
#elif defined(HAVE_WORKING_BOOST_SLEEP)
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(n));
|
||||
#else
|
||||
//should never get here
|
||||
#error missing boost sleep implementation
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string FormatISO8601DateTime(int64_t nTime) {
|
||||
struct tm ts;
|
||||
time_t time_val = nTime;
|
||||
#ifdef _MSC_VER
|
||||
gmtime_s(&ts, &time_val);
|
||||
#else
|
||||
gmtime_r(&time_val, &ts);
|
||||
#endif
|
||||
return strprintf("%04i-%02i-%02iT%02i:%02i:%02iZ", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec);
|
||||
}
|
||||
|
||||
std::string FormatISO8601Date(int64_t nTime) {
|
||||
struct tm ts;
|
||||
time_t time_val = nTime;
|
||||
#ifdef _MSC_VER
|
||||
gmtime_s(&ts, &time_val);
|
||||
#else
|
||||
gmtime_r(&time_val, &ts);
|
||||
#endif
|
||||
return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday);
|
||||
}
|
||||
|
||||
std::string FormatISO8601Time(int64_t nTime) {
|
||||
struct tm ts;
|
||||
time_t time_val = nTime;
|
||||
#ifdef _MSC_VER
|
||||
gmtime_s(&ts, &time_val);
|
||||
#else
|
||||
gmtime_r(&time_val, &ts);
|
||||
#endif
|
||||
return strprintf("%02i:%02i:%02iZ", ts.tm_hour, ts.tm_min, ts.tm_sec);
|
||||
}
|
||||
38
src/util/time.h
Normal file
38
src/util/time.h
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_UTIL_TIME_H
|
||||
#define BITCOIN_UTIL_TIME_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* GetTimeMicros() and GetTimeMillis() both return the system time, but in
|
||||
* different units. GetTime() returns the system time in seconds, but also
|
||||
* supports mocktime, where the time can be specified by the user, eg for
|
||||
* testing (eg with the setmocktime rpc, or -mocktime argument).
|
||||
*
|
||||
* TODO: Rework these functions to be type-safe (so that we don't inadvertently
|
||||
* compare numbers with different units, or compare a mocktime to system time).
|
||||
*/
|
||||
|
||||
int64_t GetTime();
|
||||
int64_t GetTimeMillis();
|
||||
int64_t GetTimeMicros();
|
||||
int64_t GetSystemTimeInSeconds(); // Like GetTime(), but not mockable
|
||||
void SetMockTime(int64_t nMockTimeIn);
|
||||
int64_t GetMockTime();
|
||||
void MilliSleep(int64_t n);
|
||||
|
||||
/**
|
||||
* ISO 8601 formatting is preferred. Use the FormatISO8601{DateTime,Date,Time}
|
||||
* helper functions if possible.
|
||||
*/
|
||||
std::string FormatISO8601DateTime(int64_t nTime);
|
||||
std::string FormatISO8601Date(int64_t nTime);
|
||||
std::string FormatISO8601Time(int64_t nTime);
|
||||
|
||||
#endif // BITCOIN_UTIL_TIME_H
|
||||
Reference in New Issue
Block a user