6 #ifndef BITCOIN_SERIALIZE_H 7 #define BITCOIN_SERIALIZE_H 51 template <
typename T>
inline T &
REF(
const T &val) {
52 return const_cast<T &
>(val);
59 template <
typename T>
inline T *
NCONST_PTR(
const T *val) {
60 return const_cast<T *
>(val);
73 inline const char *
CharCast(
const uint8_t *c) {
74 return (
const char *)c;
81 template <
typename Stream>
inline void ser_writedata8(Stream &s, uint8_t obj) {
82 s.write((
char *)&obj, 1);
84 template <
typename Stream>
87 s.write((
char *)&obj, 2);
89 template <
typename Stream>
92 s.write((
char *)&obj, 2);
94 template <
typename Stream>
97 s.write((
char *)&obj, 4);
99 template <
typename Stream>
102 s.write((
char *)&obj, 4);
104 template <
typename Stream>
107 s.write((
char *)&obj, 8);
111 s.read((
char *)&obj, 1);
116 s.read((
char *)&obj, 2);
121 s.read((
char *)&obj, 2);
126 s.read((
char *)&obj, 4);
131 s.read((
char *)&obj, 4);
136 s.read((
char *)&obj, 8);
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");
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");
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");
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");
191 #define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__)) 192 #define READWRITEAS(type, obj) \ 193 (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj))) 201 #define ADD_SERIALIZE_METHODS \ 202 template <typename Stream> void Serialize(Stream &s) const { \ 203 NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \ 205 template <typename Stream> void Unserialize(Stream &s) { \ 206 SerializationOp(s, CSerActionUnserialize()); \ 227 #define FORMATTER_METHODS(cls, obj) \ 228 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \ 229 SerializationOps(obj, s, CSerActionSerialize()); \ 231 template <typename Stream> static void Unser(Stream &s, cls &obj) { \ 232 SerializationOps(obj, s, CSerActionUnserialize()); \ 234 template <typename Stream, typename Type, typename Operation> \ 235 static inline void SerializationOps(Type &obj, Stream &s, \ 236 Operation ser_action) 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"); \ 252 template <typename Stream> void Unserialize(Stream &s) { \ 253 static_assert(std::is_same<cls &, decltype(*this)>::value, \ 254 "Unserialize type mismatch"); \ 257 FORMATTER_METHODS(cls, obj) 259 #ifndef CHAR_EQUALS_INT8 261 template <
typename Stream>
inline void Serialize(Stream &s,
char a) {
265 template <
typename Stream>
inline void Serialize(Stream &s, int8_t a) {
268 template <
typename Stream>
inline void Serialize(Stream &s, uint8_t a) {
271 template <
typename Stream>
inline void Serialize(Stream &s, int16_t a) {
274 template <
typename Stream>
inline void Serialize(Stream &s, uint16_t a) {
277 template <
typename Stream>
inline void Serialize(Stream &s, int32_t a) {
280 template <
typename Stream>
inline void Serialize(Stream &s, uint32_t a) {
283 template <
typename Stream>
inline void Serialize(Stream &s, int64_t a) {
286 template <
typename Stream>
inline void Serialize(Stream &s, uint64_t a) {
289 template <
typename Stream>
inline void Serialize(Stream &s,
float a) {
292 template <
typename Stream>
inline void Serialize(Stream &s,
double a) {
295 template <
typename Stream,
size_t N>
296 inline void Serialize(Stream &s,
const int8_t (&a)[N]) {
299 template <
typename Stream,
size_t N>
300 inline void Serialize(Stream &s,
const uint8_t (&a)[N]) {
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);
307 template <
typename Stream,
size_t N>
308 inline void Serialize(Stream &s,
const std::array<uint8_t, N> &a) {
311 #ifndef CHAR_EQUALS_INT8 313 template <
typename Stream>
inline void Unserialize(Stream &s,
char &a) {
316 template <
typename Stream,
size_t N>
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);
325 template <
typename Stream>
329 template <
typename Stream>
333 template <
typename Stream>
inline void Unserialize(Stream &s, int8_t &a) {
336 template <
typename Stream>
inline void Unserialize(Stream &s, uint8_t &a) {
339 template <
typename Stream>
inline void Unserialize(Stream &s, int16_t &a) {
342 template <
typename Stream>
inline void Unserialize(Stream &s, uint16_t &a) {
345 template <
typename Stream>
inline void Unserialize(Stream &s, int32_t &a) {
348 template <
typename Stream>
inline void Unserialize(Stream &s, uint32_t &a) {
351 template <
typename Stream>
inline void Unserialize(Stream &s, int64_t &a) {
354 template <
typename Stream>
inline void Unserialize(Stream &s, uint64_t &a) {
357 template <
typename Stream>
inline void Unserialize(Stream &s,
float &a) {
360 template <
typename Stream>
inline void Unserialize(Stream &s,
double &a) {
363 template <
typename Stream,
size_t N>
367 template <
typename Stream,
size_t N>
371 template <
typename Stream,
size_t N>
375 template <
typename Stream,
size_t N>
379 #ifndef CHAR_EQUALS_INT8 380 template <
typename Stream,
size_t N>
384 template <
typename Stream,
size_t N>
390 template <
typename Stream>
inline void Serialize(Stream &s,
bool a) {
394 template <
typename Stream>
inline void Unserialize(Stream &s,
bool &a) {
398 template <
typename Stream>
412 return sizeof(uint8_t);
414 if (nSize <= std::numeric_limits<uint16_t>::max()) {
415 return sizeof(uint8_t) +
sizeof(uint16_t);
417 if (nSize <= std::numeric_limits<uint32_t>::max()) {
418 return sizeof(uint8_t) +
sizeof(uint32_t);
421 return sizeof(uint8_t) +
sizeof(uint64_t);
429 }
else if (nSize <= std::numeric_limits<uint16_t>::max()) {
432 }
else if (nSize <= std::numeric_limits<uint32_t>::max()) {
444 uint64_t nSizeRet = 0;
447 }
else if (chSize == 253) {
449 if (nSizeRet < 253) {
450 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
452 }
else if (chSize == 254) {
454 if (nSizeRet < 0x10000u) {
455 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
459 if (nSizeRet < 0x100000000ULL) {
460 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
464 throw std::ios_base::failure(
"ReadCompactSize(): size too large");
508 "Unsigned type required with mode DEFAULT.");
510 std::is_signed<I>::value,
511 "Signed type required with mode NONNEGATIVE_SIGNED.");
515 template <VarIntMode Mode,
typename I>
530 template <
typename Stream, VarIntMode Mode,
typename I>
533 uint8_t tmp[(
sizeof(n) * 8 + 6) / 7];
536 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
548 template <
typename Stream, VarIntMode Mode,
typename I>
554 if (n > (std::numeric_limits<I>::max() >> 7)) {
555 throw std::ios_base::failure(
"ReadVarInt(): size too large");
557 n = (n << 7) | (chData & 0x7F);
558 if ((chData & 0x80) == 0) {
561 if (n == std::numeric_limits<I>::max()) {
562 throw std::ios_base::failure(
"ReadVarInt(): size too large");
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");
581 template <
typename Stream>
void Serialize(Stream &s)
const {
582 Formatter().Ser(s, m_object);
585 Formatter().Unser(s, m_object);
602 template <
typename Formatter,
typename T>
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)) 616 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
617 WriteVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s, v);
620 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
621 v = ReadVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s);
626 static_assert(Bytes > 0 && Bytes <= 8,
627 "CustomUintFormatter Bytes out of range");
628 static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
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");
636 s.write((
const char *)&raw, Bytes);
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");
644 s.read((
char *)&raw, Bytes);
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");
672 template <
typename Stream>
void Serialize(Stream &s)
const {
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");
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");
699 WriteCompactSize<Stream>(s, v);
713 throw std::ios_base::failure(
"String length limit exceeded");
717 s.read((
char *)
string.data(), size);
721 template <
typename Stream>
void Serialize(Stream &s)
const {
723 if (!
string.empty()) {
724 s.write((
char *)
string.data(),
string.size());
750 template <
typename Stream,
typename V>
void Ser(Stream &s,
const V &v) {
753 for (
const typename V::value_type &elem : v) {
754 formatter.Ser(s, elem);
758 template <
typename Stream,
typename V>
void Unser(Stream &s, V &v) {
762 size_t allocated = 0;
763 while (allocated < size) {
769 "Vector element size too large");
772 sizeof(
typename V::value_type));
773 v.reserve(allocated);
774 while (v.size() < allocated) {
776 formatter.Unser(s, v.back());
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);
799 template <
typename Stream,
unsigned int N,
typename T>
801 template <
typename Stream,
unsigned int N,
typename T,
typename V>
803 template <
typename Stream,
unsigned int N,
typename T>
805 template <
typename Stream,
unsigned int N,
typename T>
807 template <
typename Stream,
unsigned int N,
typename T,
typename V>
809 template <
typename Stream,
unsigned int N,
typename T>
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>
827 template <
typename Stream,
typename T,
typename A,
typename V>
829 template <
typename Stream,
typename T,
typename A>
830 inline void Unserialize(Stream &is, std::vector<T, A> &v);
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);
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);
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);
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);
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);
876 template <
typename Stream,
typename T>
881 template <
typename Stream,
typename T>
893 template <
typename Stream,
typename T>
894 static void Ser(Stream &s,
const T &t) {
898 template <
typename Stream,
typename T>
static void Unser(Stream &s, T &t) {
906 template <
typename Stream,
typename C>
907 void Serialize(Stream &os,
const std::basic_string<C> &str) {
910 os.write((
char *)str.data(), str.size() *
sizeof(C));
914 template <
typename Stream,
typename C>
919 is.read((
char *)str.data(), nSize *
sizeof(C));
926 template <
typename Stream,
unsigned int N,
typename T>
930 os.write((
char *)v.
data(), v.
size() *
sizeof(T));
934 template <
typename Stream,
unsigned int N,
typename T,
typename V>
939 template <
typename Stream,
unsigned int N,
typename T>
944 template <
typename Stream,
unsigned int N,
typename T>
951 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
953 is.read((
char *)&v[i], blk *
sizeof(T));
958 template <
typename Stream,
unsigned int N,
typename T,
typename V>
963 template <
typename Stream,
unsigned int N,
typename T>
971 template <
typename Stream,
typename T,
typename A>
975 os.write((
char *)v.data(), v.size() *
sizeof(T));
979 template <
typename Stream,
typename T,
typename A>
985 for (
bool elem : v) {
990 template <
typename Stream,
typename T,
typename A,
typename V>
995 template <
typename Stream,
typename T,
typename A>
996 inline void Serialize(Stream &os,
const std::vector<T, A> &v) {
1000 template <
typename Stream,
typename T,
typename A>
1007 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
1009 is.read((
char *)&v[i], blk *
sizeof(T));
1014 template <
typename Stream,
typename T,
typename A,
typename V>
1019 template <
typename Stream,
typename T,
typename A>
1027 template <
typename Stream,
typename K,
typename T>
1033 template <
typename Stream,
typename K,
typename T>
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) {
1045 for (
const auto &entry : m) {
1050 template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
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;
1058 mi = m.insert(mi, item);
1065 template <
typename Stream,
typename K,
typename Pred,
typename A>
1068 for (
const K &i : m) {
1073 template <
typename Stream,
typename K,
typename Pred,
typename A>
1077 typename std::set<K, Pred, A>::iterator it = m.begin();
1078 for (
size_t i = 0; i < nSize; i++) {
1081 it = m.insert(it, key);
1088 template <
typename Stream,
typename T>
1089 void Serialize(Stream &os,
const std::unique_ptr<const T> &p) {
1093 template <
typename Stream,
typename T>
1101 template <
typename Stream,
typename T>
1102 void Serialize(Stream &os,
const std::shared_ptr<const T> &p) {
1106 template <
typename Stream,
typename T>
1142 void write(
const char *psz,
size_t _nSize) { this->nSize += _nSize; }
1145 void seek(
size_t _nSize) { this->nSize += _nSize; }
1152 size_t size()
const {
return nSize; }
1159 template <
typename Stream,
typename Arg,
typename... Args>
1167 template <
typename Stream,
typename Arg,
typename... Args>
1173 template <
typename Stream,
typename... Args>
1175 const Args &... args) {
1179 template <
typename Stream,
typename... Args>
1186 s.
seek(GetSizeOfVarInt<I>(n));
1197 template <
typename... T>
1204 #endif // BITCOIN_SERIALIZE_H uint64_t ser_double_to_uint64(double x)
CSizeComputer(int nVersionIn)
X & ReadWriteAsHelper(X &x)
Convert the reference base type to X, without changing constness or reference type.
constexpr std::ptrdiff_t size() const noexcept
uint32_t ser_float_to_uint32(float x)
uint8_t ser_readdata8(Stream &s)
void ser_writedata64(Stream &s, uint64_t obj)
uint64_t ReadCompactSize(Stream &is)
void WriteVarInt(CSizeComputer &os, I n)
void WriteCompactSize(CSizeComputer &os, uint64_t nSize)
static const unsigned int MAX_VECTOR_ALLOCATE
Maximum amount of memory (in bytes) to allocate at once when deserializing vectors.
void ser_writedata32(Stream &s, uint32_t obj)
constexpr deserialize_type deserialize
void Unserialize_impl(Stream &is, prevector< N, T > &v, const uint8_t &)
uint32_t be32toh(uint32_t big_endian_32bits)
void resize_uninitialized(size_type new_size)
void UnserializeMany(Stream &s)
BigEndian< I > WrapBigEndian(I &n)
Simple wrapper class to serialize objects using a formatter; used by Using().
uint32_t htole32(uint32_t host_32bits)
Dummy data type to identify deserializing constructors.
char * CharCast(char *c)
Safely convert odd char pointer types to standard ones.
size_t GetSerializeSize(const T &t, int nVersion=0)
void Serialize(Stream &s, char a)
uint32_t htobe32(uint32_t host_32bits)
void Serialize(Stream &s) const
void Unserialize(Stream &s)
CSizeComputer & operator<<(const T &obj)
void Serialize(Stream &s) const
void SerReadWriteMany(Stream &s, CSerActionSerialize ser_action, const Args &... args)
uint16_t ser_readdata16(Stream &s)
uint32_t ser_readdata32(Stream &s)
Serialization wrapper class for big-endian integers.
constexpr CheckVarIntMode()
void ser_writedata16(Stream &s, uint16_t obj)
uint16_t htobe16(uint16_t host_16bits)
constexpr bool ForRead() const
VarIntMode
Variable-length integers: bytes are a MSB base-128 encoding of the number.
static const uint64_t MAX_SIZE
uint16_t le16toh(uint16_t little_endian_16bits)
void ser_writedata32be(Stream &s, uint32_t obj)
double ser_uint64_to_double(uint64_t y)
Support for ADD_SERIALIZE_METHODS and READWRITE macro.
constexpr bool ForRead() const
void SerializeMany(Stream &s)
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
uint64_t ser_readdata64(Stream &s)
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
uint16_t htole16(uint16_t host_16bits)
uint16_t ser_readdata16be(Stream &s)
uint64_t le64toh(uint64_t little_endian_64bits)
uint16_t be16toh(uint16_t big_endian_16bits)
constexpr C * data() const noexcept
void Unserialize(Stream &s)
uint64_t htole64(uint64_t host_64bits)
void write(const char *psz, size_t _nSize)
uint32_t ser_readdata32be(Stream &s)
unsigned int GetSizeOfVarInt(I n)
size_t GetSerializeSizeMany(int nVersion, const T &... t)
void Unserialize(Stream &s, char &a)
void ser_writedata16be(Stream &s, uint16_t obj)
uint32_t GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 ...
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...
void Unserialize(Stream &s)
void Serialize(Stream &s) const
A Span is an object that can refer to a contiguous sequence of objects.
T * NCONST_PTR(const T *val)
Used to acquire a non-const pointer "this" to generate bodies of const serialization operations from ...
static Wrapper< Formatter, T & > Using(T &&t)
Cause serialization/deserialization of an object to be done using a specified formatter class...
GetSerializeSize implementations
uint32_t le32toh(uint32_t little_endian_32bits)
T & REF(const T &val)
Used to bypass the rule against non-const reference to temporary where it makes sense with wrappers...
LimitedString(std::string &_string)
void ser_writedata8(Stream &s, uint8_t obj)
Lowest-level serialization and conversion.
float ser_uint32_to_float(uint32_t y)