Browse Source

Add optimized CSizeComputer serializers

To get the advantages of faster GetSerializeSize() implementations
back that were removed in "Make GetSerializeSize a wrapper on top of
CSizeComputer", reintroduce them in the few places in the form of a
specialized Serialize() implementation. This actually gets us in a
better state than before, as these even get used when they're invoked
indirectly in the serialization of another object.
0.14
Pieter Wuille 8 years ago
parent
commit
25a211aa9e
  1. 5
      src/pubkey.h
  2. 35
      src/serialize.h

5
src/pubkey.h

@ -210,6 +210,11 @@ struct CExtPubKey {
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtPubKey& out, unsigned int nChild) const; bool Derive(CExtPubKey& out, unsigned int nChild) const;
void Serialize(CSizeComputer& s) const
{
// Optimized implementation for ::GetSerializeSize that avoids copying.
s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int)
}
template <typename Stream> template <typename Stream>
void Serialize(Stream& s) const void Serialize(Stream& s) const
{ {

35
src/serialize.h

@ -151,6 +151,8 @@ inline float ser_uint32_to_float(uint32_t y)
// i.e. anything that supports .read(char*, size_t) and .write(char*, size_t) // i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
// //
class CSizeComputer;
enum enum
{ {
// primary actions // primary actions
@ -225,6 +227,8 @@ inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
else return sizeof(unsigned char) + sizeof(uint64_t); else return sizeof(unsigned char) + sizeof(uint64_t);
} }
inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
template<typename Stream> template<typename Stream>
void WriteCompactSize(Stream& os, uint64_t nSize) void WriteCompactSize(Stream& os, uint64_t nSize)
{ {
@ -319,6 +323,9 @@ inline unsigned int GetSizeOfVarInt(I n)
return nRet; return nRet;
} }
template<typename I>
inline void WriteVarInt(CSizeComputer& os, I n);
template<typename Stream, typename I> template<typename Stream, typename I>
void WriteVarInt(Stream& os, I n) void WriteVarInt(Stream& os, I n)
{ {
@ -800,6 +807,17 @@ inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action)
/* ::GetSerializeSize implementations
*
* Computing the serialized size of objects is done through a special stream
* object of type CSizeComputer, which only records the number of bytes written
* to it.
*
* If your Serialize or SerializationOp method has non-trivial overhead for
* serialization, it may be worthwhile to implement a specialized version for
* CSizeComputer, which uses the s.seek() method to record bytes that would
* be written instead.
*/
class CSizeComputer class CSizeComputer
{ {
protected: protected:
@ -815,6 +833,12 @@ public:
this->nSize += _nSize; this->nSize += _nSize;
} }
/** Pretend _nSize bytes are written, without specifying them. */
void seek(size_t _nSize)
{
this->nSize += _nSize;
}
template<typename T> template<typename T>
CSizeComputer& operator<<(const T& obj) CSizeComputer& operator<<(const T& obj)
{ {
@ -878,6 +902,17 @@ inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&.
::UnserializeMany(s, args...); ::UnserializeMany(s, args...);
} }
template<typename I>
inline void WriteVarInt(CSizeComputer &s, I n)
{
s.seek(GetSizeOfVarInt<I>(n));
}
inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
{
s.seek(GetSizeOfCompactSize(nSize));
}
template <typename T> template <typename T>
size_t GetSerializeSize(const T& t, int nType, int nVersion = 0) size_t GetSerializeSize(const T& t, int nType, int nVersion = 0)
{ {

Loading…
Cancel
Save