]> Git Repo - VerusCoin.git/blob - src/serialize.h
Cleanup
[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 <assert.h>
13 #include <ios>
14 #include <limits>
15 #include <list>
16 #include <map>
17 #include <set>
18 #include <stdint.h>
19 #include <string>
20 #include <string.h>
21 #include <utility>
22 #include <vector>
23
24 #include <boost/array.hpp>
25 #include <boost/optional.hpp>
26
27 class CScript;
28
29 static const unsigned int MAX_SIZE = 0x02000000;
30
31 /**
32  * Used to bypass the rule against non-const reference to temporary
33  * where it makes sense with wrappers such as CFlatData or CTxDB
34  */
35 template<typename T>
36 inline T& REF(const T& val)
37 {
38     return const_cast<T&>(val);
39 }
40
41 /**
42  * Used to acquire a non-const pointer "this" to generate bodies
43  * of const serialization operations from a template
44  */
45 template<typename T>
46 inline T* NCONST_PTR(const T* val)
47 {
48     return const_cast<T*>(val);
49 }
50
51 /** 
52  * Get begin pointer of vector (non-const version).
53  * @note These functions avoid the undefined case of indexing into an empty
54  * vector, as well as that of indexing after the end of the vector.
55  */
56 template <class T, class TAl>
57 inline T* begin_ptr(std::vector<T,TAl>& v)
58 {
59     return v.empty() ? NULL : &v[0];
60 }
61 /** Get begin pointer of vector (const version) */
62 template <class T, class TAl>
63 inline const T* begin_ptr(const std::vector<T,TAl>& v)
64 {
65     return v.empty() ? NULL : &v[0];
66 }
67 /** Get end pointer of vector (non-const version) */
68 template <class T, class TAl>
69 inline T* end_ptr(std::vector<T,TAl>& v)
70 {
71     return v.empty() ? NULL : (&v[0] + v.size());
72 }
73 /** Get end pointer of vector (const version) */
74 template <class T, class TAl>
75 inline const T* end_ptr(const std::vector<T,TAl>& v)
76 {
77     return v.empty() ? NULL : (&v[0] + v.size());
78 }
79
80 /*
81  * Lowest-level serialization and conversion.
82  * @note Sizes of these types are verified in the tests
83  */
84 template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj)
85 {
86     s.write((char*)&obj, 1);
87 }
88 template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
89 {
90     obj = htole16(obj);
91     s.write((char*)&obj, 2);
92 }
93 template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
94 {
95     obj = htole32(obj);
96     s.write((char*)&obj, 4);
97 }
98 template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj)
99 {
100     obj = htobe32(obj);
101     s.write((char*)&obj, 4);
102 }
103 template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
104 {
105     obj = htole64(obj);
106     s.write((char*)&obj, 8);
107 }
108 template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
109 {
110     uint8_t obj;
111     s.read((char*)&obj, 1);
112     return obj;
113 }
114 template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
115 {
116     uint16_t obj;
117     s.read((char*)&obj, 2);
118     return le16toh(obj);
119 }
120 template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
121 {
122     uint32_t obj;
123     s.read((char*)&obj, 4);
124     return le32toh(obj);
125 }
126 template<typename Stream> inline uint32_t ser_readdata32be(Stream &s)
127 {
128     uint32_t obj;
129     s.read((char*)&obj, 4);
130     return be32toh(obj);
131 }
132 template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
133 {
134     uint64_t obj;
135     s.read((char*)&obj, 8);
136     return le64toh(obj);
137 }
138 inline uint64_t ser_double_to_uint64(double x)
139 {
140     union { double x; uint64_t y; } tmp;
141     tmp.x = x;
142     return tmp.y;
143 }
144 inline uint32_t ser_float_to_uint32(float x)
145 {
146     union { float x; uint32_t y; } tmp;
147     tmp.x = x;
148     return tmp.y;
149 }
150 inline double ser_uint64_to_double(uint64_t y)
151 {
152     union { double x; uint64_t y; } tmp;
153     tmp.y = y;
154     return tmp.x;
155 }
156 inline float ser_uint32_to_float(uint32_t y)
157 {
158     union { float x; uint32_t y; } tmp;
159     tmp.y = y;
160     return tmp.x;
161 }
162
163
164 /////////////////////////////////////////////////////////////////
165 //
166 // Templates for serializing to anything that looks like a stream,
167 // i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
168 //
169
170 enum
171 {
172     // primary actions
173     SER_NETWORK         = (1 << 0),
174     SER_DISK            = (1 << 1),
175     SER_GETHASH         = (1 << 2),
176 };
177
178 #define READWRITE(obj)      (::SerReadWrite(s, (obj), nType, nVersion, ser_action))
179
180 /** 
181  * Implement three methods for serializable objects. These are actually wrappers over
182  * "SerializationOp" template, which implements the body of each class' serialization
183  * code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
184  * added as members. 
185  */
186 #define ADD_SERIALIZE_METHODS                                                          \
187     size_t GetSerializeSize(int nType, int nVersion) const {                         \
188         CSizeComputer s(nType, nVersion);                                            \
189         NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion);\
190         return s.size();                                                             \
191     }                                                                                \
192     template<typename Stream>                                                        \
193     void Serialize(Stream& s, int nType, int nVersion) const {                       \
194         NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion);\
195     }                                                                                \
196     template<typename Stream>                                                        \
197     void Unserialize(Stream& s, int nType, int nVersion) {                           \
198         SerializationOp(s, CSerActionUnserialize(), nType, nVersion);                \
199     }
200
201 /*
202  * Basic Types
203  */
204 inline unsigned int GetSerializeSize(char a,      int, int=0) { return 1; }
205 inline unsigned int GetSerializeSize(int8_t a,    int, int=0) { return 1; }
206 inline unsigned int GetSerializeSize(uint8_t a,   int, int=0) { return 1; }
207 inline unsigned int GetSerializeSize(int16_t a,   int, int=0) { return 2; }
208 inline unsigned int GetSerializeSize(uint16_t a,  int, int=0) { return 2; }
209 inline unsigned int GetSerializeSize(int32_t a,   int, int=0) { return 4; }
210 inline unsigned int GetSerializeSize(uint32_t a,  int, int=0) { return 4; }
211 inline unsigned int GetSerializeSize(int64_t a,   int, int=0) { return 8; }
212 inline unsigned int GetSerializeSize(uint64_t a,  int, int=0) { return 8; }
213 inline unsigned int GetSerializeSize(float a,     int, int=0) { return 4; }
214 inline unsigned int GetSerializeSize(double a,    int, int=0) { return 8; }
215
216 template<typename Stream> inline void Serialize(Stream& s, char a,         int, int=0) { ser_writedata8(s, a); } // TODO Get rid of bare char
217 template<typename Stream> inline void Serialize(Stream& s, int8_t a,       int, int=0) { ser_writedata8(s, a); }
218 template<typename Stream> inline void Serialize(Stream& s, uint8_t a,      int, int=0) { ser_writedata8(s, a); }
219 template<typename Stream> inline void Serialize(Stream& s, int16_t a,      int, int=0) { ser_writedata16(s, a); }
220 template<typename Stream> inline void Serialize(Stream& s, uint16_t a,     int, int=0) { ser_writedata16(s, a); }
221 template<typename Stream> inline void Serialize(Stream& s, int32_t a,      int, int=0) { ser_writedata32(s, a); }
222 template<typename Stream> inline void Serialize(Stream& s, uint32_t a,     int, int=0) { ser_writedata32(s, a); }
223 template<typename Stream> inline void Serialize(Stream& s, int64_t a,      int, int=0) { ser_writedata64(s, a); }
224 template<typename Stream> inline void Serialize(Stream& s, uint64_t a,     int, int=0) { ser_writedata64(s, a); }
225 template<typename Stream> inline void Serialize(Stream& s, float a,        int, int=0) { ser_writedata32(s, ser_float_to_uint32(a)); }
226 template<typename Stream> inline void Serialize(Stream& s, double a,       int, int=0) { ser_writedata64(s, ser_double_to_uint64(a)); }
227
228 template<typename Stream> inline void Unserialize(Stream& s, char& a,      int, int=0) { a = ser_readdata8(s); } // TODO Get rid of bare char
229 template<typename Stream> inline void Unserialize(Stream& s, int8_t& a,    int, int=0) { a = ser_readdata8(s); }
230 template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a,   int, int=0) { a = ser_readdata8(s); }
231 template<typename Stream> inline void Unserialize(Stream& s, int16_t& a,   int, int=0) { a = ser_readdata16(s); }
232 template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a,  int, int=0) { a = ser_readdata16(s); }
233 template<typename Stream> inline void Unserialize(Stream& s, int32_t& a,   int, int=0) { a = ser_readdata32(s); }
234 template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a,  int, int=0) { a = ser_readdata32(s); }
235 template<typename Stream> inline void Unserialize(Stream& s, int64_t& a,   int, int=0) { a = ser_readdata64(s); }
236 template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a,  int, int=0) { a = ser_readdata64(s); }
237 template<typename Stream> inline void Unserialize(Stream& s, float& a,     int, int=0) { a = ser_uint32_to_float(ser_readdata32(s)); }
238 template<typename Stream> inline void Unserialize(Stream& s, double& a,    int, int=0) { a = ser_uint64_to_double(ser_readdata64(s)); }
239
240 inline unsigned int GetSerializeSize(bool a, int, int=0)                          { return sizeof(char); }
241 template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0)    { char f=a; ser_writedata8(s, f); }
242 template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f=ser_readdata8(s); a=f; }
243
244
245
246
247
248
249 /**
250  * Compact Size
251  * size <  253        -- 1 byte
252  * size <= 0xFFFF     -- 3 bytes  (253 + 2 bytes)
253  * size <= 0xFFFFFFFF -- 5 bytes  (254 + 4 bytes)
254  * size >  0xFFFFFFFF -- 9 bytes  (255 + 8 bytes)
255  */
256 inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
257 {
258     if (nSize < 253)                return 1;
259     else if (nSize <= 0xFFFFu)      return 3;
260     else if (nSize <= 0xFFFFFFFFu)  return 5;
261     else                            return 9;
262 }
263
264 template<typename Stream>
265 void WriteCompactSize(Stream& os, uint64_t nSize)
266 {
267     if (nSize < 253)
268     {
269         ser_writedata8(os, nSize);
270     }
271     else if (nSize <= 0xFFFFu)
272     {
273         ser_writedata8(os, 253);
274         ser_writedata16(os, nSize);
275     }
276     else if (nSize <= 0xFFFFFFFFu)
277     {
278         ser_writedata8(os, 254);
279         ser_writedata32(os, nSize);
280     }
281     else
282     {
283         ser_writedata8(os, 255);
284         ser_writedata64(os, nSize);
285     }
286 }
287
288 template<typename Stream>
289 uint64_t ReadCompactSize(Stream& is)
290 {
291     uint8_t chSize = ser_readdata8(is);
292     uint64_t nSizeRet = 0;
293     if (chSize < 253)
294     {
295         nSizeRet = chSize;
296     }
297     else if (chSize == 253)
298     {
299         nSizeRet = ser_readdata16(is);
300         if (nSizeRet < 253)
301             throw std::ios_base::failure("non-canonical ReadCompactSize()");
302     }
303     else if (chSize == 254)
304     {
305         nSizeRet = ser_readdata32(is);
306         if (nSizeRet < 0x10000u)
307             throw std::ios_base::failure("non-canonical ReadCompactSize()");
308     }
309     else
310     {
311         nSizeRet = ser_readdata64(is);
312         if (nSizeRet < 0x100000000ULL)
313             throw std::ios_base::failure("non-canonical ReadCompactSize()");
314     }
315     if (nSizeRet > (uint64_t)MAX_SIZE)
316         throw std::ios_base::failure("ReadCompactSize(): size too large");
317     return nSizeRet;
318 }
319
320 /**
321  * Variable-length integers: bytes are a MSB base-128 encoding of the number.
322  * The high bit in each byte signifies whether another digit follows. To make
323  * sure the encoding is one-to-one, one is subtracted from all but the last digit.
324  * Thus, the byte sequence a[] with length len, where all but the last byte
325  * has bit 128 set, encodes the number:
326  * 
327  *  (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
328  * 
329  * Properties:
330  * * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
331  * * Every integer has exactly one encoding
332  * * Encoding does not depend on size of original integer type
333  * * No redundancy: every (infinite) byte sequence corresponds to a list
334  *   of encoded integers.
335  * 
336  * 0:         [0x00]  256:        [0x81 0x00]
337  * 1:         [0x01]  16383:      [0xFE 0x7F]
338  * 127:       [0x7F]  16384:      [0xFF 0x00]
339  * 128:  [0x80 0x00]  16511: [0x80 0xFF 0x7F]
340  * 255:  [0x80 0x7F]  65535: [0x82 0xFD 0x7F]
341  * 2^32:           [0x8E 0xFE 0xFE 0xFF 0x00]
342  */
343
344 template<typename I>
345 inline unsigned int GetSizeOfVarInt(I n)
346 {
347     int nRet = 0;
348     while(true) {
349         nRet++;
350         if (n <= 0x7F)
351             break;
352         n = (n >> 7) - 1;
353     }
354     return nRet;
355 }
356
357 template<typename Stream, typename I>
358 void WriteVarInt(Stream& os, I n)
359 {
360     unsigned char tmp[(sizeof(n)*8+6)/7];
361     int len=0;
362     while(true) {
363         tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
364         if (n <= 0x7F)
365             break;
366         n = (n >> 7) - 1;
367         len++;
368     }
369     do {
370         ser_writedata8(os, tmp[len]);
371     } while(len--);
372 }
373
374 template<typename Stream, typename I>
375 I ReadVarInt(Stream& is)
376 {
377     I n = 0;
378     while(true) {
379         unsigned char chData = ser_readdata8(is);
380         n = (n << 7) | (chData & 0x7F);
381         if (chData & 0x80)
382             n++;
383         else
384             return n;
385     }
386 }
387
388 #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
389 #define VARINT(obj) REF(WrapVarInt(REF(obj)))
390 #define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))
391
392 /** 
393  * Wrapper for serializing arrays and POD.
394  */
395 class CFlatData
396 {
397 protected:
398     char* pbegin;
399     char* pend;
400 public:
401     CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
402     template <class T, class TAl>
403     explicit CFlatData(std::vector<T,TAl> &v)
404     {
405         pbegin = (char*)begin_ptr(v);
406         pend = (char*)end_ptr(v);
407     }
408     char* begin() { return pbegin; }
409     const char* begin() const { return pbegin; }
410     char* end() { return pend; }
411     const char* end() const { return pend; }
412
413     unsigned int GetSerializeSize(int, int=0) const
414     {
415         return pend - pbegin;
416     }
417
418     template<typename Stream>
419     void Serialize(Stream& s, int, int=0) const
420     {
421         s.write(pbegin, pend - pbegin);
422     }
423
424     template<typename Stream>
425     void Unserialize(Stream& s, int, int=0)
426     {
427         s.read(pbegin, pend - pbegin);
428     }
429 };
430
431 template<typename I>
432 class CVarInt
433 {
434 protected:
435     I &n;
436 public:
437     CVarInt(I& nIn) : n(nIn) { }
438
439     unsigned int GetSerializeSize(int, int) const {
440         return GetSizeOfVarInt<I>(n);
441     }
442
443     template<typename Stream>
444     void Serialize(Stream &s, int, int) const {
445         WriteVarInt<Stream,I>(s, n);
446     }
447
448     template<typename Stream>
449     void Unserialize(Stream& s, int, int) {
450         n = ReadVarInt<Stream,I>(s);
451     }
452 };
453
454 template<size_t Limit>
455 class LimitedString
456 {
457 protected:
458     std::string& string;
459 public:
460     LimitedString(std::string& string) : string(string) {}
461
462     template<typename Stream>
463     void Unserialize(Stream& s, int, int=0)
464     {
465         size_t size = ReadCompactSize(s);
466         if (size > Limit) {
467             throw std::ios_base::failure("String length limit exceeded");
468         }
469         string.resize(size);
470         if (size != 0)
471             s.read((char*)&string[0], size);
472     }
473
474     template<typename Stream>
475     void Serialize(Stream& s, int, int=0) const
476     {
477         WriteCompactSize(s, string.size());
478         if (!string.empty())
479             s.write((char*)&string[0], string.size());
480     }
481
482     unsigned int GetSerializeSize(int, int=0) const
483     {
484         return GetSizeOfCompactSize(string.size()) + string.size();
485     }
486 };
487
488 template<typename I>
489 CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
490
491 /**
492  * Forward declarations
493  */
494
495 /**
496  *  string
497  */
498 template<typename C> unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int=0);
499 template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str, int, int=0);
500 template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str, int, int=0);
501
502 /**
503  * vector
504  * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
505  */
506 template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&);
507 template<typename T, typename A, typename V> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const V&);
508 template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion);
509 template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&);
510 template<typename Stream, typename T, typename A, typename V> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const V&);
511 template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion);
512 template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const unsigned char&);
513 template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const V&);
514 template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion);
515
516 /**
517  * others derived from vector
518  */
519 extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion);
520 template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion);
521 template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion);
522
523 /**
524  * optional
525  */
526 template<typename T> unsigned int GetSerializeSize(const boost::optional<T> &item, int nType, int nVersion);
527 template<typename Stream, typename T> void Serialize(Stream& os, const boost::optional<T>& item, int nType, int nVersion);
528 template<typename Stream, typename T> void Unserialize(Stream& is, boost::optional<T>& item, int nType, int nVersion);
529
530 /**
531  * array
532  */
533 template<typename T, std::size_t N> unsigned int GetSerializeSize(const boost::array<T, N> &item, int nType, int nVersion);
534 template<typename Stream, typename T, std::size_t N> void Serialize(Stream& os, const boost::array<T, N>& item, int nType, int nVersion);
535 template<typename Stream, typename T, std::size_t N> void Unserialize(Stream& is, boost::array<T, N>& item, int nType, int nVersion);
536
537 /**
538  * pair
539  */
540 template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion);
541 template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion);
542 template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion);
543
544 /**
545  * map
546  */
547 template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion);
548 template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion);
549 template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion);
550
551 /**
552  * set
553  */
554 template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion);
555 template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion);
556 template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion);
557
558 /**
559  * list
560  */
561 template<typename T, typename A> unsigned int GetSerializeSize(const std::list<T, A>& m, int nType, int nVersion);
562 template<typename Stream, typename T, typename A> void Serialize(Stream& os, const std::list<T, A>& m, int nType, int nVersion);
563 template<typename Stream, typename T, typename A> void Unserialize(Stream& is, std::list<T, A>& m, int nType, int nVersion);
564
565
566
567
568
569 /**
570  * If none of the specialized versions above matched, default to calling member function.
571  * "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
572  * The compiler will only cast int to long if none of the other templates matched.
573  * Thanks to Boost serialization for this idea.
574  */
575 template<typename T>
576 inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion)
577 {
578     return a.GetSerializeSize((int)nType, nVersion);
579 }
580
581 template<typename Stream, typename T>
582 inline void Serialize(Stream& os, const T& a, long nType, int nVersion)
583 {
584     a.Serialize(os, (int)nType, nVersion);
585 }
586
587 template<typename Stream, typename T>
588 inline void Unserialize(Stream& is, T& a, long nType, int nVersion)
589 {
590     a.Unserialize(is, (int)nType, nVersion);
591 }
592
593
594
595
596
597 /**
598  * string
599  */
600 template<typename C>
601 unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int)
602 {
603     return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]);
604 }
605
606 template<typename Stream, typename C>
607 void Serialize(Stream& os, const std::basic_string<C>& str, int, int)
608 {
609     WriteCompactSize(os, str.size());
610     if (!str.empty())
611         os.write((char*)&str[0], str.size() * sizeof(str[0]));
612 }
613
614 template<typename Stream, typename C>
615 void Unserialize(Stream& is, std::basic_string<C>& str, int, int)
616 {
617     unsigned int nSize = ReadCompactSize(is);
618     str.resize(nSize);
619     if (nSize != 0)
620         is.read((char*)&str[0], nSize * sizeof(str[0]));
621 }
622
623
624
625 /**
626  * vector
627  */
628 template<typename T, typename A>
629 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&)
630 {
631     return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));
632 }
633
634 template<typename T, typename A, typename V>
635 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const V&)
636 {
637     unsigned int nSize = GetSizeOfCompactSize(v.size());
638     for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
639         nSize += GetSerializeSize((*vi), nType, nVersion);
640     return nSize;
641 }
642
643 template<typename T, typename A>
644 inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion)
645 {
646     return GetSerializeSize_impl(v, nType, nVersion, T());
647 }
648
649
650 template<typename Stream, typename T, typename A>
651 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&)
652 {
653     WriteCompactSize(os, v.size());
654     if (!v.empty())
655         os.write((char*)&v[0], v.size() * sizeof(T));
656 }
657
658 template<typename Stream, typename T, typename A, typename V>
659 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const V&)
660 {
661     WriteCompactSize(os, v.size());
662     for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
663         ::Serialize(os, (*vi), nType, nVersion);
664 }
665
666 template<typename Stream, typename T, typename A>
667 inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion)
668 {
669     Serialize_impl(os, v, nType, nVersion, T());
670 }
671
672
673 template<typename Stream, typename T, typename A>
674 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const unsigned char&)
675 {
676     // Limit size per read so bogus size value won't cause out of memory
677     v.clear();
678     unsigned int nSize = ReadCompactSize(is);
679     unsigned int i = 0;
680     while (i < nSize)
681     {
682         unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
683         v.resize(i + blk);
684         is.read((char*)&v[i], blk * sizeof(T));
685         i += blk;
686     }
687 }
688
689 template<typename Stream, typename T, typename A, typename V>
690 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const V&)
691 {
692     v.clear();
693     unsigned int nSize = ReadCompactSize(is);
694     unsigned int i = 0;
695     unsigned int nMid = 0;
696     while (nMid < nSize)
697     {
698         nMid += 5000000 / sizeof(T);
699         if (nMid > nSize)
700             nMid = nSize;
701         v.resize(nMid);
702         for (; i < nMid; i++)
703             Unserialize(is, v[i], nType, nVersion);
704     }
705 }
706
707 template<typename Stream, typename T, typename A>
708 inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion)
709 {
710     Unserialize_impl(is, v, nType, nVersion, T());
711 }
712
713
714
715 /**
716  * others derived from vector
717  */
718 inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)
719 {
720     return GetSerializeSize((const std::vector<unsigned char>&)v, nType, nVersion);
721 }
722
723 template<typename Stream>
724 void Serialize(Stream& os, const CScript& v, int nType, int nVersion)
725 {
726     Serialize(os, (const std::vector<unsigned char>&)v, nType, nVersion);
727 }
728
729 template<typename Stream>
730 void Unserialize(Stream& is, CScript& v, int nType, int nVersion)
731 {
732     Unserialize(is, (std::vector<unsigned char>&)v, nType, nVersion);
733 }
734
735
736
737 /**
738  * optional
739  */
740 template<typename T>
741 unsigned int GetSerializeSize(const boost::optional<T> &item, int nType, int nVersion)
742 {
743     if (item) {
744         return 1 + GetSerializeSize(*item, nType, nVersion);
745     } else {
746         return 1;
747     }
748 }
749
750 template<typename Stream, typename T>
751 void Serialize(Stream& os, const boost::optional<T>& item, int nType, int nVersion)
752 {
753     // If the value is there, put 0x01 and then serialize the value.
754     // If it's not, put 0x00.
755     if (item) {
756         unsigned char discriminant = 0x01;
757         Serialize(os, discriminant, nType, nVersion);
758         Serialize(os, *item, nType, nVersion);
759     } else {
760         unsigned char discriminant = 0x00;
761         Serialize(os, discriminant, nType, nVersion);
762     }
763 }
764
765 template<typename Stream, typename T>
766 void Unserialize(Stream& is, boost::optional<T>& item, int nType, int nVersion)
767 {
768     unsigned char discriminant = 0x00;
769     Unserialize(is, discriminant, nType, nVersion);
770
771     if (discriminant == 0x00) {
772         item = boost::none;
773     } else if (discriminant == 0x01) {
774         T object;
775         Unserialize(is, object, nType, nVersion);
776         item = object;
777     } else {
778         throw std::ios_base::failure("non-canonical optional discriminant");
779     }
780 }
781
782
783
784 /**
785  * array
786  */
787 template<typename T, std::size_t N>
788 unsigned int GetSerializeSize(const boost::array<T, N> &item, int nType, int nVersion)
789 {
790     unsigned int size = 0;
791     for (size_t i = 0; i < N; i++) {
792         size += GetSerializeSize(item[0], nType, nVersion);
793     }
794     return size;
795 }
796
797 template<typename Stream, typename T, std::size_t N>
798 void Serialize(Stream& os, const boost::array<T, N>& item, int nType, int nVersion)
799 {
800     for (size_t i = 0; i < N; i++) {
801         Serialize(os, item[i], nType, nVersion);
802     }
803 }
804
805 template<typename Stream, typename T, std::size_t N>
806 void Unserialize(Stream& is, boost::array<T, N>& item, int nType, int nVersion)
807 {
808     for (size_t i = 0; i < N; i++) {
809         Unserialize(is, item[i], nType, nVersion);
810     }
811 }
812
813
814 /**
815  * pair
816  */
817 template<typename K, typename T>
818 unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)
819 {
820     return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion);
821 }
822
823 template<typename Stream, typename K, typename T>
824 void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion)
825 {
826     Serialize(os, item.first, nType, nVersion);
827     Serialize(os, item.second, nType, nVersion);
828 }
829
830 template<typename Stream, typename K, typename T>
831 void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
832 {
833     Unserialize(is, item.first, nType, nVersion);
834     Unserialize(is, item.second, nType, nVersion);
835 }
836
837
838
839 /**
840  * map
841  */
842 template<typename K, typename T, typename Pred, typename A>
843 unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)
844 {
845     unsigned int nSize = GetSizeOfCompactSize(m.size());
846     for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
847         nSize += GetSerializeSize((*mi), nType, nVersion);
848     return nSize;
849 }
850
851 template<typename Stream, typename K, typename T, typename Pred, typename A>
852 void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion)
853 {
854     WriteCompactSize(os, m.size());
855     for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
856         Serialize(os, (*mi), nType, nVersion);
857 }
858
859 template<typename Stream, typename K, typename T, typename Pred, typename A>
860 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion)
861 {
862     m.clear();
863     unsigned int nSize = ReadCompactSize(is);
864     typename std::map<K, T, Pred, A>::iterator mi = m.begin();
865     for (unsigned int i = 0; i < nSize; i++)
866     {
867         std::pair<K, T> item;
868         Unserialize(is, item, nType, nVersion);
869         mi = m.insert(mi, item);
870     }
871 }
872
873
874
875 /**
876  * set
877  */
878 template<typename K, typename Pred, typename A>
879 unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)
880 {
881     unsigned int nSize = GetSizeOfCompactSize(m.size());
882     for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
883         nSize += GetSerializeSize((*it), nType, nVersion);
884     return nSize;
885 }
886
887 template<typename Stream, typename K, typename Pred, typename A>
888 void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion)
889 {
890     WriteCompactSize(os, m.size());
891     for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
892         Serialize(os, (*it), nType, nVersion);
893 }
894
895 template<typename Stream, typename K, typename Pred, typename A>
896 void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
897 {
898     m.clear();
899     unsigned int nSize = ReadCompactSize(is);
900     typename std::set<K, Pred, A>::iterator it = m.begin();
901     for (unsigned int i = 0; i < nSize; i++)
902     {
903         K key;
904         Unserialize(is, key, nType, nVersion);
905         it = m.insert(it, key);
906     }
907 }
908
909
910
911 /**
912  * list
913  */
914 template<typename T, typename A>
915 unsigned int GetSerializeSize(const std::list<T, A>& l, int nType, int nVersion)
916 {
917     unsigned int nSize = GetSizeOfCompactSize(l.size());
918     for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it)
919         nSize += GetSerializeSize((*it), nType, nVersion);
920     return nSize;
921 }
922
923 template<typename Stream, typename T, typename A>
924 void Serialize(Stream& os, const std::list<T, A>& l, int nType, int nVersion)
925 {
926     WriteCompactSize(os, l.size());
927     for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it)
928         Serialize(os, (*it), nType, nVersion);
929 }
930
931 template<typename Stream, typename T, typename A>
932 void Unserialize(Stream& is, std::list<T, A>& l, int nType, int nVersion)
933 {
934     l.clear();
935     unsigned int nSize = ReadCompactSize(is);
936     typename std::list<T, A>::iterator it = l.begin();
937     for (unsigned int i = 0; i < nSize; i++)
938     {
939         T item;
940         Unserialize(is, item, nType, nVersion);
941         l.push_back(item);
942     }
943 }
944
945
946
947 /**
948  * Support for ADD_SERIALIZE_METHODS and READWRITE macro
949  */
950 struct CSerActionSerialize
951 {
952     bool ForRead() const { return false; }
953 };
954 struct CSerActionUnserialize
955 {
956     bool ForRead() const { return true; }
957 };
958
959 template<typename Stream, typename T>
960 inline void SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
961 {
962     ::Serialize(s, obj, nType, nVersion);
963 }
964
965 template<typename Stream, typename T>
966 inline void SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
967 {
968     ::Unserialize(s, obj, nType, nVersion);
969 }
970
971
972
973
974
975
976
977
978
979 class CSizeComputer
980 {
981 protected:
982     size_t nSize;
983
984 public:
985     int nType;
986     int nVersion;
987
988     CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {}
989
990     CSizeComputer& write(const char *psz, size_t nSize)
991     {
992         this->nSize += nSize;
993         return *this;
994     }
995
996     template<typename T>
997     CSizeComputer& operator<<(const T& obj)
998     {
999         ::Serialize(*this, obj, nType, nVersion);
1000         return (*this);
1001     }
1002
1003     size_t size() const {
1004         return nSize;
1005     }
1006 };
1007
1008 #endif // BITCOIN_SERIALIZE_H
This page took 0.084627 seconds and 4 git commands to generate.