From faa3ec2304051be7cfbe301cfbfbda3faf7514fc Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 4 Nov 2021 09:03:04 +0100 Subject: [PATCH] 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 830164514b9..78e8fc691db 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 9d1dfd46f1e..c5fce7bec0f 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 b1300d06ba6..108bcecc663 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(ParseHex_vec), - "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_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 15bd07b374e..cc737f724c7 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 eedb5ec2f86..f5e636726ad 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