]> Git Repo - VerusCoin.git/blame - src/serialize.h
Replace http with https: in links to the MIT license.
[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}
108template<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
113template<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
118template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
119{
120 obj = htole64(obj);
121 s.write((char*)&obj, 8);
122}
123template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
124{
125 uint8_t obj;
126 s.read((char*)&obj, 1);
127 return obj;
128}
129template<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}
135template<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
141template<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
147template<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}
153inline 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}
159inline 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}
165inline 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}
171inline 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
185class CSizeComputer;
186
0a61b0df 187enum
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
214template<typename Stream> inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char
215template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
216template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
217template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
218template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
219template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
220template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
221template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
222template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
223template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
224template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
01f9c344 225
242f1421
PW
226template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
227template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
228template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
229template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
230template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
231template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
232template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
233template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
234template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
235template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
236template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
0a61b0df 237
242f1421
PW
238template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
239template<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 253inline 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
261inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
262
0a61b0df 263template<typename Stream>
51ed9ec9 264void 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
287template<typename Stream>
51ed9ec9 288uint64_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
343template<typename I>
344inline 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
356template<typename I>
357inline void WriteVarInt(CSizeComputer& os, I n);
358
4d6144f9
PW
359template<typename Stream, typename I>
360void 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
376template<typename Stream, typename I>
377I 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 398class CFlatData
399{
400protected:
401 char* pbegin;
402 char* pend;
403public:
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
435template<typename I>
436class CVarInt
437{
438protected:
439 I &n;
440public:
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
454class CCompactSize
455{
456protected:
457 uint64_t &n;
458public:
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
472template<size_t Limit>
473class LimitedString
474{
475protected:
476 std::string& string;
477public:
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
501template<typename I>
502CVarInt<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
511template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str);
512template<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
518template<typename Stream, unsigned int N, typename T> void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&);
519template<typename Stream, unsigned int N, typename T, typename V> void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&);
520template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v);
521template<typename Stream, unsigned int N, typename T> void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&);
522template<typename Stream, unsigned int N, typename T, typename V> void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&);
523template<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
529template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&);
530template<typename Stream, typename T, typename A, typename V> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&);
531template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
532template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&);
533template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&);
534template<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
539template<typename Stream, typename T> void Serialize(Stream& os, const boost::optional<T>& item);
540template<typename Stream, typename T> void Unserialize(Stream& is, boost::optional<T>& item);
291b191b 541
5884044b
SB
542/**
543 * array
544 */
a6bbb26e
JG
545template<typename Stream, typename T, std::size_t N> void Serialize(Stream& os, const std::array<T, N>& item);
546template<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
551template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item);
552template<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
557template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m);
558template<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
563template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
564template<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
569template<typename Stream, typename T, typename A> void Serialize(Stream& os, const std::list<T, A>& m);
570template<typename Stream, typename T, typename A> void Unserialize(Stream& is, std::list<T, A>& m);
be74c80d 571
40cc9aa7
PW
572/**
573 * shared_ptr
574 */
575template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p);
576template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p);
0a61b0df 577
40cc9aa7
PW
578/**
579 * unique_ptr
580 */
581template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
582template<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 589template<typename Stream, typename T>
242f1421 590inline void Serialize(Stream& os, const T& a)
0a61b0df 591{
242f1421 592 a.Serialize(os);
0a61b0df 593}
594
595template<typename Stream, typename T>
242f1421 596inline 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 608template<typename Stream, typename C>
242f1421 609void 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
616template<typename Stream, typename C>
242f1421 617void 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 630template<typename Stream, unsigned int N, typename T>
242f1421 631void 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
638template<typename Stream, unsigned int N, typename T, typename V>
242f1421 639void 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
646template<typename Stream, unsigned int N, typename T>
242f1421 647inline void Serialize(Stream& os, const prevector<N, T>& v)
29a8ade7 648{
242f1421 649 Serialize_impl(os, v, T());
29a8ade7
PW
650}
651
652
653template<typename Stream, unsigned int N, typename T>
242f1421 654void 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
669template<typename Stream, unsigned int N, typename T, typename V>
242f1421 670void 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
687template<typename Stream, unsigned int N, typename T>
242f1421 688inline 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 698template<typename Stream, typename T, typename A>
242f1421 699void 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 706template<typename Stream, typename T, typename A, typename V>
242f1421 707void 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
714template<typename Stream, typename T, typename A>
242f1421 715inline void Serialize(Stream& os, const std::vector<T, A>& v)
0a61b0df 716{
242f1421 717 Serialize_impl(os, v, T());
0a61b0df 718}
719
720
721template<typename Stream, typename T, typename A>
242f1421 722void 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 737template<typename Stream, typename T, typename A, typename V>
242f1421 738void 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
755template<typename Stream, typename T, typename A>
242f1421 756inline 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 766template<typename Stream, typename T>
68a1a592 767void 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
781template<typename Stream, typename T>
68a1a592 782void 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 803template<typename Stream, typename T, std::size_t N>
a6bbb26e 804void 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
811template<typename Stream, typename T, std::size_t N>
a6bbb26e 812void 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 823template<typename Stream, typename K, typename T>
242f1421 824void 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
830template<typename Stream, typename K, typename T>
242f1421 831void 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 842template<typename Stream, typename K, typename T, typename Pred, typename A>
242f1421 843void 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
850template<typename Stream, typename K, typename T, typename Pred, typename A>
242f1421 851void 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 869template<typename Stream, typename K, typename Pred, typename A>
242f1421 870void 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
877template<typename Stream, typename K, typename Pred, typename A>
242f1421 878void 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 896template<typename Stream, typename T, typename A>
68a1a592 897void 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
904template<typename Stream, typename T, typename A>
68a1a592 905void 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 */
923template<typename Stream, typename T> void
924Serialize(Stream& os, const std::unique_ptr<const T>& p)
925{
926 Serialize(os, *p);
927}
928
929template<typename Stream, typename T>
930void 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 */
940template<typename Stream, typename T> void
941Serialize(Stream& os, const std::shared_ptr<const T>& p)
942{
943 Serialize(os, *p);
944}
945
946template<typename Stream, typename T>
947void 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 957struct CSerActionSerialize
0a61b0df 958{
93aaf4fc 959 constexpr bool ForRead() const { return false; }
31e9a838
PW
960};
961struct CSerActionUnserialize
962{
93aaf4fc 963 constexpr bool ForRead() const { return true; }
31e9a838 964};
0a61b0df 965
966template<typename Stream, typename T>
242f1421 967inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action)
0a61b0df 968{
242f1421 969 ::Serialize(s, obj);
0a61b0df 970}
971
972template<typename Stream, typename T>
242f1421 973inline 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
997class CSizeComputer
998{
999protected:
1000 size_t nSize;
1001
7f4acac4
PW
1002 const int nType;
1003 const int nVersion;
b069750d 1004public:
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 1033template<typename Stream>
242f1421 1034void SerializeMany(Stream& s)
d1c9ef86
CF
1035{
1036}
1037
1038template<typename Stream, typename Arg>
242f1421 1039void SerializeMany(Stream& s, Arg&& arg)
d1c9ef86 1040{
242f1421 1041 ::Serialize(s, std::forward<Arg>(arg));
d1c9ef86
CF
1042}
1043
1044template<typename Stream, typename Arg, typename... Args>
242f1421 1045void 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
1051template<typename Stream>
242f1421 1052inline void UnserializeMany(Stream& s)
d1c9ef86
CF
1053{
1054}
1055
1056template<typename Stream, typename Arg>
242f1421 1057inline void UnserializeMany(Stream& s, Arg& arg)
d1c9ef86 1058{
242f1421 1059 ::Unserialize(s, arg);
d1c9ef86
CF
1060}
1061
1062template<typename Stream, typename Arg, typename... Args>
242f1421 1063inline void UnserializeMany(Stream& s, Arg& arg, Args&... args)
d1c9ef86 1064{
242f1421
PW
1065 ::Unserialize(s, arg);
1066 ::UnserializeMany(s, args...);
d1c9ef86
CF
1067}
1068
1069template<typename Stream, typename... Args>
242f1421 1070inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args)
d1c9ef86 1071{
242f1421 1072 ::SerializeMany(s, std::forward<Args>(args)...);
d1c9ef86
CF
1073}
1074
1075template<typename Stream, typename... Args>
242f1421 1076inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args)
d1c9ef86 1077{
242f1421 1078 ::UnserializeMany(s, args...);
d1c9ef86
CF
1079}
1080
09891705
PW
1081template<typename I>
1082inline void WriteVarInt(CSizeComputer &s, I n)
1083{
1084 s.seek(GetSizeOfVarInt<I>(n));
1085}
1086
1087inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
1088{
1089 s.seek(GetSizeOfCompactSize(nSize));
1090}
1091
b8a65793
PW
1092template <typename T>
1093size_t GetSerializeSize(const T& t, int nType, int nVersion = 0)
1094{
1095 return (CSizeComputer(nType, nVersion) << t).size();
1096}
1097
1098template <typename S, typename T>
1099size_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
This page took 0.401825 seconds and 4 git commands to generate.