1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
7 #include <boost/type_traits/is_fundamental.hpp>
8 #if defined(_MSC_VER) || defined(__BORLANDC__)
10 typedef unsigned __int64 uint64
;
12 typedef long long int64
;
13 typedef unsigned long long uint64
;
15 #if defined(_MSC_VER) && _MSC_VER < 1300
16 #define for if (false) ; else for
22 static const int VERSION
= 303;
23 static const char* pszSubVer
= "";
29 /////////////////////////////////////////////////////////////////
31 // Templates for serializing to anything that looks like a stream,
32 // i.e. anything that supports .read(char*, int) and .write(char*, int)
38 SER_NETWORK
= (1 << 0),
40 SER_GETHASH
= (1 << 2),
43 SER_SKIPSIG
= (1 << 16),
44 SER_BLOCKHEADERONLY
= (1 << 17),
47 #define IMPLEMENT_SERIALIZE(statements) \
48 unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const \
50 CSerActionGetSerializeSize ser_action; \
51 const bool fGetSize = true; \
52 const bool fWrite = false; \
53 const bool fRead = false; \
54 unsigned int nSerSize = 0; \
55 ser_streamplaceholder s; \
57 s.nVersion = nVersion; \
61 template<typename Stream> \
62 void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const \
64 CSerActionSerialize ser_action; \
65 const bool fGetSize = false; \
66 const bool fWrite = true; \
67 const bool fRead = false; \
68 unsigned int nSerSize = 0; \
71 template<typename Stream> \
72 void Unserialize(Stream& s, int nType=0, int nVersion=VERSION) \
74 CSerActionUnserialize ser_action; \
75 const bool fGetSize = false; \
76 const bool fWrite = false; \
77 const bool fRead = true; \
78 unsigned int nSerSize = 0; \
82 #define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
92 #define WRITEDATA(s, obj) s.write((char*)&(obj), sizeof(obj))
93 #define READDATA(s, obj) s.read((char*)&(obj), sizeof(obj))
95 inline unsigned int GetSerializeSize(char a
, int, int=0) { return sizeof(a
); }
96 inline unsigned int GetSerializeSize(signed char a
, int, int=0) { return sizeof(a
); }
97 inline unsigned int GetSerializeSize(unsigned char a
, int, int=0) { return sizeof(a
); }
98 inline unsigned int GetSerializeSize(signed short a
, int, int=0) { return sizeof(a
); }
99 inline unsigned int GetSerializeSize(unsigned short a
, int, int=0) { return sizeof(a
); }
100 inline unsigned int GetSerializeSize(signed int a
, int, int=0) { return sizeof(a
); }
101 inline unsigned int GetSerializeSize(unsigned int a
, int, int=0) { return sizeof(a
); }
102 inline unsigned int GetSerializeSize(signed long a
, int, int=0) { return sizeof(a
); }
103 inline unsigned int GetSerializeSize(unsigned long a
, int, int=0) { return sizeof(a
); }
104 inline unsigned int GetSerializeSize(int64 a
, int, int=0) { return sizeof(a
); }
105 inline unsigned int GetSerializeSize(uint64 a
, int, int=0) { return sizeof(a
); }
106 inline unsigned int GetSerializeSize(float a
, int, int=0) { return sizeof(a
); }
107 inline unsigned int GetSerializeSize(double a
, int, int=0) { return sizeof(a
); }
109 template<typename Stream
> inline void Serialize(Stream
& s
, char a
, int, int=0) { WRITEDATA(s
, a
); }
110 template<typename Stream
> inline void Serialize(Stream
& s
, signed char a
, int, int=0) { WRITEDATA(s
, a
); }
111 template<typename Stream
> inline void Serialize(Stream
& s
, unsigned char a
, int, int=0) { WRITEDATA(s
, a
); }
112 template<typename Stream
> inline void Serialize(Stream
& s
, signed short a
, int, int=0) { WRITEDATA(s
, a
); }
113 template<typename Stream
> inline void Serialize(Stream
& s
, unsigned short a
, int, int=0) { WRITEDATA(s
, a
); }
114 template<typename Stream
> inline void Serialize(Stream
& s
, signed int a
, int, int=0) { WRITEDATA(s
, a
); }
115 template<typename Stream
> inline void Serialize(Stream
& s
, unsigned int a
, int, int=0) { WRITEDATA(s
, a
); }
116 template<typename Stream
> inline void Serialize(Stream
& s
, signed long a
, int, int=0) { WRITEDATA(s
, a
); }
117 template<typename Stream
> inline void Serialize(Stream
& s
, unsigned long a
, int, int=0) { WRITEDATA(s
, a
); }
118 template<typename Stream
> inline void Serialize(Stream
& s
, int64 a
, int, int=0) { WRITEDATA(s
, a
); }
119 template<typename Stream
> inline void Serialize(Stream
& s
, uint64 a
, int, int=0) { WRITEDATA(s
, a
); }
120 template<typename Stream
> inline void Serialize(Stream
& s
, float a
, int, int=0) { WRITEDATA(s
, a
); }
121 template<typename Stream
> inline void Serialize(Stream
& s
, double a
, int, int=0) { WRITEDATA(s
, a
); }
123 template<typename Stream
> inline void Unserialize(Stream
& s
, char& a
, int, int=0) { READDATA(s
, a
); }
124 template<typename Stream
> inline void Unserialize(Stream
& s
, signed char& a
, int, int=0) { READDATA(s
, a
); }
125 template<typename Stream
> inline void Unserialize(Stream
& s
, unsigned char& a
, int, int=0) { READDATA(s
, a
); }
126 template<typename Stream
> inline void Unserialize(Stream
& s
, signed short& a
, int, int=0) { READDATA(s
, a
); }
127 template<typename Stream
> inline void Unserialize(Stream
& s
, unsigned short& a
, int, int=0) { READDATA(s
, a
); }
128 template<typename Stream
> inline void Unserialize(Stream
& s
, signed int& a
, int, int=0) { READDATA(s
, a
); }
129 template<typename Stream
> inline void Unserialize(Stream
& s
, unsigned int& a
, int, int=0) { READDATA(s
, a
); }
130 template<typename Stream
> inline void Unserialize(Stream
& s
, signed long& a
, int, int=0) { READDATA(s
, a
); }
131 template<typename Stream
> inline void Unserialize(Stream
& s
, unsigned long& a
, int, int=0) { READDATA(s
, a
); }
132 template<typename Stream
> inline void Unserialize(Stream
& s
, int64
& a
, int, int=0) { READDATA(s
, a
); }
133 template<typename Stream
> inline void Unserialize(Stream
& s
, uint64
& a
, int, int=0) { READDATA(s
, a
); }
134 template<typename Stream
> inline void Unserialize(Stream
& s
, float& a
, int, int=0) { READDATA(s
, a
); }
135 template<typename Stream
> inline void Unserialize(Stream
& s
, double& a
, int, int=0) { READDATA(s
, a
); }
137 inline unsigned int GetSerializeSize(bool a
, int, int=0) { return sizeof(char); }
138 template<typename Stream
> inline void Serialize(Stream
& s
, bool a
, int, int=0) { char f
=a
; WRITEDATA(s
, f
); }
139 template<typename Stream
> inline void Unserialize(Stream
& s
, bool& a
, int, int=0) { char f
; READDATA(s
, f
); a
=f
; }
148 // size < 253 -- 1 byte
149 // size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)
150 // size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
151 // size > UINT_MAX -- 9 bytes (255 + 8 bytes)
153 inline unsigned int GetSizeOfCompactSize(uint64 nSize
)
155 if (nSize
< UCHAR_MAX
-2) return sizeof(unsigned char);
156 else if (nSize
<= USHRT_MAX
) return sizeof(unsigned char) + sizeof(unsigned short);
157 else if (nSize
<= UINT_MAX
) return sizeof(unsigned char) + sizeof(unsigned int);
158 else return sizeof(unsigned char) + sizeof(uint64
);
161 template<typename Stream
>
162 void WriteCompactSize(Stream
& os
, uint64 nSize
)
164 if (nSize
< UCHAR_MAX
-2)
166 unsigned char chSize
= nSize
;
167 WRITEDATA(os
, chSize
);
169 else if (nSize
<= USHRT_MAX
)
171 unsigned char chSize
= UCHAR_MAX
-2;
172 unsigned short xSize
= nSize
;
173 WRITEDATA(os
, chSize
);
174 WRITEDATA(os
, xSize
);
176 else if (nSize
<= UINT_MAX
)
178 unsigned char chSize
= UCHAR_MAX
-1;
179 unsigned int xSize
= nSize
;
180 WRITEDATA(os
, chSize
);
181 WRITEDATA(os
, xSize
);
185 unsigned char chSize
= UCHAR_MAX
;
186 WRITEDATA(os
, chSize
);
187 WRITEDATA(os
, nSize
);
192 template<typename Stream
>
193 uint64
ReadCompactSize(Stream
& is
)
195 unsigned char chSize
;
196 READDATA(is
, chSize
);
198 if (chSize
< UCHAR_MAX
-2)
202 else if (chSize
== UCHAR_MAX
-2)
204 unsigned short nSize
;
208 else if (chSize
== UCHAR_MAX
-1)
220 if (nSizeRet
> (uint64
)INT_MAX
)
221 throw std::ios_base::failure("ReadCompactSize() : size too large");
228 // Wrapper for serializing arrays and POD
229 // There's a clever template way to make arrays serialize normally, but MSVC6 doesn't support it
231 #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
238 CFlatData(void* pbeginIn
, void* pendIn
) : pbegin((char*)pbeginIn
), pend((char*)pendIn
) { }
239 char* begin() { return pbegin
; }
240 const char* begin() const { return pbegin
; }
241 char* end() { return pend
; }
242 const char* end() const { return pend
; }
244 unsigned int GetSerializeSize(int, int=0) const
246 return pend
- pbegin
;
249 template<typename Stream
>
250 void Serialize(Stream
& s
, int, int=0) const
252 s
.write(pbegin
, pend
- pbegin
);
255 template<typename Stream
>
256 void Unserialize(Stream
& s
, int, int=0)
258 s
.read(pbegin
, pend
- pbegin
);
265 // string stored as a fixed length field
267 template<std::size_t LEN
>
268 class CFixedFieldString
274 explicit CFixedFieldString(const string
& str
) : pcstr(&str
), pstr(NULL
) { }
275 explicit CFixedFieldString(string
& str
) : pcstr(&str
), pstr(&str
) { }
277 unsigned int GetSerializeSize(int, int=0) const
282 template<typename Stream
>
283 void Serialize(Stream
& s
, int, int=0) const
286 strncpy(pszBuf
, pcstr
->c_str(), LEN
);
287 s
.write(pszBuf
, LEN
);
290 template<typename Stream
>
291 void Unserialize(Stream
& s
, int, int=0)
294 throw std::ios_base::failure("CFixedFieldString::Unserialize : trying to unserialize to const string");
307 // Forward declarations
311 template<typename C
> unsigned int GetSerializeSize(const basic_string
<C
>& str
, int, int=0);
312 template<typename Stream
, typename C
> void Serialize(Stream
& os
, const basic_string
<C
>& str
, int, int=0);
313 template<typename Stream
, typename C
> void Unserialize(Stream
& is
, basic_string
<C
>& str
, int, int=0);
316 template<typename T
, typename A
> unsigned int GetSerializeSize_impl(const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&);
317 template<typename T
, typename A
> unsigned int GetSerializeSize_impl(const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&);
318 template<typename T
, typename A
> inline unsigned int GetSerializeSize(const std::vector
<T
, A
>& v
, int nType
, int nVersion
=VERSION
);
319 template<typename Stream
, typename T
, typename A
> void Serialize_impl(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&);
320 template<typename Stream
, typename T
, typename A
> void Serialize_impl(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&);
321 template<typename Stream
, typename T
, typename A
> inline void Serialize(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
=VERSION
);
322 template<typename Stream
, typename T
, typename A
> void Unserialize_impl(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&);
323 template<typename Stream
, typename T
, typename A
> void Unserialize_impl(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&);
324 template<typename Stream
, typename T
, typename A
> inline void Unserialize(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
=VERSION
);
326 // others derived from vector
327 extern inline unsigned int GetSerializeSize(const CScript
& v
, int nType
, int nVersion
=VERSION
);
328 template<typename Stream
> void Serialize(Stream
& os
, const CScript
& v
, int nType
, int nVersion
=VERSION
);
329 template<typename Stream
> void Unserialize(Stream
& is
, CScript
& v
, int nType
, int nVersion
=VERSION
);
332 template<typename K
, typename T
> unsigned int GetSerializeSize(const std::pair
<K
, T
>& item
, int nType
, int nVersion
=VERSION
);
333 template<typename Stream
, typename K
, typename T
> void Serialize(Stream
& os
, const std::pair
<K
, T
>& item
, int nType
, int nVersion
=VERSION
);
334 template<typename Stream
, typename K
, typename T
> void Unserialize(Stream
& is
, std::pair
<K
, T
>& item
, int nType
, int nVersion
=VERSION
);
337 template<typename K
, typename T
, typename Pred
, typename A
> unsigned int GetSerializeSize(const std::map
<K
, T
, Pred
, A
>& m
, int nType
, int nVersion
=VERSION
);
338 template<typename Stream
, typename K
, typename T
, typename Pred
, typename A
> void Serialize(Stream
& os
, const std::map
<K
, T
, Pred
, A
>& m
, int nType
, int nVersion
=VERSION
);
339 template<typename Stream
, typename K
, typename T
, typename Pred
, typename A
> void Unserialize(Stream
& is
, std::map
<K
, T
, Pred
, A
>& m
, int nType
, int nVersion
=VERSION
);
342 template<typename K
, typename Pred
, typename A
> unsigned int GetSerializeSize(const std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
=VERSION
);
343 template<typename Stream
, typename K
, typename Pred
, typename A
> void Serialize(Stream
& os
, const std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
=VERSION
);
344 template<typename Stream
, typename K
, typename Pred
, typename A
> void Unserialize(Stream
& is
, std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
=VERSION
);
351 // If none of the specialized versions above matched, default to calling member function.
352 // "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
353 // The compiler will only cast int to long if none of the other templates matched.
354 // Thanks to Boost serialization for this idea.
357 inline unsigned int GetSerializeSize(const T
& a
, long nType
, int nVersion
=VERSION
)
359 return a
.GetSerializeSize((int)nType
, nVersion
);
362 template<typename Stream
, typename T
>
363 inline void Serialize(Stream
& os
, const T
& a
, long nType
, int nVersion
=VERSION
)
365 a
.Serialize(os
, (int)nType
, nVersion
);
368 template<typename Stream
, typename T
>
369 inline void Unserialize(Stream
& is
, T
& a
, long nType
, int nVersion
=VERSION
)
371 a
.Unserialize(is
, (int)nType
, nVersion
);
382 unsigned int GetSerializeSize(const basic_string
<C
>& str
, int, int)
384 return GetSizeOfCompactSize(str
.size()) + str
.size() * sizeof(str
[0]);
387 template<typename Stream
, typename C
>
388 void Serialize(Stream
& os
, const basic_string
<C
>& str
, int, int)
390 WriteCompactSize(os
, str
.size());
392 os
.write((char*)&str
[0], str
.size() * sizeof(str
[0]));
395 template<typename Stream
, typename C
>
396 void Unserialize(Stream
& is
, basic_string
<C
>& str
, int, int)
398 unsigned int nSize
= ReadCompactSize(is
);
401 is
.read((char*)&str
[0], nSize
* sizeof(str
[0]));
409 template<typename T
, typename A
>
410 unsigned int GetSerializeSize_impl(const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&)
412 return (GetSizeOfCompactSize(v
.size()) + v
.size() * sizeof(T
));
415 template<typename T
, typename A
>
416 unsigned int GetSerializeSize_impl(const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&)
418 unsigned int nSize
= GetSizeOfCompactSize(v
.size());
419 for (typename
std::vector
<T
, A
>::const_iterator vi
= v
.begin(); vi
!= v
.end(); ++vi
)
420 nSize
+= GetSerializeSize((*vi
), nType
, nVersion
);
424 template<typename T
, typename A
>
425 inline unsigned int GetSerializeSize(const std::vector
<T
, A
>& v
, int nType
, int nVersion
)
427 return GetSerializeSize_impl(v
, nType
, nVersion
, boost::is_fundamental
<T
>());
431 template<typename Stream
, typename T
, typename A
>
432 void Serialize_impl(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&)
434 WriteCompactSize(os
, v
.size());
436 os
.write((char*)&v
[0], v
.size() * sizeof(T
));
439 template<typename Stream
, typename T
, typename A
>
440 void Serialize_impl(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&)
442 WriteCompactSize(os
, v
.size());
443 for (typename
std::vector
<T
, A
>::const_iterator vi
= v
.begin(); vi
!= v
.end(); ++vi
)
444 ::Serialize(os
, (*vi
), nType
, nVersion
);
447 template<typename Stream
, typename T
, typename A
>
448 inline void Serialize(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
)
450 Serialize_impl(os
, v
, nType
, nVersion
, boost::is_fundamental
<T
>());
454 template<typename Stream
, typename T
, typename A
>
455 void Unserialize_impl(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&)
457 //unsigned int nSize = ReadCompactSize(is);
459 //is.read((char*)&v[0], nSize * sizeof(T));
461 // Limit size per read so bogus size value won't cause out of memory
463 unsigned int nSize
= ReadCompactSize(is
);
467 unsigned int blk
= min(nSize
- i
, (unsigned int)(1 + 4999999 / sizeof(T
)));
469 is
.read((char*)&v
[i
], blk
* sizeof(T
));
474 template<typename Stream
, typename T
, typename A
>
475 void Unserialize_impl(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&)
477 //unsigned int nSize = ReadCompactSize(is);
479 //for (std::vector<T, A>::iterator vi = v.begin(); vi != v.end(); ++vi)
480 // Unserialize(is, (*vi), nType, nVersion);
483 unsigned int nSize
= ReadCompactSize(is
);
485 unsigned int nMid
= 0;
488 nMid
+= 5000000 / sizeof(T
);
492 for (; i
< nMid
; i
++)
493 Unserialize(is
, v
[i
], nType
, nVersion
);
497 template<typename Stream
, typename T
, typename A
>
498 inline void Unserialize(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
)
500 Unserialize_impl(is
, v
, nType
, nVersion
, boost::is_fundamental
<T
>());
506 // others derived from vector
508 inline unsigned int GetSerializeSize(const CScript
& v
, int nType
, int nVersion
)
510 return GetSerializeSize((const vector
<unsigned char>&)v
, nType
, nVersion
);
513 template<typename Stream
>
514 void Serialize(Stream
& os
, const CScript
& v
, int nType
, int nVersion
)
516 Serialize(os
, (const vector
<unsigned char>&)v
, nType
, nVersion
);
519 template<typename Stream
>
520 void Unserialize(Stream
& is
, CScript
& v
, int nType
, int nVersion
)
522 Unserialize(is
, (vector
<unsigned char>&)v
, nType
, nVersion
);
530 template<typename K
, typename T
>
531 unsigned int GetSerializeSize(const std::pair
<K
, T
>& item
, int nType
, int nVersion
)
533 return GetSerializeSize(item
.first
, nType
, nVersion
) + GetSerializeSize(item
.second
, nType
, nVersion
);
536 template<typename Stream
, typename K
, typename T
>
537 void Serialize(Stream
& os
, const std::pair
<K
, T
>& item
, int nType
, int nVersion
)
539 Serialize(os
, item
.first
, nType
, nVersion
);
540 Serialize(os
, item
.second
, nType
, nVersion
);
543 template<typename Stream
, typename K
, typename T
>
544 void Unserialize(Stream
& is
, std::pair
<K
, T
>& item
, int nType
, int nVersion
)
546 Unserialize(is
, item
.first
, nType
, nVersion
);
547 Unserialize(is
, item
.second
, nType
, nVersion
);
555 template<typename K
, typename T
, typename Pred
, typename A
>
556 unsigned int GetSerializeSize(const std::map
<K
, T
, Pred
, A
>& m
, int nType
, int nVersion
)
558 unsigned int nSize
= GetSizeOfCompactSize(m
.size());
559 for (typename
std::map
<K
, T
, Pred
, A
>::const_iterator mi
= m
.begin(); mi
!= m
.end(); ++mi
)
560 nSize
+= GetSerializeSize((*mi
), nType
, nVersion
);
564 template<typename Stream
, typename K
, typename T
, typename Pred
, typename A
>
565 void Serialize(Stream
& os
, const std::map
<K
, T
, Pred
, A
>& m
, int nType
, int nVersion
)
567 WriteCompactSize(os
, m
.size());
568 for (typename
std::map
<K
, T
, Pred
, A
>::const_iterator mi
= m
.begin(); mi
!= m
.end(); ++mi
)
569 Serialize(os
, (*mi
), nType
, nVersion
);
572 template<typename Stream
, typename K
, typename T
, typename Pred
, typename A
>
573 void Unserialize(Stream
& is
, std::map
<K
, T
, Pred
, A
>& m
, int nType
, int nVersion
)
576 unsigned int nSize
= ReadCompactSize(is
);
577 typename
std::map
<K
, T
, Pred
, A
>::iterator mi
= m
.begin();
578 for (unsigned int i
= 0; i
< nSize
; i
++)
581 Unserialize(is
, item
, nType
, nVersion
);
582 mi
= m
.insert(mi
, item
);
591 template<typename K
, typename Pred
, typename A
>
592 unsigned int GetSerializeSize(const std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
)
594 unsigned int nSize
= GetSizeOfCompactSize(m
.size());
595 for (typename
std::set
<K
, Pred
, A
>::const_iterator it
= m
.begin(); it
!= m
.end(); ++it
)
596 nSize
+= GetSerializeSize((*it
), nType
, nVersion
);
600 template<typename Stream
, typename K
, typename Pred
, typename A
>
601 void Serialize(Stream
& os
, const std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
)
603 WriteCompactSize(os
, m
.size());
604 for (typename
std::set
<K
, Pred
, A
>::const_iterator it
= m
.begin(); it
!= m
.end(); ++it
)
605 Serialize(os
, (*it
), nType
, nVersion
);
608 template<typename Stream
, typename K
, typename Pred
, typename A
>
609 void Unserialize(Stream
& is
, std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
)
612 unsigned int nSize
= ReadCompactSize(is
);
613 typename
std::set
<K
, Pred
, A
>::iterator it
= m
.begin();
614 for (unsigned int i
= 0; i
< nSize
; i
++)
617 Unserialize(is
, key
, nType
, nVersion
);
618 it
= m
.insert(it
, key
);
625 // Support for IMPLEMENT_SERIALIZE and READWRITE macro
627 class CSerActionGetSerializeSize
{ };
628 class CSerActionSerialize
{ };
629 class CSerActionUnserialize
{ };
631 template<typename Stream
, typename T
>
632 inline unsigned int SerReadWrite(Stream
& s
, const T
& obj
, int nType
, int nVersion
, CSerActionGetSerializeSize ser_action
)
634 return ::GetSerializeSize(obj
, nType
, nVersion
);
637 template<typename Stream
, typename T
>
638 inline unsigned int SerReadWrite(Stream
& s
, const T
& obj
, int nType
, int nVersion
, CSerActionSerialize ser_action
)
640 ::Serialize(s
, obj
, nType
, nVersion
);
644 template<typename Stream
, typename T
>
645 inline unsigned int SerReadWrite(Stream
& s
, T
& obj
, int nType
, int nVersion
, CSerActionUnserialize ser_action
)
647 ::Unserialize(s
, obj
, nType
, nVersion
);
651 struct ser_streamplaceholder
666 // Allocator that clears its contents before deletion
669 struct secure_allocator
: public std::allocator
<T
>
671 // MSVC8 default copy constructor is broken
672 typedef std::allocator
<T
> base
;
673 typedef typename
base::size_type size_type
;
674 typedef typename
base::difference_type difference_type
;
675 typedef typename
base::pointer pointer
;
676 typedef typename
base::const_pointer const_pointer
;
677 typedef typename
base::reference reference
;
678 typedef typename
base::const_reference const_reference
;
679 typedef typename
base::value_type value_type
;
680 secure_allocator() throw() {}
681 secure_allocator(const secure_allocator
& a
) throw() : base(a
) {}
682 ~secure_allocator() throw() {}
683 template<typename _Other
> struct rebind
684 { typedef secure_allocator
<_Other
> other
; };
686 void deallocate(T
* p
, std::size_t n
)
689 memset(p
, 0, sizeof(T
) * n
);
690 allocator
<T
>::deallocate(p
, n
);
697 // Double ended buffer combining vector and stream-like interfaces.
698 // >> and << read and write unformatted data using the above serialization templates.
699 // Fills with data in linear time; some stringstream implementations take N^2 time.
704 typedef vector
<char, secure_allocator
<char> > vector_type
;
706 unsigned int nReadPos
;
713 typedef vector_type::allocator_type allocator_type
;
714 typedef vector_type::size_type size_type
;
715 typedef vector_type::difference_type difference_type
;
716 typedef vector_type::reference reference
;
717 typedef vector_type::const_reference const_reference
;
718 typedef vector_type::value_type value_type
;
719 typedef vector_type::iterator iterator
;
720 typedef vector_type::const_iterator const_iterator
;
721 typedef vector_type::reverse_iterator reverse_iterator
;
723 explicit CDataStream(int nTypeIn
=0, int nVersionIn
=VERSION
)
725 Init(nTypeIn
, nVersionIn
);
728 CDataStream(const_iterator pbegin
, const_iterator pend
, int nTypeIn
=0, int nVersionIn
=VERSION
) : vch(pbegin
, pend
)
730 Init(nTypeIn
, nVersionIn
);
733 #if !defined(_MSC_VER) || _MSC_VER >= 1300
734 CDataStream(const char* pbegin
, const char* pend
, int nTypeIn
=0, int nVersionIn
=VERSION
) : vch(pbegin
, pend
)
736 Init(nTypeIn
, nVersionIn
);
740 CDataStream(const vector_type
& vchIn
, int nTypeIn
=0, int nVersionIn
=VERSION
) : vch(vchIn
.begin(), vchIn
.end())
742 Init(nTypeIn
, nVersionIn
);
745 CDataStream(const vector
<char>& vchIn
, int nTypeIn
=0, int nVersionIn
=VERSION
) : vch(vchIn
.begin(), vchIn
.end())
747 Init(nTypeIn
, nVersionIn
);
750 CDataStream(const vector
<unsigned char>& vchIn
, int nTypeIn
=0, int nVersionIn
=VERSION
) : vch((char*)&vchIn
.begin()[0], (char*)&vchIn
.end()[0])
752 Init(nTypeIn
, nVersionIn
);
755 void Init(int nTypeIn
=0, int nVersionIn
=VERSION
)
759 nVersion
= nVersionIn
;
761 exceptmask
= ios::badbit
| ios::failbit
;
764 CDataStream
& operator+=(const CDataStream
& b
)
766 vch
.insert(vch
.end(), b
.begin(), b
.end());
770 friend CDataStream
operator+(const CDataStream
& a
, const CDataStream
& b
)
779 return (string(begin(), end()));
786 const_iterator
begin() const { return vch
.begin() + nReadPos
; }
787 iterator
begin() { return vch
.begin() + nReadPos
; }
788 const_iterator
end() const { return vch
.end(); }
789 iterator
end() { return vch
.end(); }
790 size_type
size() const { return vch
.size() - nReadPos
; }
791 bool empty() const { return vch
.size() == nReadPos
; }
792 void resize(size_type n
, value_type c
=0) { vch
.resize(n
+ nReadPos
, c
); }
793 void reserve(size_type n
) { vch
.reserve(n
+ nReadPos
); }
794 const_reference
operator[](size_type pos
) const { return vch
[pos
+ nReadPos
]; }
795 reference
operator[](size_type pos
) { return vch
[pos
+ nReadPos
]; }
796 void clear() { vch
.clear(); nReadPos
= 0; }
797 iterator
insert(iterator it
, const char& x
=char()) { return vch
.insert(it
, x
); }
798 void insert(iterator it
, size_type n
, const char& x
) { vch
.insert(it
, n
, x
); }
800 void insert(iterator it
, const_iterator first
, const_iterator last
)
802 if (it
== vch
.begin() + nReadPos
&& last
- first
<= nReadPos
)
804 // special case for inserting at the front when there's room
805 nReadPos
-= (last
- first
);
806 memcpy(&vch
[nReadPos
], &first
[0], last
- first
);
809 vch
.insert(it
, first
, last
);
812 void insert(iterator it
, vector
<char>::const_iterator first
, vector
<char>::const_iterator last
)
814 if (it
== vch
.begin() + nReadPos
&& last
- first
<= nReadPos
)
816 // special case for inserting at the front when there's room
817 nReadPos
-= (last
- first
);
818 memcpy(&vch
[nReadPos
], &first
[0], last
- first
);
821 vch
.insert(it
, first
, last
);
824 #if !defined(_MSC_VER) || _MSC_VER >= 1300
825 void insert(iterator it
, const char* first
, const char* last
)
827 if (it
== vch
.begin() + nReadPos
&& last
- first
<= nReadPos
)
829 // special case for inserting at the front when there's room
830 nReadPos
-= (last
- first
);
831 memcpy(&vch
[nReadPos
], &first
[0], last
- first
);
834 vch
.insert(it
, first
, last
);
838 iterator
erase(iterator it
)
840 if (it
== vch
.begin() + nReadPos
)
842 // special case for erasing from the front
843 if (++nReadPos
>= vch
.size())
845 // whenever we reach the end, we take the opportunity to clear the buffer
847 return vch
.erase(vch
.begin(), vch
.end());
849 return vch
.begin() + nReadPos
;
852 return vch
.erase(it
);
855 iterator
erase(iterator first
, iterator last
)
857 if (first
== vch
.begin() + nReadPos
)
859 // special case for erasing from the front
860 if (last
== vch
.end())
863 return vch
.erase(vch
.begin(), vch
.end());
867 nReadPos
= (last
- vch
.begin());
872 return vch
.erase(first
, last
);
875 inline void Compact()
877 vch
.erase(vch
.begin(), vch
.begin() + nReadPos
);
881 bool Rewind(size_type n
)
883 // Rewind by n characters if the buffer hasn't been compacted yet
894 void setstate(short bits
, const char* psz
)
897 if (state
& exceptmask
)
898 throw std::ios_base::failure(psz
);
901 bool eof() const { return size() == 0; }
902 bool fail() const { return state
& (ios::badbit
| ios::failbit
); }
903 bool good() const { return !eof() && (state
== 0); }
904 void clear(short n
) { state
= n
; } // name conflict with vector clear()
905 short exceptions() { return exceptmask
; }
906 short exceptions(short mask
) { short prev
= exceptmask
; exceptmask
= mask
; setstate(0, "CDataStream"); return prev
; }
907 CDataStream
* rdbuf() { return this; }
908 int in_avail() { return size(); }
910 void SetType(int n
) { nType
= n
; }
911 int GetType() { return nType
; }
912 void SetVersion(int n
) { nVersion
= n
; }
913 int GetVersion() { return nVersion
; }
914 void ReadVersion() { *this >> nVersion
; }
915 void WriteVersion() { *this << nVersion
; }
917 CDataStream
& read(char* pch
, int nSize
)
919 // Read from the beginning of the buffer
921 unsigned int nReadPosNext
= nReadPos
+ nSize
;
922 if (nReadPosNext
>= vch
.size())
924 if (nReadPosNext
> vch
.size())
926 setstate(ios::failbit
, "CDataStream::read() : end of data");
927 memset(pch
, 0, nSize
);
928 nSize
= vch
.size() - nReadPos
;
930 memcpy(pch
, &vch
[nReadPos
], nSize
);
935 memcpy(pch
, &vch
[nReadPos
], nSize
);
936 nReadPos
= nReadPosNext
;
940 CDataStream
& ignore(int nSize
)
942 // Ignore from the beginning of the buffer
944 unsigned int nReadPosNext
= nReadPos
+ nSize
;
945 if (nReadPosNext
>= vch
.size())
947 if (nReadPosNext
> vch
.size())
949 setstate(ios::failbit
, "CDataStream::ignore() : end of data");
950 nSize
= vch
.size() - nReadPos
;
956 nReadPos
= nReadPosNext
;
960 CDataStream
& write(const char* pch
, int nSize
)
962 // Write to the end of the buffer
964 vch
.insert(vch
.end(), pch
, pch
+ nSize
);
968 template<typename Stream
>
969 void Serialize(Stream
& s
, int nType
=0, int nVersion
=VERSION
) const
971 // Special case: stream << stream concatenates like stream += stream
973 s
.write((char*)&vch
[0], vch
.size() * sizeof(vch
[0]));
977 unsigned int GetSerializeSize(const T
& obj
)
979 // Tells the size of the object if serialized to this stream
980 return ::GetSerializeSize(obj
, nType
, nVersion
);
984 CDataStream
& operator<<(const T
& obj
)
986 // Serialize to this stream
987 ::Serialize(*this, obj
, nType
, nVersion
);
992 CDataStream
& operator>>(T
& obj
)
994 // Unserialize from this stream
995 ::Unserialize(*this, obj
, nType
, nVersion
);
1000 #ifdef TESTCDATASTREAM
1007 // n=16000 0 seconds
1008 // n=32000 0 seconds
1009 // n=64000 1 seconds
1010 // n=128000 1 seconds
1011 // n=256000 2 seconds
1012 // n=512000 4 seconds
1013 // n=1024000 8 seconds
1014 // n=2048000 16 seconds
1015 // n=4096000 32 seconds
1019 // n=4000 13 seconds
1020 // n=8000 87 seconds
1021 // n=16000 400 seconds
1022 // n=32000 1660 seconds
1023 // n=64000 6749 seconds
1024 // n=128000 27241 seconds
1025 // n=256000 109804 seconds
1027 int main(int argc
, char *argv
[])
1029 vector
<unsigned char> vch(0xcc, 250);
1030 printf("CDataStream:\n");
1031 for (int n
= 1000; n
<= 4500000; n
*= 2)
1034 time_t nStart
= time(NULL
);
1035 for (int i
= 0; i
< n
; i
++)
1036 ss
.write((char*)&vch
[0], vch
.size());
1037 printf("n=%-10d %d seconds\n", n
, time(NULL
) - nStart
);
1039 printf("stringstream:\n");
1040 for (int n
= 1000; n
<= 4500000; n
*= 2)
1043 time_t nStart
= time(NULL
);
1044 for (int i
= 0; i
< n
; i
++)
1045 ss
.write((char*)&vch
[0], vch
.size());
1046 printf("n=%-10d %d seconds\n", n
, time(NULL
) - nStart
);
1061 // Automatic closing wrapper for FILE*
1062 // - Will automatically close the file when it goes out of scope if not null.
1063 // - If you're returning the file pointer, return file.release().
1064 // - If you need to close the file early, use file.fclose() instead of fclose(file).
1076 typedef FILE element_type
;
1078 CAutoFile(FILE* filenew
=NULL
, int nTypeIn
=SER_DISK
, int nVersionIn
=VERSION
)
1082 nVersion
= nVersionIn
;
1084 exceptmask
= ios::badbit
| ios::failbit
;
1094 if (file
!= NULL
&& file
!= stdin
&& file
!= stdout
&& file
!= stderr
)
1099 FILE* release() { FILE* ret
= file
; file
= NULL
; return ret
; }
1100 operator FILE*() { return file
; }
1101 FILE* operator->() { return file
; }
1102 FILE& operator*() { return *file
; }
1103 FILE** operator&() { return &file
; }
1104 FILE* operator=(FILE* pnew
) { return file
= pnew
; }
1105 bool operator!() { return (file
== NULL
); }
1111 void setstate(short bits
, const char* psz
)
1114 if (state
& exceptmask
)
1115 throw std::ios_base::failure(psz
);
1118 bool fail() const { return state
& (ios::badbit
| ios::failbit
); }
1119 bool good() const { return state
== 0; }
1120 void clear(short n
= 0) { state
= n
; }
1121 short exceptions() { return exceptmask
; }
1122 short exceptions(short mask
) { short prev
= exceptmask
; exceptmask
= mask
; setstate(0, "CAutoFile"); return prev
; }
1124 void SetType(int n
) { nType
= n
; }
1125 int GetType() { return nType
; }
1126 void SetVersion(int n
) { nVersion
= n
; }
1127 int GetVersion() { return nVersion
; }
1128 void ReadVersion() { *this >> nVersion
; }
1129 void WriteVersion() { *this << nVersion
; }
1131 CAutoFile
& read(char* pch
, int nSize
)
1134 throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
1135 if (fread(pch
, 1, nSize
, file
) != nSize
)
1136 setstate(ios::failbit
, feof(file
) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
1140 CAutoFile
& write(const char* pch
, int nSize
)
1143 throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
1144 if (fwrite(pch
, 1, nSize
, file
) != nSize
)
1145 setstate(ios::failbit
, "CAutoFile::write : write failed");
1149 template<typename T
>
1150 unsigned int GetSerializeSize(const T
& obj
)
1152 // Tells the size of the object if serialized to this stream
1153 return ::GetSerializeSize(obj
, nType
, nVersion
);
1156 template<typename T
>
1157 CAutoFile
& operator<<(const T
& obj
)
1159 // Serialize to this stream
1161 throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
1162 ::Serialize(*this, obj
, nType
, nVersion
);
1166 template<typename T
>
1167 CAutoFile
& operator>>(T
& obj
)
1169 // Unserialize from this stream
1171 throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");
1172 ::Unserialize(*this, obj
, nType
, nVersion
);