diff options
author | Kamil Domanski <kdomanski@kdemail.net> | 2014-08-20 08:42:31 +0200 |
---|---|---|
committer | Kamil Domanski <kdomanski@kdemail.net> | 2014-08-31 02:14:20 +0200 |
commit | 3d796f89962842e91e7d88e57c1d2d579f01052e (patch) | |
tree | d4be736c23fbc4d453a1e4e281eafb4f51cdffd8 /src | |
parent | 9f3d47677973cb894fdbb437b9b322e2062a1bf1 (diff) |
overhaul serialization code
The implementation of each class' serialization/deserialization is no longer
passed within a macro. The implementation now lies within a template of form:
template <typename T, typename Stream, typename Operation>
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) {
size_t nSerSize = 0;
/* CODE */
return nSerSize;
}
In cases when codepath should depend on whether or not we are just deserializing
(old fGetSize, fWrite, fRead flags) an additional clause can be used:
bool fRead = boost::is_same<Operation, CSerActionUnserialize>();
The IMPLEMENT_SERIALIZE macro will now be a freestanding clause added within
class' body (similiar to Qt's Q_OBJECT) to implement GetSerializeSize,
Serialize and Unserialize. These are now wrappers around
the "SerializationOp" template.
Diffstat (limited to 'src')
-rw-r--r-- | src/addrman.h | 17 | ||||
-rw-r--r-- | src/alert.h | 50 | ||||
-rw-r--r-- | src/bloom.h | 16 | ||||
-rw-r--r-- | src/core.h | 168 | ||||
-rw-r--r-- | src/crypter.h | 19 | ||||
-rw-r--r-- | src/main.h | 138 | ||||
-rw-r--r-- | src/netbase.h | 29 | ||||
-rw-r--r-- | src/protocol.h | 61 | ||||
-rw-r--r-- | src/qt/recentrequeststablemodel.h | 19 | ||||
-rw-r--r-- | src/qt/walletmodel.h | 15 | ||||
-rw-r--r-- | src/serialize.h | 68 | ||||
-rw-r--r-- | src/wallet.h | 123 | ||||
-rw-r--r-- | src/walletdb.h | 14 |
13 files changed, 463 insertions, 274 deletions
diff --git a/src/addrman.h b/src/addrman.h index 052d364655..4287cbc1b3 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -46,13 +46,18 @@ private: public: - IMPLEMENT_SERIALIZE( - CAddress* pthis = (CAddress*)(this); + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + CAddress* pthis = (CAddress*)(thisPtr); READWRITE(*pthis); - READWRITE(source); - READWRITE(nLastSuccess); - READWRITE(nAttempts); - ) + READWRITE(thisPtr->source); + READWRITE(thisPtr->nLastSuccess); + READWRITE(thisPtr->nAttempts); + return nSerSize; + } void Init() { diff --git a/src/alert.h b/src/alert.h index b9d850b565..4c8267fd06 100644 --- a/src/alert.h +++ b/src/alert.h @@ -47,23 +47,27 @@ public: std::string strReserved; IMPLEMENT_SERIALIZE - ( - READWRITE(this->nVersion); - nVersion = this->nVersion; - READWRITE(nRelayUntil); - READWRITE(nExpiration); - READWRITE(nID); - READWRITE(nCancel); - READWRITE(setCancel); - READWRITE(nMinVer); - READWRITE(nMaxVer); - READWRITE(setSubVer); - READWRITE(nPriority); - - READWRITE(LIMITED_STRING(strComment, 65536)); - READWRITE(LIMITED_STRING(strStatusBar, 256)); - READWRITE(LIMITED_STRING(strReserved, 256)); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->nVersion); + nVersion = thisPtr->nVersion; + READWRITE(thisPtr->nRelayUntil); + READWRITE(thisPtr->nExpiration); + READWRITE(thisPtr->nID); + READWRITE(thisPtr->nCancel); + READWRITE(thisPtr->setCancel); + READWRITE(thisPtr->nMinVer); + READWRITE(thisPtr->nMaxVer); + READWRITE(thisPtr->setSubVer); + READWRITE(thisPtr->nPriority); + + READWRITE(LIMITED_STRING(thisPtr->strComment, 65536)); + READWRITE(LIMITED_STRING(thisPtr->strStatusBar, 256)); + READWRITE(LIMITED_STRING(thisPtr->strReserved, 256)); + return nSerSize; + } void SetNull(); @@ -83,10 +87,14 @@ public: } IMPLEMENT_SERIALIZE - ( - READWRITE(vchMsg); - READWRITE(vchSig); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->vchMsg); + READWRITE(thisPtr->vchSig); + return nSerSize; + } void SetNull(); bool IsNull() const; diff --git a/src/bloom.h b/src/bloom.h index 54d16d7126..dafea67029 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -63,12 +63,16 @@ public: CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {} IMPLEMENT_SERIALIZE - ( - READWRITE(vData); - READWRITE(nHashFuncs); - READWRITE(nTweak); - READWRITE(nFlags); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->vData); + READWRITE(thisPtr->nHashFuncs); + READWRITE(thisPtr->nTweak); + READWRITE(thisPtr->nFlags); + return nSerSize; + } void insert(const std::vector<unsigned char>& vKey); void insert(const COutPoint& outpoint); diff --git a/src/core.h b/src/core.h index 126e1baa98..1caf9da6c0 100644 --- a/src/core.h +++ b/src/core.h @@ -30,7 +30,16 @@ public: COutPoint() { SetNull(); } COutPoint(uint256 hashIn, uint32_t nIn) { hash = hashIn; n = nIn; } - IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) + + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(FLATDATA(*thisPtr)); + return nSerSize; + } + void SetNull() { hash = 0; n = (uint32_t) -1; } bool IsNull() const { return (hash == 0 && n == (uint32_t) -1); } @@ -85,11 +94,15 @@ public: CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits<uint32_t>::max()); IMPLEMENT_SERIALIZE - ( - READWRITE(prevout); - READWRITE(scriptSig); - READWRITE(nSequence); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->prevout); + READWRITE(thisPtr->scriptSig); + READWRITE(thisPtr->nSequence); + return nSerSize; + } bool IsFinal() const { @@ -136,7 +149,14 @@ public: friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } std::string ToString() const; - IMPLEMENT_SERIALIZE( READWRITE(nSatoshisPerK); ) + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->nSatoshisPerK); + return nSerSize; + } }; @@ -157,10 +177,14 @@ public: CTxOut(int64_t nValueIn, CScript scriptPubKeyIn); IMPLEMENT_SERIALIZE - ( - READWRITE(nValue); - READWRITE(scriptPubKey); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->nValue); + READWRITE(thisPtr->scriptPubKey); + return nSerSize; + } void SetNull() { @@ -237,15 +261,23 @@ public: CTransaction& operator=(const CTransaction& tx); - IMPLEMENT_SERIALIZE( - READWRITE(*const_cast<int32_t*>(&this->nVersion)); - nVersion = this->nVersion; - READWRITE(*const_cast<std::vector<CTxIn>*>(&vin)); - READWRITE(*const_cast<std::vector<CTxOut>*>(&vout)); - READWRITE(*const_cast<uint32_t*>(&nLockTime)); + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); + + READWRITE(*const_cast<int32_t*>(&thisPtr->nVersion)); + nVersion = thisPtr->nVersion; + READWRITE(*const_cast<std::vector<CTxIn>*>(&thisPtr->vin)); + READWRITE(*const_cast<std::vector<CTxOut>*>(&thisPtr->vout)); + READWRITE(*const_cast<uint32_t*>(&thisPtr->nLockTime)); if (fRead) - UpdateHash(); - ) + thisPtr->UpdateHash(); + + return nSerSize; + } bool IsNull() const { return vin.empty() && vout.empty(); @@ -292,13 +324,20 @@ struct CMutableTransaction CMutableTransaction(); CMutableTransaction(const CTransaction& tx); - IMPLEMENT_SERIALIZE( - READWRITE(this->nVersion); - nVersion = this->nVersion; - READWRITE(vin); - READWRITE(vout); - READWRITE(nLockTime); - ) + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + + READWRITE(thisPtr->nVersion); + nVersion = thisPtr->nVersion; + READWRITE(thisPtr->vin); + READWRITE(thisPtr->vout); + READWRITE(thisPtr->nLockTime); + + return nSerSize; + } /** Compute the hash of this CMutableTransaction. This is computed on the * fly, as opposed to GetHash() in CTransaction, which uses a cached result. @@ -318,18 +357,24 @@ public: CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { } - IMPLEMENT_SERIALIZE(({ + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); + size_t nSerSize = 0; if (!fRead) { - uint64_t nVal = CompressAmount(txout.nValue); + uint64_t nVal = CompressAmount(thisPtr->txout.nValue); READWRITE(VARINT(nVal)); } else { uint64_t nVal = 0; READWRITE(VARINT(nVal)); - txout.nValue = DecompressAmount(nVal); + thisPtr->txout.nValue = DecompressAmount(nVal); } - CScriptCompressor cscript(REF(txout.scriptPubKey)); + CScriptCompressor cscript(REF(thisPtr->txout.scriptPubKey)); READWRITE(cscript); - });) + return nSerSize; + } }; /** Undo information for a CTxIn @@ -382,9 +427,14 @@ public: // undo information for all txins std::vector<CTxInUndo> vprevout; - IMPLEMENT_SERIALIZE( - READWRITE(vprevout); - ) + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->vprevout); + return nSerSize; + } }; @@ -413,15 +463,21 @@ public: } IMPLEMENT_SERIALIZE - ( - READWRITE(this->nVersion); - nVersion = this->nVersion; - READWRITE(hashPrevBlock); - READWRITE(hashMerkleRoot); - READWRITE(nTime); - READWRITE(nBits); - READWRITE(nNonce); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + + READWRITE(thisPtr->nVersion); + nVersion = thisPtr->nVersion; + READWRITE(thisPtr->hashPrevBlock); + READWRITE(thisPtr->hashMerkleRoot); + READWRITE(thisPtr->nTime); + READWRITE(thisPtr->nBits); + READWRITE(thisPtr->nNonce); + + return nSerSize; + } void SetNull() { @@ -468,10 +524,16 @@ public: } IMPLEMENT_SERIALIZE - ( - READWRITE(*(CBlockHeader*)this); - READWRITE(vtx); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + + READWRITE(*(CBlockHeader*)thisPtr); + READWRITE(thisPtr->vtx); + + return nSerSize; + } void SetNull() { @@ -516,11 +578,17 @@ struct CBlockLocator } IMPLEMENT_SERIALIZE - ( + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + if (!(nType & SER_GETHASH)) READWRITE(nVersion); - READWRITE(vHave); - ) + READWRITE(thisPtr->vHave); + + return nSerSize; + } void SetNull() { diff --git a/src/crypter.h b/src/crypter.h index f16fcef9c7..c3f4ed971c 100644 --- a/src/crypter.h +++ b/src/crypter.h @@ -44,13 +44,18 @@ public: std::vector<unsigned char> vchOtherDerivationParameters; IMPLEMENT_SERIALIZE - ( - READWRITE(vchCryptedKey); - READWRITE(vchSalt); - READWRITE(nDerivationMethod); - READWRITE(nDeriveIterations); - READWRITE(vchOtherDerivationParameters); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->vchCryptedKey); + READWRITE(thisPtr->vchSalt); + READWRITE(thisPtr->nDerivationMethod); + READWRITE(thisPtr->nDeriveIterations); + READWRITE(thisPtr->vchOtherDerivationParameters); + return nSerSize; + } + CMasterKey() { // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M diff --git a/src/main.h b/src/main.h index 9fe15d3aa3..88e3159e3f 100644 --- a/src/main.h +++ b/src/main.h @@ -197,10 +197,15 @@ struct CDiskBlockPos int nFile; unsigned int nPos; - IMPLEMENT_SERIALIZE( - READWRITE(VARINT(nFile)); - READWRITE(VARINT(nPos)); - ) + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(VARINT(thisPtr->nFile)); + READWRITE(VARINT(thisPtr->nPos)); + return nSerSize; + } CDiskBlockPos() { SetNull(); @@ -227,10 +232,15 @@ struct CDiskTxPos : public CDiskBlockPos { unsigned int nTxOffset; // after header - IMPLEMENT_SERIALIZE( - READWRITE(*(CDiskBlockPos*)this); - READWRITE(VARINT(nTxOffset)); - ) + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(*(CDiskBlockPos*)thisPtr); + READWRITE(VARINT(thisPtr->nTxOffset)); + return nSerSize; + } CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { } @@ -307,9 +317,14 @@ class CBlockUndo public: std::vector<CTxUndo> vtxundo; // for all but the coinbase - IMPLEMENT_SERIALIZE( - READWRITE(vtxundo); - ) + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->vtxundo); + return nSerSize; + } bool WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock); bool ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock); @@ -411,24 +426,32 @@ protected: public: // serialization implementation - IMPLEMENT_SERIALIZE( - READWRITE(nTransactions); - READWRITE(vHash); + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); + + READWRITE(thisPtr->nTransactions); + READWRITE(thisPtr->vHash); std::vector<unsigned char> vBytes; if (fRead) { READWRITE(vBytes); - CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this)); + CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(thisPtr)); us.vBits.resize(vBytes.size() * 8); for (unsigned int p = 0; p < us.vBits.size(); p++) us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0; us.fBad = false; } else { - vBytes.resize((vBits.size()+7)/8); - for (unsigned int p = 0; p < vBits.size(); p++) - vBytes[p / 8] |= vBits[p] << (p % 8); + vBytes.resize((thisPtr->vBits.size()+7)/8); + for (unsigned int p = 0; p < thisPtr->vBits.size(); p++) + vBytes[p / 8] |= thisPtr->vBits[p] << (p % 8); READWRITE(vBytes); } - ) + + return nSerSize; + } // Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch); @@ -484,15 +507,22 @@ public: uint64_t nTimeFirst; // earliest time of block in file uint64_t nTimeLast; // latest time of block in file - IMPLEMENT_SERIALIZE( - READWRITE(VARINT(nBlocks)); - READWRITE(VARINT(nSize)); - READWRITE(VARINT(nUndoSize)); - READWRITE(VARINT(nHeightFirst)); - READWRITE(VARINT(nHeightLast)); - READWRITE(VARINT(nTimeFirst)); - READWRITE(VARINT(nTimeLast)); - ) + IMPLEMENT_SERIALIZE + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + + READWRITE(VARINT(thisPtr->nBlocks)); + READWRITE(VARINT(thisPtr->nSize)); + READWRITE(VARINT(thisPtr->nUndoSize)); + READWRITE(VARINT(thisPtr->nHeightFirst)); + READWRITE(VARINT(thisPtr->nHeightLast)); + READWRITE(VARINT(thisPtr->nTimeFirst)); + READWRITE(VARINT(thisPtr->nTimeLast)); + + return nSerSize; + } void SetNull() { nBlocks = 0; @@ -756,28 +786,34 @@ public: } IMPLEMENT_SERIALIZE - ( + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + if (!(nType & SER_GETHASH)) READWRITE(VARINT(nVersion)); - READWRITE(VARINT(nHeight)); - READWRITE(VARINT(nStatus)); - READWRITE(VARINT(nTx)); - if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) - READWRITE(VARINT(nFile)); - if (nStatus & BLOCK_HAVE_DATA) - READWRITE(VARINT(nDataPos)); - if (nStatus & BLOCK_HAVE_UNDO) - READWRITE(VARINT(nUndoPos)); + READWRITE(VARINT(thisPtr->nHeight)); + READWRITE(VARINT(thisPtr->nStatus)); + READWRITE(VARINT(thisPtr->nTx)); + if (thisPtr->nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) + READWRITE(VARINT(thisPtr->nFile)); + if (thisPtr->nStatus & BLOCK_HAVE_DATA) + READWRITE(VARINT(thisPtr->nDataPos)); + if (thisPtr->nStatus & BLOCK_HAVE_UNDO) + READWRITE(VARINT(thisPtr->nUndoPos)); // block header - READWRITE(this->nVersion); - READWRITE(hashPrev); - READWRITE(hashMerkleRoot); - READWRITE(nTime); - READWRITE(nBits); - READWRITE(nNonce); - ) + READWRITE(thisPtr->nVersion); + READWRITE(thisPtr->hashPrev); + READWRITE(thisPtr->hashMerkleRoot); + READWRITE(thisPtr->nTime); + READWRITE(thisPtr->nBits); + READWRITE(thisPtr->nNonce); + + return nSerSize; + } uint256 GetBlockHash() const { @@ -976,10 +1012,14 @@ public: CMerkleBlock(const CBlock& block, CBloomFilter& filter); IMPLEMENT_SERIALIZE - ( - READWRITE(header); - READWRITE(txn); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->header); + READWRITE(thisPtr->txn); + return nSerSize; + } }; diff --git a/src/netbase.h b/src/netbase.h index 2df3c4474d..6f8c132502 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -89,9 +89,13 @@ class CNetAddr friend bool operator<(const CNetAddr& a, const CNetAddr& b); IMPLEMENT_SERIALIZE - ( - READWRITE(FLATDATA(ip)); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(FLATDATA(thisPtr->ip)); + return nSerSize; + } }; class CSubNet @@ -149,14 +153,19 @@ class CService : public CNetAddr CService(const struct sockaddr_in6& addr); IMPLEMENT_SERIALIZE - ( - CService* pthis = const_cast<CService*>(this); - READWRITE(FLATDATA(ip)); - unsigned short portN = htons(port); - READWRITE(portN); - if (fRead) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); + size_t nSerSize = 0; + CService* pthis = const_cast<CService*>(thisPtr); + READWRITE(FLATDATA(thisPtr->ip)); + unsigned short portN = htons(thisPtr->port); + READWRITE(portN); + if (fRead) pthis->port = ntohs(portN); - ) + return nSerSize; + } }; typedef CService proxyType; diff --git a/src/protocol.h b/src/protocol.h index d7565584af..851fca9d9e 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -36,12 +36,16 @@ class CMessageHeader bool IsValid() const; IMPLEMENT_SERIALIZE - ( - READWRITE(FLATDATA(pchMessageStart)); - READWRITE(FLATDATA(pchCommand)); - READWRITE(nMessageSize); - READWRITE(nChecksum); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(FLATDATA(thisPtr->pchMessageStart)); + READWRITE(FLATDATA(thisPtr->pchCommand)); + READWRITE(thisPtr->nMessageSize); + READWRITE(thisPtr->nChecksum); + return nSerSize; + } // TODO: make private (improves encapsulation) public: @@ -84,19 +88,26 @@ class CAddress : public CService void Init(); IMPLEMENT_SERIALIZE - ( - CAddress* pthis = const_cast<CAddress*>(this); - CService* pip = (CService*)pthis; - if (fRead) - pthis->Init(); - if (nType & SER_DISK) - READWRITE(nVersion); - if ((nType & SER_DISK) || - (nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) - READWRITE(nTime); - READWRITE(nServices); - READWRITE(*pip); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); + + CAddress* pthis = const_cast<CAddress*>(thisPtr); + CService* pip = (CService*)pthis; + if (fRead) + pthis->Init(); + if (nType & SER_DISK) + READWRITE(nVersion); + if ((nType & SER_DISK) || + (nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) + READWRITE(thisPtr->nTime); + READWRITE(thisPtr->nServices); + READWRITE(*pip); + + return nSerSize; + } // TODO: make private (improves encapsulation) public: @@ -118,10 +129,14 @@ class CInv CInv(const std::string& strType, const uint256& hashIn); IMPLEMENT_SERIALIZE - ( - READWRITE(type); - READWRITE(hash); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->type); + READWRITE(thisPtr->hash); + return nSerSize; + } friend bool operator<(const CInv& a, const CInv& b); diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index 4f0b241259..50962334f5 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -25,20 +25,27 @@ public: SendCoinsRecipient recipient; IMPLEMENT_SERIALIZE - ( - RecentRequestEntry* pthis = const_cast<RecentRequestEntry*>(this); - unsigned int nDate = date.toTime_t(); + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); + + RecentRequestEntry* pthis = const_cast<RecentRequestEntry*>(thisPtr); + + unsigned int nDate = thisPtr->date.toTime_t(); READWRITE(pthis->nVersion); nVersion = pthis->nVersion; - READWRITE(id); + READWRITE(thisPtr->id); READWRITE(nDate); - READWRITE(recipient); + READWRITE(thisPtr->recipient); if (fRead) pthis->date = QDateTime::fromTime_t(nDate); - ) + + return nSerSize; + } }; class RecentRequestEntryLessThan diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index b3a401e4cc..543843733c 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -60,8 +60,13 @@ public: int nVersion; IMPLEMENT_SERIALIZE - ( - SendCoinsRecipient* pthis = const_cast<SendCoinsRecipient*>(this); + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); + + SendCoinsRecipient* pthis = const_cast<SendCoinsRecipient*>(thisPtr); std::string sAddress = pthis->address.toStdString(); std::string sLabel = pthis->label.toStdString(); @@ -75,7 +80,7 @@ public: nVersion = pthis->nVersion; READWRITE(sAddress); READWRITE(sLabel); - READWRITE(amount); + READWRITE(thisPtr->amount); READWRITE(sMessage); READWRITE(sPaymentRequest); READWRITE(sAuthenticatedMerchant); @@ -89,7 +94,9 @@ public: pthis->paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size())); pthis->authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant); } - ) + + return nSerSize; + } }; /** Interface to Bitcoin wallet from Qt view code. */ diff --git a/src/serialize.h b/src/serialize.h index 17cb724bee..7e0ecc2edf 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -22,6 +22,7 @@ #include <boost/tuple/tuple.hpp> #include <boost/type_traits/is_fundamental.hpp> +#include <boost/typeof/typeof.hpp> class CAutoFile; class CDataStream; @@ -37,6 +38,14 @@ inline T& REF(const T& val) return const_cast<T&>(val); } +// Used to acquire a const pointer "this" and generate a const +// serialization operation from a template +template<typename T> +inline T MAKE_CONST(T val) +{ + return const_cast<const 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,48 +88,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) (nSerSize += ::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 { \ + ser_streamplaceholder s; \ + s.nType = nType; \ + s.nVersion = nVersion; \ + return SerializationOp(MAKE_CONST(this), s, CSerActionGetSerializeSize(), nType, nVersion); \ + } \ + template<typename Stream> \ + void Serialize(Stream& s, int nType, int nVersion) const { \ + SerializationOp(MAKE_CONST(this), s, CSerActionSerialize(), nType, nVersion); \ + } \ + template<typename Stream> \ + void Unserialize(Stream& s, int nType, int nVersion) { \ + SerializationOp(this, s, CSerActionUnserialize(), nType, nVersion); \ + } diff --git a/src/wallet.h b/src/wallet.h index 544b4f5bfb..36b0bafe5a 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -64,12 +64,16 @@ public: CKeyPool(const CPubKey& vchPubKeyIn); IMPLEMENT_SERIALIZE - ( + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; if (!(nType & SER_GETHASH)) READWRITE(nVersion); - READWRITE(nTime); - READWRITE(vchPubKey); - ) + READWRITE(thisPtr->nTime); + READWRITE(thisPtr->vchPubKey); + return nSerSize; + } }; /** Address book data */ @@ -489,16 +493,20 @@ public: fMerkleVerified = false; } - IMPLEMENT_SERIALIZE - ( - nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action); - nVersion = this->nVersion; - READWRITE(hashBlock); - READWRITE(vMerkleBranch); - READWRITE(nIndex); - ) + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + + nSerSize += SerReadWrite(s, *(CTransaction*)thisPtr, nType, nVersion, ser_action); + nVersion = thisPtr->nVersion; + READWRITE(thisPtr->hashBlock); + READWRITE(thisPtr->vMerkleBranch); + READWRITE(thisPtr->nIndex); + + return nSerSize; + } int SetMerkleBranch(const CBlock* pblock=NULL); @@ -513,7 +521,6 @@ public: bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true); }; - /** A transaction with a bunch of additional info that only the owner cares about. * It includes any unrecorded transactions needed to link it back to the block chain. */ @@ -604,8 +611,13 @@ public: } IMPLEMENT_SERIALIZE - ( - CWalletTx* pthis = const_cast<CWalletTx*>(this); + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); + + CWalletTx* pthis = const_cast<CWalletTx*>(thisPtr); if (fRead) pthis->Init(NULL); char fSpent = false; @@ -616,18 +628,18 @@ public: WriteOrderPos(pthis->nOrderPos, pthis->mapValue); - if (nTimeSmart) - pthis->mapValue["timesmart"] = strprintf("%u", nTimeSmart); + if (thisPtr->nTimeSmart) + pthis->mapValue["timesmart"] = strprintf("%u", thisPtr->nTimeSmart); } - nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action); + nSerSize += SerReadWrite(s, *(CMerkleTx*)thisPtr, nType, nVersion,ser_action); std::vector<CMerkleTx> vUnused; // Used to be vtxPrev READWRITE(vUnused); - READWRITE(mapValue); - READWRITE(vOrderForm); - READWRITE(fTimeReceivedIsTxTime); - READWRITE(nTimeReceived); - READWRITE(fFromMe); + READWRITE(thisPtr->mapValue); + READWRITE(thisPtr->vOrderForm); + READWRITE(thisPtr->fTimeReceivedIsTxTime); + READWRITE(thisPtr->nTimeReceived); + READWRITE(thisPtr->fFromMe); READWRITE(fSpent); if (fRead) @@ -636,7 +648,7 @@ public: ReadOrderPos(pthis->nOrderPos, pthis->mapValue); - pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0; + pthis->nTimeSmart = thisPtr->mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0; } pthis->mapValue.erase("fromaccount"); @@ -644,7 +656,9 @@ public: pthis->mapValue.erase("spent"); pthis->mapValue.erase("n"); pthis->mapValue.erase("timesmart"); - ) + + return nSerSize; + } // make sure balances are recalculated void MarkDirty() @@ -891,14 +905,18 @@ public: CWalletKey(int64_t nExpires=0); IMPLEMENT_SERIALIZE - ( + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; if (!(nType & SER_GETHASH)) READWRITE(nVersion); - READWRITE(vchPrivKey); - READWRITE(nTimeCreated); - READWRITE(nTimeExpires); - READWRITE(LIMITED_STRING(strComment, 65536)); - ) + READWRITE(thisPtr->vchPrivKey); + READWRITE(thisPtr->nTimeCreated); + READWRITE(thisPtr->nTimeExpires); + READWRITE(LIMITED_STRING(thisPtr->strComment, 65536)); + return nSerSize; + } }; @@ -925,11 +943,15 @@ public: } IMPLEMENT_SERIALIZE - ( + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; if (!(nType & SER_GETHASH)) READWRITE(nVersion); - READWRITE(vchPubKey); - ) + READWRITE(thisPtr->vchPubKey); + return nSerSize; + } }; @@ -966,38 +988,43 @@ public: } IMPLEMENT_SERIALIZE - ( - CAccountingEntry& me = *const_cast<CAccountingEntry*>(this); + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); + + CAccountingEntry& me = *const_cast<CAccountingEntry*>(thisPtr); if (!(nType & SER_GETHASH)) READWRITE(nVersion); // Note: strAccount is serialized as part of the key, not here. - READWRITE(nCreditDebit); - READWRITE(nTime); - READWRITE(LIMITED_STRING(strOtherAccount, 65536)); + READWRITE(thisPtr->nCreditDebit); + READWRITE(thisPtr->nTime); + READWRITE(LIMITED_STRING(thisPtr->strOtherAccount, 65536)); if (!fRead) { - WriteOrderPos(nOrderPos, me.mapValue); + WriteOrderPos(thisPtr->nOrderPos, me.mapValue); - if (!(mapValue.empty() && _ssExtra.empty())) + if (!(thisPtr->mapValue.empty() && thisPtr->_ssExtra.empty())) { CDataStream ss(nType, nVersion); ss.insert(ss.begin(), '\0'); - ss << mapValue; - ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end()); + ss << thisPtr->mapValue; + ss.insert(ss.end(), thisPtr->_ssExtra.begin(), thisPtr->_ssExtra.end()); me.strComment.append(ss.str()); } } - READWRITE(LIMITED_STRING(strComment, 65536)); + READWRITE(LIMITED_STRING(thisPtr->strComment, 65536)); - size_t nSepPos = strComment.find("\0", 0, 1); + size_t nSepPos = thisPtr->strComment.find("\0", 0, 1); if (fRead) { me.mapValue.clear(); if (std::string::npos != nSepPos) { - CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion); + CDataStream ss(std::vector<char>(thisPtr->strComment.begin() + nSepPos + 1, thisPtr->strComment.end()), nType, nVersion); ss >> me.mapValue; me._ssExtra = std::vector<char>(ss.begin(), ss.end()); } @@ -1007,7 +1034,9 @@ public: me.strComment.erase(nSepPos); me.mapValue.erase("n"); - ) + + return nSerSize; + } private: std::vector<char> _ssExtra; diff --git a/src/walletdb.h b/src/walletdb.h index 58b4571b16..e14c137ba8 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -55,11 +55,15 @@ public: } IMPLEMENT_SERIALIZE - ( - READWRITE(this->nVersion); - nVersion = this->nVersion; - READWRITE(nCreateTime); - ) + + template <typename T, typename Stream, typename Operation> + inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { + size_t nSerSize = 0; + READWRITE(thisPtr->nVersion); + nVersion = thisPtr->nVersion; + READWRITE(thisPtr->nCreateTime); + return nSerSize; + } void SetNull() { |