Changeset View
Changeset View
Standalone View
Standalone View
src/serialize.h
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#ifndef BITCOIN_SERIALIZE_H | #ifndef BITCOIN_SERIALIZE_H | ||||
#define BITCOIN_SERIALIZE_H | #define BITCOIN_SERIALIZE_H | ||||
#include <compat/endian.h> | #include <compat/endian.h> | ||||
#include <prevector.h> | #include <prevector.h> | ||||
#include <span.h> | |||||
#include <algorithm> | #include <algorithm> | ||||
#include <array> | #include <array> | ||||
#include <cassert> | #include <cassert> | ||||
#include <cstdint> | #include <cstdint> | ||||
#include <cstring> | #include <cstring> | ||||
#include <ios> | #include <ios> | ||||
#include <limits> | #include <limits> | ||||
Show All 15 Lines | |||||
* | * | ||||
* is a deserializing constructor, which builds the type by deserializing it | * is a deserializing constructor, which builds the type by deserializing it | ||||
* from s. If T contains const fields, this is likely the only way to do so. | * from s. If T contains const fields, this is likely the only way to do so. | ||||
*/ | */ | ||||
struct deserialize_type {}; | struct deserialize_type {}; | ||||
constexpr deserialize_type deserialize{}; | constexpr deserialize_type deserialize{}; | ||||
/** | /** | ||||
* Used to bypass the rule against non-const reference to temporary where it | * Used to bypass the rule against non-const reference to temporary | ||||
* makes sense with wrappers such as CFlatData or CTxDB | * where it makes sense with wrappers. | ||||
*/ | */ | ||||
template <typename T> inline T &REF(const T &val) { | template <typename T> inline T &REF(const T &val) { | ||||
return const_cast<T &>(val); | return const_cast<T &>(val); | ||||
} | } | ||||
/** | /** | ||||
* Used to acquire a non-const pointer "this" to generate bodies of const | * Used to acquire a non-const pointer "this" to generate bodies of const | ||||
* serialization operations from a template | * serialization operations from a template | ||||
▲ Show 20 Lines • Show All 203 Lines • ▼ Show 20 Lines | |||||
inline void Serialize(Stream &s, const char (&a)[N]) { | inline void Serialize(Stream &s, const char (&a)[N]) { | ||||
s.write(a, N); | s.write(a, N); | ||||
} | } | ||||
template <typename Stream, size_t N> | template <typename Stream, size_t N> | ||||
inline void Serialize(Stream &s, const std::array<char, N> &a) { | inline void Serialize(Stream &s, const std::array<char, N> &a) { | ||||
s.write(a.data(), N); | s.write(a.data(), N); | ||||
} | } | ||||
#endif | #endif | ||||
template <typename Stream> | |||||
inline void Serialize(Stream &s, const Span<const uint8_t> &span) { | |||||
s.write(CharCast(span.data()), span.size()); | |||||
} | |||||
template <typename Stream> | |||||
inline void Serialize(Stream &s, const Span<uint8_t> &span) { | |||||
s.write(CharCast(span.data()), span.size()); | |||||
} | |||||
template <typename Stream> inline void Unserialize(Stream &s, int8_t &a) { | template <typename Stream> inline void Unserialize(Stream &s, int8_t &a) { | ||||
a = ser_readdata8(s); | a = ser_readdata8(s); | ||||
} | } | ||||
template <typename Stream> inline void Unserialize(Stream &s, uint8_t &a) { | template <typename Stream> inline void Unserialize(Stream &s, uint8_t &a) { | ||||
a = ser_readdata8(s); | a = ser_readdata8(s); | ||||
} | } | ||||
template <typename Stream> inline void Unserialize(Stream &s, int16_t &a) { | template <typename Stream> inline void Unserialize(Stream &s, int16_t &a) { | ||||
a = ser_readdata16(s); | a = ser_readdata16(s); | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
template <typename Stream> inline void Serialize(Stream &s, bool a) { | template <typename Stream> inline void Serialize(Stream &s, bool a) { | ||||
char f = a; | char f = a; | ||||
ser_writedata8(s, f); | ser_writedata8(s, f); | ||||
} | } | ||||
template <typename Stream> inline void Unserialize(Stream &s, bool &a) { | template <typename Stream> inline void Unserialize(Stream &s, bool &a) { | ||||
char f = ser_readdata8(s); | char f = ser_readdata8(s); | ||||
a = f; | a = f; | ||||
} | } | ||||
template <typename Stream> | |||||
inline void Unserialize(Stream &s, Span<uint8_t> &span) { | |||||
s.read(CharCast(span.data()), span.size()); | |||||
} | |||||
/** | /** | ||||
* Compact Size | * Compact Size | ||||
* size < 253 -- 1 byte | * size < 253 -- 1 byte | ||||
* size <= USHRT_MAX -- 3 bytes (253 + 2 bytes) | * size <= USHRT_MAX -- 3 bytes (253 + 2 bytes) | ||||
* size <= UINT_MAX -- 5 bytes (254 + 4 bytes) | * size <= UINT_MAX -- 5 bytes (254 + 4 bytes) | ||||
* size > UINT_MAX -- 9 bytes (255 + 8 bytes) | * size > UINT_MAX -- 9 bytes (255 + 8 bytes) | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | while (true) { | ||||
} | } | ||||
if (n == std::numeric_limits<I>::max()) { | if (n == std::numeric_limits<I>::max()) { | ||||
throw std::ios_base::failure("ReadVarInt(): size too large"); | throw std::ios_base::failure("ReadVarInt(): size too large"); | ||||
} | } | ||||
n++; | n++; | ||||
} | } | ||||
} | } | ||||
#define FLATDATA(obj) CFlatData((char *)&(obj), (char *)&(obj) + sizeof(obj)) | |||||
#define VARINT(obj, ...) WrapVarInt<__VA_ARGS__>(REF(obj)) | #define VARINT(obj, ...) WrapVarInt<__VA_ARGS__>(REF(obj)) | ||||
#define COMPACTSIZE(obj) CCompactSize(REF(obj)) | #define COMPACTSIZE(obj) CCompactSize(REF(obj)) | ||||
#define LIMITED_STRING(obj, n) LimitedString<n>(REF(obj)) | #define LIMITED_STRING(obj, n) LimitedString<n>(REF(obj)) | ||||
/** | |||||
* Wrapper for serializing arrays and POD. | |||||
*/ | |||||
class CFlatData { | |||||
protected: | |||||
char *pbegin; | |||||
char *pend; | |||||
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; } | |||||
template <typename Stream> void Serialize(Stream &s) const { | |||||
s.write(pbegin, pend - pbegin); | |||||
} | |||||
template <typename Stream> void Unserialize(Stream &s) { | |||||
s.read(pbegin, pend - pbegin); | |||||
} | |||||
}; | |||||
template <VarIntMode Mode, typename I> class CVarInt { | template <VarIntMode Mode, typename I> class CVarInt { | ||||
protected: | protected: | ||||
I &n; | I &n; | ||||
public: | public: | ||||
explicit CVarInt(I &nIn) : n(nIn) {} | explicit CVarInt(I &nIn) : n(nIn) {} | ||||
template <typename Stream> void Serialize(Stream &s) const { | template <typename Stream> void Serialize(Stream &s) const { | ||||
▲ Show 20 Lines • Show All 482 Lines • Show Last 20 Lines |