From fabe18d0b39b4b918bf60e3a313eaa36fb4067f2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 4 Nov 2021 09:17:14 +0100 Subject: Use value_type in CDataStream where possible Also, simplify unit tests with the CDataStream::str method. --- src/streams.h | 12 ++++++------ src/test/streams_tests.cpp | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/streams.h b/src/streams.h index 31407287ae..9e8f379cd2 100644 --- a/src/streams.h +++ b/src/streams.h @@ -226,7 +226,7 @@ public: : nType{nTypeIn}, nVersion{nVersionIn} {} - explicit CDataStream(Span sp, int nTypeIn, int nVersionIn) + explicit CDataStream(Span sp, int nTypeIn, int nVersionIn) : vch(sp.data(), sp.data() + sp.size()), nType{nTypeIn}, nVersion{nVersionIn} {} @@ -254,17 +254,17 @@ public: iterator end() { return vch.end(); } size_type size() const { return vch.size() - nReadPos; } bool empty() const { return vch.size() == nReadPos; } - void resize(size_type n, value_type c=0) { vch.resize(n + nReadPos, c); } + void resize(size_type n, value_type c = value_type{}) { vch.resize(n + nReadPos, c); } void reserve(size_type n) { vch.reserve(n + nReadPos); } const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; } reference operator[](size_type pos) { return vch[pos + nReadPos]; } void clear() { vch.clear(); nReadPos = 0; } - iterator insert(iterator it, const uint8_t x) { return vch.insert(it, x); } - void insert(iterator it, size_type n, const uint8_t x) { vch.insert(it, n, x); } + iterator insert(iterator it, const value_type x) { return vch.insert(it, x); } + void insert(iterator it, size_type n, const value_type x) { vch.insert(it, n, x); } value_type* data() { return vch.data() + nReadPos; } const value_type* data() const { return vch.data() + nReadPos; } - void insert(iterator it, std::vector::const_iterator first, std::vector::const_iterator last) + void insert(iterator it, std::vector::const_iterator first, std::vector::const_iterator last) { if (last == first) return; assert(last - first > 0); @@ -278,7 +278,7 @@ public: vch.insert(it, first, last); } - void insert(iterator it, const char* first, const char* last) + void insert(iterator it, const value_type* first, const value_type* last) { if (last == first) return; assert(last - first > 0); diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 54f04d2e67..b8d76c9608 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -172,7 +172,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor) ds.Xor(key); BOOST_CHECK_EQUAL( std::string(expected_xor.begin(), expected_xor.end()), - std::string(ds.begin(), ds.end())); + ds.str()); in.push_back('\x0f'); in.push_back('\xf0'); @@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor) ds.Xor(key); BOOST_CHECK_EQUAL( std::string(expected_xor.begin(), expected_xor.end()), - std::string(ds.begin(), ds.end())); + ds.str()); // Multi character key @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor) ds.Xor(key); BOOST_CHECK_EQUAL( std::string(expected_xor.begin(), expected_xor.end()), - std::string(ds.begin(), ds.end())); + ds.str()); } BOOST_AUTO_TEST_CASE(streams_buffered_file) -- cgit v1.2.3 From fa18038f519db76befb9a7bd0b1540143bfeb12b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 6 Nov 2021 19:08:29 +0100 Subject: refactor: Use ignore helper when unserializing an invalid pubkey --- src/pubkey.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pubkey.h b/src/pubkey.h index 861a2cf500..ab0f429ca9 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -141,7 +141,7 @@ public: template void Unserialize(Stream& s) { - unsigned int len = ::ReadCompactSize(s); + const unsigned int len(::ReadCompactSize(s)); if (len <= SIZE) { s.read((char*)vch, len); if (len != size()) { @@ -149,9 +149,7 @@ public: } } else { // invalid pubkey, skip available data - char dummy; - while (len--) - s.read(&dummy, 1); + s.ignore(len); Invalidate(); } } -- cgit v1.2.3 From faa3ec2304051be7cfbe301cfbfbda3faf7514fc Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 4 Nov 2021 09:03:04 +0100 Subject: span: Add std::byte helpers Also, add Span interface to strencondings. --- src/span.h | 25 +++++++++++++++++++++++++ src/test/base64_tests.cpp | 10 ++++++++++ src/test/util_tests.cpp | 23 ++++++++++++++++++----- src/util/strencodings.cpp | 5 ----- src/util/strencodings.h | 4 +++- 5 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/span.h b/src/span.h index 830164514b..78e8fc691d 100644 --- a/src/span.h +++ b/src/span.h @@ -180,6 +180,7 @@ public: return m_data[m_size - 1]; } constexpr std::size_t size() const noexcept { return m_size; } + constexpr std::size_t size_bytes() const noexcept { return sizeof(C) * m_size; } constexpr bool empty() const noexcept { return size() == 0; } CONSTEXPR_IF_NOT_DEBUG C& operator[](std::size_t pos) const noexcept { @@ -236,11 +237,35 @@ T& SpanPopBack(Span& span) return back; } +// From C++20 as_bytes and as_writeable_bytes +template +Span AsBytes(Span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} +template +Span AsWritableBytes(Span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +template +Span MakeByteSpan(V&& v) noexcept +{ + return AsBytes(MakeSpan(std::forward(v))); +} +template +Span MakeWritableByteSpan(V&& v) noexcept +{ + return AsWritableBytes(MakeSpan(std::forward(v))); +} + // Helper functions to safely cast to unsigned char pointers. inline unsigned char* UCharCast(char* c) { return (unsigned char*)c; } inline unsigned char* UCharCast(unsigned char* c) { return c; } inline const unsigned char* UCharCast(const char* c) { return (unsigned char*)c; } inline const unsigned char* UCharCast(const unsigned char* c) { return c; } +inline const unsigned char* UCharCast(const std::byte* c) { return reinterpret_cast(c); } // Helper function to safely convert a Span to a Span<[const] unsigned char>. template constexpr auto UCharSpanCast(Span s) -> Span::type> { return {UCharCast(s.data()), s.size()}; } diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 9d1dfd46f1..c5fce7bec0 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -23,6 +23,16 @@ BOOST_AUTO_TEST_CASE(base64_testvectors) BOOST_CHECK_EQUAL(strDec, vstrIn[i]); } + { + const std::vector in_u{0xff, 0x01, 0xff}; + const std::vector in_b{std::byte{0xff}, std::byte{0x01}, std::byte{0xff}}; + const std::string in_s{"\xff\x01\xff"}; + const std::string out_exp{"/wH/"}; + BOOST_CHECK_EQUAL(EncodeBase64(in_u), out_exp); + BOOST_CHECK_EQUAL(EncodeBase64(in_b), out_exp); + BOOST_CHECK_EQUAL(EncodeBase64(in_s), out_exp); + } + // Decoding strings with embedded NUL characters should fail bool failure; (void)DecodeBase64("invalid\0"s, &failure); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index b1300d06ba..108bcecc66 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -151,12 +151,25 @@ BOOST_AUTO_TEST_CASE(util_HexStr) HexStr(Span(ParseHex_expected, ParseHex_expected)), ""); - std::vector ParseHex_vec(ParseHex_expected, ParseHex_expected + 5); + { + const std::vector in_s{ParseHex_expected, ParseHex_expected + 5}; + const Span in_u{MakeUCharSpan(in_s)}; + const Span in_b{MakeByteSpan(in_s)}; + const std::string out_exp{"04678afdb0"}; + + BOOST_CHECK_EQUAL(HexStr(in_u), out_exp); + BOOST_CHECK_EQUAL(HexStr(in_s), out_exp); + BOOST_CHECK_EQUAL(HexStr(in_b), out_exp); + } +} - BOOST_CHECK_EQUAL( - HexStr(ParseHex_vec), - "04678afdb0" - ); +BOOST_AUTO_TEST_CASE(span_write_bytes) +{ + std::array mut_arr{uint8_t{0xaa}, uint8_t{0xbb}}; + const auto mut_bytes{MakeWritableByteSpan(mut_arr)}; + mut_bytes[1] = std::byte{0x11}; + BOOST_CHECK_EQUAL(mut_arr.at(0), 0xaa); + BOOST_CHECK_EQUAL(mut_arr.at(1), 0x11); } BOOST_AUTO_TEST_CASE(util_Join) diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 15bd07b374..cc737f724c 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -138,11 +138,6 @@ std::string EncodeBase64(Span input) return str; } -std::string EncodeBase64(const std::string& str) -{ - return EncodeBase64(MakeUCharSpan(str)); -} - std::vector DecodeBase64(const char* p, bool* pf_invalid) { static const int decode64_table[256] = diff --git a/src/util/strencodings.h b/src/util/strencodings.h index eedb5ec2f8..f5e636726a 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -50,7 +50,8 @@ bool IsHexNumber(const std::string& str); std::vector DecodeBase64(const char* p, bool* pf_invalid = nullptr); std::string DecodeBase64(const std::string& str, bool* pf_invalid = nullptr); std::string EncodeBase64(Span input); -std::string EncodeBase64(const std::string& str); +inline std::string EncodeBase64(Span input) { return EncodeBase64(MakeUCharSpan(input)); } +inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); } std::vector DecodeBase32(const char* p, bool* pf_invalid = nullptr); std::string DecodeBase32(const std::string& str, bool* pf_invalid = nullptr); @@ -189,6 +190,7 @@ std::optional ToIntegral(const std::string& str) */ std::string HexStr(const Span s); inline std::string HexStr(const Span s) { return HexStr(MakeUCharSpan(s)); } +inline std::string HexStr(const Span s) { return HexStr(MakeUCharSpan(s)); } /** * Format a paragraph of text to a fixed width, adding spaces for -- cgit v1.2.3