diff options
author | Hodlinator <172445034+hodlinator@users.noreply.github.com> | 2024-07-23 14:51:36 +0200 |
---|---|---|
committer | Hodlinator <172445034+hodlinator@users.noreply.github.com> | 2024-07-23 14:51:36 +0200 |
commit | 01e314ce0ae30228742b6f19d2f12a050ab97e4d (patch) | |
tree | 7818b7fe9d44f8ee7cad990209f88844df5e79f9 | |
parent | 2f5577dc2e7ba668798a89a2f6ef72795db6c285 (diff) |
refactor: Change base_blob::SetHex() to take std::string_view
Clarify that hex strings are parsed as little-endian.
-rw-r--r-- | src/test/uint256_tests.cpp | 13 | ||||
-rw-r--r-- | src/uint256.cpp | 36 | ||||
-rw-r--r-- | src/uint256.h | 22 |
3 files changed, 25 insertions, 46 deletions
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 6b86eb25ff..669983c0e9 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -58,13 +58,8 @@ static std::string ArrayToString(const unsigned char A[], unsigned int width) return Stream.str(); } -inline uint160 uint160S(const char *str) -{ - uint160 rv; - rv.SetHex(str); - return rv; -} -inline uint160 uint160S(const std::string& str) +// Input is treated as little-endian. +inline uint160 uint160S(std::string_view str) { uint160 rv; rv.SetHex(str); @@ -156,6 +151,10 @@ BOOST_AUTO_TEST_CASE( comparison ) // <= >= < > BOOST_CHECK_LT(OneS, MaxS); BOOST_CHECK_LT(R1S, MaxS); BOOST_CHECK_LT(R2S, MaxS); + + // Verify hex strings are little-endian + BOOST_CHECK_LT(uint256S("2000000000000000000000000000000000000000000000000000000000000001"), + uint256S("1000000000000000000000000000000000000000000000000000000000000002")); } BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 GetSerializeSize, Serialize, Unserialize diff --git a/src/uint256.cpp b/src/uint256.cpp index 7f81c3c448..f15150ca95 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -18,40 +18,32 @@ std::string base_blob<BITS>::GetHex() const } template <unsigned int BITS> -void base_blob<BITS>::SetHex(const char* psz) +void base_blob<BITS>::SetHex(const std::string_view str) { std::fill(m_data.begin(), m_data.end(), 0); - // skip leading spaces - while (IsSpace(*psz)) - psz++; + const auto trimmed = util::RemovePrefixView(util::TrimStringView(str), "0x"); - // skip 0x - if (psz[0] == '0' && ToLower(psz[1]) == 'x') - psz += 2; - - // hex string to uint + // Note: if we are passed a greater number of digits than would fit as bytes + // in m_data, we will be discarding the leftmost ones. + // str="12bc" in a WIDTH=1 m_data => m_data[] == "\0xbc", not "0x12". size_t digits = 0; - while (::HexDigit(psz[digits]) != -1) - digits++; + for (const char c : trimmed) { + if (::HexDigit(c) == -1) break; + ++digits; + } unsigned char* p1 = m_data.data(); unsigned char* pend = p1 + WIDTH; while (digits > 0 && p1 < pend) { - *p1 = ::HexDigit(psz[--digits]); + *p1 = ::HexDigit(trimmed[--digits]); if (digits > 0) { - *p1 |= ((unsigned char)::HexDigit(psz[--digits]) << 4); + *p1 |= ((unsigned char)::HexDigit(trimmed[--digits]) << 4); p1++; } } } template <unsigned int BITS> -void base_blob<BITS>::SetHex(const std::string& str) -{ - SetHex(str.c_str()); -} - -template <unsigned int BITS> std::string base_blob<BITS>::ToString() const { return (GetHex()); @@ -60,14 +52,12 @@ std::string base_blob<BITS>::ToString() const // Explicit instantiations for base_blob<160> template std::string base_blob<160>::GetHex() const; template std::string base_blob<160>::ToString() const; -template void base_blob<160>::SetHex(const char*); -template void base_blob<160>::SetHex(const std::string&); +template void base_blob<160>::SetHex(std::string_view); // Explicit instantiations for base_blob<256> template std::string base_blob<256>::GetHex() const; template std::string base_blob<256>::ToString() const; -template void base_blob<256>::SetHex(const char*); -template void base_blob<256>::SetHex(const std::string&); +template void base_blob<256>::SetHex(std::string_view); const uint256 uint256::ZERO(0); const uint256 uint256::ONE(1); diff --git a/src/uint256.h b/src/uint256.h index d35b3a66fa..406a9c7203 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -57,9 +57,9 @@ public: friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; } friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; } + // Hex string representations are little-endian. std::string GetHex() const; - void SetHex(const char* psz); - void SetHex(const std::string& str); + void SetHex(std::string_view str); std::string ToString() const; constexpr const unsigned char* data() const { return m_data.data(); } @@ -112,21 +112,11 @@ public: static const uint256 ONE; }; -/* uint256 from const char *. - * This is a separate function because the constructor uint256(const char*) can result - * in dangerously catching uint256(0). +/* uint256 from std::string_view, treated as little-endian. + * This is not a uint256 constructor because of historical fears of uint256(0) + * resolving to a NULL string and crashing. */ -inline uint256 uint256S(const char *str) -{ - uint256 rv; - rv.SetHex(str); - return rv; -} -/* uint256 from std::string. - * This is a separate function because the constructor uint256(const std::string &str) can result - * in dangerously catching uint256(0) via std::string(const char*). - */ -inline uint256 uint256S(const std::string& str) +inline uint256 uint256S(std::string_view str) { uint256 rv; rv.SetHex(str); |