aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHodlinator <172445034+hodlinator@users.noreply.github.com>2024-07-23 14:51:36 +0200
committerHodlinator <172445034+hodlinator@users.noreply.github.com>2024-07-23 14:51:36 +0200
commit01e314ce0ae30228742b6f19d2f12a050ab97e4d (patch)
tree7818b7fe9d44f8ee7cad990209f88844df5e79f9
parent2f5577dc2e7ba668798a89a2f6ef72795db6c285 (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.cpp13
-rw-r--r--src/uint256.cpp36
-rw-r--r--src/uint256.h22
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);