diff options
-rw-r--r-- | src/netbase.cpp | 4 | ||||
-rw-r--r-- | src/rpc/server.cpp | 5 | ||||
-rw-r--r-- | src/test/netbase_tests.cpp | 18 | ||||
-rw-r--r-- | src/test/util_tests.cpp | 39 | ||||
-rw-r--r-- | src/utilstrencodings.cpp | 13 | ||||
-rw-r--r-- | src/utilstrencodings.h | 44 | ||||
-rwxr-xr-x | test/lint/lint-includes.sh | 1 | ||||
-rwxr-xr-x | test/lint/lint-locale-dependence.sh | 2 |
8 files changed, 116 insertions, 10 deletions
diff --git a/src/netbase.cpp b/src/netbase.cpp index 9750173987..4b63757f3d 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -19,8 +19,6 @@ #include <fcntl.h> #endif -#include <boost/algorithm/string/case_conv.hpp> // for to_lower() - #if !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 #endif @@ -37,7 +35,7 @@ static const int SOCKS5_RECV_TIMEOUT = 20 * 1000; static std::atomic<bool> 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 e46bf2f765..7d7e83fea8 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -16,7 +16,6 @@ #include <boost/bind.hpp> #include <boost/signals2/signal.hpp> -#include <boost/algorithm/string/case_conv.hpp> // for to_upper() #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/split.hpp> @@ -192,9 +191,7 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& 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 9c1af6bdf6..8072eb922d 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -302,4 +302,22 @@ BOOST_AUTO_TEST_CASE(netbase_getgroup) BOOST_CHECK(CreateInternal("baz.net").GetGroup() == internal_group); } +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 b2960446eb..8e2f5abe66 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1217,4 +1217,43 @@ BOOST_AUTO_TEST_CASE(test_DirIsWritable) fs::remove(tmpdirname); } +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/utilstrencodings.cpp b/src/utilstrencodings.cpp index e66e2c238c..2326383586 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -7,6 +7,7 @@ #include <tinyformat.h> +#include <algorithm> #include <cstdlib> #include <cstring> #include <errno.h> @@ -584,3 +585,15 @@ bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypa } 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; +} diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 8f29f8f322..846a3917a2 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -186,4 +186,48 @@ bool ConvertBits(const O& outfn, I it, I end) { /** 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_UTILSTRENCODINGS_H diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh index a38ce6f4cf..346829e24b 100755 --- a/test/lint/lint-includes.sh +++ b/test/lint/lint-includes.sh @@ -47,7 +47,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 cbe1143bd0..a5b97ca1e9 100755 --- a/test/lint/lint-locale-dependence.sh +++ b/test/lint/lint-locale-dependence.sh @@ -11,11 +11,9 @@ KNOWN_VIOLATIONS=( "src/dbwrapper.cpp:.*vsnprintf" "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/test/dbwrapper_tests.cpp:.*snprintf" "src/test/getarg_tests.cpp.*split" "src/torcontrol.cpp:.*atoi" |