[tests] Add -blocknotify functional test
[bitcoinplatinum.git] / src / serialize.h
blobeeb05fa76c8a064fd514e98ca5a49d98bcb26c4d
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #ifndef BITCOIN_SERIALIZE_H
7 #define BITCOIN_SERIALIZE_H
9 #include "compat/endian.h"
11 #include <algorithm>
12 #include <assert.h>
13 #include <ios>
14 #include <limits>
15 #include <map>
16 #include <memory>
17 #include <set>
18 #include <stdint.h>
19 #include <string>
20 #include <string.h>
21 #include <utility>
22 #include <vector>
24 #include "prevector.h"
26 static const unsigned int MAX_SIZE = 0x02000000;
28 /**
29 * Dummy data type to identify deserializing constructors.
31 * By convention, a constructor of a type T with signature
33 * template <typename Stream> T::T(deserialize_type, Stream& s)
35 * is a deserializing constructor, which builds the type by
36 * deserializing it from s. If T contains const fields, this
37 * is likely the only way to do so.
39 struct deserialize_type {};
40 constexpr deserialize_type deserialize {};
42 /**
43 * Used to bypass the rule against non-const reference to temporary
44 * where it makes sense with wrappers such as CFlatData or CTxDB
46 template<typename T>
47 inline T& REF(const T& val)
49 return const_cast<T&>(val);
52 /**
53 * Used to acquire a non-const pointer "this" to generate bodies
54 * of const serialization operations from a template
56 template<typename T>
57 inline T* NCONST_PTR(const T* val)
59 return const_cast<T*>(val);
63 * Lowest-level serialization and conversion.
64 * @note Sizes of these types are verified in the tests
66 template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj)
68 s.write((char*)&obj, 1);
70 template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
72 obj = htole16(obj);
73 s.write((char*)&obj, 2);
75 template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
77 obj = htole32(obj);
78 s.write((char*)&obj, 4);
80 template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
82 obj = htole64(obj);
83 s.write((char*)&obj, 8);
85 template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
87 uint8_t obj;
88 s.read((char*)&obj, 1);
89 return obj;
91 template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
93 uint16_t obj;
94 s.read((char*)&obj, 2);
95 return le16toh(obj);
97 template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
99 uint32_t obj;
100 s.read((char*)&obj, 4);
101 return le32toh(obj);
103 template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
105 uint64_t obj;
106 s.read((char*)&obj, 8);
107 return le64toh(obj);
109 inline uint64_t ser_double_to_uint64(double x)
111 union { double x; uint64_t y; } tmp;
112 tmp.x = x;
113 return tmp.y;
115 inline uint32_t ser_float_to_uint32(float x)
117 union { float x; uint32_t y; } tmp;
118 tmp.x = x;
119 return tmp.y;
121 inline double ser_uint64_to_double(uint64_t y)
123 union { double x; uint64_t y; } tmp;
124 tmp.y = y;
125 return tmp.x;
127 inline float ser_uint32_to_float(uint32_t y)
129 union { float x; uint32_t y; } tmp;
130 tmp.y = y;
131 return tmp.x;
135 /////////////////////////////////////////////////////////////////
137 // Templates for serializing to anything that looks like a stream,
138 // i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
141 class CSizeComputer;
143 enum
145 // primary actions
146 SER_NETWORK = (1 << 0),
147 SER_DISK = (1 << 1),
148 SER_GETHASH = (1 << 2),
151 #define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action))
152 #define READWRITEMANY(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
154 /**
155 * Implement three methods for serializable objects. These are actually wrappers over
156 * "SerializationOp" template, which implements the body of each class' serialization
157 * code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
158 * added as members.
160 #define ADD_SERIALIZE_METHODS \
161 template<typename Stream> \
162 void Serialize(Stream& s) const { \
163 NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \
165 template<typename Stream> \
166 void Unserialize(Stream& s) { \
167 SerializationOp(s, CSerActionUnserialize()); \
170 template<typename Stream> inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char
171 template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
172 template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
173 template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
174 template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
175 template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
176 template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
177 template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
178 template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
179 template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
180 template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
182 template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
183 template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
184 template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
185 template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
186 template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
187 template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
188 template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
189 template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
190 template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
191 template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
192 template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
194 template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
195 template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }
203 * Compact Size
204 * size < 253 -- 1 byte
205 * size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)
206 * size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
207 * size > UINT_MAX -- 9 bytes (255 + 8 bytes)
209 inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
211 if (nSize < 253) return sizeof(unsigned char);
212 else if (nSize <= std::numeric_limits<unsigned short>::max()) return sizeof(unsigned char) + sizeof(unsigned short);
213 else if (nSize <= std::numeric_limits<unsigned int>::max()) return sizeof(unsigned char) + sizeof(unsigned int);
214 else return sizeof(unsigned char) + sizeof(uint64_t);
217 inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
219 template<typename Stream>
220 void WriteCompactSize(Stream& os, uint64_t nSize)
222 if (nSize < 253)
224 ser_writedata8(os, nSize);
226 else if (nSize <= std::numeric_limits<unsigned short>::max())
228 ser_writedata8(os, 253);
229 ser_writedata16(os, nSize);
231 else if (nSize <= std::numeric_limits<unsigned int>::max())
233 ser_writedata8(os, 254);
234 ser_writedata32(os, nSize);
236 else
238 ser_writedata8(os, 255);
239 ser_writedata64(os, nSize);
241 return;
244 template<typename Stream>
245 uint64_t ReadCompactSize(Stream& is)
247 uint8_t chSize = ser_readdata8(is);
248 uint64_t nSizeRet = 0;
249 if (chSize < 253)
251 nSizeRet = chSize;
253 else if (chSize == 253)
255 nSizeRet = ser_readdata16(is);
256 if (nSizeRet < 253)
257 throw std::ios_base::failure("non-canonical ReadCompactSize()");
259 else if (chSize == 254)
261 nSizeRet = ser_readdata32(is);
262 if (nSizeRet < 0x10000u)
263 throw std::ios_base::failure("non-canonical ReadCompactSize()");
265 else
267 nSizeRet = ser_readdata64(is);
268 if (nSizeRet < 0x100000000ULL)
269 throw std::ios_base::failure("non-canonical ReadCompactSize()");
271 if (nSizeRet > (uint64_t)MAX_SIZE)
272 throw std::ios_base::failure("ReadCompactSize(): size too large");
273 return nSizeRet;
277 * Variable-length integers: bytes are a MSB base-128 encoding of the number.
278 * The high bit in each byte signifies whether another digit follows. To make
279 * sure the encoding is one-to-one, one is subtracted from all but the last digit.
280 * Thus, the byte sequence a[] with length len, where all but the last byte
281 * has bit 128 set, encodes the number:
283 * (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
285 * Properties:
286 * * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
287 * * Every integer has exactly one encoding
288 * * Encoding does not depend on size of original integer type
289 * * No redundancy: every (infinite) byte sequence corresponds to a list
290 * of encoded integers.
292 * 0: [0x00] 256: [0x81 0x00]
293 * 1: [0x01] 16383: [0xFE 0x7F]
294 * 127: [0x7F] 16384: [0xFF 0x00]
295 * 128: [0x80 0x00] 16511: [0xFF 0x7F]
296 * 255: [0x80 0x7F] 65535: [0x82 0xFE 0x7F]
297 * 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]
300 template<typename I>
301 inline unsigned int GetSizeOfVarInt(I n)
303 int nRet = 0;
304 while(true) {
305 nRet++;
306 if (n <= 0x7F)
307 break;
308 n = (n >> 7) - 1;
310 return nRet;
313 template<typename I>
314 inline void WriteVarInt(CSizeComputer& os, I n);
316 template<typename Stream, typename I>
317 void WriteVarInt(Stream& os, I n)
319 unsigned char tmp[(sizeof(n)*8+6)/7];
320 int len=0;
321 while(true) {
322 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
323 if (n <= 0x7F)
324 break;
325 n = (n >> 7) - 1;
326 len++;
328 do {
329 ser_writedata8(os, tmp[len]);
330 } while(len--);
333 template<typename Stream, typename I>
334 I ReadVarInt(Stream& is)
336 I n = 0;
337 while(true) {
338 unsigned char chData = ser_readdata8(is);
339 if (n > (std::numeric_limits<I>::max() >> 7)) {
340 throw std::ios_base::failure("ReadVarInt(): size too large");
342 n = (n << 7) | (chData & 0x7F);
343 if (chData & 0x80) {
344 if (n == std::numeric_limits<I>::max()) {
345 throw std::ios_base::failure("ReadVarInt(): size too large");
347 n++;
348 } else {
349 return n;
354 #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
355 #define VARINT(obj) REF(WrapVarInt(REF(obj)))
356 #define COMPACTSIZE(obj) REF(CCompactSize(REF(obj)))
357 #define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))
359 /**
360 * Wrapper for serializing arrays and POD.
362 class CFlatData
364 protected:
365 char* pbegin;
366 char* pend;
367 public:
368 CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
369 template <class T, class TAl>
370 explicit CFlatData(std::vector<T,TAl> &v)
372 pbegin = (char*)v.data();
373 pend = (char*)(v.data() + v.size());
375 template <unsigned int N, typename T, typename S, typename D>
376 explicit CFlatData(prevector<N, T, S, D> &v)
378 pbegin = (char*)v.data();
379 pend = (char*)(v.data() + v.size());
381 char* begin() { return pbegin; }
382 const char* begin() const { return pbegin; }
383 char* end() { return pend; }
384 const char* end() const { return pend; }
386 template<typename Stream>
387 void Serialize(Stream& s) const
389 s.write(pbegin, pend - pbegin);
392 template<typename Stream>
393 void Unserialize(Stream& s)
395 s.read(pbegin, pend - pbegin);
399 template<typename I>
400 class CVarInt
402 protected:
403 I &n;
404 public:
405 explicit CVarInt(I& nIn) : n(nIn) { }
407 template<typename Stream>
408 void Serialize(Stream &s) const {
409 WriteVarInt<Stream,I>(s, n);
412 template<typename Stream>
413 void Unserialize(Stream& s) {
414 n = ReadVarInt<Stream,I>(s);
418 class CCompactSize
420 protected:
421 uint64_t &n;
422 public:
423 explicit CCompactSize(uint64_t& nIn) : n(nIn) { }
425 template<typename Stream>
426 void Serialize(Stream &s) const {
427 WriteCompactSize<Stream>(s, n);
430 template<typename Stream>
431 void Unserialize(Stream& s) {
432 n = ReadCompactSize<Stream>(s);
436 template<size_t Limit>
437 class LimitedString
439 protected:
440 std::string& string;
441 public:
442 explicit LimitedString(std::string& _string) : string(_string) {}
444 template<typename Stream>
445 void Unserialize(Stream& s)
447 size_t size = ReadCompactSize(s);
448 if (size > Limit) {
449 throw std::ios_base::failure("String length limit exceeded");
451 string.resize(size);
452 if (size != 0)
453 s.read((char*)string.data(), size);
456 template<typename Stream>
457 void Serialize(Stream& s) const
459 WriteCompactSize(s, string.size());
460 if (!string.empty())
461 s.write((char*)string.data(), string.size());
465 template<typename I>
466 CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
469 * Forward declarations
473 * string
475 template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str);
476 template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str);
479 * prevector
480 * prevectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
482 template<typename Stream, unsigned int N, typename T> void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&);
483 template<typename Stream, unsigned int N, typename T, typename V> void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&);
484 template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v);
485 template<typename Stream, unsigned int N, typename T> void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&);
486 template<typename Stream, unsigned int N, typename T, typename V> void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&);
487 template<typename Stream, unsigned int N, typename T> inline void Unserialize(Stream& is, prevector<N, T>& v);
490 * vector
491 * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
493 template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&);
494 template<typename Stream, typename T, typename A, typename V> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&);
495 template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
496 template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&);
497 template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&);
498 template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v);
501 * pair
503 template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item);
504 template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item);
507 * map
509 template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m);
510 template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m);
513 * set
515 template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
516 template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m);
519 * shared_ptr
521 template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p);
522 template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p);
525 * unique_ptr
527 template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
528 template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
533 * If none of the specialized versions above matched, default to calling member function.
535 template<typename Stream, typename T>
536 inline void Serialize(Stream& os, const T& a)
538 a.Serialize(os);
541 template<typename Stream, typename T>
542 inline void Unserialize(Stream& is, T& a)
544 a.Unserialize(is);
552 * string
554 template<typename Stream, typename C>
555 void Serialize(Stream& os, const std::basic_string<C>& str)
557 WriteCompactSize(os, str.size());
558 if (!str.empty())
559 os.write((char*)str.data(), str.size() * sizeof(C));
562 template<typename Stream, typename C>
563 void Unserialize(Stream& is, std::basic_string<C>& str)
565 unsigned int nSize = ReadCompactSize(is);
566 str.resize(nSize);
567 if (nSize != 0)
568 is.read((char*)str.data(), nSize * sizeof(C));
574 * prevector
576 template<typename Stream, unsigned int N, typename T>
577 void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&)
579 WriteCompactSize(os, v.size());
580 if (!v.empty())
581 os.write((char*)v.data(), v.size() * sizeof(T));
584 template<typename Stream, unsigned int N, typename T, typename V>
585 void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&)
587 WriteCompactSize(os, v.size());
588 for (typename prevector<N, T>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
589 ::Serialize(os, (*vi));
592 template<typename Stream, unsigned int N, typename T>
593 inline void Serialize(Stream& os, const prevector<N, T>& v)
595 Serialize_impl(os, v, T());
599 template<typename Stream, unsigned int N, typename T>
600 void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)
602 // Limit size per read so bogus size value won't cause out of memory
603 v.clear();
604 unsigned int nSize = ReadCompactSize(is);
605 unsigned int i = 0;
606 while (i < nSize)
608 unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
609 v.resize(i + blk);
610 is.read((char*)&v[i], blk * sizeof(T));
611 i += blk;
615 template<typename Stream, unsigned int N, typename T, typename V>
616 void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&)
618 v.clear();
619 unsigned int nSize = ReadCompactSize(is);
620 unsigned int i = 0;
621 unsigned int nMid = 0;
622 while (nMid < nSize)
624 nMid += 5000000 / sizeof(T);
625 if (nMid > nSize)
626 nMid = nSize;
627 v.resize(nMid);
628 for (; i < nMid; i++)
629 Unserialize(is, v[i]);
633 template<typename Stream, unsigned int N, typename T>
634 inline void Unserialize(Stream& is, prevector<N, T>& v)
636 Unserialize_impl(is, v, T());
642 * vector
644 template<typename Stream, typename T, typename A>
645 void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&)
647 WriteCompactSize(os, v.size());
648 if (!v.empty())
649 os.write((char*)v.data(), v.size() * sizeof(T));
652 template<typename Stream, typename T, typename A, typename V>
653 void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&)
655 WriteCompactSize(os, v.size());
656 for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
657 ::Serialize(os, (*vi));
660 template<typename Stream, typename T, typename A>
661 inline void Serialize(Stream& os, const std::vector<T, A>& v)
663 Serialize_impl(os, v, T());
667 template<typename Stream, typename T, typename A>
668 void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&)
670 // Limit size per read so bogus size value won't cause out of memory
671 v.clear();
672 unsigned int nSize = ReadCompactSize(is);
673 unsigned int i = 0;
674 while (i < nSize)
676 unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
677 v.resize(i + blk);
678 is.read((char*)&v[i], blk * sizeof(T));
679 i += blk;
683 template<typename Stream, typename T, typename A, typename V>
684 void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&)
686 v.clear();
687 unsigned int nSize = ReadCompactSize(is);
688 unsigned int i = 0;
689 unsigned int nMid = 0;
690 while (nMid < nSize)
692 nMid += 5000000 / sizeof(T);
693 if (nMid > nSize)
694 nMid = nSize;
695 v.resize(nMid);
696 for (; i < nMid; i++)
697 Unserialize(is, v[i]);
701 template<typename Stream, typename T, typename A>
702 inline void Unserialize(Stream& is, std::vector<T, A>& v)
704 Unserialize_impl(is, v, T());
710 * pair
712 template<typename Stream, typename K, typename T>
713 void Serialize(Stream& os, const std::pair<K, T>& item)
715 Serialize(os, item.first);
716 Serialize(os, item.second);
719 template<typename Stream, typename K, typename T>
720 void Unserialize(Stream& is, std::pair<K, T>& item)
722 Unserialize(is, item.first);
723 Unserialize(is, item.second);
729 * map
731 template<typename Stream, typename K, typename T, typename Pred, typename A>
732 void Serialize(Stream& os, const std::map<K, T, Pred, A>& m)
734 WriteCompactSize(os, m.size());
735 for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
736 Serialize(os, (*mi));
739 template<typename Stream, typename K, typename T, typename Pred, typename A>
740 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)
742 m.clear();
743 unsigned int nSize = ReadCompactSize(is);
744 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
745 for (unsigned int i = 0; i < nSize; i++)
747 std::pair<K, T> item;
748 Unserialize(is, item);
749 mi = m.insert(mi, item);
756 * set
758 template<typename Stream, typename K, typename Pred, typename A>
759 void Serialize(Stream& os, const std::set<K, Pred, A>& m)
761 WriteCompactSize(os, m.size());
762 for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
763 Serialize(os, (*it));
766 template<typename Stream, typename K, typename Pred, typename A>
767 void Unserialize(Stream& is, std::set<K, Pred, A>& m)
769 m.clear();
770 unsigned int nSize = ReadCompactSize(is);
771 typename std::set<K, Pred, A>::iterator it = m.begin();
772 for (unsigned int i = 0; i < nSize; i++)
774 K key;
775 Unserialize(is, key);
776 it = m.insert(it, key);
783 * unique_ptr
785 template<typename Stream, typename T> void
786 Serialize(Stream& os, const std::unique_ptr<const T>& p)
788 Serialize(os, *p);
791 template<typename Stream, typename T>
792 void Unserialize(Stream& is, std::unique_ptr<const T>& p)
794 p.reset(new T(deserialize, is));
800 * shared_ptr
802 template<typename Stream, typename T> void
803 Serialize(Stream& os, const std::shared_ptr<const T>& p)
805 Serialize(os, *p);
808 template<typename Stream, typename T>
809 void Unserialize(Stream& is, std::shared_ptr<const T>& p)
811 p = std::make_shared<const T>(deserialize, is);
817 * Support for ADD_SERIALIZE_METHODS and READWRITE macro
819 struct CSerActionSerialize
821 constexpr bool ForRead() const { return false; }
823 struct CSerActionUnserialize
825 constexpr bool ForRead() const { return true; }
828 template<typename Stream, typename T>
829 inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action)
831 ::Serialize(s, obj);
834 template<typename Stream, typename T>
835 inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action)
837 ::Unserialize(s, obj);
848 /* ::GetSerializeSize implementations
850 * Computing the serialized size of objects is done through a special stream
851 * object of type CSizeComputer, which only records the number of bytes written
852 * to it.
854 * If your Serialize or SerializationOp method has non-trivial overhead for
855 * serialization, it may be worthwhile to implement a specialized version for
856 * CSizeComputer, which uses the s.seek() method to record bytes that would
857 * be written instead.
859 class CSizeComputer
861 protected:
862 size_t nSize;
864 const int nType;
865 const int nVersion;
866 public:
867 CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {}
869 void write(const char *psz, size_t _nSize)
871 this->nSize += _nSize;
874 /** Pretend _nSize bytes are written, without specifying them. */
875 void seek(size_t _nSize)
877 this->nSize += _nSize;
880 template<typename T>
881 CSizeComputer& operator<<(const T& obj)
883 ::Serialize(*this, obj);
884 return (*this);
887 size_t size() const {
888 return nSize;
891 int GetVersion() const { return nVersion; }
892 int GetType() const { return nType; }
895 template<typename Stream>
896 void SerializeMany(Stream& s)
900 template<typename Stream, typename Arg>
901 void SerializeMany(Stream& s, Arg&& arg)
903 ::Serialize(s, std::forward<Arg>(arg));
906 template<typename Stream, typename Arg, typename... Args>
907 void SerializeMany(Stream& s, Arg&& arg, Args&&... args)
909 ::Serialize(s, std::forward<Arg>(arg));
910 ::SerializeMany(s, std::forward<Args>(args)...);
913 template<typename Stream>
914 inline void UnserializeMany(Stream& s)
918 template<typename Stream, typename Arg>
919 inline void UnserializeMany(Stream& s, Arg& arg)
921 ::Unserialize(s, arg);
924 template<typename Stream, typename Arg, typename... Args>
925 inline void UnserializeMany(Stream& s, Arg& arg, Args&... args)
927 ::Unserialize(s, arg);
928 ::UnserializeMany(s, args...);
931 template<typename Stream, typename... Args>
932 inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args)
934 ::SerializeMany(s, std::forward<Args>(args)...);
937 template<typename Stream, typename... Args>
938 inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args)
940 ::UnserializeMany(s, args...);
943 template<typename I>
944 inline void WriteVarInt(CSizeComputer &s, I n)
946 s.seek(GetSizeOfVarInt<I>(n));
949 inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
951 s.seek(GetSizeOfCompactSize(nSize));
954 template <typename T>
955 size_t GetSerializeSize(const T& t, int nType, int nVersion = 0)
957 return (CSizeComputer(nType, nVersion) << t).size();
960 template <typename S, typename T>
961 size_t GetSerializeSize(const S& s, const T& t)
963 return (CSizeComputer(s.GetType(), s.GetVersion()) << t).size();
966 #endif // BITCOIN_SERIALIZE_H