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