1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 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"
26 #include <boost/optional.hpp>
28 #include "prevector.h"
30 static const unsigned int MAX_SIZE = 0x02000000;
33 * Dummy data type to identify deserializing constructors.
35 * By convention, a constructor of a type T with signature
37 * template <typename Stream> T::T(deserialize_type, Stream& s)
39 * is a deserializing constructor, which builds the type by
40 * deserializing it from s. If T contains const fields, this
41 * is likely the only way to do so.
43 struct deserialize_type {};
44 constexpr deserialize_type deserialize {};
47 * Used to bypass the rule against non-const reference to temporary
48 * where it makes sense with wrappers such as CFlatData or CTxDB
51 inline T& REF(const T& val)
53 return const_cast<T&>(val);
57 * Used to acquire a non-const pointer "this" to generate bodies
58 * of const serialization operations from a template
61 inline T* NCONST_PTR(const T* val)
63 return const_cast<T*>(val);
67 * Get begin pointer of vector (non-const version).
68 * @note These functions avoid the undefined case of indexing into an empty
69 * vector, as well as that of indexing after the end of the vector.
72 inline typename V::value_type* begin_ptr(V& v)
74 return v.empty() ? NULL : &v[0];
76 /** Get begin pointer of vector (const version) */
78 inline const typename V::value_type* begin_ptr(const V& v)
80 return v.empty() ? NULL : &v[0];
82 /** Get end pointer of vector (non-const version) */
84 inline typename V::value_type* end_ptr(V& v)
86 return v.empty() ? NULL : (&v[0] + v.size());
88 /** Get end pointer of vector (const version) */
90 inline const typename V::value_type* end_ptr(const V& v)
92 return v.empty() ? NULL : (&v[0] + v.size());
96 * Lowest-level serialization and conversion.
97 * @note Sizes of these types are verified in the tests
99 template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj)
101 s.write((char*)&obj, 1);
103 template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
106 s.write((char*)&obj, 2);
108 template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj)
111 s.write((char*)&obj, 2);
113 template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
116 s.write((char*)&obj, 4);
118 template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj)
121 s.write((char*)&obj, 4);
123 template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
126 s.write((char*)&obj, 8);
128 template<typename Stream> inline void ser_writedata64be(Stream &s, uint64_t obj)
131 s.write((char*)&obj, 8);
133 template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
136 s.read((char*)&obj, 1);
139 template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
142 s.read((char*)&obj, 2);
145 template<typename Stream> inline uint16_t ser_readdata16be(Stream &s)
148 s.read((char*)&obj, 2);
151 template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
154 s.read((char*)&obj, 4);
157 template<typename Stream> inline uint32_t ser_readdata32be(Stream &s)
160 s.read((char*)&obj, 4);
163 template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
166 s.read((char*)&obj, 8);
169 template<typename Stream> inline uint64_t ser_readdata64be(Stream &s)
172 s.read((char*)&obj, 8);
175 inline uint64_t ser_double_to_uint64(double x)
177 union { double x; uint64_t y; } tmp;
181 inline uint32_t ser_float_to_uint32(float x)
183 union { float x; uint32_t y; } tmp;
187 inline double ser_uint64_to_double(uint64_t y)
189 union { double x; uint64_t y; } tmp;
193 inline float ser_uint32_to_float(uint32_t y)
195 union { float x; uint32_t y; } tmp;
201 /////////////////////////////////////////////////////////////////
203 // Templates for serializing to anything that looks like a stream,
204 // i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
212 SER_NETWORK = (1 << 0),
214 SER_GETHASH = (1 << 2),
217 #define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action))
218 #define READWRITEMANY(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
221 * Implement three methods for serializable objects. These are actually wrappers over
222 * "SerializationOp" template, which implements the body of each class' serialization
223 * code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
226 #define ADD_SERIALIZE_METHODS \
227 template<typename Stream> \
228 void Serialize(Stream& s) const { \
229 NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \
231 template<typename Stream> \
232 void Unserialize(Stream& s) { \
233 SerializationOp(s, CSerActionUnserialize()); \
236 template<typename Stream> inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char
237 template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
238 template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
239 template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
240 template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
241 template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
242 template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
243 template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
244 template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
245 template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
246 template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
248 template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
249 template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
250 template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
251 template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
252 template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
253 template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
254 template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
255 template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
256 template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
257 template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
258 template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
260 template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
261 template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }
270 * size < 253 -- 1 byte
271 * size <= 0xFFFF -- 3 bytes (253 + 2 bytes)
272 * size <= 0xFFFFFFFF -- 5 bytes (254 + 4 bytes)
273 * size > 0xFFFFFFFF -- 9 bytes (255 + 8 bytes)
275 inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
277 if (nSize < 253) return 1;
278 else if (nSize <= 0xFFFFu) return 3;
279 else if (nSize <= 0xFFFFFFFFu) return 5;
283 inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
285 template<typename Stream>
286 void WriteCompactSize(Stream& os, uint64_t nSize)
290 ser_writedata8(os, nSize);
292 else if (nSize <= 0xFFFFu)
294 ser_writedata8(os, 253);
295 ser_writedata16(os, nSize);
297 else if (nSize <= 0xFFFFFFFFu)
299 ser_writedata8(os, 254);
300 ser_writedata32(os, nSize);
304 ser_writedata8(os, 255);
305 ser_writedata64(os, nSize);
309 template<typename Stream>
310 uint64_t ReadCompactSize(Stream& is)
312 uint8_t chSize = ser_readdata8(is);
313 uint64_t nSizeRet = 0;
318 else if (chSize == 253)
320 nSizeRet = ser_readdata16(is);
322 throw std::ios_base::failure("non-canonical ReadCompactSize()");
324 else if (chSize == 254)
326 nSizeRet = ser_readdata32(is);
327 if (nSizeRet < 0x10000u)
328 throw std::ios_base::failure("non-canonical ReadCompactSize()");
332 nSizeRet = ser_readdata64(is);
333 if (nSizeRet < 0x100000000ULL)
334 throw std::ios_base::failure("non-canonical ReadCompactSize()");
336 if (nSizeRet > (uint64_t)MAX_SIZE)
337 throw std::ios_base::failure("ReadCompactSize(): size too large");
342 * Variable-length integers: bytes are a MSB base-128 encoding of the number.
343 * The high bit in each byte signifies whether another digit follows. To make
344 * sure the encoding is one-to-one, one is subtracted from all but the last digit.
345 * Thus, the byte sequence a[] with length len, where all but the last byte
346 * has bit 128 set, encodes the number:
348 * (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
351 * * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
352 * * Every integer has exactly one encoding
353 * * Encoding does not depend on size of original integer type
354 * * No redundancy: every (infinite) byte sequence corresponds to a list
355 * of encoded integers.
357 * 0: [0x00] 256: [0x81 0x00]
358 * 1: [0x01] 16383: [0xFE 0x7F]
359 * 127: [0x7F] 16384: [0xFF 0x00]
360 * 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F]
361 * 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F]
362 * 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]
366 inline unsigned int GetSizeOfVarInt(I n)
379 inline void WriteVarInt(CSizeComputer& os, I n);
381 template<typename Stream, typename I>
382 void WriteVarInt(Stream& os, I n)
384 unsigned char tmp[(sizeof(n)*8+6)/7];
387 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
394 ser_writedata8(os, tmp[len]);
398 template<typename Stream, typename I>
399 I ReadVarInt(Stream& is)
403 unsigned char chData = ser_readdata8(is);
404 n = (n << 7) | (chData & 0x7F);
412 #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
413 #define VARINT(obj) REF(WrapVarInt(REF(obj)))
414 #define COMPACTSIZE(obj) REF(CCompactSize(REF(obj)))
415 #define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))
418 * Wrapper for serializing arrays and POD.
426 CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
427 template <class T, class TAl>
428 explicit CFlatData(std::vector<T,TAl> &v)
430 pbegin = (char*)begin_ptr(v);
431 pend = (char*)end_ptr(v);
433 template <unsigned int N, typename T, typename S, typename D>
434 explicit CFlatData(prevector<N, T, S, D> &v)
436 pbegin = (char*)begin_ptr(v);
437 pend = (char*)end_ptr(v);
439 char* begin() { return pbegin; }
440 const char* begin() const { return pbegin; }
441 char* end() { return pend; }
442 const char* end() const { return pend; }
444 template<typename Stream>
445 void Serialize(Stream& s) const
447 s.write(pbegin, pend - pbegin);
450 template<typename Stream>
451 void Unserialize(Stream& s)
453 s.read(pbegin, pend - pbegin);
463 CVarInt(I& nIn) : n(nIn) { }
465 template<typename Stream>
466 void Serialize(Stream &s) const {
467 WriteVarInt<Stream,I>(s, n);
470 template<typename Stream>
471 void Unserialize(Stream& s) {
472 n = ReadVarInt<Stream,I>(s);
481 CCompactSize(uint64_t& nIn) : n(nIn) { }
483 template<typename Stream>
484 void Serialize(Stream &s) const {
485 WriteCompactSize<Stream>(s, n);
488 template<typename Stream>
489 void Unserialize(Stream& s) {
490 n = ReadCompactSize<Stream>(s);
494 template<size_t Limit>
500 LimitedString(std::string& _string) : string(_string) {}
502 template<typename Stream>
503 void Unserialize(Stream& s)
505 size_t size = ReadCompactSize(s);
507 throw std::ios_base::failure("String length limit exceeded");
511 s.read((char*)&string[0], size);
514 template<typename Stream>
515 void Serialize(Stream& s) const
517 WriteCompactSize(s, string.size());
519 s.write((char*)&string[0], string.size());
524 CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
527 * Forward declarations
533 template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str);
534 template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str);
538 * prevectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
540 template<typename Stream, unsigned int N, typename T> void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&);
541 template<typename Stream, unsigned int N, typename T, typename V> void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&);
542 template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v);
543 template<typename Stream, unsigned int N, typename T> void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&);
544 template<typename Stream, unsigned int N, typename T, typename V> void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&);
545 template<typename Stream, unsigned int N, typename T> inline void Unserialize(Stream& is, prevector<N, T>& v);
549 * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
551 template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&);
552 template<typename Stream, typename T, typename A, typename V> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&);
553 template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
554 template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&);
555 template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&);
556 template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v);
561 template<typename Stream, typename T> void Serialize(Stream& os, const boost::optional<T>& item);
562 template<typename Stream, typename T> void Unserialize(Stream& is, boost::optional<T>& item);
567 template<typename Stream, typename T, std::size_t N> void Serialize(Stream& os, const std::array<T, N>& item);
568 template<typename Stream, typename T, std::size_t N> void Unserialize(Stream& is, std::array<T, N>& item);
573 template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item);
574 template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item);
579 template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m);
580 template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m);
585 template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
586 template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m);
591 template<typename Stream, typename T, typename A> void Serialize(Stream& os, const std::list<T, A>& m);
592 template<typename Stream, typename T, typename A> void Unserialize(Stream& is, std::list<T, A>& m);
597 template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p);
598 template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p);
603 template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
604 template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
609 * If none of the specialized versions above matched, default to calling member function.
611 template<typename Stream, typename T>
612 inline void Serialize(Stream& os, const T& a)
617 template<typename Stream, typename T>
618 inline void Unserialize(Stream& is, T& a)
630 template<typename Stream, typename C>
631 void Serialize(Stream& os, const std::basic_string<C>& str)
633 WriteCompactSize(os, str.size());
635 os.write((char*)&str[0], str.size() * sizeof(str[0]));
638 template<typename Stream, typename C>
639 void Unserialize(Stream& is, std::basic_string<C>& str)
641 unsigned int nSize = ReadCompactSize(is);
644 is.read((char*)&str[0], nSize * sizeof(str[0]));
652 template<typename Stream, unsigned int N, typename T>
653 void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&)
655 WriteCompactSize(os, v.size());
657 os.write((char*)&v[0], v.size() * sizeof(T));
660 template<typename Stream, unsigned int N, typename T, typename V>
661 void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&)
663 WriteCompactSize(os, v.size());
664 for (typename prevector<N, T>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
665 ::Serialize(os, (*vi));
668 template<typename Stream, unsigned int N, typename T>
669 inline void Serialize(Stream& os, const prevector<N, T>& v)
671 Serialize_impl(os, v, T());
675 template<typename Stream, unsigned int N, typename T>
676 void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)
678 // Limit size per read so bogus size value won't cause out of memory
680 unsigned int nSize = ReadCompactSize(is);
684 unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
686 is.read((char*)&v[i], blk * sizeof(T));
691 template<typename Stream, unsigned int N, typename T, typename V>
692 void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&)
695 unsigned int nSize = ReadCompactSize(is);
697 unsigned int nMid = 0;
700 nMid += 5000000 / sizeof(T);
704 for (; i < nMid; i++)
705 Unserialize(is, v[i]);
709 template<typename Stream, unsigned int N, typename T>
710 inline void Unserialize(Stream& is, prevector<N, T>& v)
712 Unserialize_impl(is, v, T());
720 template<typename Stream, typename T, typename A>
721 void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&)
723 WriteCompactSize(os, v.size());
725 os.write((char*)&v[0], v.size() * sizeof(T));
728 template<typename Stream, typename T, typename A, typename V>
729 void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&)
731 WriteCompactSize(os, v.size());
732 for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
733 ::Serialize(os, (*vi));
736 template<typename Stream, typename T, typename A>
737 inline void Serialize(Stream& os, const std::vector<T, A>& v)
739 Serialize_impl(os, v, T());
743 template<typename Stream, typename T, typename A>
744 void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&)
746 // Limit size per read so bogus size value won't cause out of memory
748 unsigned int nSize = ReadCompactSize(is);
752 unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
754 is.read((char*)&v[i], blk * sizeof(T));
759 template<typename Stream, typename T, typename A, typename V>
760 void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&)
763 unsigned int nSize = ReadCompactSize(is);
765 unsigned int nMid = 0;
768 nMid += 5000000 / sizeof(T);
772 for (; i < nMid; i++)
773 Unserialize(is, v[i]);
777 template<typename Stream, typename T, typename A>
778 inline void Unserialize(Stream& is, std::vector<T, A>& v)
780 Unserialize_impl(is, v, T());
788 template<typename Stream, typename T>
789 void Serialize(Stream& os, const boost::optional<T>& item)
791 // If the value is there, put 0x01 and then serialize the value.
792 // If it's not, put 0x00.
794 unsigned char discriminant = 0x01;
795 Serialize(os, discriminant);
796 Serialize(os, *item);
798 unsigned char discriminant = 0x00;
799 Serialize(os, discriminant);
803 template<typename Stream, typename T>
804 void Unserialize(Stream& is, boost::optional<T>& item)
806 unsigned char discriminant = 0x00;
807 Unserialize(is, discriminant);
809 if (discriminant == 0x00) {
811 } else if (discriminant == 0x01) {
813 Unserialize(is, object);
816 throw std::ios_base::failure("non-canonical optional discriminant");
825 template<typename Stream, typename T, std::size_t N>
826 void Serialize(Stream& os, const std::array<T, N>& item)
828 for (size_t i = 0; i < N; i++) {
829 Serialize(os, item[i]);
833 template<typename Stream, typename T, std::size_t N>
834 void Unserialize(Stream& is, std::array<T, N>& item)
836 for (size_t i = 0; i < N; i++) {
837 Unserialize(is, item[i]);
845 template<typename Stream, typename K, typename T>
846 void Serialize(Stream& os, const std::pair<K, T>& item)
848 Serialize(os, item.first);
849 Serialize(os, item.second);
852 template<typename Stream, typename K, typename T>
853 void Unserialize(Stream& is, std::pair<K, T>& item)
855 Unserialize(is, item.first);
856 Unserialize(is, item.second);
864 template<typename Stream, typename K, typename T, typename Pred, typename A>
865 void Serialize(Stream& os, const std::map<K, T, Pred, A>& m)
867 WriteCompactSize(os, m.size());
868 for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
869 Serialize(os, (*mi));
872 template<typename Stream, typename K, typename T, typename Pred, typename A>
873 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)
876 unsigned int nSize = ReadCompactSize(is);
877 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
878 for (unsigned int i = 0; i < nSize; i++)
880 std::pair<K, T> item;
881 Unserialize(is, item);
882 mi = m.insert(mi, item);
891 template<typename Stream, typename K, typename Pred, typename A>
892 void Serialize(Stream& os, const std::set<K, Pred, A>& m)
894 WriteCompactSize(os, m.size());
895 for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
896 Serialize(os, (*it));
899 template<typename Stream, typename K, typename Pred, typename A>
900 void Unserialize(Stream& is, std::set<K, Pred, A>& m)
903 unsigned int nSize = ReadCompactSize(is);
904 typename std::set<K, Pred, A>::iterator it = m.begin();
905 for (unsigned int i = 0; i < nSize; i++)
908 Unserialize(is, key);
909 it = m.insert(it, key);
918 template<typename Stream, typename T, typename A>
919 void Serialize(Stream& os, const std::list<T, A>& l)
921 WriteCompactSize(os, l.size());
922 for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it)
923 Serialize(os, (*it));
926 template<typename Stream, typename T, typename A>
927 void Unserialize(Stream& is, std::list<T, A>& l)
930 unsigned int nSize = ReadCompactSize(is);
931 typename std::list<T, A>::iterator it = l.begin();
932 for (unsigned int i = 0; i < nSize; i++)
935 Unserialize(is, item);
945 template<typename Stream, typename T> void
946 Serialize(Stream& os, const std::unique_ptr<const T>& p)
951 template<typename Stream, typename T>
952 void Unserialize(Stream& is, std::unique_ptr<const T>& p)
954 p.reset(new T(deserialize, is));
962 template<typename Stream, typename T> void
963 Serialize(Stream& os, const std::shared_ptr<const T>& p)
968 template<typename Stream, typename T>
969 void Unserialize(Stream& is, std::shared_ptr<const T>& p)
971 p = std::make_shared<const T>(deserialize, is);
977 * Support for ADD_SERIALIZE_METHODS and READWRITE macro
979 struct CSerActionSerialize
981 constexpr bool ForRead() const { return false; }
983 struct CSerActionUnserialize
985 constexpr bool ForRead() const { return true; }
988 template<typename Stream, typename T>
989 inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action)
994 template<typename Stream, typename T>
995 inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action)
997 ::Unserialize(s, obj);
1008 /* ::GetSerializeSize implementations
1010 * Computing the serialized size of objects is done through a special stream
1011 * object of type CSizeComputer, which only records the number of bytes written
1014 * If your Serialize or SerializationOp method has non-trivial overhead for
1015 * serialization, it may be worthwhile to implement a specialized version for
1016 * CSizeComputer, which uses the s.seek() method to record bytes that would
1017 * be written instead.
1027 CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {}
1029 void write(const char *psz, size_t _nSize)
1031 this->nSize += _nSize;
1034 /** Pretend _nSize bytes are written, without specifying them. */
1035 void seek(size_t _nSize)
1037 this->nSize += _nSize;
1040 template<typename T>
1041 CSizeComputer& operator<<(const T& obj)
1043 ::Serialize(*this, obj);
1047 size_t size() const {
1051 int GetVersion() const { return nVersion; }
1052 int GetType() const { return nType; }
1055 template<typename Stream>
1056 void SerializeMany(Stream& s)
1060 template<typename Stream, typename Arg>
1061 void SerializeMany(Stream& s, Arg&& arg)
1063 ::Serialize(s, std::forward<Arg>(arg));
1066 template<typename Stream, typename Arg, typename... Args>
1067 void SerializeMany(Stream& s, Arg&& arg, Args&&... args)
1069 ::Serialize(s, std::forward<Arg>(arg));
1070 ::SerializeMany(s, std::forward<Args>(args)...);
1073 template<typename Stream>
1074 inline void UnserializeMany(Stream& s)
1078 template<typename Stream, typename Arg>
1079 inline void UnserializeMany(Stream& s, Arg& arg)
1081 ::Unserialize(s, arg);
1084 template<typename Stream, typename Arg, typename... Args>
1085 inline void UnserializeMany(Stream& s, Arg& arg, Args&... args)
1087 ::Unserialize(s, arg);
1088 ::UnserializeMany(s, args...);
1091 template<typename Stream, typename... Args>
1092 inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args)
1094 ::SerializeMany(s, std::forward<Args>(args)...);
1097 template<typename Stream, typename... Args>
1098 inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args)
1100 ::UnserializeMany(s, args...);
1103 template<typename I>
1104 inline void WriteVarInt(CSizeComputer &s, I n)
1106 s.seek(GetSizeOfVarInt<I>(n));
1109 inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
1111 s.seek(GetSizeOfCompactSize(nSize));
1114 template <typename T>
1115 size_t GetSerializeSize(const T& t, int nType, int nVersion = 0)
1117 return (CSizeComputer(nType, nVersion) << t).size();
1120 template <typename S, typename T>
1121 size_t GetSerializeSize(const S& s, const T& t)
1123 return (CSizeComputer(s.GetType(), s.GetVersion()) << t).size();
1126 #endif // BITCOIN_SERIALIZE_H