]> Git Repo - VerusCoin.git/blob - src/serialize.h
improve check
[VerusCoin.git] / src / serialize.h
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.
5
6 #ifndef BITCOIN_SERIALIZE_H
7 #define BITCOIN_SERIALIZE_H
8
9 #include "compat/endian.h"
10
11 #include <algorithm>
12 #include <array>
13 #include <assert.h>
14 #include <ios>
15 #include <limits>
16 #include <list>
17 #include <map>
18 #include <memory>
19 #include <set>
20 #include <stdint.h>
21 #include <string>
22 #include <string.h>
23 #include <utility>
24 #include <vector>
25
26 #include <boost/optional.hpp>
27
28 #include "prevector.h"
29
30 static const unsigned int MAX_SIZE = 0x02000000;
31
32 /**
33  * Dummy data type to identify deserializing constructors.
34  *
35  * By convention, a constructor of a type T with signature
36  *
37  *   template <typename Stream> T::T(deserialize_type, Stream& s)
38  *
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.
42  */
43 struct deserialize_type {};
44 constexpr deserialize_type deserialize {};
45
46 /**
47  * Used to bypass the rule against non-const reference to temporary
48  * where it makes sense with wrappers such as CFlatData or CTxDB
49  */
50 template<typename T>
51 inline T& REF(const T& val)
52 {
53     return const_cast<T&>(val);
54 }
55
56 /**
57  * Used to acquire a non-const pointer "this" to generate bodies
58  * of const serialization operations from a template
59  */
60 template<typename T>
61 inline T* NCONST_PTR(const T* val)
62 {
63     return const_cast<T*>(val);
64 }
65
66 /** 
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.
70  */
71 template <typename V>
72 inline typename V::value_type* begin_ptr(V& v)
73 {
74     return v.empty() ? NULL : &v[0];
75 }
76 /** Get begin pointer of vector (const version) */
77 template <typename V>
78 inline const typename V::value_type* begin_ptr(const V& v)
79 {
80     return v.empty() ? NULL : &v[0];
81 }
82 /** Get end pointer of vector (non-const version) */
83 template <typename V>
84 inline typename V::value_type* end_ptr(V& v)
85 {
86     return v.empty() ? NULL : (&v[0] + v.size());
87 }
88 /** Get end pointer of vector (const version) */
89 template <typename V>
90 inline const typename V::value_type* end_ptr(const V& v)
91 {
92     return v.empty() ? NULL : (&v[0] + v.size());
93 }
94
95 /*
96  * Lowest-level serialization and conversion.
97  * @note Sizes of these types are verified in the tests
98  */
99 template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj)
100 {
101     s.write((char*)&obj, 1);
102 }
103 template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
104 {
105     obj = htole16(obj);
106     s.write((char*)&obj, 2);
107 }
108 template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj)
109 {
110     obj = htobe16(obj);
111     s.write((char*)&obj, 2);
112 }
113 template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
114 {
115     obj = htole32(obj);
116     s.write((char*)&obj, 4);
117 }
118 template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj)
119 {
120     obj = htobe32(obj);
121     s.write((char*)&obj, 4);
122 }
123 template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
124 {
125     obj = htole64(obj);
126     s.write((char*)&obj, 8);
127 }
128 template<typename Stream> inline void ser_writedata64be(Stream &s, uint64_t obj)
129 {
130     obj = htobe64(obj);
131     s.write((char*)&obj, 8);
132 }
133 template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
134 {
135     uint8_t obj;
136     s.read((char*)&obj, 1);
137     return obj;
138 }
139 template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
140 {
141     uint16_t obj;
142     s.read((char*)&obj, 2);
143     return le16toh(obj);
144 }
145 template<typename Stream> inline uint16_t ser_readdata16be(Stream &s)
146 {
147     uint16_t obj;
148     s.read((char*)&obj, 2);
149     return be16toh(obj);
150 }
151 template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
152 {
153     uint32_t obj;
154     s.read((char*)&obj, 4);
155     return le32toh(obj);
156 }
157 template<typename Stream> inline uint32_t ser_readdata32be(Stream &s)
158 {
159     uint32_t obj;
160     s.read((char*)&obj, 4);
161     return be32toh(obj);
162 }
163 template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
164 {
165     uint64_t obj;
166     s.read((char*)&obj, 8);
167     return le64toh(obj);
168 }
169 template<typename Stream> inline uint64_t ser_readdata64be(Stream &s)
170 {
171     uint64_t obj;
172     s.read((char*)&obj, 8);
173     return be64toh(obj);
174 }
175 inline uint64_t ser_double_to_uint64(double x)
176 {
177     union { double x; uint64_t y; } tmp;
178     tmp.x = x;
179     return tmp.y;
180 }
181 inline uint32_t ser_float_to_uint32(float x)
182 {
183     union { float x; uint32_t y; } tmp;
184     tmp.x = x;
185     return tmp.y;
186 }
187 inline double ser_uint64_to_double(uint64_t y)
188 {
189     union { double x; uint64_t y; } tmp;
190     tmp.y = y;
191     return tmp.x;
192 }
193 inline float ser_uint32_to_float(uint32_t y)
194 {
195     union { float x; uint32_t y; } tmp;
196     tmp.y = y;
197     return tmp.x;
198 }
199
200
201 /////////////////////////////////////////////////////////////////
202 //
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)
205 //
206
207 class CSizeComputer;
208
209 enum
210 {
211     // primary actions
212     SER_NETWORK         = (1 << 0),
213     SER_DISK            = (1 << 1),
214     SER_GETHASH         = (1 << 2),
215 };
216
217 #define READWRITE(obj)      (::SerReadWrite(s, (obj), ser_action))
218 #define READWRITEMANY(...)      (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
219
220 /** 
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
224  * added as members. 
225  */
226 #define ADD_SERIALIZE_METHODS                                         \
227     template<typename Stream>                                         \
228     void Serialize(Stream& s) const {                                 \
229         NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize());  \
230     }                                                                 \
231     template<typename Stream>                                         \
232     void Unserialize(Stream& s) {                                     \
233         SerializationOp(s, CSerActionUnserialize());                  \
234     }
235
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)); }
247
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)); }
259
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; }
262
263
264
265
266
267
268 /**
269  * Compact Size
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)
274  */
275 inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
276 {
277     if (nSize < 253)                return 1;
278     else if (nSize <= 0xFFFFu)      return 3;
279     else if (nSize <= 0xFFFFFFFFu)  return 5;
280     else                            return 9;
281 }
282
283 inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
284
285 template<typename Stream>
286 void WriteCompactSize(Stream& os, uint64_t nSize)
287 {
288     if (nSize < 253)
289     {
290         ser_writedata8(os, nSize);
291     }
292     else if (nSize <= 0xFFFFu)
293     {
294         ser_writedata8(os, 253);
295         ser_writedata16(os, nSize);
296     }
297     else if (nSize <= 0xFFFFFFFFu)
298     {
299         ser_writedata8(os, 254);
300         ser_writedata32(os, nSize);
301     }
302     else
303     {
304         ser_writedata8(os, 255);
305         ser_writedata64(os, nSize);
306     }
307 }
308
309 template<typename Stream>
310 uint64_t ReadCompactSize(Stream& is)
311 {
312     uint8_t chSize = ser_readdata8(is);
313     uint64_t nSizeRet = 0;
314     if (chSize < 253)
315     {
316         nSizeRet = chSize;
317     }
318     else if (chSize == 253)
319     {
320         nSizeRet = ser_readdata16(is);
321         if (nSizeRet < 253)
322             throw std::ios_base::failure("non-canonical ReadCompactSize()");
323     }
324     else if (chSize == 254)
325     {
326         nSizeRet = ser_readdata32(is);
327         if (nSizeRet < 0x10000u)
328             throw std::ios_base::failure("non-canonical ReadCompactSize()");
329     }
330     else
331     {
332         nSizeRet = ser_readdata64(is);
333         if (nSizeRet < 0x100000000ULL)
334             throw std::ios_base::failure("non-canonical ReadCompactSize()");
335     }
336     if (nSizeRet > (uint64_t)MAX_SIZE)
337         throw std::ios_base::failure("ReadCompactSize(): size too large");
338     return nSizeRet;
339 }
340
341 /**
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:
347  * 
348  *  (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
349  * 
350  * Properties:
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.
356  * 
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]
363  */
364
365 template<typename I>
366 inline unsigned int GetSizeOfVarInt(I n)
367 {
368     int nRet = 0;
369     while(true) {
370         nRet++;
371         if (n <= 0x7F)
372             break;
373         n = (n >> 7) - 1;
374     }
375     return nRet;
376 }
377
378 template<typename I>
379 inline void WriteVarInt(CSizeComputer& os, I n);
380
381 template<typename Stream, typename I>
382 void WriteVarInt(Stream& os, I n)
383 {
384     unsigned char tmp[(sizeof(n)*8+6)/7];
385     int len=0;
386     while(true) {
387         tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
388         if (n <= 0x7F)
389             break;
390         n = (n >> 7) - 1;
391         len++;
392     }
393     do {
394         ser_writedata8(os, tmp[len]);
395     } while(len--);
396 }
397
398 template<typename Stream, typename I>
399 I ReadVarInt(Stream& is)
400 {
401     I n = 0;
402     while(true) {
403         unsigned char chData = ser_readdata8(is);
404         n = (n << 7) | (chData & 0x7F);
405         if (chData & 0x80)
406             n++;
407         else
408             return n;
409     }
410 }
411
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)))
416
417 /** 
418  * Wrapper for serializing arrays and POD.
419  */
420 class CFlatData
421 {
422 protected:
423     char* pbegin;
424     char* pend;
425 public:
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)
429     {
430         pbegin = (char*)begin_ptr(v);
431         pend = (char*)end_ptr(v);
432     }
433     template <unsigned int N, typename T, typename S, typename D>
434     explicit CFlatData(prevector<N, T, S, D> &v)
435     {
436         pbegin = (char*)begin_ptr(v);
437         pend = (char*)end_ptr(v);
438     }
439     char* begin() { return pbegin; }
440     const char* begin() const { return pbegin; }
441     char* end() { return pend; }
442     const char* end() const { return pend; }
443
444     template<typename Stream>
445     void Serialize(Stream& s) const
446     {
447         s.write(pbegin, pend - pbegin);
448     }
449
450     template<typename Stream>
451     void Unserialize(Stream& s)
452     {
453         s.read(pbegin, pend - pbegin);
454     }
455 };
456
457 template<typename I>
458 class CVarInt
459 {
460 protected:
461     I &n;
462 public:
463     CVarInt(I& nIn) : n(nIn) { }
464
465     template<typename Stream>
466     void Serialize(Stream &s) const {
467         WriteVarInt<Stream,I>(s, n);
468     }
469
470     template<typename Stream>
471     void Unserialize(Stream& s) {
472         n = ReadVarInt<Stream,I>(s);
473     }
474 };
475
476 class CCompactSize
477 {
478 protected:
479     uint64_t &n;
480 public:
481     CCompactSize(uint64_t& nIn) : n(nIn) { }
482
483     template<typename Stream>
484     void Serialize(Stream &s) const {
485         WriteCompactSize<Stream>(s, n);
486     }
487
488     template<typename Stream>
489     void Unserialize(Stream& s) {
490         n = ReadCompactSize<Stream>(s);
491     }
492 };
493
494 template<size_t Limit>
495 class LimitedString
496 {
497 protected:
498     std::string& string;
499 public:
500     LimitedString(std::string& _string) : string(_string) {}
501
502     template<typename Stream>
503     void Unserialize(Stream& s)
504     {
505         size_t size = ReadCompactSize(s);
506         if (size > Limit) {
507             throw std::ios_base::failure("String length limit exceeded");
508         }
509         string.resize(size);
510         if (size != 0)
511             s.read((char*)&string[0], size);
512     }
513
514     template<typename Stream>
515     void Serialize(Stream& s) const
516     {
517         WriteCompactSize(s, string.size());
518         if (!string.empty())
519             s.write((char*)&string[0], string.size());
520     }
521 };
522
523 template<typename I>
524 CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
525
526 /**
527  * Forward declarations
528  */
529
530 /**
531  *  string
532  */
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);
535
536 /**
537  * prevector
538  * prevectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
539  */
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);
546
547 /**
548  * vector
549  * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
550  */
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);
557
558 /**
559  * optional
560  */
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);
563
564 /**
565  * array
566  */
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);
569
570 /**
571  * pair
572  */
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);
575
576 /**
577  * map
578  */
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);
581
582 /**
583  * set
584  */
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);
587
588 /**
589  * list
590  */
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);
593
594 /**
595  * shared_ptr
596  */
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);
599
600 /**
601  * unique_ptr
602  */
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);
605
606
607
608 /**
609  * If none of the specialized versions above matched, default to calling member function.
610  */
611 template<typename Stream, typename T>
612 inline void Serialize(Stream& os, const T& a)
613 {
614     a.Serialize(os);
615 }
616
617 template<typename Stream, typename T>
618 inline void Unserialize(Stream& is, T& a)
619 {
620     a.Unserialize(is);
621 }
622
623
624
625
626
627 /**
628  * string
629  */
630 template<typename Stream, typename C>
631 void Serialize(Stream& os, const std::basic_string<C>& str)
632 {
633     WriteCompactSize(os, str.size());
634     if (!str.empty())
635         os.write((char*)&str[0], str.size() * sizeof(str[0]));
636 }
637
638 template<typename Stream, typename C>
639 void Unserialize(Stream& is, std::basic_string<C>& str)
640 {
641     unsigned int nSize = ReadCompactSize(is);
642     str.resize(nSize);
643     if (nSize != 0)
644         is.read((char*)&str[0], nSize * sizeof(str[0]));
645 }
646
647
648
649 /**
650  * prevector
651  */
652 template<typename Stream, unsigned int N, typename T>
653 void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&)
654 {
655     WriteCompactSize(os, v.size());
656     if (!v.empty())
657         os.write((char*)&v[0], v.size() * sizeof(T));
658 }
659
660 template<typename Stream, unsigned int N, typename T, typename V>
661 void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&)
662 {
663     WriteCompactSize(os, v.size());
664     for (typename prevector<N, T>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
665         ::Serialize(os, (*vi));
666 }
667
668 template<typename Stream, unsigned int N, typename T>
669 inline void Serialize(Stream& os, const prevector<N, T>& v)
670 {
671     Serialize_impl(os, v, T());
672 }
673
674
675 template<typename Stream, unsigned int N, typename T>
676 void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)
677 {
678     // Limit size per read so bogus size value won't cause out of memory
679     v.clear();
680     unsigned int nSize = ReadCompactSize(is);
681     unsigned int i = 0;
682     while (i < nSize)
683     {
684         unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
685         v.resize(i + blk);
686         is.read((char*)&v[i], blk * sizeof(T));
687         i += blk;
688     }
689 }
690
691 template<typename Stream, unsigned int N, typename T, typename V>
692 void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&)
693 {
694     v.clear();
695     unsigned int nSize = ReadCompactSize(is);
696     unsigned int i = 0;
697     unsigned int nMid = 0;
698     while (nMid < nSize)
699     {
700         nMid += 5000000 / sizeof(T);
701         if (nMid > nSize)
702             nMid = nSize;
703         v.resize(nMid);
704         for (; i < nMid; i++)
705             Unserialize(is, v[i]);
706     }
707 }
708
709 template<typename Stream, unsigned int N, typename T>
710 inline void Unserialize(Stream& is, prevector<N, T>& v)
711 {
712     Unserialize_impl(is, v, T());
713 }
714
715
716
717 /**
718  * vector
719  */
720 template<typename Stream, typename T, typename A>
721 void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&)
722 {
723     WriteCompactSize(os, v.size());
724     if (!v.empty())
725         os.write((char*)&v[0], v.size() * sizeof(T));
726 }
727
728 template<typename Stream, typename T, typename A, typename V>
729 void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&)
730 {
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));
734 }
735
736 template<typename Stream, typename T, typename A>
737 inline void Serialize(Stream& os, const std::vector<T, A>& v)
738 {
739     Serialize_impl(os, v, T());
740 }
741
742
743 template<typename Stream, typename T, typename A>
744 void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&)
745 {
746     // Limit size per read so bogus size value won't cause out of memory
747     v.clear();
748     unsigned int nSize = ReadCompactSize(is);
749     unsigned int i = 0;
750     while (i < nSize)
751     {
752         unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
753         v.resize(i + blk);
754         is.read((char*)&v[i], blk * sizeof(T));
755         i += blk;
756     }
757 }
758
759 template<typename Stream, typename T, typename A, typename V>
760 void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&)
761 {
762     v.clear();
763     unsigned int nSize = ReadCompactSize(is);
764     unsigned int i = 0;
765     unsigned int nMid = 0;
766     while (nMid < nSize)
767     {
768         nMid += 5000000 / sizeof(T);
769         if (nMid > nSize)
770             nMid = nSize;
771         v.resize(nMid);
772         for (; i < nMid; i++)
773             Unserialize(is, v[i]);
774     }
775 }
776
777 template<typename Stream, typename T, typename A>
778 inline void Unserialize(Stream& is, std::vector<T, A>& v)
779 {
780     Unserialize_impl(is, v, T());
781 }
782
783
784
785 /**
786  * optional
787  */
788 template<typename Stream, typename T>
789 void Serialize(Stream& os, const boost::optional<T>& item)
790 {
791     // If the value is there, put 0x01 and then serialize the value.
792     // If it's not, put 0x00.
793     if (item) {
794         unsigned char discriminant = 0x01;
795         Serialize(os, discriminant);
796         Serialize(os, *item);
797     } else {
798         unsigned char discriminant = 0x00;
799         Serialize(os, discriminant);
800     }
801 }
802
803 template<typename Stream, typename T>
804 void Unserialize(Stream& is, boost::optional<T>& item)
805 {
806     unsigned char discriminant = 0x00;
807     Unserialize(is, discriminant);
808
809     if (discriminant == 0x00) {
810         item = boost::none;
811     } else if (discriminant == 0x01) {
812         T object;
813         Unserialize(is, object);
814         item = object;
815     } else {
816         throw std::ios_base::failure("non-canonical optional discriminant");
817     }
818 }
819
820
821
822 /**
823  * array
824  */
825 template<typename Stream, typename T, std::size_t N>
826 void Serialize(Stream& os, const std::array<T, N>& item)
827 {
828     for (size_t i = 0; i < N; i++) {
829         Serialize(os, item[i]);
830     }
831 }
832
833 template<typename Stream, typename T, std::size_t N>
834 void Unserialize(Stream& is, std::array<T, N>& item)
835 {
836     for (size_t i = 0; i < N; i++) {
837         Unserialize(is, item[i]);
838     }
839 }
840
841
842 /**
843  * pair
844  */
845 template<typename Stream, typename K, typename T>
846 void Serialize(Stream& os, const std::pair<K, T>& item)
847 {
848     Serialize(os, item.first);
849     Serialize(os, item.second);
850 }
851
852 template<typename Stream, typename K, typename T>
853 void Unserialize(Stream& is, std::pair<K, T>& item)
854 {
855     Unserialize(is, item.first);
856     Unserialize(is, item.second);
857 }
858
859
860
861 /**
862  * map
863  */
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)
866 {
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));
870 }
871
872 template<typename Stream, typename K, typename T, typename Pred, typename A>
873 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)
874 {
875     m.clear();
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++)
879     {
880         std::pair<K, T> item;
881         Unserialize(is, item);
882         mi = m.insert(mi, item);
883     }
884 }
885
886
887
888 /**
889  * set
890  */
891 template<typename Stream, typename K, typename Pred, typename A>
892 void Serialize(Stream& os, const std::set<K, Pred, A>& m)
893 {
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));
897 }
898
899 template<typename Stream, typename K, typename Pred, typename A>
900 void Unserialize(Stream& is, std::set<K, Pred, A>& m)
901 {
902     m.clear();
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++)
906     {
907         K key;
908         Unserialize(is, key);
909         it = m.insert(it, key);
910     }
911 }
912
913
914
915 /**
916  * list
917  */
918 template<typename Stream, typename T, typename A>
919 void Serialize(Stream& os, const std::list<T, A>& l)
920 {
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));
924 }
925
926 template<typename Stream, typename T, typename A>
927 void Unserialize(Stream& is, std::list<T, A>& l)
928 {
929     l.clear();
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++)
933     {
934         T item;
935         Unserialize(is, item);
936         l.push_back(item);
937     }
938 }
939
940
941
942 /**
943  * unique_ptr
944  */
945 template<typename Stream, typename T> void
946 Serialize(Stream& os, const std::unique_ptr<const T>& p)
947 {
948     Serialize(os, *p);
949 }
950
951 template<typename Stream, typename T>
952 void Unserialize(Stream& is, std::unique_ptr<const T>& p)
953 {
954     p.reset(new T(deserialize, is));
955 }
956
957
958
959 /**
960  * shared_ptr
961  */
962 template<typename Stream, typename T> void
963 Serialize(Stream& os, const std::shared_ptr<const T>& p)
964 {
965     Serialize(os, *p);
966 }
967
968 template<typename Stream, typename T>
969 void Unserialize(Stream& is, std::shared_ptr<const T>& p)
970 {
971     p = std::make_shared<const T>(deserialize, is);
972 }
973
974
975
976 /**
977  * Support for ADD_SERIALIZE_METHODS and READWRITE macro
978  */
979 struct CSerActionSerialize
980 {
981     constexpr bool ForRead() const { return false; }
982 };
983 struct CSerActionUnserialize
984 {
985     constexpr bool ForRead() const { return true; }
986 };
987
988 template<typename Stream, typename T>
989 inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action)
990 {
991     ::Serialize(s, obj);
992 }
993
994 template<typename Stream, typename T>
995 inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action)
996 {
997     ::Unserialize(s, obj);
998 }
999
1000
1001
1002
1003
1004
1005
1006
1007
1008 /* ::GetSerializeSize implementations
1009  *
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
1012  * to it.
1013  *
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.
1018  */
1019 class CSizeComputer
1020 {
1021 protected:
1022     size_t nSize;
1023
1024     const int nType;
1025     const int nVersion;
1026 public:
1027     CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {}
1028
1029     void write(const char *psz, size_t _nSize)
1030     {
1031         this->nSize += _nSize;
1032     }
1033
1034     /** Pretend _nSize bytes are written, without specifying them. */
1035     void seek(size_t _nSize)
1036     {
1037         this->nSize += _nSize;
1038     }
1039
1040     template<typename T>
1041     CSizeComputer& operator<<(const T& obj)
1042     {
1043         ::Serialize(*this, obj);
1044         return (*this);
1045     }
1046
1047     size_t size() const {
1048         return nSize;
1049     }
1050
1051     int GetVersion() const { return nVersion; }
1052     int GetType() const { return nType; }
1053 };
1054
1055 template<typename Stream>
1056 void SerializeMany(Stream& s)
1057 {
1058 }
1059
1060 template<typename Stream, typename Arg>
1061 void SerializeMany(Stream& s, Arg&& arg)
1062 {
1063     ::Serialize(s, std::forward<Arg>(arg));
1064 }
1065
1066 template<typename Stream, typename Arg, typename... Args>
1067 void SerializeMany(Stream& s, Arg&& arg, Args&&... args)
1068 {
1069     ::Serialize(s, std::forward<Arg>(arg));
1070     ::SerializeMany(s, std::forward<Args>(args)...);
1071 }
1072
1073 template<typename Stream>
1074 inline void UnserializeMany(Stream& s)
1075 {
1076 }
1077
1078 template<typename Stream, typename Arg>
1079 inline void UnserializeMany(Stream& s, Arg& arg)
1080 {
1081     ::Unserialize(s, arg);
1082 }
1083
1084 template<typename Stream, typename Arg, typename... Args>
1085 inline void UnserializeMany(Stream& s, Arg& arg, Args&... args)
1086 {
1087     ::Unserialize(s, arg);
1088     ::UnserializeMany(s, args...);
1089 }
1090
1091 template<typename Stream, typename... Args>
1092 inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args)
1093 {
1094     ::SerializeMany(s, std::forward<Args>(args)...);
1095 }
1096
1097 template<typename Stream, typename... Args>
1098 inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args)
1099 {
1100     ::UnserializeMany(s, args...);
1101 }
1102
1103 template<typename I>
1104 inline void WriteVarInt(CSizeComputer &s, I n)
1105 {
1106     s.seek(GetSizeOfVarInt<I>(n));
1107 }
1108
1109 inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
1110 {
1111     s.seek(GetSizeOfCompactSize(nSize));
1112 }
1113
1114 template <typename T>
1115 size_t GetSerializeSize(const T& t, int nType, int nVersion = 0)
1116 {
1117     return (CSizeComputer(nType, nVersion) << t).size();
1118 }
1119
1120 template <typename S, typename T>
1121 size_t GetSerializeSize(const S& s, const T& t)
1122 {
1123     return (CSizeComputer(s.GetType(), s.GetVersion()) << t).size();
1124 }
1125
1126 #endif // BITCOIN_SERIALIZE_H
This page took 0.08834 seconds and 4 git commands to generate.