Skip to content

Commit

Permalink
Implements custom tolower and toupper functions.
Browse files Browse the repository at this point in the history
This commit implements custom equivalents for the C and C++ `tolower` and `toupper` Standard Library functions.
In addition it implements a utility function to capitalize the first letter of a string.

Cherry-picked from: 7a208d9
  • Loading branch information
xanimo committed Mar 29, 2024
1 parent 2194db8 commit aee1f2d
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/test/netbase_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,13 @@ 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("onion"), NET_TOR);
BOOST_CHECK_EQUAL(ParseNetwork("tor"), NET_TOR);

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("ONION"), NET_TOR);
BOOST_CHECK_EQUAL(ParseNetwork("TOR"), NET_TOR);

BOOST_CHECK_EQUAL(ParseNetwork(":)"), NET_UNROUTABLE);
BOOST_CHECK_EQUAL(ParseNetwork("tÖr"), NET_UNROUTABLE);
Expand Down
39 changes: 39 additions & 0 deletions src/test/util_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,4 +565,43 @@ BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
}

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()
12 changes: 12 additions & 0 deletions src/utilstrencodings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "tinyformat.h"

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <errno.h>
Expand Down Expand Up @@ -707,3 +708,14 @@ bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
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;
}
44 changes: 44 additions & 0 deletions src/utilstrencodings.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,48 @@ bool TimingResistantEqual(const T& a, const T& b)
*/
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out);

/**
* 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

0 comments on commit aee1f2d

Please sign in to comment.