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