Bitcoin ABC  0.22.13
P2P Digital Currency
serialize.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef BITCOIN_SERIALIZE_H
7 #define BITCOIN_SERIALIZE_H
8 
9 #include <compat/endian.h>
10 #include <prevector.h>
11 #include <span.h>
12 
13 #include <algorithm>
14 #include <array>
15 #include <cstdint>
16 #include <cstring>
17 #include <ios>
18 #include <limits>
19 #include <map>
20 #include <memory>
21 #include <set>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 
26 static const uint64_t MAX_SIZE = 0x02000000;
27 
32 static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
33 
44 struct deserialize_type {};
46 
51 template <typename T> inline T &REF(const T &val) {
52  return const_cast<T &>(val);
53 }
54 
59 template <typename T> inline T *NCONST_PTR(const T *val) {
60  return const_cast<T *>(val);
61 }
62 
64 inline char *CharCast(char *c) {
65  return c;
66 }
67 inline char *CharCast(uint8_t *c) {
68  return (char *)c;
69 }
70 inline const char *CharCast(const char *c) {
71  return c;
72 }
73 inline const char *CharCast(const uint8_t *c) {
74  return (const char *)c;
75 }
76 
81 template <typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj) {
82  s.write((char *)&obj, 1);
83 }
84 template <typename Stream>
85 inline void ser_writedata16(Stream &s, uint16_t obj) {
86  obj = htole16(obj);
87  s.write((char *)&obj, 2);
88 }
89 template <typename Stream>
90 inline void ser_writedata16be(Stream &s, uint16_t obj) {
91  obj = htobe16(obj);
92  s.write((char *)&obj, 2);
93 }
94 template <typename Stream>
95 inline void ser_writedata32(Stream &s, uint32_t obj) {
96  obj = htole32(obj);
97  s.write((char *)&obj, 4);
98 }
99 template <typename Stream>
100 inline void ser_writedata32be(Stream &s, uint32_t obj) {
101  obj = htobe32(obj);
102  s.write((char *)&obj, 4);
103 }
104 template <typename Stream>
105 inline void ser_writedata64(Stream &s, uint64_t obj) {
106  obj = htole64(obj);
107  s.write((char *)&obj, 8);
108 }
109 template <typename Stream> inline uint8_t ser_readdata8(Stream &s) {
110  uint8_t obj;
111  s.read((char *)&obj, 1);
112  return obj;
113 }
114 template <typename Stream> inline uint16_t ser_readdata16(Stream &s) {
115  uint16_t obj;
116  s.read((char *)&obj, 2);
117  return le16toh(obj);
118 }
119 template <typename Stream> inline uint16_t ser_readdata16be(Stream &s) {
120  uint16_t obj;
121  s.read((char *)&obj, 2);
122  return be16toh(obj);
123 }
124 template <typename Stream> inline uint32_t ser_readdata32(Stream &s) {
125  uint32_t obj;
126  s.read((char *)&obj, 4);
127  return le32toh(obj);
128 }
129 template <typename Stream> inline uint32_t ser_readdata32be(Stream &s) {
130  uint32_t obj;
131  s.read((char *)&obj, 4);
132  return be32toh(obj);
133 }
134 template <typename Stream> inline uint64_t ser_readdata64(Stream &s) {
135  uint64_t obj;
136  s.read((char *)&obj, 8);
137  return le64toh(obj);
138 }
139 inline uint64_t ser_double_to_uint64(double x) {
140  uint64_t tmp;
141  std::memcpy(&tmp, &x, sizeof(x));
142  static_assert(sizeof(tmp) == sizeof(x),
143  "double and uint64_t assumed to have the same size");
144  return tmp;
145 }
146 inline uint32_t ser_float_to_uint32(float x) {
147  uint32_t tmp;
148  std::memcpy(&tmp, &x, sizeof(x));
149  static_assert(sizeof(tmp) == sizeof(x),
150  "float and uint32_t assumed to have the same size");
151  return tmp;
152 }
153 inline double ser_uint64_to_double(uint64_t y) {
154  double tmp;
155  std::memcpy(&tmp, &y, sizeof(y));
156  static_assert(sizeof(tmp) == sizeof(y),
157  "double and uint64_t assumed to have the same size");
158  return tmp;
159 }
160 inline float ser_uint32_to_float(uint32_t y) {
161  float tmp;
162  std::memcpy(&tmp, &y, sizeof(y));
163  static_assert(sizeof(tmp) == sizeof(y),
164  "float and uint32_t assumed to have the same size");
165  return tmp;
166 }
167 
169 //
170 // Templates for serializing to anything that looks like a stream,
171 // i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
172 //
173 class CSizeComputer;
174 
175 enum {
176  // primary actions
177  SER_NETWORK = (1 << 0),
178  SER_DISK = (1 << 1),
179  SER_GETHASH = (1 << 2),
180 };
181 
184 template <typename X> X &ReadWriteAsHelper(X &x) {
185  return x;
186 }
187 template <typename X> const X &ReadWriteAsHelper(const X &x) {
188  return x;
189 }
190 
191 #define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
192 #define READWRITEAS(type, obj) \
193  (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
194 
201 #define ADD_SERIALIZE_METHODS \
202  template <typename Stream> void Serialize(Stream &s) const { \
203  NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \
204  } \
205  template <typename Stream> void Unserialize(Stream &s) { \
206  SerializationOp(s, CSerActionUnserialize()); \
207  }
208 
227 #define FORMATTER_METHODS(cls, obj) \
228  template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
229  SerializationOps(obj, s, CSerActionSerialize()); \
230  } \
231  template <typename Stream> static void Unser(Stream &s, cls &obj) { \
232  SerializationOps(obj, s, CSerActionUnserialize()); \
233  } \
234  template <typename Stream, typename Type, typename Operation> \
235  static inline void SerializationOps(Type &obj, Stream &s, \
236  Operation ser_action)
237 
246 #define SERIALIZE_METHODS(cls, obj) \
247  template <typename Stream> void Serialize(Stream &s) const { \
248  static_assert(std::is_same<const cls &, decltype(*this)>::value, \
249  "Serialize type mismatch"); \
250  Ser(s, *this); \
251  } \
252  template <typename Stream> void Unserialize(Stream &s) { \
253  static_assert(std::is_same<cls &, decltype(*this)>::value, \
254  "Unserialize type mismatch"); \
255  Unser(s, *this); \
256  } \
257  FORMATTER_METHODS(cls, obj)
258 
259 #ifndef CHAR_EQUALS_INT8
260 // TODO Get rid of bare char
261 template <typename Stream> inline void Serialize(Stream &s, char a) {
262  ser_writedata8(s, a);
263 }
264 #endif
265 template <typename Stream> inline void Serialize(Stream &s, int8_t a) {
266  ser_writedata8(s, a);
267 }
268 template <typename Stream> inline void Serialize(Stream &s, uint8_t a) {
269  ser_writedata8(s, a);
270 }
271 template <typename Stream> inline void Serialize(Stream &s, int16_t a) {
272  ser_writedata16(s, a);
273 }
274 template <typename Stream> inline void Serialize(Stream &s, uint16_t a) {
275  ser_writedata16(s, a);
276 }
277 template <typename Stream> inline void Serialize(Stream &s, int32_t a) {
278  ser_writedata32(s, a);
279 }
280 template <typename Stream> inline void Serialize(Stream &s, uint32_t a) {
281  ser_writedata32(s, a);
282 }
283 template <typename Stream> inline void Serialize(Stream &s, int64_t a) {
284  ser_writedata64(s, a);
285 }
286 template <typename Stream> inline void Serialize(Stream &s, uint64_t a) {
287  ser_writedata64(s, a);
288 }
289 template <typename Stream> inline void Serialize(Stream &s, float a) {
291 }
292 template <typename Stream> inline void Serialize(Stream &s, double a) {
294 }
295 template <typename Stream, size_t N>
296 inline void Serialize(Stream &s, const int8_t (&a)[N]) {
297  s.write(a, N);
298 }
299 template <typename Stream, size_t N>
300 inline void Serialize(Stream &s, const uint8_t (&a)[N]) {
301  s.write(CharCast(a), N);
302 }
303 template <typename Stream, size_t N>
304 inline void Serialize(Stream &s, const std::array<int8_t, N> &a) {
305  s.write(a.data(), N);
306 }
307 template <typename Stream, size_t N>
308 inline void Serialize(Stream &s, const std::array<uint8_t, N> &a) {
309  s.write(CharCast(a.data()), N);
310 }
311 #ifndef CHAR_EQUALS_INT8
312 // TODO Get rid of bare char
313 template <typename Stream> inline void Unserialize(Stream &s, char &a) {
314  a = ser_readdata8(s);
315 }
316 template <typename Stream, size_t N>
317 inline void Serialize(Stream &s, const char (&a)[N]) {
318  s.write(a, N);
319 }
320 template <typename Stream, size_t N>
321 inline void Serialize(Stream &s, const std::array<char, N> &a) {
322  s.write(a.data(), N);
323 }
324 #endif
325 template <typename Stream>
326 inline void Serialize(Stream &s, const Span<const uint8_t> &span) {
327  s.write(CharCast(span.data()), span.size());
328 }
329 template <typename Stream>
330 inline void Serialize(Stream &s, const Span<uint8_t> &span) {
331  s.write(CharCast(span.data()), span.size());
332 }
333 template <typename Stream> inline void Unserialize(Stream &s, int8_t &a) {
334  a = ser_readdata8(s);
335 }
336 template <typename Stream> inline void Unserialize(Stream &s, uint8_t &a) {
337  a = ser_readdata8(s);
338 }
339 template <typename Stream> inline void Unserialize(Stream &s, int16_t &a) {
340  a = ser_readdata16(s);
341 }
342 template <typename Stream> inline void Unserialize(Stream &s, uint16_t &a) {
343  a = ser_readdata16(s);
344 }
345 template <typename Stream> inline void Unserialize(Stream &s, int32_t &a) {
346  a = ser_readdata32(s);
347 }
348 template <typename Stream> inline void Unserialize(Stream &s, uint32_t &a) {
349  a = ser_readdata32(s);
350 }
351 template <typename Stream> inline void Unserialize(Stream &s, int64_t &a) {
352  a = ser_readdata64(s);
353 }
354 template <typename Stream> inline void Unserialize(Stream &s, uint64_t &a) {
355  a = ser_readdata64(s);
356 }
357 template <typename Stream> inline void Unserialize(Stream &s, float &a) {
359 }
360 template <typename Stream> inline void Unserialize(Stream &s, double &a) {
362 }
363 template <typename Stream, size_t N>
364 inline void Unserialize(Stream &s, int8_t (&a)[N]) {
365  s.read(a, N);
366 }
367 template <typename Stream, size_t N>
368 inline void Unserialize(Stream &s, uint8_t (&a)[N]) {
369  s.read(CharCast(a), N);
370 }
371 template <typename Stream, size_t N>
372 inline void Unserialize(Stream &s, std::array<int8_t, N> &a) {
373  s.read(a.data(), N);
374 }
375 template <typename Stream, size_t N>
376 inline void Unserialize(Stream &s, std::array<uint8_t, N> &a) {
377  s.read(CharCast(a.data()), N);
378 }
379 #ifndef CHAR_EQUALS_INT8
380 template <typename Stream, size_t N>
381 inline void Unserialize(Stream &s, char (&a)[N]) {
382  s.read(CharCast(a), N);
383 }
384 template <typename Stream, size_t N>
385 inline void Unserialize(Stream &s, std::array<char, N> &a) {
386  s.read(CharCast(a.data()), N);
387 }
388 #endif
389 
390 template <typename Stream> inline void Serialize(Stream &s, bool a) {
391  char f = a;
392  ser_writedata8(s, f);
393 }
394 template <typename Stream> inline void Unserialize(Stream &s, bool &a) {
395  char f = ser_readdata8(s);
396  a = f;
397 }
398 template <typename Stream>
399 inline void Unserialize(Stream &s, Span<uint8_t> &span) {
400  s.read(CharCast(span.data()), span.size());
401 }
402 
410 inline uint32_t GetSizeOfCompactSize(uint64_t nSize) {
411  if (nSize < 253) {
412  return sizeof(uint8_t);
413  }
414  if (nSize <= std::numeric_limits<uint16_t>::max()) {
415  return sizeof(uint8_t) + sizeof(uint16_t);
416  }
417  if (nSize <= std::numeric_limits<uint32_t>::max()) {
418  return sizeof(uint8_t) + sizeof(uint32_t);
419  }
420 
421  return sizeof(uint8_t) + sizeof(uint64_t);
422 }
423 
424 inline void WriteCompactSize(CSizeComputer &os, uint64_t nSize);
425 
426 template <typename Stream> void WriteCompactSize(Stream &os, uint64_t nSize) {
427  if (nSize < 253) {
428  ser_writedata8(os, nSize);
429  } else if (nSize <= std::numeric_limits<uint16_t>::max()) {
430  ser_writedata8(os, 253);
431  ser_writedata16(os, nSize);
432  } else if (nSize <= std::numeric_limits<uint32_t>::max()) {
433  ser_writedata8(os, 254);
434  ser_writedata32(os, nSize);
435  } else {
436  ser_writedata8(os, 255);
437  ser_writedata64(os, nSize);
438  }
439  return;
440 }
441 
442 template <typename Stream> uint64_t ReadCompactSize(Stream &is) {
443  uint8_t chSize = ser_readdata8(is);
444  uint64_t nSizeRet = 0;
445  if (chSize < 253) {
446  nSizeRet = chSize;
447  } else if (chSize == 253) {
448  nSizeRet = ser_readdata16(is);
449  if (nSizeRet < 253) {
450  throw std::ios_base::failure("non-canonical ReadCompactSize()");
451  }
452  } else if (chSize == 254) {
453  nSizeRet = ser_readdata32(is);
454  if (nSizeRet < 0x10000u) {
455  throw std::ios_base::failure("non-canonical ReadCompactSize()");
456  }
457  } else {
458  nSizeRet = ser_readdata64(is);
459  if (nSizeRet < 0x100000000ULL) {
460  throw std::ios_base::failure("non-canonical ReadCompactSize()");
461  }
462  }
463  if (nSizeRet > MAX_SIZE) {
464  throw std::ios_base::failure("ReadCompactSize(): size too large");
465  }
466  return nSizeRet;
467 }
468 
504 
505 template <VarIntMode Mode, typename I> struct CheckVarIntMode {
506  constexpr CheckVarIntMode() {
507  static_assert(Mode != VarIntMode::DEFAULT || std::is_unsigned<I>::value,
508  "Unsigned type required with mode DEFAULT.");
509  static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED ||
510  std::is_signed<I>::value,
511  "Signed type required with mode NONNEGATIVE_SIGNED.");
512  }
513 };
514 
515 template <VarIntMode Mode, typename I>
516 inline unsigned int GetSizeOfVarInt(I n) {
518  int nRet = 0;
519  while (true) {
520  nRet++;
521  if (n <= 0x7F) {
522  return nRet;
523  }
524  n = (n >> 7) - 1;
525  }
526 }
527 
528 template <typename I> inline void WriteVarInt(CSizeComputer &os, I n);
529 
530 template <typename Stream, VarIntMode Mode, typename I>
531 void WriteVarInt(Stream &os, I n) {
533  uint8_t tmp[(sizeof(n) * 8 + 6) / 7];
534  int len = 0;
535  while (true) {
536  tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
537  if (n <= 0x7F) {
538  break;
539  }
540  n = (n >> 7) - 1;
541  len++;
542  }
543  do {
544  ser_writedata8(os, tmp[len]);
545  } while (len--);
546 }
547 
548 template <typename Stream, VarIntMode Mode, typename I>
549 I ReadVarInt(Stream &is) {
551  I n = 0;
552  while (true) {
553  uint8_t chData = ser_readdata8(is);
554  if (n > (std::numeric_limits<I>::max() >> 7)) {
555  throw std::ios_base::failure("ReadVarInt(): size too large");
556  }
557  n = (n << 7) | (chData & 0x7F);
558  if ((chData & 0x80) == 0) {
559  return n;
560  }
561  if (n == std::numeric_limits<I>::max()) {
562  throw std::ios_base::failure("ReadVarInt(): size too large");
563  }
564  n++;
565  }
566 }
567 
572 template <typename Formatter, typename T> class Wrapper {
573  static_assert(std::is_lvalue_reference<T>::value,
574  "Wrapper needs an lvalue reference type T");
575 
576 protected:
577  T m_object;
578 
579 public:
580  explicit Wrapper(T obj) : m_object(obj) {}
581  template <typename Stream> void Serialize(Stream &s) const {
582  Formatter().Ser(s, m_object);
583  }
584  template <typename Stream> void Unserialize(Stream &s) {
585  Formatter().Unser(s, m_object);
586  }
587 };
588 
602 template <typename Formatter, typename T>
603 static inline Wrapper<Formatter, T &> Using(T &&t) {
604  return Wrapper<Formatter, T &>(t);
605 }
606 
607 #define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
608 #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
609 #define COMPACTSIZE(obj) Using<CompactSizeFormatter>(obj)
610 #define LIMITED_STRING(obj, n) LimitedString<n>(REF(obj))
611 
615 template <VarIntMode Mode> struct VarIntFormatter {
616  template <typename Stream, typename I> void Ser(Stream &s, I v) {
617  WriteVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s, v);
618  }
619 
620  template <typename Stream, typename I> void Unser(Stream &s, I &v) {
621  v = ReadVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s);
622  }
623 };
624 
625 template <int Bytes> struct CustomUintFormatter {
626  static_assert(Bytes > 0 && Bytes <= 8,
627  "CustomUintFormatter Bytes out of range");
628  static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
629 
630  template <typename Stream, typename I> void Ser(Stream &s, I v) {
631  if (v < 0 || v > MAX) {
632  throw std::ios_base::failure(
633  "CustomUintFormatter value out of range");
634  }
635  uint64_t raw = htole64(v);
636  s.write((const char *)&raw, Bytes);
637  }
638 
639  template <typename Stream, typename I> void Unser(Stream &s, I &v) {
640  static_assert(std::numeric_limits<I>::max() >= MAX &&
641  std::numeric_limits<I>::min() <= 0,
642  "CustomUintFormatter type too small");
643  uint64_t raw = 0;
644  s.read((char *)&raw, Bytes);
645  v = le64toh(raw);
646  }
647 };
648 
658 template <typename I> class BigEndian {
659 protected:
660  I &m_val;
661 
662 public:
663  explicit BigEndian(I &val) : m_val(val) {
664  static_assert(std::is_unsigned<I>::value,
665  "BigEndian type must be unsigned integer");
666  static_assert(sizeof(I) == 2 && std::numeric_limits<I>::min() == 0 &&
667  std::numeric_limits<I>::max() ==
668  std::numeric_limits<uint16_t>::max(),
669  "Unsupported BigEndian size");
670  }
671 
672  template <typename Stream> void Serialize(Stream &s) const {
673  ser_writedata16be(s, m_val);
674  }
675 
676  template <typename Stream> void Unserialize(Stream &s) {
677  m_val = ser_readdata16be(s);
678  }
679 };
680 
683  template <typename Stream, typename I> void Unser(Stream &s, I &v) {
684  uint64_t n = ReadCompactSize<Stream>(s);
685  if (n < std::numeric_limits<I>::min() ||
686  n > std::numeric_limits<I>::max()) {
687  throw std::ios_base::failure("CompactSize exceeds limit of type");
688  }
689  v = n;
690  }
691 
692  template <typename Stream, typename I> void Ser(Stream &s, I v) {
693  static_assert(std::is_unsigned<I>::value,
694  "CompactSize only supported for unsigned integers");
695  static_assert(std::numeric_limits<I>::max() <=
696  std::numeric_limits<uint64_t>::max(),
697  "CompactSize only supports 64-bit integers and below");
698 
699  WriteCompactSize<Stream>(s, v);
700  }
701 };
702 
703 template <size_t Limit> class LimitedString {
704 protected:
705  std::string &string;
706 
707 public:
708  explicit LimitedString(std::string &_string) : string(_string) {}
709 
710  template <typename Stream> void Unserialize(Stream &s) {
711  size_t size = ReadCompactSize(s);
712  if (size > Limit) {
713  throw std::ios_base::failure("String length limit exceeded");
714  }
715  string.resize(size);
716  if (size != 0) {
717  s.read((char *)string.data(), size);
718  }
719  }
720 
721  template <typename Stream> void Serialize(Stream &s) const {
722  WriteCompactSize(s, string.size());
723  if (!string.empty()) {
724  s.write((char *)string.data(), string.size());
725  }
726  }
727 };
728 
729 template <typename I> BigEndian<I> WrapBigEndian(I &n) {
730  return BigEndian<I>(n);
731 }
732 
749 template <class Formatter> struct VectorFormatter {
750  template <typename Stream, typename V> void Ser(Stream &s, const V &v) {
751  Formatter formatter;
752  WriteCompactSize(s, v.size());
753  for (const typename V::value_type &elem : v) {
754  formatter.Ser(s, elem);
755  }
756  }
757 
758  template <typename Stream, typename V> void Unser(Stream &s, V &v) {
759  Formatter formatter;
760  v.clear();
761  size_t size = ReadCompactSize(s);
762  size_t allocated = 0;
763  while (allocated < size) {
764  // For DoS prevention, do not blindly allocate as much as the stream
765  // claims to contain. Instead, allocate in 5MiB batches, so that an
766  // attacker actually needs to provide X MiB of data to make us
767  // allocate X+5 Mib.
768  static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE,
769  "Vector element size too large");
770  allocated =
771  std::min(size, allocated + MAX_VECTOR_ALLOCATE /
772  sizeof(typename V::value_type));
773  v.reserve(allocated);
774  while (v.size() < allocated) {
775  v.emplace_back();
776  formatter.Unser(s, v.back());
777  }
778  }
779  };
780 };
781 
789 template <typename Stream, typename C>
790 void Serialize(Stream &os, const std::basic_string<C> &str);
791 template <typename Stream, typename C>
792 void Unserialize(Stream &is, std::basic_string<C> &str);
793 
799 template <typename Stream, unsigned int N, typename T>
800 void Serialize_impl(Stream &os, const prevector<N, T> &v, const uint8_t &);
801 template <typename Stream, unsigned int N, typename T, typename V>
802 void Serialize_impl(Stream &os, const prevector<N, T> &v, const V &);
803 template <typename Stream, unsigned int N, typename T>
804 inline void Serialize(Stream &os, const prevector<N, T> &v);
805 template <typename Stream, unsigned int N, typename T>
806 void Unserialize_impl(Stream &is, prevector<N, T> &v, const uint8_t &);
807 template <typename Stream, unsigned int N, typename T, typename V>
808 void Unserialize_impl(Stream &is, prevector<N, T> &v, const V &);
809 template <typename Stream, unsigned int N, typename T>
810 inline void Unserialize(Stream &is, prevector<N, T> &v);
811 
817 template <typename Stream, typename T, typename A>
818 void Serialize_impl(Stream &os, const std::vector<T, A> &v, const uint8_t &);
819 template <typename Stream, typename T, typename A>
820 void Serialize_impl(Stream &os, const std::vector<T, A> &v, const bool &);
821 template <typename Stream, typename T, typename A, typename V>
822 void Serialize_impl(Stream &os, const std::vector<T, A> &v, const V &);
823 template <typename Stream, typename T, typename A>
824 inline void Serialize(Stream &os, const std::vector<T, A> &v);
825 template <typename Stream, typename T, typename A>
826 void Unserialize_impl(Stream &is, std::vector<T, A> &v, const uint8_t &);
827 template <typename Stream, typename T, typename A, typename V>
828 void Unserialize_impl(Stream &is, std::vector<T, A> &v, const V &);
829 template <typename Stream, typename T, typename A>
830 inline void Unserialize(Stream &is, std::vector<T, A> &v);
831 
835 template <typename Stream, typename K, typename T>
836 void Serialize(Stream &os, const std::pair<K, T> &item);
837 template <typename Stream, typename K, typename T>
838 void Unserialize(Stream &is, std::pair<K, T> &item);
839 
843 template <typename Stream, typename K, typename T, typename Pred, typename A>
844 void Serialize(Stream &os, const std::map<K, T, Pred, A> &m);
845 template <typename Stream, typename K, typename T, typename Pred, typename A>
846 void Unserialize(Stream &is, std::map<K, T, Pred, A> &m);
847 
851 template <typename Stream, typename K, typename Pred, typename A>
852 void Serialize(Stream &os, const std::set<K, Pred, A> &m);
853 template <typename Stream, typename K, typename Pred, typename A>
854 void Unserialize(Stream &is, std::set<K, Pred, A> &m);
855 
859 template <typename Stream, typename T>
860 void Serialize(Stream &os, const std::shared_ptr<const T> &p);
861 template <typename Stream, typename T>
862 void Unserialize(Stream &os, std::shared_ptr<const T> &p);
863 
867 template <typename Stream, typename T>
868 void Serialize(Stream &os, const std::unique_ptr<const T> &p);
869 template <typename Stream, typename T>
870 void Unserialize(Stream &os, std::unique_ptr<const T> &p);
871 
876 template <typename Stream, typename T>
877 inline void Serialize(Stream &os, const T &a) {
878  a.Serialize(os);
879 }
880 
881 template <typename Stream, typename T>
882 inline void Unserialize(Stream &is, T &&a) {
883  a.Unserialize(is);
884 }
885 
893  template <typename Stream, typename T>
894  static void Ser(Stream &s, const T &t) {
895  Serialize(s, t);
896  }
897 
898  template <typename Stream, typename T> static void Unser(Stream &s, T &t) {
899  Unserialize(s, t);
900  }
901 };
902 
906 template <typename Stream, typename C>
907 void Serialize(Stream &os, const std::basic_string<C> &str) {
908  WriteCompactSize(os, str.size());
909  if (!str.empty()) {
910  os.write((char *)str.data(), str.size() * sizeof(C));
911  }
912 }
913 
914 template <typename Stream, typename C>
915 void Unserialize(Stream &is, std::basic_string<C> &str) {
916  size_t nSize = ReadCompactSize(is);
917  str.resize(nSize);
918  if (nSize != 0) {
919  is.read((char *)str.data(), nSize * sizeof(C));
920  }
921 }
922 
926 template <typename Stream, unsigned int N, typename T>
927 void Serialize_impl(Stream &os, const prevector<N, T> &v, const uint8_t &) {
928  WriteCompactSize(os, v.size());
929  if (!v.empty()) {
930  os.write((char *)v.data(), v.size() * sizeof(T));
931  }
932 }
933 
934 template <typename Stream, unsigned int N, typename T, typename V>
935 void Serialize_impl(Stream &os, const prevector<N, T> &v, const V &) {
937 }
938 
939 template <typename Stream, unsigned int N, typename T>
940 inline void Serialize(Stream &os, const prevector<N, T> &v) {
941  Serialize_impl(os, v, T());
942 }
943 
944 template <typename Stream, unsigned int N, typename T>
945 void Unserialize_impl(Stream &is, prevector<N, T> &v, const uint8_t &) {
946  // Limit size per read so bogus size value won't cause out of memory
947  v.clear();
948  size_t nSize = ReadCompactSize(is);
949  size_t i = 0;
950  while (i < nSize) {
951  size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
952  v.resize_uninitialized(i + blk);
953  is.read((char *)&v[i], blk * sizeof(T));
954  i += blk;
955  }
956 }
957 
958 template <typename Stream, unsigned int N, typename T, typename V>
959 void Unserialize_impl(Stream &is, prevector<N, T> &v, const V &) {
961 }
962 
963 template <typename Stream, unsigned int N, typename T>
964 inline void Unserialize(Stream &is, prevector<N, T> &v) {
965  Unserialize_impl(is, v, T());
966 }
967 
971 template <typename Stream, typename T, typename A>
972 void Serialize_impl(Stream &os, const std::vector<T, A> &v, const uint8_t &) {
973  WriteCompactSize(os, v.size());
974  if (!v.empty()) {
975  os.write((char *)v.data(), v.size() * sizeof(T));
976  }
977 }
978 
979 template <typename Stream, typename T, typename A>
980 void Serialize_impl(Stream &os, const std::vector<T, A> &v, const bool &) {
981  // A special case for std::vector<bool>, as dereferencing
982  // std::vector<bool>::const_iterator does not result in a const bool&
983  // due to std::vector's special casing for bool arguments.
984  WriteCompactSize(os, v.size());
985  for (bool elem : v) {
986  ::Serialize(os, elem);
987  }
988 }
989 
990 template <typename Stream, typename T, typename A, typename V>
991 void Serialize_impl(Stream &os, const std::vector<T, A> &v, const V &) {
993 }
994 
995 template <typename Stream, typename T, typename A>
996 inline void Serialize(Stream &os, const std::vector<T, A> &v) {
997  Serialize_impl(os, v, T());
998 }
999 
1000 template <typename Stream, typename T, typename A>
1001 void Unserialize_impl(Stream &is, std::vector<T, A> &v, const uint8_t &) {
1002  // Limit size per read so bogus size value won't cause out of memory
1003  v.clear();
1004  size_t nSize = ReadCompactSize(is);
1005  size_t i = 0;
1006  while (i < nSize) {
1007  size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
1008  v.resize(i + blk);
1009  is.read((char *)&v[i], blk * sizeof(T));
1010  i += blk;
1011  }
1012 }
1013 
1014 template <typename Stream, typename T, typename A, typename V>
1015 void Unserialize_impl(Stream &is, std::vector<T, A> &v, const V &) {
1017 }
1018 
1019 template <typename Stream, typename T, typename A>
1020 inline void Unserialize(Stream &is, std::vector<T, A> &v) {
1021  Unserialize_impl(is, v, T());
1022 }
1023 
1027 template <typename Stream, typename K, typename T>
1028 void Serialize(Stream &os, const std::pair<K, T> &item) {
1029  Serialize(os, item.first);
1030  Serialize(os, item.second);
1031 }
1032 
1033 template <typename Stream, typename K, typename T>
1034 void Unserialize(Stream &is, std::pair<K, T> &item) {
1035  Unserialize(is, item.first);
1036  Unserialize(is, item.second);
1037 }
1038 
1042 template <typename Stream, typename K, typename T, typename Pred, typename A>
1043 void Serialize(Stream &os, const std::map<K, T, Pred, A> &m) {
1044  WriteCompactSize(os, m.size());
1045  for (const auto &entry : m) {
1046  Serialize(os, entry);
1047  }
1048 }
1049 
1050 template <typename Stream, typename K, typename T, typename Pred, typename A>
1051 void Unserialize(Stream &is, std::map<K, T, Pred, A> &m) {
1052  m.clear();
1053  size_t nSize = ReadCompactSize(is);
1054  typename std::map<K, T, Pred, A>::iterator mi = m.begin();
1055  for (size_t i = 0; i < nSize; i++) {
1056  std::pair<K, T> item;
1057  Unserialize(is, item);
1058  mi = m.insert(mi, item);
1059  }
1060 }
1061 
1065 template <typename Stream, typename K, typename Pred, typename A>
1066 void Serialize(Stream &os, const std::set<K, Pred, A> &m) {
1067  WriteCompactSize(os, m.size());
1068  for (const K &i : m) {
1069  Serialize(os, i);
1070  }
1071 }
1072 
1073 template <typename Stream, typename K, typename Pred, typename A>
1074 void Unserialize(Stream &is, std::set<K, Pred, A> &m) {
1075  m.clear();
1076  size_t nSize = ReadCompactSize(is);
1077  typename std::set<K, Pred, A>::iterator it = m.begin();
1078  for (size_t i = 0; i < nSize; i++) {
1079  K key;
1080  Unserialize(is, key);
1081  it = m.insert(it, key);
1082  }
1083 }
1084 
1088 template <typename Stream, typename T>
1089 void Serialize(Stream &os, const std::unique_ptr<const T> &p) {
1090  Serialize(os, *p);
1091 }
1092 
1093 template <typename Stream, typename T>
1094 void Unserialize(Stream &is, std::unique_ptr<const T> &p) {
1095  p.reset(new T(deserialize, is));
1096 }
1097 
1101 template <typename Stream, typename T>
1102 void Serialize(Stream &os, const std::shared_ptr<const T> &p) {
1103  Serialize(os, *p);
1104 }
1105 
1106 template <typename Stream, typename T>
1107 void Unserialize(Stream &is, std::shared_ptr<const T> &p) {
1108  p = std::make_shared<const T>(deserialize, is);
1109 }
1110 
1115  constexpr bool ForRead() const { return false; }
1116 };
1118  constexpr bool ForRead() const { return true; }
1119 };
1120 
1134 protected:
1135  size_t nSize;
1136 
1137  const int nVersion;
1138 
1139 public:
1140  explicit CSizeComputer(int nVersionIn) : nSize(0), nVersion(nVersionIn) {}
1141 
1142  void write(const char *psz, size_t _nSize) { this->nSize += _nSize; }
1143 
1145  void seek(size_t _nSize) { this->nSize += _nSize; }
1146 
1147  template <typename T> CSizeComputer &operator<<(const T &obj) {
1148  ::Serialize(*this, obj);
1149  return (*this);
1150  }
1151 
1152  size_t size() const { return nSize; }
1153 
1154  int GetVersion() const { return nVersion; }
1155 };
1156 
1157 template <typename Stream> void SerializeMany(Stream &s) {}
1158 
1159 template <typename Stream, typename Arg, typename... Args>
1160 void SerializeMany(Stream &s, const Arg &arg, const Args &... args) {
1161  ::Serialize(s, arg);
1162  ::SerializeMany(s, args...);
1163 }
1164 
1165 template <typename Stream> inline void UnserializeMany(Stream &s) {}
1166 
1167 template <typename Stream, typename Arg, typename... Args>
1168 inline void UnserializeMany(Stream &s, Arg &&arg, Args &&... args) {
1169  ::Unserialize(s, arg);
1170  ::UnserializeMany(s, args...);
1171 }
1172 
1173 template <typename Stream, typename... Args>
1174 inline void SerReadWriteMany(Stream &s, CSerActionSerialize ser_action,
1175  const Args &... args) {
1176  ::SerializeMany(s, args...);
1177 }
1178 
1179 template <typename Stream, typename... Args>
1180 inline void SerReadWriteMany(Stream &s, CSerActionUnserialize ser_action,
1181  Args &&... args) {
1182  ::UnserializeMany(s, args...);
1183 }
1184 
1185 template <typename I> inline void WriteVarInt(CSizeComputer &s, I n) {
1186  s.seek(GetSizeOfVarInt<I>(n));
1187 }
1188 
1189 inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize) {
1190  s.seek(GetSizeOfCompactSize(nSize));
1191 }
1192 
1193 template <typename T> size_t GetSerializeSize(const T &t, int nVersion = 0) {
1194  return (CSizeComputer(nVersion) << t).size();
1195 }
1196 
1197 template <typename... T>
1198 size_t GetSerializeSizeMany(int nVersion, const T &... t) {
1199  CSizeComputer sc(nVersion);
1200  SerializeMany(sc, t...);
1201  return sc.size();
1202 }
1203 
1204 #endif // BITCOIN_SERIALIZE_H
uint64_t ser_double_to_uint64(double x)
Definition: serialize.h:139
CSizeComputer(int nVersionIn)
Definition: serialize.h:1140
std::string & string
Definition: serialize.h:705
X & ReadWriteAsHelper(X &x)
Convert the reference base type to X, without changing constness or reference type.
Definition: serialize.h:184
constexpr std::ptrdiff_t size() const noexcept
Definition: span.h:55
uint32_t ser_float_to_uint32(float x)
Definition: serialize.h:146
uint8_t ser_readdata8(Stream &s)
Definition: serialize.h:109
void clear()
Definition: prevector.h:439
void ser_writedata64(Stream &s, uint64_t obj)
Definition: serialize.h:105
uint64_t ReadCompactSize(Stream &is)
Definition: serialize.h:442
void WriteVarInt(CSizeComputer &os, I n)
Definition: serialize.h:1185
void WriteCompactSize(CSizeComputer &os, uint64_t nSize)
Definition: serialize.h:1189
static const unsigned int MAX_VECTOR_ALLOCATE
Maximum amount of memory (in bytes) to allocate at once when deserializing vectors.
Definition: serialize.h:32
void Unser(Stream &s, I &v)
Definition: serialize.h:620
size_t size() const
Definition: serialize.h:1152
void ser_writedata32(Stream &s, uint32_t obj)
Definition: serialize.h:95
constexpr deserialize_type deserialize
Definition: serialize.h:45
Formatter for integers in CompactSize format.
Definition: serialize.h:682
void Ser(Stream &s, I v)
Definition: serialize.h:630
void Unserialize_impl(Stream &is, prevector< N, T > &v, const uint8_t &)
Definition: serialize.h:945
uint32_t be32toh(uint32_t big_endian_32bits)
Definition: endian.h:180
void resize_uninitialized(size_type new_size)
Definition: prevector.h:480
BigEndian(I &val)
Definition: serialize.h:663
const int nVersion
Definition: serialize.h:1137
void UnserializeMany(Stream &s)
Definition: serialize.h:1165
BigEndian< I > WrapBigEndian(I &n)
Definition: serialize.h:729
Simple wrapper class to serialize objects using a formatter; used by Using().
Definition: serialize.h:572
void Ser(Stream &s, const V &v)
Definition: serialize.h:750
uint32_t htole32(uint32_t host_32bits)
Definition: endian.h:174
Dummy data type to identify deserializing constructors.
Definition: serialize.h:44
char * CharCast(char *c)
Safely convert odd char pointer types to standard ones.
Definition: serialize.h:64
value_type * data()
Definition: prevector.h:608
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1193
void Serialize(Stream &s, char a)
Definition: serialize.h:261
uint32_t htobe32(uint32_t host_32bits)
Definition: endian.h:168
void Serialize(Stream &s) const
Definition: serialize.h:581
void Unserialize(Stream &s)
Definition: serialize.h:710
CSizeComputer & operator<<(const T &obj)
Definition: serialize.h:1147
Serialization wrapper class for integers in VarInt format.
Definition: serialize.h:615
void Serialize(Stream &s) const
Definition: serialize.h:721
void SerReadWriteMany(Stream &s, CSerActionSerialize ser_action, const Args &... args)
Definition: serialize.h:1174
void Unser(Stream &s, V &v)
Definition: serialize.h:758
uint16_t ser_readdata16(Stream &s)
Definition: serialize.h:114
uint32_t ser_readdata32(Stream &s)
Definition: serialize.h:124
Serialization wrapper class for big-endian integers.
Definition: serialize.h:658
constexpr CheckVarIntMode()
Definition: serialize.h:506
void ser_writedata16(Stream &s, uint16_t obj)
Definition: serialize.h:85
void Unser(Stream &s, I &v)
Definition: serialize.h:683
uint16_t htobe16(uint16_t host_16bits)
Definition: endian.h:144
constexpr bool ForRead() const
Definition: serialize.h:1118
VarIntMode
Variable-length integers: bytes are a MSB base-128 encoding of the number.
Definition: serialize.h:503
static const uint64_t MAX_SIZE
Definition: serialize.h:26
I ReadVarInt(Stream &is)
Definition: serialize.h:549
uint16_t le16toh(uint16_t little_endian_16bits)
Definition: endian.h:162
void ser_writedata32be(Stream &s, uint32_t obj)
Definition: serialize.h:100
double ser_uint64_to_double(uint64_t y)
Definition: serialize.h:153
Support for ADD_SERIALIZE_METHODS and READWRITE macro.
Definition: serialize.h:1114
constexpr bool ForRead() const
Definition: serialize.h:1115
void SerializeMany(Stream &s)
Definition: serialize.h:1157
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
Definition: prevector.h:38
uint64_t ser_readdata64(Stream &s)
Definition: serialize.h:134
Default formatter.
Definition: serialize.h:892
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
Definition: serialize.h:1145
uint16_t htole16(uint16_t host_16bits)
Definition: endian.h:150
uint16_t ser_readdata16be(Stream &s)
Definition: serialize.h:119
uint64_t le64toh(uint64_t little_endian_64bits)
Definition: endian.h:210
uint16_t be16toh(uint16_t big_endian_16bits)
Definition: endian.h:156
constexpr C * data() const noexcept
Definition: span.h:50
int GetVersion() const
Definition: serialize.h:1154
void Unserialize(Stream &s)
Definition: serialize.h:676
bool empty() const
Definition: prevector.h:386
uint64_t htole64(uint64_t host_64bits)
Definition: endian.h:198
void write(const char *psz, size_t _nSize)
Definition: serialize.h:1142
uint32_t ser_readdata32be(Stream &s)
Definition: serialize.h:129
unsigned int GetSizeOfVarInt(I n)
Definition: serialize.h:516
size_t GetSerializeSizeMany(int nVersion, const T &... t)
Definition: serialize.h:1198
I & m_val
Definition: serialize.h:660
void Unserialize(Stream &s, char &a)
Definition: serialize.h:313
void ser_writedata16be(Stream &s, uint16_t obj)
Definition: serialize.h:90
uint32_t GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 ...
Definition: serialize.h:410
void Serialize_impl(Stream &os, const prevector< N, T > &v, const uint8_t &)
prevector prevectors of uint8_t are a special case and are intended to be serialized as a single opaq...
Definition: serialize.h:927
size_type size() const
Definition: prevector.h:384
void Unserialize(Stream &s)
Definition: serialize.h:584
void Serialize(Stream &s) const
Definition: serialize.h:672
Formatter to serialize/deserialize vector elements using another formatter.
Definition: serialize.h:749
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:17
T * NCONST_PTR(const T *val)
Used to acquire a non-const pointer "this" to generate bodies of const serialization operations from ...
Definition: serialize.h:59
static Wrapper< Formatter, T & > Using(T &&t)
Cause serialization/deserialization of an object to be done using a specified formatter class...
Definition: serialize.h:603
void Ser(Stream &s, I v)
Definition: serialize.h:692
void Unser(Stream &s, I &v)
Definition: serialize.h:639
GetSerializeSize implementations
Definition: serialize.h:1133
T m_object
Definition: serialize.h:574
uint32_t le32toh(uint32_t little_endian_32bits)
Definition: endian.h:186
T & REF(const T &val)
Used to bypass the rule against non-const reference to temporary where it makes sense with wrappers...
Definition: serialize.h:51
static void Unser(Stream &s, T &t)
Definition: serialize.h:898
size_t nSize
Definition: serialize.h:1135
LimitedString(std::string &_string)
Definition: serialize.h:708
static void Ser(Stream &s, const T &t)
Definition: serialize.h:894
void Ser(Stream &s, I v)
Definition: serialize.h:616
void ser_writedata8(Stream &s, uint8_t obj)
Lowest-level serialization and conversion.
Definition: serialize.h:81
float ser_uint32_to_float(uint32_t y)
Definition: serialize.h:160
Wrapper(T obj)
Definition: serialize.h:580