Merge pull request #4737

31e9a83 Use CSizeComputer to avoid counting sizes in SerializationOp (Pieter Wuille)
84881f8 rework overhauled serialization methods to non-static (Kamil Domanski)
5d96b4a remove fields of ser_streamplaceholder (Kamil Domanski)
3d796f8 overhaul serialization code (Kamil Domanski)
This commit is contained in:
Pieter Wuille
2014-09-01 21:00:32 +02:00
13 changed files with 277 additions and 199 deletions

View File

@@ -37,6 +37,14 @@ 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
template<typename T>
inline T* NCONST_PTR(const T* val)
{
return const_cast<T*>(val);
}
/** 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.
@@ -79,49 +87,27 @@ enum
SER_GETHASH = (1 << 2),
};
#define IMPLEMENT_SERIALIZE(statements) \
unsigned int GetSerializeSize(int nType, int nVersion) const \
{ \
CSerActionGetSerializeSize ser_action; \
const bool fGetSize = true; \
const bool fWrite = false; \
const bool fRead = false; \
unsigned int nSerSize = 0; \
ser_streamplaceholder s; \
assert(fGetSize||fWrite||fRead); /* suppress warning */ \
s.nType = nType; \
s.nVersion = nVersion; \
{statements} \
return nSerSize; \
} \
template<typename Stream> \
void Serialize(Stream& s, int nType, int nVersion) const \
{ \
CSerActionSerialize ser_action; \
const bool fGetSize = false; \
const bool fWrite = true; \
const bool fRead = false; \
unsigned int nSerSize = 0; \
assert(fGetSize||fWrite||fRead); /* suppress warning */ \
{statements} \
} \
template<typename Stream> \
void Unserialize(Stream& s, int nType, int nVersion) \
{ \
CSerActionUnserialize ser_action; \
const bool fGetSize = false; \
const bool fWrite = false; \
const bool fRead = true; \
unsigned int nSerSize = 0; \
assert(fGetSize||fWrite||fRead); /* suppress warning */ \
{statements} \
#define READWRITE(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action))
/* Implement three methods for serializable objects. These are actually wrappers over
* "SerializationOp" template, which implements the body of each class' serialization
* code. Adding "IMPLEMENT_SERIALIZE" in the body of the class causes these wrappers to be
* added as members. */
#define IMPLEMENT_SERIALIZE \
size_t GetSerializeSize(int nType, int nVersion) const { \
CSizeComputer s(nType, nVersion); \
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion);\
return s.size(); \
} \
template<typename Stream> \
void Serialize(Stream& s, int nType, int nVersion) const { \
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion);\
} \
template<typename Stream> \
void Unserialize(Stream& s, int nType, int nVersion) { \
SerializationOp(s, CSerActionUnserialize(), nType, nVersion); \
}
#define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
//
@@ -823,37 +809,26 @@ void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
//
// Support for IMPLEMENT_SERIALIZE and READWRITE macro
//
class CSerActionGetSerializeSize { };
class CSerActionSerialize { };
class CSerActionUnserialize { };
template<typename Stream, typename T>
inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action)
struct CSerActionSerialize
{
return ::GetSerializeSize(obj, nType, nVersion);
}
template<typename Stream, typename T>
inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
bool ForRead() const { return false; }
};
struct CSerActionUnserialize
{
::Serialize(s, obj, nType, nVersion);
return 0;
}
template<typename Stream, typename T>
inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
{
::Unserialize(s, obj, nType, nVersion);
return 0;
}
struct ser_streamplaceholder
{
int nType;
int nVersion;
bool ForRead() const { return true; }
};
template<typename Stream, typename T>
inline void SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
{
::Serialize(s, obj, nType, nVersion);
}
template<typename Stream, typename T>
inline void SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
{
::Unserialize(s, obj, nType, nVersion);
}