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.
9 #include <boost/type_traits/is_fundamental.hpp>
10 #if defined(_MSC_VER) || defined(__BORLANDC__)
11 typedef __int64 int64
;
12 typedef unsigned __int64 uint64
;
14 typedef long long int64
;
15 typedef unsigned long long uint64
;
17 #if defined(_MSC_VER) && _MSC_VER < 1300
18 #define for if (false) ; else for
23 static const unsigned int MAX_SIZE
= 0x02000000;
25 static const int VERSION
= 31601;
26 static const char* pszSubVer
= "";
33 /////////////////////////////////////////////////////////////////
35 // Templates for serializing to anything that looks like a stream,
36 // i.e. anything that supports .read(char*, int) and .write(char*, int)
42 SER_NETWORK
= (1 << 0),
44 SER_GETHASH
= (1 << 2),
47 SER_SKIPSIG
= (1 << 16),
48 SER_BLOCKHEADERONLY
= (1 << 17),
51 #define IMPLEMENT_SERIALIZE(statements) \
52 unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const \
54 CSerActionGetSerializeSize ser_action; \
55 const bool fGetSize = true; \
56 const bool fWrite = false; \
57 const bool fRead = false; \
58 unsigned int nSerSize = 0; \
59 ser_streamplaceholder s; \
61 s.nVersion = nVersion; \
65 template<typename Stream> \
66 void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const \
68 CSerActionSerialize ser_action; \
69 const bool fGetSize = false; \
70 const bool fWrite = true; \
71 const bool fRead = false; \
72 unsigned int nSerSize = 0; \
75 template<typename Stream> \
76 void Unserialize(Stream& s, int nType=0, int nVersion=VERSION) \
78 CSerActionUnserialize ser_action; \
79 const bool fGetSize = false; \
80 const bool fWrite = false; \
81 const bool fRead = true; \
82 unsigned int nSerSize = 0; \
86 #define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
96 #define WRITEDATA(s, obj) s.write((char*)&(obj), sizeof(obj))
97 #define READDATA(s, obj) s.read((char*)&(obj), sizeof(obj))
99 inline unsigned int GetSerializeSize(char a
, int, int=0) { return sizeof(a
); }
100 inline unsigned int GetSerializeSize(signed char a
, int, int=0) { return sizeof(a
); }
101 inline unsigned int GetSerializeSize(unsigned char a
, int, int=0) { return sizeof(a
); }
102 inline unsigned int GetSerializeSize(signed short a
, int, int=0) { return sizeof(a
); }
103 inline unsigned int GetSerializeSize(unsigned short a
, int, int=0) { return sizeof(a
); }
104 inline unsigned int GetSerializeSize(signed int a
, int, int=0) { return sizeof(a
); }
105 inline unsigned int GetSerializeSize(unsigned int a
, int, int=0) { return sizeof(a
); }
106 inline unsigned int GetSerializeSize(signed long a
, int, int=0) { return sizeof(a
); }
107 inline unsigned int GetSerializeSize(unsigned long a
, int, int=0) { return sizeof(a
); }
108 inline unsigned int GetSerializeSize(int64 a
, int, int=0) { return sizeof(a
); }
109 inline unsigned int GetSerializeSize(uint64 a
, int, int=0) { return sizeof(a
); }
110 inline unsigned int GetSerializeSize(float a
, int, int=0) { return sizeof(a
); }
111 inline unsigned int GetSerializeSize(double a
, int, int=0) { return sizeof(a
); }
113 template<typename Stream
> inline void Serialize(Stream
& s
, char a
, int, int=0) { WRITEDATA(s
, a
); }
114 template<typename Stream
> inline void Serialize(Stream
& s
, signed char a
, int, int=0) { WRITEDATA(s
, a
); }
115 template<typename Stream
> inline void Serialize(Stream
& s
, unsigned char a
, int, int=0) { WRITEDATA(s
, a
); }
116 template<typename Stream
> inline void Serialize(Stream
& s
, signed short a
, int, int=0) { WRITEDATA(s
, a
); }
117 template<typename Stream
> inline void Serialize(Stream
& s
, unsigned short a
, int, int=0) { WRITEDATA(s
, a
); }
118 template<typename Stream
> inline void Serialize(Stream
& s
, signed int a
, int, int=0) { WRITEDATA(s
, a
); }
119 template<typename Stream
> inline void Serialize(Stream
& s
, unsigned int a
, int, int=0) { WRITEDATA(s
, a
); }
120 template<typename Stream
> inline void Serialize(Stream
& s
, signed long a
, int, int=0) { WRITEDATA(s
, a
); }
121 template<typename Stream
> inline void Serialize(Stream
& s
, unsigned long a
, int, int=0) { WRITEDATA(s
, a
); }
122 template<typename Stream
> inline void Serialize(Stream
& s
, int64 a
, int, int=0) { WRITEDATA(s
, a
); }
123 template<typename Stream
> inline void Serialize(Stream
& s
, uint64 a
, int, int=0) { WRITEDATA(s
, a
); }
124 template<typename Stream
> inline void Serialize(Stream
& s
, float a
, int, int=0) { WRITEDATA(s
, a
); }
125 template<typename Stream
> inline void Serialize(Stream
& s
, double a
, int, int=0) { WRITEDATA(s
, a
); }
127 template<typename Stream
> inline void Unserialize(Stream
& s
, char& a
, int, int=0) { READDATA(s
, a
); }
128 template<typename Stream
> inline void Unserialize(Stream
& s
, signed char& a
, int, int=0) { READDATA(s
, a
); }
129 template<typename Stream
> inline void Unserialize(Stream
& s
, unsigned char& a
, int, int=0) { READDATA(s
, a
); }
130 template<typename Stream
> inline void Unserialize(Stream
& s
, signed short& a
, int, int=0) { READDATA(s
, a
); }
131 template<typename Stream
> inline void Unserialize(Stream
& s
, unsigned short& a
, int, int=0) { READDATA(s
, a
); }
132 template<typename Stream
> inline void Unserialize(Stream
& s
, signed int& a
, int, int=0) { READDATA(s
, a
); }
133 template<typename Stream
> inline void Unserialize(Stream
& s
, unsigned int& a
, int, int=0) { READDATA(s
, a
); }
134 template<typename Stream
> inline void Unserialize(Stream
& s
, signed long& a
, int, int=0) { READDATA(s
, a
); }
135 template<typename Stream
> inline void Unserialize(Stream
& s
, unsigned long& a
, int, int=0) { READDATA(s
, a
); }
136 template<typename Stream
> inline void Unserialize(Stream
& s
, int64
& a
, int, int=0) { READDATA(s
, a
); }
137 template<typename Stream
> inline void Unserialize(Stream
& s
, uint64
& a
, int, int=0) { READDATA(s
, a
); }
138 template<typename Stream
> inline void Unserialize(Stream
& s
, float& a
, int, int=0) { READDATA(s
, a
); }
139 template<typename Stream
> inline void Unserialize(Stream
& s
, double& a
, int, int=0) { READDATA(s
, a
); }
141 inline unsigned int GetSerializeSize(bool a
, int, int=0) { return sizeof(char); }
142 template<typename Stream
> inline void Serialize(Stream
& s
, bool a
, int, int=0) { char f
=a
; WRITEDATA(s
, f
); }
143 template<typename Stream
> inline void Unserialize(Stream
& s
, bool& a
, int, int=0) { char f
; READDATA(s
, f
); a
=f
; }
152 // size < 253 -- 1 byte
153 // size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)
154 // size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
155 // size > UINT_MAX -- 9 bytes (255 + 8 bytes)
157 inline unsigned int GetSizeOfCompactSize(uint64 nSize
)
159 if (nSize
< 253) return sizeof(unsigned char);
160 else if (nSize
<= USHRT_MAX
) return sizeof(unsigned char) + sizeof(unsigned short);
161 else if (nSize
<= UINT_MAX
) return sizeof(unsigned char) + sizeof(unsigned int);
162 else return sizeof(unsigned char) + sizeof(uint64
);
165 template<typename Stream
>
166 void WriteCompactSize(Stream
& os
, uint64 nSize
)
170 unsigned char chSize
= nSize
;
171 WRITEDATA(os
, chSize
);
173 else if (nSize
<= USHRT_MAX
)
175 unsigned char chSize
= 253;
176 unsigned short xSize
= nSize
;
177 WRITEDATA(os
, chSize
);
178 WRITEDATA(os
, xSize
);
180 else if (nSize
<= UINT_MAX
)
182 unsigned char chSize
= 254;
183 unsigned int xSize
= nSize
;
184 WRITEDATA(os
, chSize
);
185 WRITEDATA(os
, xSize
);
189 unsigned char chSize
= 255;
190 uint64 xSize
= nSize
;
191 WRITEDATA(os
, chSize
);
192 WRITEDATA(os
, xSize
);
197 template<typename Stream
>
198 uint64
ReadCompactSize(Stream
& is
)
200 unsigned char chSize
;
201 READDATA(is
, chSize
);
207 else if (chSize
== 253)
209 unsigned short xSize
;
213 else if (chSize
== 254)
225 if (nSizeRet
> (uint64
)MAX_SIZE
)
226 throw std::ios_base::failure("ReadCompactSize() : size too large");
233 // Wrapper for serializing arrays and POD
234 // There's a clever template way to make arrays serialize normally, but MSVC6 doesn't support it
236 #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
243 CFlatData(void* pbeginIn
, void* pendIn
) : pbegin((char*)pbeginIn
), pend((char*)pendIn
) { }
244 char* begin() { return pbegin
; }
245 const char* begin() const { return pbegin
; }
246 char* end() { return pend
; }
247 const char* end() const { return pend
; }
249 unsigned int GetSerializeSize(int, int=0) const
251 return pend
- pbegin
;
254 template<typename Stream
>
255 void Serialize(Stream
& s
, int, int=0) const
257 s
.write(pbegin
, pend
- pbegin
);
260 template<typename Stream
>
261 void Unserialize(Stream
& s
, int, int=0)
263 s
.read(pbegin
, pend
- pbegin
);
270 // string stored as a fixed length field
272 template<std::size_t LEN
>
273 class CFixedFieldString
279 explicit CFixedFieldString(const string
& str
) : pcstr(&str
), pstr(NULL
) { }
280 explicit CFixedFieldString(string
& str
) : pcstr(&str
), pstr(&str
) { }
282 unsigned int GetSerializeSize(int, int=0) const
287 template<typename Stream
>
288 void Serialize(Stream
& s
, int, int=0) const
291 strncpy(pszBuf
, pcstr
->c_str(), LEN
);
292 s
.write(pszBuf
, LEN
);
295 template<typename Stream
>
296 void Unserialize(Stream
& s
, int, int=0)
299 throw std::ios_base::failure("CFixedFieldString::Unserialize : trying to unserialize to const string");
312 // Forward declarations
316 template<typename C
> unsigned int GetSerializeSize(const basic_string
<C
>& str
, int, int=0);
317 template<typename Stream
, typename C
> void Serialize(Stream
& os
, const basic_string
<C
>& str
, int, int=0);
318 template<typename Stream
, typename C
> void Unserialize(Stream
& is
, basic_string
<C
>& str
, int, int=0);
321 template<typename T
, typename A
> unsigned int GetSerializeSize_impl(const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&);
322 template<typename T
, typename A
> unsigned int GetSerializeSize_impl(const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&);
323 template<typename T
, typename A
> inline unsigned int GetSerializeSize(const std::vector
<T
, A
>& v
, int nType
, int nVersion
=VERSION
);
324 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
&);
325 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
&);
326 template<typename Stream
, typename T
, typename A
> inline void Serialize(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
=VERSION
);
327 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
&);
328 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
&);
329 template<typename Stream
, typename T
, typename A
> inline void Unserialize(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
=VERSION
);
331 // others derived from vector
332 extern inline unsigned int GetSerializeSize(const CScript
& v
, int nType
, int nVersion
=VERSION
);
333 template<typename Stream
> void Serialize(Stream
& os
, const CScript
& v
, int nType
, int nVersion
=VERSION
);
334 template<typename Stream
> void Unserialize(Stream
& is
, CScript
& v
, int nType
, int nVersion
=VERSION
);
337 template<typename K
, typename T
> unsigned int GetSerializeSize(const std::pair
<K
, T
>& item
, int nType
, int nVersion
=VERSION
);
338 template<typename Stream
, typename K
, typename T
> void Serialize(Stream
& os
, const std::pair
<K
, T
>& item
, int nType
, int nVersion
=VERSION
);
339 template<typename Stream
, typename K
, typename T
> void Unserialize(Stream
& is
, std::pair
<K
, T
>& item
, int nType
, int nVersion
=VERSION
);
342 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
);
343 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
);
344 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
);
347 template<typename K
, typename Pred
, typename A
> unsigned int GetSerializeSize(const std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
=VERSION
);
348 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
);
349 template<typename Stream
, typename K
, typename Pred
, typename A
> void Unserialize(Stream
& is
, std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
=VERSION
);
356 // If none of the specialized versions above matched, default to calling member function.
357 // "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
358 // The compiler will only cast int to long if none of the other templates matched.
359 // Thanks to Boost serialization for this idea.
362 inline unsigned int GetSerializeSize(const T
& a
, long nType
, int nVersion
=VERSION
)
364 return a
.GetSerializeSize((int)nType
, nVersion
);
367 template<typename Stream
, typename T
>
368 inline void Serialize(Stream
& os
, const T
& a
, long nType
, int nVersion
=VERSION
)
370 a
.Serialize(os
, (int)nType
, nVersion
);
373 template<typename Stream
, typename T
>
374 inline void Unserialize(Stream
& is
, T
& a
, long nType
, int nVersion
=VERSION
)
376 a
.Unserialize(is
, (int)nType
, nVersion
);
387 unsigned int GetSerializeSize(const basic_string
<C
>& str
, int, int)
389 return GetSizeOfCompactSize(str
.size()) + str
.size() * sizeof(str
[0]);
392 template<typename Stream
, typename C
>
393 void Serialize(Stream
& os
, const basic_string
<C
>& str
, int, int)
395 WriteCompactSize(os
, str
.size());
397 os
.write((char*)&str
[0], str
.size() * sizeof(str
[0]));
400 template<typename Stream
, typename C
>
401 void Unserialize(Stream
& is
, basic_string
<C
>& str
, int, int)
403 unsigned int nSize
= ReadCompactSize(is
);
406 is
.read((char*)&str
[0], nSize
* sizeof(str
[0]));
414 template<typename T
, typename A
>
415 unsigned int GetSerializeSize_impl(const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&)
417 return (GetSizeOfCompactSize(v
.size()) + v
.size() * sizeof(T
));
420 template<typename T
, typename A
>
421 unsigned int GetSerializeSize_impl(const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&)
423 unsigned int nSize
= GetSizeOfCompactSize(v
.size());
424 for (typename
std::vector
<T
, A
>::const_iterator vi
= v
.begin(); vi
!= v
.end(); ++vi
)
425 nSize
+= GetSerializeSize((*vi
), nType
, nVersion
);
429 template<typename T
, typename A
>
430 inline unsigned int GetSerializeSize(const std::vector
<T
, A
>& v
, int nType
, int nVersion
)
432 return GetSerializeSize_impl(v
, nType
, nVersion
, boost::is_fundamental
<T
>());
436 template<typename Stream
, typename T
, typename A
>
437 void Serialize_impl(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&)
439 WriteCompactSize(os
, v
.size());
441 os
.write((char*)&v
[0], v
.size() * sizeof(T
));
444 template<typename Stream
, typename T
, typename A
>
445 void Serialize_impl(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&)
447 WriteCompactSize(os
, v
.size());
448 for (typename
std::vector
<T
, A
>::const_iterator vi
= v
.begin(); vi
!= v
.end(); ++vi
)
449 ::Serialize(os
, (*vi
), nType
, nVersion
);
452 template<typename Stream
, typename T
, typename A
>
453 inline void Serialize(Stream
& os
, const std::vector
<T
, A
>& v
, int nType
, int nVersion
)
455 Serialize_impl(os
, v
, nType
, nVersion
, boost::is_fundamental
<T
>());
459 template<typename Stream
, typename T
, typename A
>
460 void Unserialize_impl(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::true_type
&)
462 //unsigned int nSize = ReadCompactSize(is);
464 //is.read((char*)&v[0], nSize * sizeof(T));
466 // Limit size per read so bogus size value won't cause out of memory
468 unsigned int nSize
= ReadCompactSize(is
);
472 unsigned int blk
= min(nSize
- i
, (unsigned int)(1 + 4999999 / sizeof(T
)));
474 is
.read((char*)&v
[i
], blk
* sizeof(T
));
479 template<typename Stream
, typename T
, typename A
>
480 void Unserialize_impl(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
, const boost::false_type
&)
482 //unsigned int nSize = ReadCompactSize(is);
484 //for (std::vector<T, A>::iterator vi = v.begin(); vi != v.end(); ++vi)
485 // Unserialize(is, (*vi), nType, nVersion);
488 unsigned int nSize
= ReadCompactSize(is
);
490 unsigned int nMid
= 0;
493 nMid
+= 5000000 / sizeof(T
);
497 for (; i
< nMid
; i
++)
498 Unserialize(is
, v
[i
], nType
, nVersion
);
502 template<typename Stream
, typename T
, typename A
>
503 inline void Unserialize(Stream
& is
, std::vector
<T
, A
>& v
, int nType
, int nVersion
)
505 Unserialize_impl(is
, v
, nType
, nVersion
, boost::is_fundamental
<T
>());
511 // others derived from vector
513 inline unsigned int GetSerializeSize(const CScript
& v
, int nType
, int nVersion
)
515 return GetSerializeSize((const vector
<unsigned char>&)v
, nType
, nVersion
);
518 template<typename Stream
>
519 void Serialize(Stream
& os
, const CScript
& v
, int nType
, int nVersion
)
521 Serialize(os
, (const vector
<unsigned char>&)v
, nType
, nVersion
);
524 template<typename Stream
>
525 void Unserialize(Stream
& is
, CScript
& v
, int nType
, int nVersion
)
527 Unserialize(is
, (vector
<unsigned char>&)v
, nType
, nVersion
);
535 template<typename K
, typename T
>
536 unsigned int GetSerializeSize(const std::pair
<K
, T
>& item
, int nType
, int nVersion
)
538 return GetSerializeSize(item
.first
, nType
, nVersion
) + GetSerializeSize(item
.second
, nType
, nVersion
);
541 template<typename Stream
, typename K
, typename T
>
542 void Serialize(Stream
& os
, const std::pair
<K
, T
>& item
, int nType
, int nVersion
)
544 Serialize(os
, item
.first
, nType
, nVersion
);
545 Serialize(os
, item
.second
, nType
, nVersion
);
548 template<typename Stream
, typename K
, typename T
>
549 void Unserialize(Stream
& is
, std::pair
<K
, T
>& item
, int nType
, int nVersion
)
551 Unserialize(is
, item
.first
, nType
, nVersion
);
552 Unserialize(is
, item
.second
, nType
, nVersion
);
560 template<typename K
, typename T
, typename Pred
, typename A
>
561 unsigned int GetSerializeSize(const std::map
<K
, T
, Pred
, A
>& m
, int nType
, int nVersion
)
563 unsigned int nSize
= GetSizeOfCompactSize(m
.size());
564 for (typename
std::map
<K
, T
, Pred
, A
>::const_iterator mi
= m
.begin(); mi
!= m
.end(); ++mi
)
565 nSize
+= GetSerializeSize((*mi
), nType
, nVersion
);
569 template<typename Stream
, typename K
, typename T
, typename Pred
, typename A
>
570 void Serialize(Stream
& os
, const std::map
<K
, T
, Pred
, A
>& m
, int nType
, int nVersion
)
572 WriteCompactSize(os
, m
.size());
573 for (typename
std::map
<K
, T
, Pred
, A
>::const_iterator mi
= m
.begin(); mi
!= m
.end(); ++mi
)
574 Serialize(os
, (*mi
), nType
, nVersion
);
577 template<typename Stream
, typename K
, typename T
, typename Pred
, typename A
>
578 void Unserialize(Stream
& is
, std::map
<K
, T
, Pred
, A
>& m
, int nType
, int nVersion
)
581 unsigned int nSize
= ReadCompactSize(is
);
582 typename
std::map
<K
, T
, Pred
, A
>::iterator mi
= m
.begin();
583 for (unsigned int i
= 0; i
< nSize
; i
++)
586 Unserialize(is
, item
, nType
, nVersion
);
587 mi
= m
.insert(mi
, item
);
596 template<typename K
, typename Pred
, typename A
>
597 unsigned int GetSerializeSize(const std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
)
599 unsigned int nSize
= GetSizeOfCompactSize(m
.size());
600 for (typename
std::set
<K
, Pred
, A
>::const_iterator it
= m
.begin(); it
!= m
.end(); ++it
)
601 nSize
+= GetSerializeSize((*it
), nType
, nVersion
);
605 template<typename Stream
, typename K
, typename Pred
, typename A
>
606 void Serialize(Stream
& os
, const std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
)
608 WriteCompactSize(os
, m
.size());
609 for (typename
std::set
<K
, Pred
, A
>::const_iterator it
= m
.begin(); it
!= m
.end(); ++it
)
610 Serialize(os
, (*it
), nType
, nVersion
);
613 template<typename Stream
, typename K
, typename Pred
, typename A
>
614 void Unserialize(Stream
& is
, std::set
<K
, Pred
, A
>& m
, int nType
, int nVersion
)
617 unsigned int nSize
= ReadCompactSize(is
);
618 typename
std::set
<K
, Pred
, A
>::iterator it
= m
.begin();
619 for (unsigned int i
= 0; i
< nSize
; i
++)
622 Unserialize(is
, key
, nType
, nVersion
);
623 it
= m
.insert(it
, key
);
630 // Support for IMPLEMENT_SERIALIZE and READWRITE macro
632 class CSerActionGetSerializeSize
{ };
633 class CSerActionSerialize
{ };
634 class CSerActionUnserialize
{ };
636 template<typename Stream
, typename T
>
637 inline unsigned int SerReadWrite(Stream
& s
, const T
& obj
, int nType
, int nVersion
, CSerActionGetSerializeSize ser_action
)
639 return ::GetSerializeSize(obj
, nType
, nVersion
);
642 template<typename Stream
, typename T
>
643 inline unsigned int SerReadWrite(Stream
& s
, const T
& obj
, int nType
, int nVersion
, CSerActionSerialize ser_action
)
645 ::Serialize(s
, obj
, nType
, nVersion
);
649 template<typename Stream
, typename T
>
650 inline unsigned int SerReadWrite(Stream
& s
, T
& obj
, int nType
, int nVersion
, CSerActionUnserialize ser_action
)
652 ::Unserialize(s
, obj
, nType
, nVersion
);
656 struct ser_streamplaceholder
671 // Allocator that clears its contents before deletion
674 struct secure_allocator
: public std::allocator
<T
>
676 // MSVC8 default copy constructor is broken
677 typedef std::allocator
<T
> base
;
678 typedef typename
base::size_type size_type
;
679 typedef typename
base::difference_type difference_type
;
680 typedef typename
base::pointer pointer
;
681 typedef typename
base::const_pointer const_pointer
;
682 typedef typename
base::reference reference
;
683 typedef typename
base::const_reference const_reference
;
684 typedef typename
base::value_type value_type
;
685 secure_allocator() throw() {}
686 secure_allocator(const secure_allocator
& a
) throw() : base(a
) {}
687 ~secure_allocator() throw() {}
688 template<typename _Other
> struct rebind
689 { typedef secure_allocator
<_Other
> other
; };
691 void deallocate(T
* p
, std::size_t n
)
694 memset(p
, 0, sizeof(T
) * n
);
695 allocator
<T
>::deallocate(p
, n
);
702 // Double ended buffer combining vector and stream-like interfaces.
703 // >> and << read and write unformatted data using the above serialization templates.
704 // Fills with data in linear time; some stringstream implementations take N^2 time.
709 typedef vector
<char, secure_allocator
<char> > vector_type
;
711 unsigned int nReadPos
;
718 typedef vector_type::allocator_type allocator_type
;
719 typedef vector_type::size_type size_type
;
720 typedef vector_type::difference_type difference_type
;
721 typedef vector_type::reference reference
;
722 typedef vector_type::const_reference const_reference
;
723 typedef vector_type::value_type value_type
;
724 typedef vector_type::iterator iterator
;
725 typedef vector_type::const_iterator const_iterator
;
726 typedef vector_type::reverse_iterator reverse_iterator
;
728 explicit CDataStream(int nTypeIn
=SER_NETWORK
, int nVersionIn
=VERSION
)
730 Init(nTypeIn
, nVersionIn
);
733 CDataStream(const_iterator pbegin
, const_iterator pend
, int nTypeIn
=SER_NETWORK
, int nVersionIn
=VERSION
) : vch(pbegin
, pend
)
735 Init(nTypeIn
, nVersionIn
);
738 #if !defined(_MSC_VER) || _MSC_VER >= 1300
739 CDataStream(const char* pbegin
, const char* pend
, int nTypeIn
=SER_NETWORK
, int nVersionIn
=VERSION
) : vch(pbegin
, pend
)
741 Init(nTypeIn
, nVersionIn
);
745 CDataStream(const vector_type
& vchIn
, int nTypeIn
=SER_NETWORK
, int nVersionIn
=VERSION
) : vch(vchIn
.begin(), vchIn
.end())
747 Init(nTypeIn
, nVersionIn
);
750 CDataStream(const vector
<char>& vchIn
, int nTypeIn
=SER_NETWORK
, int nVersionIn
=VERSION
) : vch(vchIn
.begin(), vchIn
.end())
752 Init(nTypeIn
, nVersionIn
);
755 CDataStream(const vector
<unsigned char>& vchIn
, int nTypeIn
=SER_NETWORK
, int nVersionIn
=VERSION
) : vch((char*)&vchIn
.begin()[0], (char*)&vchIn
.end()[0])
757 Init(nTypeIn
, nVersionIn
);
760 void Init(int nTypeIn
=SER_NETWORK
, int nVersionIn
=VERSION
)
764 nVersion
= nVersionIn
;
766 exceptmask
= ios::badbit
| ios::failbit
;
769 CDataStream
& operator+=(const CDataStream
& b
)
771 vch
.insert(vch
.end(), b
.begin(), b
.end());
775 friend CDataStream
operator+(const CDataStream
& a
, const CDataStream
& b
)
784 return (string(begin(), end()));
791 const_iterator
begin() const { return vch
.begin() + nReadPos
; }
792 iterator
begin() { return vch
.begin() + nReadPos
; }
793 const_iterator
end() const { return vch
.end(); }
794 iterator
end() { return vch
.end(); }
795 size_type
size() const { return vch
.size() - nReadPos
; }
796 bool empty() const { return vch
.size() == nReadPos
; }
797 void resize(size_type n
, value_type c
=0) { vch
.resize(n
+ nReadPos
, c
); }
798 void reserve(size_type n
) { vch
.reserve(n
+ nReadPos
); }
799 const_reference
operator[](size_type pos
) const { return vch
[pos
+ nReadPos
]; }
800 reference
operator[](size_type pos
) { return vch
[pos
+ nReadPos
]; }
801 void clear() { vch
.clear(); nReadPos
= 0; }
802 iterator
insert(iterator it
, const char& x
=char()) { return vch
.insert(it
, x
); }
803 void insert(iterator it
, size_type n
, const char& x
) { vch
.insert(it
, n
, x
); }
805 void insert(iterator it
, const_iterator first
, const_iterator last
)
807 if (it
== vch
.begin() + nReadPos
&& last
- first
<= nReadPos
)
809 // special case for inserting at the front when there's room
810 nReadPos
-= (last
- first
);
811 memcpy(&vch
[nReadPos
], &first
[0], last
- first
);
814 vch
.insert(it
, first
, last
);
817 void insert(iterator it
, vector
<char>::const_iterator first
, vector
<char>::const_iterator last
)
819 if (it
== vch
.begin() + nReadPos
&& last
- first
<= nReadPos
)
821 // special case for inserting at the front when there's room
822 nReadPos
-= (last
- first
);
823 memcpy(&vch
[nReadPos
], &first
[0], last
- first
);
826 vch
.insert(it
, first
, last
);
829 #if !defined(_MSC_VER) || _MSC_VER >= 1300
830 void insert(iterator it
, const char* first
, const char* last
)
832 if (it
== vch
.begin() + nReadPos
&& last
- first
<= nReadPos
)
834 // special case for inserting at the front when there's room
835 nReadPos
-= (last
- first
);
836 memcpy(&vch
[nReadPos
], &first
[0], last
- first
);
839 vch
.insert(it
, first
, last
);
843 iterator
erase(iterator it
)
845 if (it
== vch
.begin() + nReadPos
)
847 // special case for erasing from the front
848 if (++nReadPos
>= vch
.size())
850 // whenever we reach the end, we take the opportunity to clear the buffer
852 return vch
.erase(vch
.begin(), vch
.end());
854 return vch
.begin() + nReadPos
;
857 return vch
.erase(it
);
860 iterator
erase(iterator first
, iterator last
)
862 if (first
== vch
.begin() + nReadPos
)
864 // special case for erasing from the front
865 if (last
== vch
.end())
868 return vch
.erase(vch
.begin(), vch
.end());
872 nReadPos
= (last
- vch
.begin());
877 return vch
.erase(first
, last
);
880 inline void Compact()
882 vch
.erase(vch
.begin(), vch
.begin() + nReadPos
);
886 bool Rewind(size_type n
)
888 // Rewind by n characters if the buffer hasn't been compacted yet
899 void setstate(short bits
, const char* psz
)
902 if (state
& exceptmask
)
903 throw std::ios_base::failure(psz
);
906 bool eof() const { return size() == 0; }
907 bool fail() const { return state
& (ios::badbit
| ios::failbit
); }
908 bool good() const { return !eof() && (state
== 0); }
909 void clear(short n
) { state
= n
; } // name conflict with vector clear()
910 short exceptions() { return exceptmask
; }
911 short exceptions(short mask
) { short prev
= exceptmask
; exceptmask
= mask
; setstate(0, "CDataStream"); return prev
; }
912 CDataStream
* rdbuf() { return this; }
913 int in_avail() { return size(); }
915 void SetType(int n
) { nType
= n
; }
916 int GetType() { return nType
; }
917 void SetVersion(int n
) { nVersion
= n
; }
918 int GetVersion() { return nVersion
; }
919 void ReadVersion() { *this >> nVersion
; }
920 void WriteVersion() { *this << nVersion
; }
922 CDataStream
& read(char* pch
, int nSize
)
924 // Read from the beginning of the buffer
926 unsigned int nReadPosNext
= nReadPos
+ nSize
;
927 if (nReadPosNext
>= vch
.size())
929 if (nReadPosNext
> vch
.size())
931 setstate(ios::failbit
, "CDataStream::read() : end of data");
932 memset(pch
, 0, nSize
);
933 nSize
= vch
.size() - nReadPos
;
935 memcpy(pch
, &vch
[nReadPos
], nSize
);
940 memcpy(pch
, &vch
[nReadPos
], nSize
);
941 nReadPos
= nReadPosNext
;
945 CDataStream
& ignore(int nSize
)
947 // Ignore from the beginning of the buffer
949 unsigned int nReadPosNext
= nReadPos
+ nSize
;
950 if (nReadPosNext
>= vch
.size())
952 if (nReadPosNext
> vch
.size())
954 setstate(ios::failbit
, "CDataStream::ignore() : end of data");
955 nSize
= vch
.size() - nReadPos
;
961 nReadPos
= nReadPosNext
;
965 CDataStream
& write(const char* pch
, int nSize
)
967 // Write to the end of the buffer
969 vch
.insert(vch
.end(), pch
, pch
+ nSize
);
973 template<typename Stream
>
974 void Serialize(Stream
& s
, int nType
=0, int nVersion
=VERSION
) const
976 // Special case: stream << stream concatenates like stream += stream
978 s
.write((char*)&vch
[0], vch
.size() * sizeof(vch
[0]));
982 unsigned int GetSerializeSize(const T
& obj
)
984 // Tells the size of the object if serialized to this stream
985 return ::GetSerializeSize(obj
, nType
, nVersion
);
989 CDataStream
& operator<<(const T
& obj
)
991 // Serialize to this stream
992 ::Serialize(*this, obj
, nType
, nVersion
);
997 CDataStream
& operator>>(T
& obj
)
999 // Unserialize from this stream
1000 ::Unserialize(*this, obj
, nType
, nVersion
);
1005 #ifdef TESTCDATASTREAM
1012 // n=16000 0 seconds
1013 // n=32000 0 seconds
1014 // n=64000 1 seconds
1015 // n=128000 1 seconds
1016 // n=256000 2 seconds
1017 // n=512000 4 seconds
1018 // n=1024000 8 seconds
1019 // n=2048000 16 seconds
1020 // n=4096000 32 seconds
1024 // n=4000 13 seconds
1025 // n=8000 87 seconds
1026 // n=16000 400 seconds
1027 // n=32000 1660 seconds
1028 // n=64000 6749 seconds
1029 // n=128000 27241 seconds
1030 // n=256000 109804 seconds
1032 int main(int argc
, char *argv
[])
1034 vector
<unsigned char> vch(0xcc, 250);
1035 printf("CDataStream:\n");
1036 for (int n
= 1000; n
<= 4500000; n
*= 2)
1039 time_t nStart
= time(NULL
);
1040 for (int i
= 0; i
< n
; i
++)
1041 ss
.write((char*)&vch
[0], vch
.size());
1042 printf("n=%-10d %d seconds\n", n
, time(NULL
) - nStart
);
1044 printf("stringstream:\n");
1045 for (int n
= 1000; n
<= 4500000; n
*= 2)
1048 time_t nStart
= time(NULL
);
1049 for (int i
= 0; i
< n
; i
++)
1050 ss
.write((char*)&vch
[0], vch
.size());
1051 printf("n=%-10d %d seconds\n", n
, time(NULL
) - nStart
);
1066 // Automatic closing wrapper for FILE*
1067 // - Will automatically close the file when it goes out of scope if not null.
1068 // - If you're returning the file pointer, return file.release().
1069 // - If you need to close the file early, use file.fclose() instead of fclose(file).
1081 typedef FILE element_type
;
1083 CAutoFile(FILE* filenew
=NULL
, int nTypeIn
=SER_DISK
, int nVersionIn
=VERSION
)
1087 nVersion
= nVersionIn
;
1089 exceptmask
= ios::badbit
| ios::failbit
;
1099 if (file
!= NULL
&& file
!= stdin
&& file
!= stdout
&& file
!= stderr
)
1104 FILE* release() { FILE* ret
= file
; file
= NULL
; return ret
; }
1105 operator FILE*() { return file
; }
1106 FILE* operator->() { return file
; }
1107 FILE& operator*() { return *file
; }
1108 FILE** operator&() { return &file
; }
1109 FILE* operator=(FILE* pnew
) { return file
= pnew
; }
1110 bool operator!() { return (file
== NULL
); }
1116 void setstate(short bits
, const char* psz
)
1119 if (state
& exceptmask
)
1120 throw std::ios_base::failure(psz
);
1123 bool fail() const { return state
& (ios::badbit
| ios::failbit
); }
1124 bool good() const { return state
== 0; }
1125 void clear(short n
= 0) { state
= n
; }
1126 short exceptions() { return exceptmask
; }
1127 short exceptions(short mask
) { short prev
= exceptmask
; exceptmask
= mask
; setstate(0, "CAutoFile"); return prev
; }
1129 void SetType(int n
) { nType
= n
; }
1130 int GetType() { return nType
; }
1131 void SetVersion(int n
) { nVersion
= n
; }
1132 int GetVersion() { return nVersion
; }
1133 void ReadVersion() { *this >> nVersion
; }
1134 void WriteVersion() { *this << nVersion
; }
1136 CAutoFile
& read(char* pch
, int nSize
)
1139 throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
1140 if (fread(pch
, 1, nSize
, file
) != nSize
)
1141 setstate(ios::failbit
, feof(file
) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
1145 CAutoFile
& write(const char* pch
, int nSize
)
1148 throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
1149 if (fwrite(pch
, 1, nSize
, file
) != nSize
)
1150 setstate(ios::failbit
, "CAutoFile::write : write failed");
1154 template<typename T
>
1155 unsigned int GetSerializeSize(const T
& obj
)
1157 // Tells the size of the object if serialized to this stream
1158 return ::GetSerializeSize(obj
, nType
, nVersion
);
1161 template<typename T
>
1162 CAutoFile
& operator<<(const T
& obj
)
1164 // Serialize to this stream
1166 throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
1167 ::Serialize(*this, obj
, nType
, nVersion
);
1171 template<typename T
>
1172 CAutoFile
& operator>>(T
& obj
)
1174 // Unserialize from this stream
1176 throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");
1177 ::Unserialize(*this, obj
, nType
, nVersion
);