Skip to content

Commit 01e314c

Browse files
committed
refactor: Change base_blob::SetHex() to take std::string_view
Clarify that hex strings are parsed as little-endian.
1 parent 2f5577d commit 01e314c

File tree

3 files changed

+25
-46
lines changed

3 files changed

+25
-46
lines changed

src/test/uint256_tests.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,8 @@ static std::string ArrayToString(const unsigned char A[], unsigned int width)
5858
return Stream.str();
5959
}
6060

61-
inline uint160 uint160S(const char *str)
62-
{
63-
uint160 rv;
64-
rv.SetHex(str);
65-
return rv;
66-
}
67-
inline uint160 uint160S(const std::string& str)
61+
// Input is treated as little-endian.
62+
inline uint160 uint160S(std::string_view str)
6863
{
6964
uint160 rv;
7065
rv.SetHex(str);
@@ -156,6 +151,10 @@ BOOST_AUTO_TEST_CASE( comparison ) // <= >= < >
156151
BOOST_CHECK_LT(OneS, MaxS);
157152
BOOST_CHECK_LT(R1S, MaxS);
158153
BOOST_CHECK_LT(R2S, MaxS);
154+
155+
// Verify hex strings are little-endian
156+
BOOST_CHECK_LT(uint256S("2000000000000000000000000000000000000000000000000000000000000001"),
157+
uint256S("1000000000000000000000000000000000000000000000000000000000000002"));
159158
}
160159

161160
BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 GetSerializeSize, Serialize, Unserialize

src/uint256.cpp

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,31 @@ std::string base_blob<BITS>::GetHex() const
1818
}
1919

2020
template <unsigned int BITS>
21-
void base_blob<BITS>::SetHex(const char* psz)
21+
void base_blob<BITS>::SetHex(const std::string_view str)
2222
{
2323
std::fill(m_data.begin(), m_data.end(), 0);
2424

25-
// skip leading spaces
26-
while (IsSpace(*psz))
27-
psz++;
25+
const auto trimmed = util::RemovePrefixView(util::TrimStringView(str), "0x");
2826

29-
// skip 0x
30-
if (psz[0] == '0' && ToLower(psz[1]) == 'x')
31-
psz += 2;
32-
33-
// hex string to uint
27+
// Note: if we are passed a greater number of digits than would fit as bytes
28+
// in m_data, we will be discarding the leftmost ones.
29+
// str="12bc" in a WIDTH=1 m_data => m_data[] == "\0xbc", not "0x12".
3430
size_t digits = 0;
35-
while (::HexDigit(psz[digits]) != -1)
36-
digits++;
31+
for (const char c : trimmed) {
32+
if (::HexDigit(c) == -1) break;
33+
++digits;
34+
}
3735
unsigned char* p1 = m_data.data();
3836
unsigned char* pend = p1 + WIDTH;
3937
while (digits > 0 && p1 < pend) {
40-
*p1 = ::HexDigit(psz[--digits]);
38+
*p1 = ::HexDigit(trimmed[--digits]);
4139
if (digits > 0) {
42-
*p1 |= ((unsigned char)::HexDigit(psz[--digits]) << 4);
40+
*p1 |= ((unsigned char)::HexDigit(trimmed[--digits]) << 4);
4341
p1++;
4442
}
4543
}
4644
}
4745

48-
template <unsigned int BITS>
49-
void base_blob<BITS>::SetHex(const std::string& str)
50-
{
51-
SetHex(str.c_str());
52-
}
53-
5446
template <unsigned int BITS>
5547
std::string base_blob<BITS>::ToString() const
5648
{
@@ -60,14 +52,12 @@ std::string base_blob<BITS>::ToString() const
6052
// Explicit instantiations for base_blob<160>
6153
template std::string base_blob<160>::GetHex() const;
6254
template std::string base_blob<160>::ToString() const;
63-
template void base_blob<160>::SetHex(const char*);
64-
template void base_blob<160>::SetHex(const std::string&);
55+
template void base_blob<160>::SetHex(std::string_view);
6556

6657
// Explicit instantiations for base_blob<256>
6758
template std::string base_blob<256>::GetHex() const;
6859
template std::string base_blob<256>::ToString() const;
69-
template void base_blob<256>::SetHex(const char*);
70-
template void base_blob<256>::SetHex(const std::string&);
60+
template void base_blob<256>::SetHex(std::string_view);
7161

7262
const uint256 uint256::ZERO(0);
7363
const uint256 uint256::ONE(1);

src/uint256.h

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ class base_blob
5757
friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; }
5858
friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; }
5959

60+
// Hex string representations are little-endian.
6061
std::string GetHex() const;
61-
void SetHex(const char* psz);
62-
void SetHex(const std::string& str);
62+
void SetHex(std::string_view str);
6363
std::string ToString() const;
6464

6565
constexpr const unsigned char* data() const { return m_data.data(); }
@@ -112,21 +112,11 @@ class uint256 : public base_blob<256> {
112112
static const uint256 ONE;
113113
};
114114

115-
/* uint256 from const char *.
116-
* This is a separate function because the constructor uint256(const char*) can result
117-
* in dangerously catching uint256(0).
115+
/* uint256 from std::string_view, treated as little-endian.
116+
* This is not a uint256 constructor because of historical fears of uint256(0)
117+
* resolving to a NULL string and crashing.
118118
*/
119-
inline uint256 uint256S(const char *str)
120-
{
121-
uint256 rv;
122-
rv.SetHex(str);
123-
return rv;
124-
}
125-
/* uint256 from std::string.
126-
* This is a separate function because the constructor uint256(const std::string &str) can result
127-
* in dangerously catching uint256(0) via std::string(const char*).
128-
*/
129-
inline uint256 uint256S(const std::string& str)
119+
inline uint256 uint256S(std::string_view str)
130120
{
131121
uint256 rv;
132122
rv.SetHex(str);

0 commit comments

Comments
 (0)