mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-11 06:28:31 +01:00
Use spans of std::byte in serialize
This switches .read() and .write() to take spans of bytes.
This commit is contained in:
@@ -47,79 +47,72 @@ static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
|
||||
struct deserialize_type {};
|
||||
constexpr deserialize_type deserialize {};
|
||||
|
||||
//! Safely convert odd char pointer types to standard ones.
|
||||
inline char* CharCast(char* c) { return c; }
|
||||
inline char* CharCast(unsigned char* c) { return (char*)c; }
|
||||
inline const char* CharCast(const char* c) { return c; }
|
||||
inline const char* CharCast(const unsigned char* c) { return (const char*)c; }
|
||||
|
||||
/*
|
||||
* Lowest-level serialization and conversion.
|
||||
* @note Sizes of these types are verified in the tests
|
||||
*/
|
||||
template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj)
|
||||
{
|
||||
s.write((char*)&obj, 1);
|
||||
s.write(AsBytes(Span{&obj, 1}));
|
||||
}
|
||||
template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
|
||||
{
|
||||
obj = htole16(obj);
|
||||
s.write((char*)&obj, 2);
|
||||
s.write(AsBytes(Span{&obj, 1}));
|
||||
}
|
||||
template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj)
|
||||
{
|
||||
obj = htobe16(obj);
|
||||
s.write((char*)&obj, 2);
|
||||
s.write(AsBytes(Span{&obj, 1}));
|
||||
}
|
||||
template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
|
||||
{
|
||||
obj = htole32(obj);
|
||||
s.write((char*)&obj, 4);
|
||||
s.write(AsBytes(Span{&obj, 1}));
|
||||
}
|
||||
template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj)
|
||||
{
|
||||
obj = htobe32(obj);
|
||||
s.write((char*)&obj, 4);
|
||||
s.write(AsBytes(Span{&obj, 1}));
|
||||
}
|
||||
template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
|
||||
{
|
||||
obj = htole64(obj);
|
||||
s.write((char*)&obj, 8);
|
||||
s.write(AsBytes(Span{&obj, 1}));
|
||||
}
|
||||
template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
|
||||
{
|
||||
uint8_t obj;
|
||||
s.read((char*)&obj, 1);
|
||||
s.read(AsWritableBytes(Span{&obj, 1}));
|
||||
return obj;
|
||||
}
|
||||
template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
|
||||
{
|
||||
uint16_t obj;
|
||||
s.read((char*)&obj, 2);
|
||||
s.read(AsWritableBytes(Span{&obj, 1}));
|
||||
return le16toh(obj);
|
||||
}
|
||||
template<typename Stream> inline uint16_t ser_readdata16be(Stream &s)
|
||||
{
|
||||
uint16_t obj;
|
||||
s.read((char*)&obj, 2);
|
||||
s.read(AsWritableBytes(Span{&obj, 1}));
|
||||
return be16toh(obj);
|
||||
}
|
||||
template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
|
||||
{
|
||||
uint32_t obj;
|
||||
s.read((char*)&obj, 4);
|
||||
s.read(AsWritableBytes(Span{&obj, 1}));
|
||||
return le32toh(obj);
|
||||
}
|
||||
template<typename Stream> inline uint32_t ser_readdata32be(Stream &s)
|
||||
{
|
||||
uint32_t obj;
|
||||
s.read((char*)&obj, 4);
|
||||
s.read(AsWritableBytes(Span{&obj, 1}));
|
||||
return be32toh(obj);
|
||||
}
|
||||
template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
|
||||
{
|
||||
uint64_t obj;
|
||||
s.read((char*)&obj, 8);
|
||||
s.read(AsWritableBytes(Span{&obj, 1}));
|
||||
return le64toh(obj);
|
||||
}
|
||||
|
||||
@@ -127,7 +120,7 @@ template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Templates for serializing to anything that looks like a stream,
|
||||
// i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
|
||||
// i.e. anything that supports .read(Span<std::byte>) and .write(Span<const std::byte>)
|
||||
//
|
||||
|
||||
class CSizeComputer;
|
||||
@@ -206,10 +199,10 @@ template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_wri
|
||||
template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
|
||||
template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
|
||||
template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
|
||||
template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(a, N); }
|
||||
template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(CharCast(a), N); }
|
||||
template<typename Stream> inline void Serialize(Stream& s, const Span<const unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
|
||||
template<typename Stream> inline void Serialize(Stream& s, const Span<unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
|
||||
template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(MakeByteSpan(a)); }
|
||||
template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(MakeByteSpan(a)); }
|
||||
template<typename Stream> inline void Serialize(Stream& s, const Span<const unsigned char>& span) { s.write(AsBytes(span)); }
|
||||
template<typename Stream> inline void Serialize(Stream& s, const Span<unsigned char>& span) { s.write(AsBytes(span)); }
|
||||
|
||||
#ifndef CHAR_EQUALS_INT8
|
||||
template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
|
||||
@@ -222,9 +215,9 @@ template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a =
|
||||
template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
|
||||
template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
|
||||
template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
|
||||
template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(a, N); }
|
||||
template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(CharCast(a), N); }
|
||||
template<typename Stream> inline void Unserialize(Stream& s, Span<unsigned char>& span) { s.read(CharCast(span.data()), span.size()); }
|
||||
template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(MakeWritableByteSpan(a)); }
|
||||
template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(MakeWritableByteSpan(a)); }
|
||||
template<typename Stream> inline void Unserialize(Stream& s, Span<unsigned char>& span) { s.read(AsWritableBytes(span)); }
|
||||
|
||||
template <typename Stream> inline void Serialize(Stream& s, bool a) { uint8_t f = a; ser_writedata8(s, f); }
|
||||
template <typename Stream> inline void Unserialize(Stream& s, bool& a) { uint8_t f = ser_readdata8(s); a = f; }
|
||||
@@ -479,10 +472,10 @@ struct CustomUintFormatter
|
||||
if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
|
||||
if (BigEndian) {
|
||||
uint64_t raw = htobe64(v);
|
||||
s.write(((const char*)&raw) + 8 - Bytes, Bytes);
|
||||
s.write({BytePtr(&raw) + 8 - Bytes, Bytes});
|
||||
} else {
|
||||
uint64_t raw = htole64(v);
|
||||
s.write((const char*)&raw, Bytes);
|
||||
s.write({BytePtr(&raw), Bytes});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,10 +485,10 @@ struct CustomUintFormatter
|
||||
static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
|
||||
uint64_t raw = 0;
|
||||
if (BigEndian) {
|
||||
s.read(((char*)&raw) + 8 - Bytes, Bytes);
|
||||
s.read({BytePtr(&raw) + 8 - Bytes, Bytes});
|
||||
v = static_cast<I>(be64toh(raw));
|
||||
} else {
|
||||
s.read((char*)&raw, Bytes);
|
||||
s.read({BytePtr(&raw), Bytes});
|
||||
v = static_cast<I>(le64toh(raw));
|
||||
}
|
||||
}
|
||||
@@ -551,7 +544,7 @@ struct LimitedStringFormatter
|
||||
throw std::ios_base::failure("String length limit exceeded");
|
||||
}
|
||||
v.resize(size);
|
||||
if (size != 0) s.read((char*)v.data(), size);
|
||||
if (size != 0) s.read(MakeWritableByteSpan(v));
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
@@ -715,7 +708,7 @@ void Serialize(Stream& os, const std::basic_string<C>& str)
|
||||
{
|
||||
WriteCompactSize(os, str.size());
|
||||
if (!str.empty())
|
||||
os.write((char*)str.data(), str.size() * sizeof(C));
|
||||
os.write(MakeByteSpan(str));
|
||||
}
|
||||
|
||||
template<typename Stream, typename C>
|
||||
@@ -724,7 +717,7 @@ void Unserialize(Stream& is, std::basic_string<C>& str)
|
||||
unsigned int nSize = ReadCompactSize(is);
|
||||
str.resize(nSize);
|
||||
if (nSize != 0)
|
||||
is.read((char*)str.data(), nSize * sizeof(C));
|
||||
is.read(MakeWritableByteSpan(str));
|
||||
}
|
||||
|
||||
|
||||
@@ -737,7 +730,7 @@ void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&)
|
||||
{
|
||||
WriteCompactSize(os, v.size());
|
||||
if (!v.empty())
|
||||
os.write((char*)v.data(), v.size() * sizeof(T));
|
||||
os.write(MakeByteSpan(v));
|
||||
}
|
||||
|
||||
template<typename Stream, unsigned int N, typename T, typename V>
|
||||
@@ -764,7 +757,7 @@ void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)
|
||||
{
|
||||
unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
|
||||
v.resize_uninitialized(i + blk);
|
||||
is.read((char*)&v[i], blk * sizeof(T));
|
||||
is.read(AsWritableBytes(Span{&v[i], blk}));
|
||||
i += blk;
|
||||
}
|
||||
}
|
||||
@@ -791,7 +784,7 @@ void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&
|
||||
{
|
||||
WriteCompactSize(os, v.size());
|
||||
if (!v.empty())
|
||||
os.write((char*)v.data(), v.size() * sizeof(T));
|
||||
os.write(MakeByteSpan(v));
|
||||
}
|
||||
|
||||
template<typename Stream, typename T, typename A>
|
||||
@@ -830,7 +823,7 @@ void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&)
|
||||
{
|
||||
unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
|
||||
v.resize(i + blk);
|
||||
is.read((char*)&v[i], blk * sizeof(T));
|
||||
is.read(AsWritableBytes(Span{&v[i], blk}));
|
||||
i += blk;
|
||||
}
|
||||
}
|
||||
@@ -995,9 +988,9 @@ protected:
|
||||
public:
|
||||
explicit CSizeComputer(int nVersionIn) : nSize(0), nVersion(nVersionIn) {}
|
||||
|
||||
void write(const char *psz, size_t _nSize)
|
||||
void write(Span<const std::byte> src)
|
||||
{
|
||||
this->nSize += _nSize;
|
||||
this->nSize += src.size();
|
||||
}
|
||||
|
||||
/** Pretend _nSize bytes are written, without specifying them. */
|
||||
|
||||
Reference in New Issue
Block a user