|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
|
|
|
// Copyright (c) 2009-2013 The Bitcoin developers
|
|
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
|
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
|
|
#ifndef BITCOIN_SERIALIZE_H
|
|
|
|
@ -22,23 +22,28 @@ class CScript;
|
|
|
|
|
|
|
|
|
|
static const unsigned int MAX_SIZE = 0x02000000;
|
|
|
|
|
|
|
|
|
|
// Used to bypass the rule against non-const reference to temporary
|
|
|
|
|
// where it makes sense with wrappers such as CFlatData or CTxDB
|
|
|
|
|
/**
|
|
|
|
|
* Used to bypass the rule against non-const reference to temporary
|
|
|
|
|
* where it makes sense with wrappers such as CFlatData or CTxDB
|
|
|
|
|
*/
|
|
|
|
|
template<typename T>
|
|
|
|
|
inline T& REF(const T& val)
|
|
|
|
|
{
|
|
|
|
|
return const_cast<T&>(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Used to acquire a non-const pointer "this" to generate bodies
|
|
|
|
|
// of const serialization operations from a template
|
|
|
|
|
/**
|
|
|
|
|
* Used to acquire a non-const pointer "this" to generate bodies
|
|
|
|
|
* of const serialization operations from a template
|
|
|
|
|
*/
|
|
|
|
|
template<typename T>
|
|
|
|
|
inline T* NCONST_PTR(const T* val)
|
|
|
|
|
{
|
|
|
|
|
return const_cast<T*>(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Get begin pointer of vector (non-const version).
|
|
|
|
|
/**
|
|
|
|
|
* Get begin pointer of vector (non-const version).
|
|
|
|
|
* @note These functions avoid the undefined case of indexing into an empty
|
|
|
|
|
* vector, as well as that of indexing after the end of the vector.
|
|
|
|
|
*/
|
|
|
|
@ -82,10 +87,12 @@ enum
|
|
|
|
|
|
|
|
|
|
#define READWRITE(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action))
|
|
|
|
|
|
|
|
|
|
/* Implement three methods for serializable objects. These are actually wrappers over
|
|
|
|
|
/**
|
|
|
|
|
* Implement three methods for serializable objects. These are actually wrappers over
|
|
|
|
|
* "SerializationOp" template, which implements the body of each class' serialization
|
|
|
|
|
* code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
|
|
|
|
|
* added as members. */
|
|
|
|
|
* added as members.
|
|
|
|
|
*/
|
|
|
|
|
#define ADD_SERIALIZE_METHODS \
|
|
|
|
|
size_t GetSerializeSize(int nType, int nVersion) const { \
|
|
|
|
|
CSizeComputer s(nType, nVersion); \
|
|
|
|
@ -103,9 +110,9 @@ enum
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Basic types
|
|
|
|
|
//
|
|
|
|
|
/*
|
|
|
|
|
* Basic Types
|
|
|
|
|
*/
|
|
|
|
|
#define WRITEDATA(s, obj) s.write((char*)&(obj), sizeof(obj))
|
|
|
|
|
#define READDATA(s, obj) s.read((char*)&(obj), sizeof(obj))
|
|
|
|
|
|
|
|
|
@ -160,13 +167,13 @@ template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Compact size
|
|
|
|
|
// size < 253 -- 1 byte
|
|
|
|
|
// size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)
|
|
|
|
|
// size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
|
|
|
|
|
// size > UINT_MAX -- 9 bytes (255 + 8 bytes)
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* Compact Size
|
|
|
|
|
* size < 253 -- 1 byte
|
|
|
|
|
* size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)
|
|
|
|
|
* size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
|
|
|
|
|
* size > UINT_MAX -- 9 bytes (255 + 8 bytes)
|
|
|
|
|
*/
|
|
|
|
|
inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
|
|
|
|
|
{
|
|
|
|
|
if (nSize < 253) return sizeof(unsigned char);
|
|
|
|
@ -246,27 +253,29 @@ uint64_t ReadCompactSize(Stream& is)
|
|
|
|
|
return nSizeRet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Variable-length integers: bytes are a MSB base-128 encoding of the number.
|
|
|
|
|
// The high bit in each byte signifies whether another digit follows. To make
|
|
|
|
|
// the encoding is one-to-one, one is subtracted from all but the last digit.
|
|
|
|
|
// Thus, the byte sequence a[] with length len, where all but the last byte
|
|
|
|
|
// has bit 128 set, encodes the number:
|
|
|
|
|
//
|
|
|
|
|
// (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
|
|
|
|
|
//
|
|
|
|
|
// Properties:
|
|
|
|
|
// * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
|
|
|
|
|
// * Every integer has exactly one encoding
|
|
|
|
|
// * Encoding does not depend on size of original integer type
|
|
|
|
|
// * No redundancy: every (infinite) byte sequence corresponds to a list
|
|
|
|
|
// of encoded integers.
|
|
|
|
|
//
|
|
|
|
|
// 0: [0x00] 256: [0x81 0x00]
|
|
|
|
|
// 1: [0x01] 16383: [0xFE 0x7F]
|
|
|
|
|
// 127: [0x7F] 16384: [0xFF 0x00]
|
|
|
|
|
// 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F]
|
|
|
|
|
// 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F]
|
|
|
|
|
// 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]
|
|
|
|
|
/**
|
|
|
|
|
* Variable-length integers: bytes are a MSB base-128 encoding of the number.
|
|
|
|
|
* The high bit in each byte signifies whether another digit follows. To make
|
|
|
|
|
* sure the encoding is one-to-one, one is subtracted from all but the last digit.
|
|
|
|
|
* Thus, the byte sequence a[] with length len, where all but the last byte
|
|
|
|
|
* has bit 128 set, encodes the number:
|
|
|
|
|
*
|
|
|
|
|
* (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
|
|
|
|
|
*
|
|
|
|
|
* Properties:
|
|
|
|
|
* * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
|
|
|
|
|
* * Every integer has exactly one encoding
|
|
|
|
|
* * Encoding does not depend on size of original integer type
|
|
|
|
|
* * No redundancy: every (infinite) byte sequence corresponds to a list
|
|
|
|
|
* of encoded integers.
|
|
|
|
|
*
|
|
|
|
|
* 0: [0x00] 256: [0x81 0x00]
|
|
|
|
|
* 1: [0x01] 16383: [0xFE 0x7F]
|
|
|
|
|
* 127: [0x7F] 16384: [0xFF 0x00]
|
|
|
|
|
* 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F]
|
|
|
|
|
* 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F]
|
|
|
|
|
* 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
template<typename I>
|
|
|
|
|
inline unsigned int GetSizeOfVarInt(I n)
|
|
|
|
@ -317,7 +326,8 @@ I ReadVarInt(Stream& is)
|
|
|
|
|
#define VARINT(obj) REF(WrapVarInt(REF(obj)))
|
|
|
|
|
#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))
|
|
|
|
|
|
|
|
|
|
/** Wrapper for serializing arrays and POD.
|
|
|
|
|
/**
|
|
|
|
|
* Wrapper for serializing arrays and POD.
|
|
|
|
|
*/
|
|
|
|
|
class CFlatData
|
|
|
|
|
{
|
|
|
|
@ -415,17 +425,21 @@ public:
|
|
|
|
|
template<typename I>
|
|
|
|
|
CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Forward declarations
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* Forward declarations
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// string
|
|
|
|
|
/**
|
|
|
|
|
* string
|
|
|
|
|
*/
|
|
|
|
|
template<typename C> unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int=0);
|
|
|
|
|
template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str, int, int=0);
|
|
|
|
|
template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str, int, int=0);
|
|
|
|
|
|
|
|
|
|
// vector
|
|
|
|
|
// vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
|
|
|
|
|
/**
|
|
|
|
|
* vector
|
|
|
|
|
* vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
|
|
|
|
|
*/
|
|
|
|
|
template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&);
|
|
|
|
|
template<typename T, typename A, typename V> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const V&);
|
|
|
|
|
template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion);
|
|
|
|
@ -436,22 +450,30 @@ template<typename Stream, typename T, typename A> void Unserialize_impl(Stream&
|
|
|
|
|
template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const V&);
|
|
|
|
|
template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion);
|
|
|
|
|
|
|
|
|
|
// others derived from vector
|
|
|
|
|
/**
|
|
|
|
|
* others derived from vector
|
|
|
|
|
*/
|
|
|
|
|
extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion);
|
|
|
|
|
template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion);
|
|
|
|
|
template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion);
|
|
|
|
|
|
|
|
|
|
// pair
|
|
|
|
|
/**
|
|
|
|
|
* pair
|
|
|
|
|
*/
|
|
|
|
|
template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion);
|
|
|
|
|
template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion);
|
|
|
|
|
template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion);
|
|
|
|
|
|
|
|
|
|
// map
|
|
|
|
|
/**
|
|
|
|
|
* map
|
|
|
|
|
*/
|
|
|
|
|
template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion);
|
|
|
|
|
template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion);
|
|
|
|
|
template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion);
|
|
|
|
|
|
|
|
|
|
// set
|
|
|
|
|
/**
|
|
|
|
|
* set
|
|
|
|
|
*/
|
|
|
|
|
template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion);
|
|
|
|
|
template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion);
|
|
|
|
|
template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion);
|
|
|
|
@ -460,12 +482,12 @@ template<typename Stream, typename K, typename Pred, typename A> void Unserializ
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// If none of the specialized versions above matched, default to calling member function.
|
|
|
|
|
// "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
|
|
|
|
|
// The compiler will only cast int to long if none of the other templates matched.
|
|
|
|
|
// Thanks to Boost serialization for this idea.
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* If none of the specialized versions above matched, default to calling member function.
|
|
|
|
|
* "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
|
|
|
|
|
* The compiler will only cast int to long if none of the other templates matched.
|
|
|
|
|
* Thanks to Boost serialization for this idea.
|
|
|
|
|
*/
|
|
|
|
|
template<typename T>
|
|
|
|
|
inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion)
|
|
|
|
|
{
|
|
|
|
@ -488,9 +510,9 @@ inline void Unserialize(Stream& is, T& a, long nType, int nVersion)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// string
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* string
|
|
|
|
|
*/
|
|
|
|
|
template<typename C>
|
|
|
|
|
unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int)
|
|
|
|
|
{
|
|
|
|
@ -516,9 +538,9 @@ void Unserialize(Stream& is, std::basic_string<C>& str, int, int)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// vector
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* vector
|
|
|
|
|
*/
|
|
|
|
|
template<typename T, typename A>
|
|
|
|
|
unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&)
|
|
|
|
|
{
|
|
|
|
@ -606,9 +628,9 @@ inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersio
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// others derived from vector
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* others derived from vector
|
|
|
|
|
*/
|
|
|
|
|
inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)
|
|
|
|
|
{
|
|
|
|
|
return GetSerializeSize((const std::vector<unsigned char>&)v, nType, nVersion);
|
|
|
|
@ -628,9 +650,9 @@ void Unserialize(Stream& is, CScript& v, int nType, int nVersion)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// pair
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* pair
|
|
|
|
|
*/
|
|
|
|
|
template<typename K, typename T>
|
|
|
|
|
unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)
|
|
|
|
|
{
|
|
|
|
@ -653,9 +675,9 @@ void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// map
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* map
|
|
|
|
|
*/
|
|
|
|
|
template<typename K, typename T, typename Pred, typename A>
|
|
|
|
|
unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)
|
|
|
|
|
{
|
|
|
|
@ -689,9 +711,9 @@ void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// set
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* set
|
|
|
|
|
*/
|
|
|
|
|
template<typename K, typename Pred, typename A>
|
|
|
|
|
unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)
|
|
|
|
|
{
|
|
|
|
@ -725,9 +747,9 @@ void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Support for ADD_SERIALIZE_METHODS and READWRITE macro
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* Support for ADD_SERIALIZE_METHODS and READWRITE macro
|
|
|
|
|
*/
|
|
|
|
|
struct CSerActionSerialize
|
|
|
|
|
{
|
|
|
|
|
bool ForRead() const { return false; }
|
|
|
|
|