Skip to content

Commit 9394964

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#23451: span: Add std::byte helpers
faa3ec2 span: Add std::byte helpers (MarcoFalke) fa18038 refactor: Use ignore helper when unserializing an invalid pubkey (MarcoFalke) fabe18d Use value_type in CDataStream where possible (MarcoFalke) Pull request description: This adds (currently unused) span std::byte helpers, so that they can be used in new code. The refactors are also required for bitcoin/bitcoin#23438, but they are split up because the other pull doesn't compile with msvc right now. The third commit is not needed for the other pull, but still nice. ACKs for top commit: klementtan: reACK faa3ec2. Verified that all the new `std::byte` helper functions are tested. laanwj: Code review ACK faa3ec2 Tree-SHA512: b1f6af39f03ea4dfebf20d4a8538fa993a6104e7fc92ddf0c4606a7efc3ca9a8c1a4741d98a1418569c11bb9ce9258bf0c0c06d93d85ed7e208902a2db04e407
2 parents 73ac195 + faa3ec2 commit 9394964

File tree

8 files changed

+67
-24
lines changed

8 files changed

+67
-24
lines changed

src/pubkey.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,17 +141,15 @@ class CPubKey
141141
template <typename Stream>
142142
void Unserialize(Stream& s)
143143
{
144-
unsigned int len = ::ReadCompactSize(s);
144+
const unsigned int len(::ReadCompactSize(s));
145145
if (len <= SIZE) {
146146
s.read((char*)vch, len);
147147
if (len != size()) {
148148
Invalidate();
149149
}
150150
} else {
151151
// invalid pubkey, skip available data
152-
char dummy;
153-
while (len--)
154-
s.read(&dummy, 1);
152+
s.ignore(len);
155153
Invalidate();
156154
}
157155
}

src/span.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ class Span
184184
return m_data[m_size - 1];
185185
}
186186
constexpr std::size_t size() const noexcept { return m_size; }
187+
constexpr std::size_t size_bytes() const noexcept { return sizeof(C) * m_size; }
187188
constexpr bool empty() const noexcept { return size() == 0; }
188189
CONSTEXPR_IF_NOT_DEBUG C& operator[](std::size_t pos) const noexcept
189190
{
@@ -240,11 +241,35 @@ T& SpanPopBack(Span<T>& span)
240241
return back;
241242
}
242243

244+
// From C++20 as_bytes and as_writeable_bytes
245+
template <typename T>
246+
Span<const std::byte> AsBytes(Span<T> s) noexcept
247+
{
248+
return {reinterpret_cast<const std::byte*>(s.data()), s.size_bytes()};
249+
}
250+
template <typename T>
251+
Span<std::byte> AsWritableBytes(Span<T> s) noexcept
252+
{
253+
return {reinterpret_cast<std::byte*>(s.data()), s.size_bytes()};
254+
}
255+
256+
template <typename V>
257+
Span<const std::byte> MakeByteSpan(V&& v) noexcept
258+
{
259+
return AsBytes(MakeSpan(std::forward<V>(v)));
260+
}
261+
template <typename V>
262+
Span<std::byte> MakeWritableByteSpan(V&& v) noexcept
263+
{
264+
return AsWritableBytes(MakeSpan(std::forward<V>(v)));
265+
}
266+
243267
// Helper functions to safely cast to unsigned char pointers.
244268
inline unsigned char* UCharCast(char* c) { return (unsigned char*)c; }
245269
inline unsigned char* UCharCast(unsigned char* c) { return c; }
246270
inline const unsigned char* UCharCast(const char* c) { return (unsigned char*)c; }
247271
inline const unsigned char* UCharCast(const unsigned char* c) { return c; }
272+
inline const unsigned char* UCharCast(const std::byte* c) { return reinterpret_cast<const unsigned char*>(c); }
248273

249274
// Helper function to safely convert a Span to a Span<[const] unsigned char>.
250275
template <typename T> constexpr auto UCharSpanCast(Span<T> s) -> Span<typename std::remove_pointer<decltype(UCharCast(s.data()))>::type> { return {UCharCast(s.data()), s.size()}; }

src/streams.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ class CDataStream
226226
: nType{nTypeIn},
227227
nVersion{nVersionIn} {}
228228

229-
explicit CDataStream(Span<const uint8_t> sp, int nTypeIn, int nVersionIn)
229+
explicit CDataStream(Span<const value_type> sp, int nTypeIn, int nVersionIn)
230230
: vch(sp.data(), sp.data() + sp.size()),
231231
nType{nTypeIn},
232232
nVersion{nVersionIn} {}
@@ -254,17 +254,17 @@ class CDataStream
254254
iterator end() { return vch.end(); }
255255
size_type size() const { return vch.size() - nReadPos; }
256256
bool empty() const { return vch.size() == nReadPos; }
257-
void resize(size_type n, value_type c=0) { vch.resize(n + nReadPos, c); }
257+
void resize(size_type n, value_type c = value_type{}) { vch.resize(n + nReadPos, c); }
258258
void reserve(size_type n) { vch.reserve(n + nReadPos); }
259259
const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; }
260260
reference operator[](size_type pos) { return vch[pos + nReadPos]; }
261261
void clear() { vch.clear(); nReadPos = 0; }
262-
iterator insert(iterator it, const uint8_t x) { return vch.insert(it, x); }
263-
void insert(iterator it, size_type n, const uint8_t x) { vch.insert(it, n, x); }
262+
iterator insert(iterator it, const value_type x) { return vch.insert(it, x); }
263+
void insert(iterator it, size_type n, const value_type x) { vch.insert(it, n, x); }
264264
value_type* data() { return vch.data() + nReadPos; }
265265
const value_type* data() const { return vch.data() + nReadPos; }
266266

267-
void insert(iterator it, std::vector<uint8_t>::const_iterator first, std::vector<uint8_t>::const_iterator last)
267+
void insert(iterator it, std::vector<value_type>::const_iterator first, std::vector<value_type>::const_iterator last)
268268
{
269269
if (last == first) return;
270270
assert(last - first > 0);
@@ -278,7 +278,7 @@ class CDataStream
278278
vch.insert(it, first, last);
279279
}
280280

281-
void insert(iterator it, const char* first, const char* last)
281+
void insert(iterator it, const value_type* first, const value_type* last)
282282
{
283283
if (last == first) return;
284284
assert(last - first > 0);

src/test/base64_tests.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ BOOST_AUTO_TEST_CASE(base64_testvectors)
2323
BOOST_CHECK_EQUAL(strDec, vstrIn[i]);
2424
}
2525

26+
{
27+
const std::vector<uint8_t> in_u{0xff, 0x01, 0xff};
28+
const std::vector<std::byte> in_b{std::byte{0xff}, std::byte{0x01}, std::byte{0xff}};
29+
const std::string in_s{"\xff\x01\xff"};
30+
const std::string out_exp{"/wH/"};
31+
BOOST_CHECK_EQUAL(EncodeBase64(in_u), out_exp);
32+
BOOST_CHECK_EQUAL(EncodeBase64(in_b), out_exp);
33+
BOOST_CHECK_EQUAL(EncodeBase64(in_s), out_exp);
34+
}
35+
2636
// Decoding strings with embedded NUL characters should fail
2737
bool failure;
2838
(void)DecodeBase64("invalid\0"s, &failure);

src/test/streams_tests.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
172172
ds.Xor(key);
173173
BOOST_CHECK_EQUAL(
174174
std::string(expected_xor.begin(), expected_xor.end()),
175-
std::string(ds.begin(), ds.end()));
175+
ds.str());
176176

177177
in.push_back('\x0f');
178178
in.push_back('\xf0');
@@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
189189
ds.Xor(key);
190190
BOOST_CHECK_EQUAL(
191191
std::string(expected_xor.begin(), expected_xor.end()),
192-
std::string(ds.begin(), ds.end()));
192+
ds.str());
193193

194194
// Multi character key
195195

@@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
210210
ds.Xor(key);
211211
BOOST_CHECK_EQUAL(
212212
std::string(expected_xor.begin(), expected_xor.end()),
213-
std::string(ds.begin(), ds.end()));
213+
ds.str());
214214
}
215215

216216
BOOST_AUTO_TEST_CASE(streams_buffered_file)

src/test/util_tests.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,25 @@ BOOST_AUTO_TEST_CASE(util_HexStr)
151151
HexStr(Span<const unsigned char>(ParseHex_expected, ParseHex_expected)),
152152
"");
153153

154-
std::vector<unsigned char> ParseHex_vec(ParseHex_expected, ParseHex_expected + 5);
154+
{
155+
const std::vector<char> in_s{ParseHex_expected, ParseHex_expected + 5};
156+
const Span<const uint8_t> in_u{MakeUCharSpan(in_s)};
157+
const Span<const std::byte> in_b{MakeByteSpan(in_s)};
158+
const std::string out_exp{"04678afdb0"};
159+
160+
BOOST_CHECK_EQUAL(HexStr(in_u), out_exp);
161+
BOOST_CHECK_EQUAL(HexStr(in_s), out_exp);
162+
BOOST_CHECK_EQUAL(HexStr(in_b), out_exp);
163+
}
164+
}
155165

156-
BOOST_CHECK_EQUAL(
157-
HexStr(ParseHex_vec),
158-
"04678afdb0"
159-
);
166+
BOOST_AUTO_TEST_CASE(span_write_bytes)
167+
{
168+
std::array mut_arr{uint8_t{0xaa}, uint8_t{0xbb}};
169+
const auto mut_bytes{MakeWritableByteSpan(mut_arr)};
170+
mut_bytes[1] = std::byte{0x11};
171+
BOOST_CHECK_EQUAL(mut_arr.at(0), 0xaa);
172+
BOOST_CHECK_EQUAL(mut_arr.at(1), 0x11);
160173
}
161174

162175
BOOST_AUTO_TEST_CASE(util_Join)

src/util/strencodings.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,6 @@ std::string EncodeBase64(Span<const unsigned char> input)
139139
return str;
140140
}
141141

142-
std::string EncodeBase64(const std::string& str)
143-
{
144-
return EncodeBase64(MakeUCharSpan(str));
145-
}
146-
147142
std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
148143
{
149144
static const int decode64_table[256] =

src/util/strencodings.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ bool IsHexNumber(const std::string& str);
6767
std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid = nullptr);
6868
std::string DecodeBase64(const std::string& str, bool* pf_invalid = nullptr);
6969
std::string EncodeBase64(Span<const unsigned char> input);
70-
std::string EncodeBase64(const std::string& str);
70+
inline std::string EncodeBase64(Span<const std::byte> input) { return EncodeBase64(MakeUCharSpan(input)); }
71+
inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); }
7172
std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid = nullptr);
7273
std::string DecodeBase32(const std::string& str, bool* pf_invalid = nullptr);
7374

@@ -206,6 +207,7 @@ std::optional<T> ToIntegral(const std::string& str)
206207
*/
207208
std::string HexStr(const Span<const uint8_t> s);
208209
inline std::string HexStr(const Span<const char> s) { return HexStr(MakeUCharSpan(s)); }
210+
inline std::string HexStr(const Span<const std::byte> s) { return HexStr(MakeUCharSpan(s)); }
209211

210212
/**
211213
* Format a paragraph of text to a fixed width, adding spaces for

0 commit comments

Comments
 (0)