]>
Commit | Line | Data |
---|---|---|
0a61b0df | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
f914f1a7 | 2 | // Copyright (c) 2009-2014 The Bitcoin Core developers |
1c0aa911 | 3 | // Distributed under the MIT software license, see the accompanying |
bc909a7a | 4 | // file COPYING or https://www.opensource.org/licenses/mit-license.php . |
51ed9ec9 | 5 | |
223b6f1b WL |
6 | #ifndef BITCOIN_SERIALIZE_H |
7 | #define BITCOIN_SERIALIZE_H | |
0a61b0df | 8 | |
5207f33f PK |
9 | #include "compat/endian.h" |
10 | ||
51ed9ec9 | 11 | #include <algorithm> |
a6bbb26e | 12 | #include <array> |
51ed9ec9 | 13 | #include <assert.h> |
51ed9ec9 | 14 | #include <ios> |
611116d4 | 15 | #include <limits> |
be74c80d | 16 | #include <list> |
0a61b0df | 17 | #include <map> |
40cc9aa7 | 18 | #include <memory> |
d743f035 | 19 | #include <set> |
51ed9ec9 BD |
20 | #include <stdint.h> |
21 | #include <string> | |
22 | #include <string.h> | |
23 | #include <utility> | |
24 | #include <vector> | |
223b6f1b | 25 | |
291b191b | 26 | #include <boost/optional.hpp> |
5884044b | 27 | |
29a8ade7 | 28 | #include "prevector.h" |
51ed9ec9 | 29 | |
0a61b0df | 30 | static const unsigned int MAX_SIZE = 0x02000000; |
31 | ||
40cc9aa7 PW |
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 | ||
1c0aa911 MF |
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 | */ | |
82dc6426 GS |
50 | template<typename T> |
51 | inline T& REF(const T& val) | |
52 | { | |
53 | return const_cast<T&>(val); | |
54 | } | |
0a61b0df | 55 | |
1c0aa911 MF |
56 | /** |
57 | * Used to acquire a non-const pointer "this" to generate bodies | |
58 | * of const serialization operations from a template | |
59 | */ | |
3d796f89 | 60 | template<typename T> |
84881f8c | 61 | inline T* NCONST_PTR(const T* val) |
3d796f89 | 62 | { |
84881f8c | 63 | return const_cast<T*>(val); |
3d796f89 KD |
64 | } |
65 | ||
1c0aa911 MF |
66 | /** |
67 | * Get begin pointer of vector (non-const version). | |
fa126eff WL |
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 | */ | |
29a8ade7 PW |
71 | template <typename V> |
72 | inline typename V::value_type* begin_ptr(V& v) | |
fa126eff WL |
73 | { |
74 | return v.empty() ? NULL : &v[0]; | |
75 | } | |
76 | /** Get begin pointer of vector (const version) */ | |
29a8ade7 PW |
77 | template <typename V> |
78 | inline const typename V::value_type* begin_ptr(const V& v) | |
fa126eff WL |
79 | { |
80 | return v.empty() ? NULL : &v[0]; | |
81 | } | |
82 | /** Get end pointer of vector (non-const version) */ | |
29a8ade7 PW |
83 | template <typename V> |
84 | inline typename V::value_type* end_ptr(V& v) | |
fa126eff WL |
85 | { |
86 | return v.empty() ? NULL : (&v[0] + v.size()); | |
87 | } | |
88 | /** Get end pointer of vector (const version) */ | |
29a8ade7 PW |
89 | template <typename V> |
90 | inline const typename V::value_type* end_ptr(const V& v) | |
fa126eff WL |
91 | { |
92 | return v.empty() ? NULL : (&v[0] + v.size()); | |
93 | } | |
94 | ||
01f9c344 WL |
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_writedata32(Stream &s, uint32_t obj) | |
109 | { | |
110 | obj = htole32(obj); | |
111 | s.write((char*)&obj, 4); | |
112 | } | |
6cf0e50b LR |
113 | template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj) |
114 | { | |
115 | obj = htobe32(obj); | |
116 | s.write((char*)&obj, 4); | |
117 | } | |
01f9c344 WL |
118 | template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj) |
119 | { | |
120 | obj = htole64(obj); | |
121 | s.write((char*)&obj, 8); | |
122 | } | |
123 | template<typename Stream> inline uint8_t ser_readdata8(Stream &s) | |
124 | { | |
125 | uint8_t obj; | |
126 | s.read((char*)&obj, 1); | |
127 | return obj; | |
128 | } | |
129 | template<typename Stream> inline uint16_t ser_readdata16(Stream &s) | |
130 | { | |
131 | uint16_t obj; | |
132 | s.read((char*)&obj, 2); | |
133 | return le16toh(obj); | |
134 | } | |
135 | template<typename Stream> inline uint32_t ser_readdata32(Stream &s) | |
136 | { | |
137 | uint32_t obj; | |
138 | s.read((char*)&obj, 4); | |
139 | return le32toh(obj); | |
140 | } | |
6cf0e50b LR |
141 | template<typename Stream> inline uint32_t ser_readdata32be(Stream &s) |
142 | { | |
143 | uint32_t obj; | |
144 | s.read((char*)&obj, 4); | |
145 | return be32toh(obj); | |
146 | } | |
01f9c344 WL |
147 | template<typename Stream> inline uint64_t ser_readdata64(Stream &s) |
148 | { | |
149 | uint64_t obj; | |
150 | s.read((char*)&obj, 8); | |
151 | return le64toh(obj); | |
152 | } | |
153 | inline uint64_t ser_double_to_uint64(double x) | |
154 | { | |
155 | union { double x; uint64_t y; } tmp; | |
156 | tmp.x = x; | |
157 | return tmp.y; | |
158 | } | |
159 | inline uint32_t ser_float_to_uint32(float x) | |
160 | { | |
161 | union { float x; uint32_t y; } tmp; | |
162 | tmp.x = x; | |
163 | return tmp.y; | |
164 | } | |
165 | inline double ser_uint64_to_double(uint64_t y) | |
166 | { | |
167 | union { double x; uint64_t y; } tmp; | |
168 | tmp.y = y; | |
169 | return tmp.x; | |
170 | } | |
171 | inline float ser_uint32_to_float(uint32_t y) | |
172 | { | |
173 | union { float x; uint32_t y; } tmp; | |
174 | tmp.y = y; | |
175 | return tmp.x; | |
176 | } | |
177 | ||
178 | ||
0a61b0df | 179 | ///////////////////////////////////////////////////////////////// |
180 | // | |
181 | // Templates for serializing to anything that looks like a stream, | |
8695a393 | 182 | // i.e. anything that supports .read(char*, size_t) and .write(char*, size_t) |
0a61b0df | 183 | // |
184 | ||
09891705 PW |
185 | class CSizeComputer; |
186 | ||
0a61b0df | 187 | enum |
188 | { | |
189 | // primary actions | |
190 | SER_NETWORK = (1 << 0), | |
191 | SER_DISK = (1 << 1), | |
192 | SER_GETHASH = (1 << 2), | |
0a61b0df | 193 | }; |
194 | ||
242f1421 PW |
195 | #define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action)) |
196 | #define READWRITEMANY(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__)) | |
0a61b0df | 197 | |
1c0aa911 MF |
198 | /** |
199 | * Implement three methods for serializable objects. These are actually wrappers over | |
3d796f89 | 200 | * "SerializationOp" template, which implements the body of each class' serialization |
3f6540ad | 201 | * code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be |
1c0aa911 MF |
202 | * added as members. |
203 | */ | |
242f1421 PW |
204 | #define ADD_SERIALIZE_METHODS \ |
205 | template<typename Stream> \ | |
206 | void Serialize(Stream& s) const { \ | |
207 | NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \ | |
208 | } \ | |
209 | template<typename Stream> \ | |
210 | void Unserialize(Stream& s) { \ | |
211 | SerializationOp(s, CSerActionUnserialize()); \ | |
0a61b0df | 212 | } |
213 | ||
242f1421 PW |
214 | template<typename Stream> inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char |
215 | template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); } | |
216 | template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); } | |
217 | template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); } | |
218 | template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); } | |
219 | template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); } | |
220 | template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); } | |
221 | template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); } | |
222 | template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); } | |
223 | template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); } | |
224 | template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); } | |
01f9c344 | 225 | |
242f1421 PW |
226 | template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char |
227 | template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); } | |
228 | template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); } | |
229 | template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); } | |
230 | template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); } | |
231 | template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); } | |
232 | template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); } | |
233 | template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); } | |
234 | template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); } | |
235 | template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); } | |
236 | template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); } | |
0a61b0df | 237 | |
242f1421 PW |
238 | template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); } |
239 | template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; } | |
0a61b0df | 240 | |
241 | ||
242 | ||
243 | ||
244 | ||
245 | ||
1c0aa911 MF |
246 | /** |
247 | * Compact Size | |
248 | * size < 253 -- 1 byte | |
d76ed723 DH |
249 | * size <= 0xFFFF -- 3 bytes (253 + 2 bytes) |
250 | * size <= 0xFFFFFFFF -- 5 bytes (254 + 4 bytes) | |
251 | * size > 0xFFFFFFFF -- 9 bytes (255 + 8 bytes) | |
1c0aa911 | 252 | */ |
51ed9ec9 | 253 | inline unsigned int GetSizeOfCompactSize(uint64_t nSize) |
0a61b0df | 254 | { |
d76ed723 DH |
255 | if (nSize < 253) return 1; |
256 | else if (nSize <= 0xFFFFu) return 3; | |
257 | else if (nSize <= 0xFFFFFFFFu) return 5; | |
258 | else return 9; | |
0a61b0df | 259 | } |
260 | ||
09891705 PW |
261 | inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize); |
262 | ||
0a61b0df | 263 | template<typename Stream> |
51ed9ec9 | 264 | void WriteCompactSize(Stream& os, uint64_t nSize) |
0a61b0df | 265 | { |
a790fa46 | 266 | if (nSize < 253) |
0a61b0df | 267 | { |
01f9c344 | 268 | ser_writedata8(os, nSize); |
0a61b0df | 269 | } |
d76ed723 | 270 | else if (nSize <= 0xFFFFu) |
0a61b0df | 271 | { |
01f9c344 WL |
272 | ser_writedata8(os, 253); |
273 | ser_writedata16(os, nSize); | |
0a61b0df | 274 | } |
d76ed723 | 275 | else if (nSize <= 0xFFFFFFFFu) |
0a61b0df | 276 | { |
01f9c344 WL |
277 | ser_writedata8(os, 254); |
278 | ser_writedata32(os, nSize); | |
0a61b0df | 279 | } |
280 | else | |
281 | { | |
01f9c344 WL |
282 | ser_writedata8(os, 255); |
283 | ser_writedata64(os, nSize); | |
0a61b0df | 284 | } |
0a61b0df | 285 | } |
286 | ||
287 | template<typename Stream> | |
51ed9ec9 | 288 | uint64_t ReadCompactSize(Stream& is) |
0a61b0df | 289 | { |
01f9c344 | 290 | uint8_t chSize = ser_readdata8(is); |
51ed9ec9 | 291 | uint64_t nSizeRet = 0; |
a790fa46 | 292 | if (chSize < 253) |
0a61b0df | 293 | { |
294 | nSizeRet = chSize; | |
295 | } | |
a790fa46 | 296 | else if (chSize == 253) |
0a61b0df | 297 | { |
01f9c344 | 298 | nSizeRet = ser_readdata16(is); |
8dc206a1 GA |
299 | if (nSizeRet < 253) |
300 | throw std::ios_base::failure("non-canonical ReadCompactSize()"); | |
0a61b0df | 301 | } |
a790fa46 | 302 | else if (chSize == 254) |
0a61b0df | 303 | { |
01f9c344 | 304 | nSizeRet = ser_readdata32(is); |
8dc206a1 GA |
305 | if (nSizeRet < 0x10000u) |
306 | throw std::ios_base::failure("non-canonical ReadCompactSize()"); | |
0a61b0df | 307 | } |
308 | else | |
309 | { | |
01f9c344 | 310 | nSizeRet = ser_readdata64(is); |
775b7b8d | 311 | if (nSizeRet < 0x100000000ULL) |
8dc206a1 | 312 | throw std::ios_base::failure("non-canonical ReadCompactSize()"); |
0a61b0df | 313 | } |
51ed9ec9 | 314 | if (nSizeRet > (uint64_t)MAX_SIZE) |
5262fde0 | 315 | throw std::ios_base::failure("ReadCompactSize(): size too large"); |
0a61b0df | 316 | return nSizeRet; |
317 | } | |
318 | ||
1c0aa911 MF |
319 | /** |
320 | * Variable-length integers: bytes are a MSB base-128 encoding of the number. | |
321 | * The high bit in each byte signifies whether another digit follows. To make | |
322 | * sure the encoding is one-to-one, one is subtracted from all but the last digit. | |
323 | * Thus, the byte sequence a[] with length len, where all but the last byte | |
324 | * has bit 128 set, encodes the number: | |
325 | * | |
326 | * (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1)) | |
327 | * | |
328 | * Properties: | |
329 | * * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes) | |
330 | * * Every integer has exactly one encoding | |
331 | * * Encoding does not depend on size of original integer type | |
332 | * * No redundancy: every (infinite) byte sequence corresponds to a list | |
333 | * of encoded integers. | |
334 | * | |
335 | * 0: [0x00] 256: [0x81 0x00] | |
336 | * 1: [0x01] 16383: [0xFE 0x7F] | |
337 | * 127: [0x7F] 16384: [0xFF 0x00] | |
338 | * 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F] | |
339 | * 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F] | |
340 | * 2^32: [0x8E 0xFE 0xFE 0xFF 0x00] | |
341 | */ | |
4d6144f9 PW |
342 | |
343 | template<typename I> | |
344 | inline unsigned int GetSizeOfVarInt(I n) | |
345 | { | |
346 | int nRet = 0; | |
347 | while(true) { | |
348 | nRet++; | |
349 | if (n <= 0x7F) | |
350 | break; | |
351 | n = (n >> 7) - 1; | |
352 | } | |
353 | return nRet; | |
354 | } | |
355 | ||
09891705 PW |
356 | template<typename I> |
357 | inline void WriteVarInt(CSizeComputer& os, I n); | |
358 | ||
4d6144f9 PW |
359 | template<typename Stream, typename I> |
360 | void WriteVarInt(Stream& os, I n) | |
361 | { | |
362 | unsigned char tmp[(sizeof(n)*8+6)/7]; | |
363 | int len=0; | |
364 | while(true) { | |
365 | tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00); | |
366 | if (n <= 0x7F) | |
367 | break; | |
368 | n = (n >> 7) - 1; | |
369 | len++; | |
370 | } | |
371 | do { | |
01f9c344 | 372 | ser_writedata8(os, tmp[len]); |
4d6144f9 PW |
373 | } while(len--); |
374 | } | |
0a61b0df | 375 | |
4d6144f9 PW |
376 | template<typename Stream, typename I> |
377 | I ReadVarInt(Stream& is) | |
378 | { | |
379 | I n = 0; | |
380 | while(true) { | |
01f9c344 | 381 | unsigned char chData = ser_readdata8(is); |
4d6144f9 PW |
382 | n = (n << 7) | (chData & 0x7F); |
383 | if (chData & 0x80) | |
384 | n++; | |
385 | else | |
386 | return n; | |
387 | } | |
388 | } | |
0a61b0df | 389 | |
216e9a44 PW |
390 | #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) |
391 | #define VARINT(obj) REF(WrapVarInt(REF(obj))) | |
c803fa10 | 392 | #define COMPACTSIZE(obj) REF(CCompactSize(REF(obj))) |
216e9a44 | 393 | #define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj))) |
6b8de05d | 394 | |
1c0aa911 MF |
395 | /** |
396 | * Wrapper for serializing arrays and POD. | |
6b8de05d | 397 | */ |
0a61b0df | 398 | class CFlatData |
399 | { | |
400 | protected: | |
401 | char* pbegin; | |
402 | char* pend; | |
403 | public: | |
404 | CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { } | |
fa126eff WL |
405 | template <class T, class TAl> |
406 | explicit CFlatData(std::vector<T,TAl> &v) | |
407 | { | |
408 | pbegin = (char*)begin_ptr(v); | |
409 | pend = (char*)end_ptr(v); | |
410 | } | |
29a8ade7 PW |
411 | template <unsigned int N, typename T, typename S, typename D> |
412 | explicit CFlatData(prevector<N, T, S, D> &v) | |
413 | { | |
414 | pbegin = (char*)begin_ptr(v); | |
415 | pend = (char*)end_ptr(v); | |
416 | } | |
0a61b0df | 417 | char* begin() { return pbegin; } |
418 | const char* begin() const { return pbegin; } | |
419 | char* end() { return pend; } | |
420 | const char* end() const { return pend; } | |
421 | ||
0a61b0df | 422 | template<typename Stream> |
242f1421 | 423 | void Serialize(Stream& s) const |
0a61b0df | 424 | { |
425 | s.write(pbegin, pend - pbegin); | |
426 | } | |
427 | ||
428 | template<typename Stream> | |
242f1421 | 429 | void Unserialize(Stream& s) |
0a61b0df | 430 | { |
431 | s.read(pbegin, pend - pbegin); | |
432 | } | |
433 | }; | |
434 | ||
4d6144f9 PW |
435 | template<typename I> |
436 | class CVarInt | |
437 | { | |
438 | protected: | |
439 | I &n; | |
440 | public: | |
441 | CVarInt(I& nIn) : n(nIn) { } | |
442 | ||
4d6144f9 | 443 | template<typename Stream> |
242f1421 | 444 | void Serialize(Stream &s) const { |
4d6144f9 PW |
445 | WriteVarInt<Stream,I>(s, n); |
446 | } | |
447 | ||
448 | template<typename Stream> | |
242f1421 | 449 | void Unserialize(Stream& s) { |
4d6144f9 PW |
450 | n = ReadVarInt<Stream,I>(s); |
451 | } | |
452 | }; | |
453 | ||
c803fa10 MC |
454 | class CCompactSize |
455 | { | |
456 | protected: | |
457 | uint64_t &n; | |
458 | public: | |
459 | CCompactSize(uint64_t& nIn) : n(nIn) { } | |
460 | ||
c803fa10 | 461 | template<typename Stream> |
242f1421 | 462 | void Serialize(Stream &s) const { |
c803fa10 MC |
463 | WriteCompactSize<Stream>(s, n); |
464 | } | |
465 | ||
466 | template<typename Stream> | |
242f1421 | 467 | void Unserialize(Stream& s) { |
c803fa10 MC |
468 | n = ReadCompactSize<Stream>(s); |
469 | } | |
470 | }; | |
471 | ||
216e9a44 PW |
472 | template<size_t Limit> |
473 | class LimitedString | |
474 | { | |
475 | protected: | |
476 | std::string& string; | |
477 | public: | |
9b228f03 | 478 | LimitedString(std::string& _string) : string(_string) {} |
216e9a44 PW |
479 | |
480 | template<typename Stream> | |
242f1421 | 481 | void Unserialize(Stream& s) |
216e9a44 PW |
482 | { |
483 | size_t size = ReadCompactSize(s); | |
484 | if (size > Limit) { | |
485 | throw std::ios_base::failure("String length limit exceeded"); | |
486 | } | |
487 | string.resize(size); | |
488 | if (size != 0) | |
489 | s.read((char*)&string[0], size); | |
490 | } | |
491 | ||
492 | template<typename Stream> | |
242f1421 | 493 | void Serialize(Stream& s) const |
216e9a44 PW |
494 | { |
495 | WriteCompactSize(s, string.size()); | |
496 | if (!string.empty()) | |
497 | s.write((char*)&string[0], string.size()); | |
498 | } | |
216e9a44 PW |
499 | }; |
500 | ||
4d6144f9 PW |
501 | template<typename I> |
502 | CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); } | |
503 | ||
1c0aa911 MF |
504 | /** |
505 | * Forward declarations | |
506 | */ | |
0a61b0df | 507 | |
1c0aa911 MF |
508 | /** |
509 | * string | |
510 | */ | |
242f1421 PW |
511 | template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str); |
512 | template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str); | |
0a61b0df | 513 | |
29a8ade7 PW |
514 | /** |
515 | * prevector | |
516 | * prevectors of unsigned char are a special case and are intended to be serialized as a single opaque blob. | |
517 | */ | |
242f1421 PW |
518 | template<typename Stream, unsigned int N, typename T> void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&); |
519 | template<typename Stream, unsigned int N, typename T, typename V> void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&); | |
520 | template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v); | |
521 | template<typename Stream, unsigned int N, typename T> void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&); | |
522 | template<typename Stream, unsigned int N, typename T, typename V> void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&); | |
523 | template<typename Stream, unsigned int N, typename T> inline void Unserialize(Stream& is, prevector<N, T>& v); | |
29a8ade7 | 524 | |
1c0aa911 MF |
525 | /** |
526 | * vector | |
527 | * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob. | |
528 | */ | |
242f1421 PW |
529 | template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&); |
530 | template<typename Stream, typename T, typename A, typename V> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&); | |
531 | template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v); | |
532 | template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&); | |
533 | template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&); | |
534 | template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v); | |
0a61b0df | 535 | |
291b191b SB |
536 | /** |
537 | * optional | |
538 | */ | |
68a1a592 JG |
539 | template<typename Stream, typename T> void Serialize(Stream& os, const boost::optional<T>& item); |
540 | template<typename Stream, typename T> void Unserialize(Stream& is, boost::optional<T>& item); | |
291b191b | 541 | |
5884044b SB |
542 | /** |
543 | * array | |
544 | */ | |
a6bbb26e JG |
545 | template<typename Stream, typename T, std::size_t N> void Serialize(Stream& os, const std::array<T, N>& item); |
546 | template<typename Stream, typename T, std::size_t N> void Unserialize(Stream& is, std::array<T, N>& item); | |
5884044b | 547 | |
1c0aa911 MF |
548 | /** |
549 | * pair | |
550 | */ | |
242f1421 PW |
551 | template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item); |
552 | template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item); | |
0a61b0df | 553 | |
1c0aa911 MF |
554 | /** |
555 | * map | |
556 | */ | |
242f1421 PW |
557 | template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m); |
558 | template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m); | |
0a61b0df | 559 | |
1c0aa911 MF |
560 | /** |
561 | * set | |
562 | */ | |
242f1421 PW |
563 | template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m); |
564 | template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m); | |
0a61b0df | 565 | |
be74c80d JG |
566 | /** |
567 | * list | |
568 | */ | |
68a1a592 JG |
569 | template<typename Stream, typename T, typename A> void Serialize(Stream& os, const std::list<T, A>& m); |
570 | template<typename Stream, typename T, typename A> void Unserialize(Stream& is, std::list<T, A>& m); | |
be74c80d | 571 | |
40cc9aa7 PW |
572 | /** |
573 | * shared_ptr | |
574 | */ | |
575 | template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p); | |
576 | template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p); | |
0a61b0df | 577 | |
40cc9aa7 PW |
578 | /** |
579 | * unique_ptr | |
580 | */ | |
581 | template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p); | |
582 | template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p); | |
0a61b0df | 583 | |
584 | ||
585 | ||
1c0aa911 MF |
586 | /** |
587 | * If none of the specialized versions above matched, default to calling member function. | |
1c0aa911 | 588 | */ |
0a61b0df | 589 | template<typename Stream, typename T> |
242f1421 | 590 | inline void Serialize(Stream& os, const T& a) |
0a61b0df | 591 | { |
242f1421 | 592 | a.Serialize(os); |
0a61b0df | 593 | } |
594 | ||
595 | template<typename Stream, typename T> | |
242f1421 | 596 | inline void Unserialize(Stream& is, T& a) |
0a61b0df | 597 | { |
242f1421 | 598 | a.Unserialize(is); |
0a61b0df | 599 | } |
600 | ||
601 | ||
602 | ||
603 | ||
604 | ||
1c0aa911 MF |
605 | /** |
606 | * string | |
607 | */ | |
0a61b0df | 608 | template<typename Stream, typename C> |
242f1421 | 609 | void Serialize(Stream& os, const std::basic_string<C>& str) |
0a61b0df | 610 | { |
611 | WriteCompactSize(os, str.size()); | |
612 | if (!str.empty()) | |
613 | os.write((char*)&str[0], str.size() * sizeof(str[0])); | |
614 | } | |
615 | ||
616 | template<typename Stream, typename C> | |
242f1421 | 617 | void Unserialize(Stream& is, std::basic_string<C>& str) |
0a61b0df | 618 | { |
619 | unsigned int nSize = ReadCompactSize(is); | |
620 | str.resize(nSize); | |
621 | if (nSize != 0) | |
622 | is.read((char*)&str[0], nSize * sizeof(str[0])); | |
623 | } | |
624 | ||
625 | ||
626 | ||
29a8ade7 PW |
627 | /** |
628 | * prevector | |
629 | */ | |
29a8ade7 | 630 | template<typename Stream, unsigned int N, typename T> |
242f1421 | 631 | void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&) |
29a8ade7 PW |
632 | { |
633 | WriteCompactSize(os, v.size()); | |
634 | if (!v.empty()) | |
635 | os.write((char*)&v[0], v.size() * sizeof(T)); | |
636 | } | |
637 | ||
638 | template<typename Stream, unsigned int N, typename T, typename V> | |
242f1421 | 639 | void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&) |
29a8ade7 PW |
640 | { |
641 | WriteCompactSize(os, v.size()); | |
642 | for (typename prevector<N, T>::const_iterator vi = v.begin(); vi != v.end(); ++vi) | |
242f1421 | 643 | ::Serialize(os, (*vi)); |
29a8ade7 PW |
644 | } |
645 | ||
646 | template<typename Stream, unsigned int N, typename T> | |
242f1421 | 647 | inline void Serialize(Stream& os, const prevector<N, T>& v) |
29a8ade7 | 648 | { |
242f1421 | 649 | Serialize_impl(os, v, T()); |
29a8ade7 PW |
650 | } |
651 | ||
652 | ||
653 | template<typename Stream, unsigned int N, typename T> | |
242f1421 | 654 | void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&) |
29a8ade7 PW |
655 | { |
656 | // Limit size per read so bogus size value won't cause out of memory | |
657 | v.clear(); | |
658 | unsigned int nSize = ReadCompactSize(is); | |
659 | unsigned int i = 0; | |
660 | while (i < nSize) | |
661 | { | |
662 | unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T))); | |
663 | v.resize(i + blk); | |
664 | is.read((char*)&v[i], blk * sizeof(T)); | |
665 | i += blk; | |
666 | } | |
667 | } | |
668 | ||
669 | template<typename Stream, unsigned int N, typename T, typename V> | |
242f1421 | 670 | void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&) |
29a8ade7 PW |
671 | { |
672 | v.clear(); | |
673 | unsigned int nSize = ReadCompactSize(is); | |
674 | unsigned int i = 0; | |
675 | unsigned int nMid = 0; | |
676 | while (nMid < nSize) | |
677 | { | |
678 | nMid += 5000000 / sizeof(T); | |
679 | if (nMid > nSize) | |
680 | nMid = nSize; | |
681 | v.resize(nMid); | |
682 | for (; i < nMid; i++) | |
242f1421 | 683 | Unserialize(is, v[i]); |
29a8ade7 PW |
684 | } |
685 | } | |
686 | ||
687 | template<typename Stream, unsigned int N, typename T> | |
242f1421 | 688 | inline void Unserialize(Stream& is, prevector<N, T>& v) |
29a8ade7 | 689 | { |
242f1421 | 690 | Unserialize_impl(is, v, T()); |
29a8ade7 PW |
691 | } |
692 | ||
693 | ||
694 | ||
1c0aa911 MF |
695 | /** |
696 | * vector | |
697 | */ | |
0a61b0df | 698 | template<typename Stream, typename T, typename A> |
242f1421 | 699 | void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&) |
0a61b0df | 700 | { |
701 | WriteCompactSize(os, v.size()); | |
702 | if (!v.empty()) | |
703 | os.write((char*)&v[0], v.size() * sizeof(T)); | |
704 | } | |
705 | ||
1d9b86d5 | 706 | template<typename Stream, typename T, typename A, typename V> |
242f1421 | 707 | void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&) |
0a61b0df | 708 | { |
709 | WriteCompactSize(os, v.size()); | |
710 | for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi) | |
242f1421 | 711 | ::Serialize(os, (*vi)); |
0a61b0df | 712 | } |
713 | ||
714 | template<typename Stream, typename T, typename A> | |
242f1421 | 715 | inline void Serialize(Stream& os, const std::vector<T, A>& v) |
0a61b0df | 716 | { |
242f1421 | 717 | Serialize_impl(os, v, T()); |
0a61b0df | 718 | } |
719 | ||
720 | ||
721 | template<typename Stream, typename T, typename A> | |
242f1421 | 722 | void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&) |
0a61b0df | 723 | { |
0a61b0df | 724 | // Limit size per read so bogus size value won't cause out of memory |
725 | v.clear(); | |
726 | unsigned int nSize = ReadCompactSize(is); | |
727 | unsigned int i = 0; | |
728 | while (i < nSize) | |
729 | { | |
223b6f1b | 730 | unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T))); |
0a61b0df | 731 | v.resize(i + blk); |
732 | is.read((char*)&v[i], blk * sizeof(T)); | |
733 | i += blk; | |
734 | } | |
735 | } | |
736 | ||
1d9b86d5 | 737 | template<typename Stream, typename T, typename A, typename V> |
242f1421 | 738 | void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&) |
0a61b0df | 739 | { |
0a61b0df | 740 | v.clear(); |
741 | unsigned int nSize = ReadCompactSize(is); | |
742 | unsigned int i = 0; | |
743 | unsigned int nMid = 0; | |
744 | while (nMid < nSize) | |
745 | { | |
746 | nMid += 5000000 / sizeof(T); | |
747 | if (nMid > nSize) | |
748 | nMid = nSize; | |
749 | v.resize(nMid); | |
750 | for (; i < nMid; i++) | |
242f1421 | 751 | Unserialize(is, v[i]); |
0a61b0df | 752 | } |
753 | } | |
754 | ||
755 | template<typename Stream, typename T, typename A> | |
242f1421 | 756 | inline void Unserialize(Stream& is, std::vector<T, A>& v) |
0a61b0df | 757 | { |
242f1421 | 758 | Unserialize_impl(is, v, T()); |
0a61b0df | 759 | } |
760 | ||
761 | ||
762 | ||
291b191b SB |
763 | /** |
764 | * optional | |
765 | */ | |
291b191b | 766 | template<typename Stream, typename T> |
68a1a592 | 767 | void Serialize(Stream& os, const boost::optional<T>& item) |
291b191b SB |
768 | { |
769 | // If the value is there, put 0x01 and then serialize the value. | |
770 | // If it's not, put 0x00. | |
771 | if (item) { | |
772 | unsigned char discriminant = 0x01; | |
68a1a592 JG |
773 | Serialize(os, discriminant); |
774 | Serialize(os, *item); | |
291b191b SB |
775 | } else { |
776 | unsigned char discriminant = 0x00; | |
68a1a592 | 777 | Serialize(os, discriminant); |
291b191b SB |
778 | } |
779 | } | |
780 | ||
781 | template<typename Stream, typename T> | |
68a1a592 | 782 | void Unserialize(Stream& is, boost::optional<T>& item) |
291b191b SB |
783 | { |
784 | unsigned char discriminant = 0x00; | |
68a1a592 | 785 | Unserialize(is, discriminant); |
291b191b SB |
786 | |
787 | if (discriminant == 0x00) { | |
788 | item = boost::none; | |
e1ff849d | 789 | } else if (discriminant == 0x01) { |
291b191b | 790 | T object; |
68a1a592 | 791 | Unserialize(is, object); |
291b191b | 792 | item = object; |
e1ff849d SB |
793 | } else { |
794 | throw std::ios_base::failure("non-canonical optional discriminant"); | |
291b191b SB |
795 | } |
796 | } | |
797 | ||
798 | ||
799 | ||
5884044b SB |
800 | /** |
801 | * array | |
802 | */ | |
5884044b | 803 | template<typename Stream, typename T, std::size_t N> |
a6bbb26e | 804 | void Serialize(Stream& os, const std::array<T, N>& item) |
5884044b SB |
805 | { |
806 | for (size_t i = 0; i < N; i++) { | |
68a1a592 | 807 | Serialize(os, item[i]); |
5884044b SB |
808 | } |
809 | } | |
810 | ||
811 | template<typename Stream, typename T, std::size_t N> | |
a6bbb26e | 812 | void Unserialize(Stream& is, std::array<T, N>& item) |
5884044b SB |
813 | { |
814 | for (size_t i = 0; i < N; i++) { | |
68a1a592 | 815 | Unserialize(is, item[i]); |
5884044b SB |
816 | } |
817 | } | |
818 | ||
0a61b0df | 819 | |
1c0aa911 MF |
820 | /** |
821 | * pair | |
822 | */ | |
0a61b0df | 823 | template<typename Stream, typename K, typename T> |
242f1421 | 824 | void Serialize(Stream& os, const std::pair<K, T>& item) |
0a61b0df | 825 | { |
242f1421 PW |
826 | Serialize(os, item.first); |
827 | Serialize(os, item.second); | |
0a61b0df | 828 | } |
829 | ||
830 | template<typename Stream, typename K, typename T> | |
242f1421 | 831 | void Unserialize(Stream& is, std::pair<K, T>& item) |
0a61b0df | 832 | { |
242f1421 PW |
833 | Unserialize(is, item.first); |
834 | Unserialize(is, item.second); | |
0a61b0df | 835 | } |
836 | ||
837 | ||
838 | ||
1c0aa911 MF |
839 | /** |
840 | * map | |
841 | */ | |
0a61b0df | 842 | template<typename Stream, typename K, typename T, typename Pred, typename A> |
242f1421 | 843 | void Serialize(Stream& os, const std::map<K, T, Pred, A>& m) |
0a61b0df | 844 | { |
845 | WriteCompactSize(os, m.size()); | |
846 | for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi) | |
242f1421 | 847 | Serialize(os, (*mi)); |
0a61b0df | 848 | } |
849 | ||
850 | template<typename Stream, typename K, typename T, typename Pred, typename A> | |
242f1421 | 851 | void Unserialize(Stream& is, std::map<K, T, Pred, A>& m) |
0a61b0df | 852 | { |
853 | m.clear(); | |
854 | unsigned int nSize = ReadCompactSize(is); | |
855 | typename std::map<K, T, Pred, A>::iterator mi = m.begin(); | |
856 | for (unsigned int i = 0; i < nSize; i++) | |
857 | { | |
223b6f1b | 858 | std::pair<K, T> item; |
242f1421 | 859 | Unserialize(is, item); |
0a61b0df | 860 | mi = m.insert(mi, item); |
861 | } | |
862 | } | |
863 | ||
864 | ||
865 | ||
1c0aa911 MF |
866 | /** |
867 | * set | |
868 | */ | |
0a61b0df | 869 | template<typename Stream, typename K, typename Pred, typename A> |
242f1421 | 870 | void Serialize(Stream& os, const std::set<K, Pred, A>& m) |
0a61b0df | 871 | { |
872 | WriteCompactSize(os, m.size()); | |
873 | for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it) | |
242f1421 | 874 | Serialize(os, (*it)); |
0a61b0df | 875 | } |
876 | ||
877 | template<typename Stream, typename K, typename Pred, typename A> | |
242f1421 | 878 | void Unserialize(Stream& is, std::set<K, Pred, A>& m) |
0a61b0df | 879 | { |
880 | m.clear(); | |
881 | unsigned int nSize = ReadCompactSize(is); | |
882 | typename std::set<K, Pred, A>::iterator it = m.begin(); | |
883 | for (unsigned int i = 0; i < nSize; i++) | |
884 | { | |
885 | K key; | |
242f1421 | 886 | Unserialize(is, key); |
0a61b0df | 887 | it = m.insert(it, key); |
888 | } | |
889 | } | |
890 | ||
891 | ||
892 | ||
be74c80d JG |
893 | /** |
894 | * list | |
895 | */ | |
be74c80d | 896 | template<typename Stream, typename T, typename A> |
68a1a592 | 897 | void Serialize(Stream& os, const std::list<T, A>& l) |
be74c80d JG |
898 | { |
899 | WriteCompactSize(os, l.size()); | |
900 | for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it) | |
68a1a592 | 901 | Serialize(os, (*it)); |
be74c80d JG |
902 | } |
903 | ||
904 | template<typename Stream, typename T, typename A> | |
68a1a592 | 905 | void Unserialize(Stream& is, std::list<T, A>& l) |
be74c80d JG |
906 | { |
907 | l.clear(); | |
908 | unsigned int nSize = ReadCompactSize(is); | |
909 | typename std::list<T, A>::iterator it = l.begin(); | |
910 | for (unsigned int i = 0; i < nSize; i++) | |
911 | { | |
912 | T item; | |
68a1a592 | 913 | Unserialize(is, item); |
be74c80d JG |
914 | l.push_back(item); |
915 | } | |
916 | } | |
917 | ||
918 | ||
919 | ||
40cc9aa7 PW |
920 | /** |
921 | * unique_ptr | |
922 | */ | |
923 | template<typename Stream, typename T> void | |
924 | Serialize(Stream& os, const std::unique_ptr<const T>& p) | |
925 | { | |
926 | Serialize(os, *p); | |
927 | } | |
928 | ||
929 | template<typename Stream, typename T> | |
930 | void Unserialize(Stream& is, std::unique_ptr<const T>& p) | |
931 | { | |
932 | p.reset(new T(deserialize, is)); | |
933 | } | |
934 | ||
935 | ||
936 | ||
937 | /** | |
938 | * shared_ptr | |
939 | */ | |
940 | template<typename Stream, typename T> void | |
941 | Serialize(Stream& os, const std::shared_ptr<const T>& p) | |
942 | { | |
943 | Serialize(os, *p); | |
944 | } | |
945 | ||
946 | template<typename Stream, typename T> | |
947 | void Unserialize(Stream& is, std::shared_ptr<const T>& p) | |
948 | { | |
949 | p = std::make_shared<const T>(deserialize, is); | |
950 | } | |
951 | ||
952 | ||
953 | ||
1c0aa911 MF |
954 | /** |
955 | * Support for ADD_SERIALIZE_METHODS and READWRITE macro | |
956 | */ | |
31e9a838 | 957 | struct CSerActionSerialize |
0a61b0df | 958 | { |
93aaf4fc | 959 | constexpr bool ForRead() const { return false; } |
31e9a838 PW |
960 | }; |
961 | struct CSerActionUnserialize | |
962 | { | |
93aaf4fc | 963 | constexpr bool ForRead() const { return true; } |
31e9a838 | 964 | }; |
0a61b0df | 965 | |
966 | template<typename Stream, typename T> | |
242f1421 | 967 | inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action) |
0a61b0df | 968 | { |
242f1421 | 969 | ::Serialize(s, obj); |
0a61b0df | 970 | } |
971 | ||
972 | template<typename Stream, typename T> | |
242f1421 | 973 | inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action) |
0a61b0df | 974 | { |
242f1421 | 975 | ::Unserialize(s, obj); |
0a61b0df | 976 | } |
977 | ||
0a61b0df | 978 | |
979 | ||
980 | ||
981 | ||
982 | ||
983 | ||
f7a9a113 MC |
984 | |
985 | ||
09891705 PW |
986 | /* ::GetSerializeSize implementations |
987 | * | |
988 | * Computing the serialized size of objects is done through a special stream | |
989 | * object of type CSizeComputer, which only records the number of bytes written | |
990 | * to it. | |
991 | * | |
992 | * If your Serialize or SerializationOp method has non-trivial overhead for | |
993 | * serialization, it may be worthwhile to implement a specialized version for | |
994 | * CSizeComputer, which uses the s.seek() method to record bytes that would | |
995 | * be written instead. | |
996 | */ | |
b069750d PW |
997 | class CSizeComputer |
998 | { | |
999 | protected: | |
1000 | size_t nSize; | |
1001 | ||
7f4acac4 PW |
1002 | const int nType; |
1003 | const int nVersion; | |
b069750d | 1004 | public: |
b069750d PW |
1005 | CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {} |
1006 | ||
9b228f03 | 1007 | void write(const char *psz, size_t _nSize) |
b069750d | 1008 | { |
9b228f03 | 1009 | this->nSize += _nSize; |
b069750d PW |
1010 | } |
1011 | ||
09891705 PW |
1012 | /** Pretend _nSize bytes are written, without specifying them. */ |
1013 | void seek(size_t _nSize) | |
1014 | { | |
1015 | this->nSize += _nSize; | |
1016 | } | |
1017 | ||
b069750d PW |
1018 | template<typename T> |
1019 | CSizeComputer& operator<<(const T& obj) | |
1020 | { | |
242f1421 | 1021 | ::Serialize(*this, obj); |
b069750d PW |
1022 | return (*this); |
1023 | } | |
1024 | ||
1025 | size_t size() const { | |
1026 | return nSize; | |
1027 | } | |
242f1421 PW |
1028 | |
1029 | int GetVersion() const { return nVersion; } | |
1030 | int GetType() const { return nType; } | |
b069750d PW |
1031 | }; |
1032 | ||
d1c9ef86 | 1033 | template<typename Stream> |
242f1421 | 1034 | void SerializeMany(Stream& s) |
d1c9ef86 CF |
1035 | { |
1036 | } | |
1037 | ||
1038 | template<typename Stream, typename Arg> | |
242f1421 | 1039 | void SerializeMany(Stream& s, Arg&& arg) |
d1c9ef86 | 1040 | { |
242f1421 | 1041 | ::Serialize(s, std::forward<Arg>(arg)); |
d1c9ef86 CF |
1042 | } |
1043 | ||
1044 | template<typename Stream, typename Arg, typename... Args> | |
242f1421 | 1045 | void SerializeMany(Stream& s, Arg&& arg, Args&&... args) |
d1c9ef86 | 1046 | { |
242f1421 PW |
1047 | ::Serialize(s, std::forward<Arg>(arg)); |
1048 | ::SerializeMany(s, std::forward<Args>(args)...); | |
d1c9ef86 CF |
1049 | } |
1050 | ||
1051 | template<typename Stream> | |
242f1421 | 1052 | inline void UnserializeMany(Stream& s) |
d1c9ef86 CF |
1053 | { |
1054 | } | |
1055 | ||
1056 | template<typename Stream, typename Arg> | |
242f1421 | 1057 | inline void UnserializeMany(Stream& s, Arg& arg) |
d1c9ef86 | 1058 | { |
242f1421 | 1059 | ::Unserialize(s, arg); |
d1c9ef86 CF |
1060 | } |
1061 | ||
1062 | template<typename Stream, typename Arg, typename... Args> | |
242f1421 | 1063 | inline void UnserializeMany(Stream& s, Arg& arg, Args&... args) |
d1c9ef86 | 1064 | { |
242f1421 PW |
1065 | ::Unserialize(s, arg); |
1066 | ::UnserializeMany(s, args...); | |
d1c9ef86 CF |
1067 | } |
1068 | ||
1069 | template<typename Stream, typename... Args> | |
242f1421 | 1070 | inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args) |
d1c9ef86 | 1071 | { |
242f1421 | 1072 | ::SerializeMany(s, std::forward<Args>(args)...); |
d1c9ef86 CF |
1073 | } |
1074 | ||
1075 | template<typename Stream, typename... Args> | |
242f1421 | 1076 | inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args) |
d1c9ef86 | 1077 | { |
242f1421 | 1078 | ::UnserializeMany(s, args...); |
d1c9ef86 CF |
1079 | } |
1080 | ||
09891705 PW |
1081 | template<typename I> |
1082 | inline void WriteVarInt(CSizeComputer &s, I n) | |
1083 | { | |
1084 | s.seek(GetSizeOfVarInt<I>(n)); | |
1085 | } | |
1086 | ||
1087 | inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize) | |
1088 | { | |
1089 | s.seek(GetSizeOfCompactSize(nSize)); | |
1090 | } | |
1091 | ||
b8a65793 PW |
1092 | template <typename T> |
1093 | size_t GetSerializeSize(const T& t, int nType, int nVersion = 0) | |
1094 | { | |
1095 | return (CSizeComputer(nType, nVersion) << t).size(); | |
1096 | } | |
1097 | ||
1098 | template <typename S, typename T> | |
1099 | size_t GetSerializeSize(const S& s, const T& t) | |
1100 | { | |
1101 | return (CSizeComputer(s.GetType(), s.GetVersion()) << t).size(); | |
1102 | } | |
1103 | ||
093303a8 | 1104 | #endif // BITCOIN_SERIALIZE_H |