diff --git a/src/core_read.cpp b/src/core_read.cpp index 0eba29a5cd..a98e9e046a 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -41,8 +40,9 @@ CScript ParseScript(const std::string& s) std::string strName(name); mapOpNames[strName] = static_cast(op); // Convenience: OP_ADD and just ADD are both recognized: - boost::algorithm::replace_first(strName, "OP_", ""); - mapOpNames[strName] = static_cast(op); + if (strName.compare(0, 3, "OP_") == 0) { // strName starts with "OP_" + mapOpNames[strName.substr(3)] = static_cast(op); + } } } diff --git a/src/init.cpp b/src/init.cpp index dc8e2c6abf..8d193e92a1 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -852,6 +852,10 @@ static void ThreadImport(std::vector vImportFiles) break; // This error is logged in OpenBlockFile LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile); LoadExternalBlockFile(chainparams, file, &pos); + if (ShutdownRequested()) { + LogPrintf("Shutdown requested. Exit %s\n", __func__); + return; + } nFile++; } pblocktree->WriteReindexing(false); @@ -881,6 +885,10 @@ static void ThreadImport(std::vector vImportFiles) if (file) { LogPrintf("Importing blocks file %s...\n", path.string()); LoadExternalBlockFile(chainparams, file); + if (ShutdownRequested()) { + LogPrintf("Shutdown requested. Exit %s\n", __func__); + return; + } } else { LogPrintf("Warning: Could not open blocks file %s\n", path.string()); } diff --git a/src/netbase.cpp b/src/netbase.cpp index a17934e717..13483a9d57 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -23,7 +23,6 @@ #include #endif -#include // for to_lower() #ifdef USE_POLL #include #endif @@ -44,7 +43,7 @@ static const int SOCKS5_RECV_TIMEOUT = 20 * 1000; static std::atomic interruptSocks5Recv(false); enum Network ParseNetwork(std::string net) { - boost::to_lower(net); + Downcase(net); if (net == "ipv4") return NET_IPV4; if (net == "ipv6") return NET_IPV6; if (net == "onion") return NET_ONION; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index b8700f163c..7712037eab 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -17,7 +17,6 @@ #include #include -#include // for to_upper() #include #include @@ -248,9 +247,7 @@ std::string CRPCTable::help(const std::string& strCommand, const std::string& st if (!category.empty()) strRet += "\n"; category = pcmd->category; - std::string firstLetter = category.substr(0,1); - boost::to_upper(firstLetter); - strRet += "== " + firstLetter + category.substr(1) + " ==\n"; + strRet += "== " + Capitalize(category) + " ==\n"; } } strRet += strHelp + "\n"; diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index cdb2304ca8..92d5e2c76c 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -431,4 +431,22 @@ BOOST_AUTO_TEST_CASE(caddress_unserialize_v2) BOOST_CHECK(fixture_addresses == addresses_unserialized); } +BOOST_AUTO_TEST_CASE(netbase_parsenetwork) +{ + BOOST_CHECK_EQUAL(ParseNetwork("ipv4"), NET_IPV4); + BOOST_CHECK_EQUAL(ParseNetwork("ipv6"), NET_IPV6); + BOOST_CHECK_EQUAL(ParseNetwork("onion"), NET_ONION); + BOOST_CHECK_EQUAL(ParseNetwork("tor"), NET_ONION); + + BOOST_CHECK_EQUAL(ParseNetwork("IPv4"), NET_IPV4); + BOOST_CHECK_EQUAL(ParseNetwork("IPv6"), NET_IPV6); + BOOST_CHECK_EQUAL(ParseNetwork("ONION"), NET_ONION); + BOOST_CHECK_EQUAL(ParseNetwork("TOR"), NET_ONION); + + BOOST_CHECK_EQUAL(ParseNetwork(":)"), NET_UNROUTABLE); + BOOST_CHECK_EQUAL(ParseNetwork("tÖr"), NET_UNROUTABLE); + BOOST_CHECK_EQUAL(ParseNetwork("\xfe\xff"), NET_UNROUTABLE); + BOOST_CHECK_EQUAL(ParseNetwork(""), NET_UNROUTABLE); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 2b564d8512..aab2331866 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1289,4 +1289,43 @@ BOOST_AUTO_TEST_CASE(test_tracked_vector) BOOST_CHECK_EQUAL(v8[2].copies, 0); } +BOOST_AUTO_TEST_CASE(test_ToLower) +{ + BOOST_CHECK_EQUAL(ToLower('@'), '@'); + BOOST_CHECK_EQUAL(ToLower('A'), 'a'); + BOOST_CHECK_EQUAL(ToLower('Z'), 'z'); + BOOST_CHECK_EQUAL(ToLower('['), '['); + BOOST_CHECK_EQUAL(ToLower(0), 0); + BOOST_CHECK_EQUAL(ToLower(255), 255); + + std::string testVector; + Downcase(testVector); + BOOST_CHECK_EQUAL(testVector, ""); + + testVector = "#HODL"; + Downcase(testVector); + BOOST_CHECK_EQUAL(testVector, "#hodl"); + + testVector = "\x00\xfe\xff"; + Downcase(testVector); + BOOST_CHECK_EQUAL(testVector, "\x00\xfe\xff"); +} + +BOOST_AUTO_TEST_CASE(test_ToUpper) +{ + BOOST_CHECK_EQUAL(ToUpper('`'), '`'); + BOOST_CHECK_EQUAL(ToUpper('a'), 'A'); + BOOST_CHECK_EQUAL(ToUpper('z'), 'Z'); + BOOST_CHECK_EQUAL(ToUpper('{'), '{'); + BOOST_CHECK_EQUAL(ToUpper(0), 0); + BOOST_CHECK_EQUAL(ToUpper(255), 255); +} + +BOOST_AUTO_TEST_CASE(test_Capitalize) +{ + BOOST_CHECK_EQUAL(Capitalize(""), ""); + BOOST_CHECK_EQUAL(Capitalize("bitcoin"), "Bitcoin"); + BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff"); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 5dda538e41..47456440ed 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -615,3 +616,15 @@ std::string HexStr(const Span s) } return rv; } + +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; +} diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 3ebc0bf32f..711cf5bcf1 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -188,6 +188,50 @@ bool ConvertBits(const O& outfn, I it, I end) { return true; } +/** + * 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); + /** Parse an HD keypaths like "m/7/0'/2000". */ bool ParseHDKeypath(const std::string& keypath_str, std::vector& keypath); diff --git a/src/validation.cpp b/src/validation.cpp index d469e0b312..5a027ba8ab 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4836,7 +4836,7 @@ bool LoadGenesisBlock(const CChainParams& chainparams) return g_chainstate.LoadGenesisBlock(chainparams); } -bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp) +void LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos* dbp) { // Map of disk positions for blocks with unknown parent (only used for reindex) static std::multimap mapBlocksUnknownParent; @@ -4849,7 +4849,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB CBufferedFile blkdat(fileIn, 2*nMaxBlockSize, nMaxBlockSize+8, SER_DISK, CLIENT_VERSION); uint64_t nRewind = blkdat.GetPos(); while (!blkdat.eof()) { - boost::this_thread::interruption_point(); + if (ShutdownRequested()) return; blkdat.SetPos(nRewind); nRewind++; // start one byte further next time, in case of failure @@ -4953,9 +4953,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB } catch (const std::runtime_error& e) { AbortNode(std::string("System error: ") + e.what()); } - if (nLoaded > 0) - LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart); - return nLoaded > 0; + LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart); } void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams) diff --git a/src/validation.h b/src/validation.h index 33ef386178..f16f3c2990 100644 --- a/src/validation.h +++ b/src/validation.h @@ -267,7 +267,7 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); /** Import blocks from an external file */ -bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = nullptr); +void LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos* dbp = nullptr); /** Ensures we have a genesis block in the block tree, possibly writing one to disk. */ bool LoadGenesisBlock(const CChainParams& chainparams); /** Load the block tree and coins database from disk, diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 085cea8d7c..0393a43481 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -17,8 +17,6 @@ #include #endif -#include - namespace { //! Make sure database has a unique fileid within the environment. If it @@ -153,10 +151,9 @@ BerkeleyEnvironment::~BerkeleyEnvironment() bool BerkeleyEnvironment::Open(bool retry) { - if (fDbEnvInit) + if (fDbEnvInit) { return true; - - boost::this_thread::interruption_point(); + } fs::path pathIn = strPath; TryCreateDirectories(pathIn); @@ -225,13 +222,11 @@ bool BerkeleyEnvironment::Open(bool retry) return true; } -//! Construct an in-memory mock Berkeley environment for testing and as a place-holder for g_dbenvs emplace +//! Construct an in-memory mock Berkeley environment for testing BerkeleyEnvironment::BerkeleyEnvironment() { Reset(); - boost::this_thread::interruption_point(); - LogPrint(BCLog::DB, "BerkeleyEnvironment::MakeMock\n"); dbenv->set_cachesize(1, 0, 1); @@ -250,8 +245,9 @@ BerkeleyEnvironment::BerkeleyEnvironment() DB_THREAD | DB_PRIVATE, S_IRUSR | S_IWUSR); - if (ret > 0) + if (ret > 0) { throw std::runtime_error(strprintf("BerkeleyEnvironment::MakeMock: Error %d opening database environment.", ret)); + } fDbEnvInit = true; fMockDb = true; @@ -772,7 +768,6 @@ bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase& database) if (nRefCount == 0) { - boost::this_thread::interruption_point(); std::map::iterator mi = env->mapFileUseCount.find(strFile); if (mi != env->mapFileUseCount.end()) { diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 7520f16d79..8d777e205b 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -21,8 +21,6 @@ #include -#include - // // WalletBatch // @@ -666,11 +664,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet) // Store initial external keypool size since we mostly use external keys in mixing pwallet->nKeysLeftSinceAutoBackup = pwallet->KeypoolCountExternalKeys(); pwallet->WalletLogPrintf("nKeysLeftSinceAutoBackup: %d\n", pwallet->nKeysLeftSinceAutoBackup); - } - catch (const boost::thread_interrupted&) { - throw; - } - catch (...) { + } catch (...) { result = DBErrors::CORRUPT; } @@ -762,11 +756,7 @@ DBErrors WalletBatch::FindWalletTx(std::vector& vTxHash, std::vectorclose(); - } - catch (const boost::thread_interrupted&) { - throw; - } - catch (...) { + } catch (...) { result = DBErrors::CORRUPT; } diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh index da57ce0163..02ca9baa0f 100755 --- a/test/lint/lint-includes.sh +++ b/test/lint/lint-includes.sh @@ -50,7 +50,6 @@ fi EXPECTED_BOOST_INCLUDES=( boost/algorithm/string.hpp - boost/algorithm/string/case_conv.hpp boost/algorithm/string/classification.hpp boost/algorithm/string/replace.hpp boost/algorithm/string/split.hpp diff --git a/test/lint/lint-locale-dependence.sh b/test/lint/lint-locale-dependence.sh index 938fadfc79..1cb9feb6b9 100755 --- a/test/lint/lint-locale-dependence.sh +++ b/test/lint/lint-locale-dependence.sh @@ -15,11 +15,9 @@ KNOWN_VIOLATIONS=( "src/governance/governance-validators.cpp.*tolower" "src/httprpc.cpp.*trim" "src/init.cpp:.*atoi" - "src/netbase.cpp.*to_lower" "src/qt/rpcconsole.cpp:.*atoi" "src/qt/rpcconsole.cpp:.*isdigit" "src/rest.cpp:.*strtol" - "src/rpc/server.cpp.*to_upper" "src/rpc/blockchain.cpp.*atoi" "src/rpc/governance.cpp.*atoi" "src/rpc/masternode.cpp.*atoi"