diff options
Diffstat (limited to 'src/serialize.h')
-rw-r--r-- | src/serialize.h | 96 |
1 files changed, 56 insertions, 40 deletions
diff --git a/src/serialize.h b/src/serialize.h index 247e915298..e54c7483d2 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -22,6 +22,7 @@ #include <vector> #include <prevector.h> +#include <span.h> static const unsigned int MAX_SIZE = 0x02000000; @@ -41,7 +42,7 @@ constexpr deserialize_type deserialize {}; /** * Used to bypass the rule against non-const reference to temporary - * where it makes sense with wrappers such as CFlatData or CTxDB + * where it makes sense with wrappers. */ template<typename T> inline T& REF(const T& val) @@ -78,6 +79,11 @@ template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj) obj = htole16(obj); s.write((char*)&obj, 2); } +template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj) +{ + obj = htobe16(obj); + s.write((char*)&obj, 2); +} template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj) { obj = htole32(obj); @@ -100,6 +106,12 @@ template<typename Stream> inline uint16_t ser_readdata16(Stream &s) s.read((char*)&obj, 2); return le16toh(obj); } +template<typename Stream> inline uint16_t ser_readdata16be(Stream &s) +{ + uint16_t obj; + s.read((char*)&obj, 2); + return be16toh(obj); +} template<typename Stream> inline uint32_t ser_readdata32(Stream &s) { uint32_t obj; @@ -154,7 +166,12 @@ enum SER_GETHASH = (1 << 2), }; -#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__)) +//! Convert the reference base type to X, without changing constness or reference type. +template<typename X> X& ReadWriteAsHelper(X& x) { return x; } +template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; } + +#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__)) +#define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj))) /** * Implement three methods for serializable objects. These are actually wrappers over @@ -185,6 +202,8 @@ template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_wri template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(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> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); } @@ -199,6 +218,7 @@ template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(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> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); } template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; } @@ -384,67 +404,60 @@ I ReadVarInt(Stream& is) } } -#define FLATDATA(obj) CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)) #define VARINT(obj, ...) WrapVarInt<__VA_ARGS__>(REF(obj)) #define COMPACTSIZE(obj) CCompactSize(REF(obj)) #define LIMITED_STRING(obj,n) LimitedString< n >(REF(obj)) -/** - * Wrapper for serializing arrays and POD. - */ -class CFlatData +template<VarIntMode Mode, typename I> +class CVarInt { protected: - char* pbegin; - char* pend; + I &n; public: - CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { } - template <class T, class TAl> - explicit CFlatData(std::vector<T,TAl> &v) - { - pbegin = (char*)v.data(); - pend = (char*)(v.data() + v.size()); - } - template <unsigned int N, typename T, typename S, typename D> - explicit CFlatData(prevector<N, T, S, D> &v) - { - pbegin = (char*)v.data(); - pend = (char*)(v.data() + v.size()); - } - char* begin() { return pbegin; } - const char* begin() const { return pbegin; } - char* end() { return pend; } - const char* end() const { return pend; } + explicit CVarInt(I& nIn) : n(nIn) { } template<typename Stream> - void Serialize(Stream& s) const - { - s.write(pbegin, pend - pbegin); + void Serialize(Stream &s) const { + WriteVarInt<Stream,Mode,I>(s, n); } template<typename Stream> - void Unserialize(Stream& s) - { - s.read(pbegin, pend - pbegin); + void Unserialize(Stream& s) { + n = ReadVarInt<Stream,Mode,I>(s); } }; -template<VarIntMode Mode, typename I> -class CVarInt +/** Serialization wrapper class for big-endian integers. + * + * Use this wrapper around integer types that are stored in memory in native + * byte order, but serialized in big endian notation. This is only intended + * to implement serializers that are compatible with existing formats, and + * its use is not recommended for new data structures. + * + * Only 16-bit types are supported for now. + */ +template<typename I> +class BigEndian { protected: - I &n; + I& m_val; public: - explicit CVarInt(I& nIn) : n(nIn) { } + explicit BigEndian(I& val) : m_val(val) + { + static_assert(std::is_unsigned<I>::value, "BigEndian type must be unsigned integer"); + static_assert(sizeof(I) == 2 && std::numeric_limits<I>::min() == 0 && std::numeric_limits<I>::max() == std::numeric_limits<uint16_t>::max(), "Unsupported BigEndian size"); + } template<typename Stream> - void Serialize(Stream &s) const { - WriteVarInt<Stream,Mode,I>(s, n); + void Serialize(Stream& s) const + { + ser_writedata16be(s, m_val); } template<typename Stream> - void Unserialize(Stream& s) { - n = ReadVarInt<Stream,Mode,I>(s); + void Unserialize(Stream& s) + { + m_val = ser_readdata16be(s); } }; @@ -498,6 +511,9 @@ public: template<VarIntMode Mode=VarIntMode::DEFAULT, typename I> CVarInt<Mode, I> WrapVarInt(I& n) { return CVarInt<Mode, I>{n}; } +template<typename I> +BigEndian<I> WrapBigEndian(I& n) { return BigEndian<I>(n); } + /** * Forward declarations */ |