]> Git Repo - VerusCoin.git/blob - serialize.h
misc exit code, updated setup.nsi
[VerusCoin.git] / serialize.h
1 // Copyright (c) 2009 Satoshi Nakamoto\r
2 // Distributed under the MIT/X11 software license, see the accompanying\r
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
4 \r
5 #include <vector>\r
6 #include <map>\r
7 #include <boost/type_traits/is_fundamental.hpp>\r
8 #if defined(_MSC_VER) || defined(__BORLANDC__)\r
9 typedef __int64  int64;\r
10 typedef unsigned __int64  uint64;\r
11 #else\r
12 typedef long long  int64;\r
13 typedef unsigned long long  uint64;\r
14 #endif\r
15 #if defined(_MSC_VER) && _MSC_VER < 1300\r
16 #define for  if (false) ; else for\r
17 #endif\r
18 class CScript;\r
19 class CDataStream;\r
20 class CAutoFile;\r
21 \r
22 static const int VERSION = 200;\r
23 static const char* pszSubVer = " rc1";\r
24 \r
25 \r
26 \r
27 \r
28 \r
29 /////////////////////////////////////////////////////////////////\r
30 //\r
31 // Templates for serializing to anything that looks like a stream,\r
32 // i.e. anything that supports .read(char*, int) and .write(char*, int)\r
33 //\r
34 \r
35 enum\r
36 {\r
37     // primary actions\r
38     SER_NETWORK         = (1 << 0),\r
39     SER_DISK            = (1 << 1),\r
40     SER_GETHASH         = (1 << 2),\r
41 \r
42     // modifiers\r
43     SER_SKIPSIG         = (1 << 16),\r
44     SER_BLOCKHEADERONLY = (1 << 17),\r
45 };\r
46 \r
47 #define IMPLEMENT_SERIALIZE(statements)    \\r
48     unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const  \\r
49     {                                           \\r
50         CSerActionGetSerializeSize ser_action;  \\r
51         const bool fGetSize = true;             \\r
52         const bool fWrite = false;              \\r
53         const bool fRead = false;               \\r
54         unsigned int nSerSize = 0;              \\r
55         ser_streamplaceholder s;                \\r
56         s.nType = nType;                        \\r
57         s.nVersion = nVersion;                  \\r
58         {statements}                            \\r
59         return nSerSize;                        \\r
60     }                                           \\r
61     template<typename Stream>                   \\r
62     void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const  \\r
63     {                                           \\r
64         CSerActionSerialize ser_action;         \\r
65         const bool fGetSize = false;            \\r
66         const bool fWrite = true;               \\r
67         const bool fRead = false;               \\r
68         unsigned int nSerSize = 0;              \\r
69         {statements}                            \\r
70     }                                           \\r
71     template<typename Stream>                   \\r
72     void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)  \\r
73     {                                           \\r
74         CSerActionUnserialize ser_action;       \\r
75         const bool fGetSize = false;            \\r
76         const bool fWrite = false;              \\r
77         const bool fRead = true;                \\r
78         unsigned int nSerSize = 0;              \\r
79         {statements}                            \\r
80     }\r
81 \r
82 #define READWRITE(obj)      (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))\r
83 \r
84 \r
85 \r
86 \r
87 \r
88 \r
89 //\r
90 // Basic types\r
91 //\r
92 #define WRITEDATA(s, obj)   s.write((char*)&(obj), sizeof(obj))\r
93 #define READDATA(s, obj)    s.read((char*)&(obj), sizeof(obj))\r
94 \r
95 inline unsigned int GetSerializeSize(char a,           int, int=0) { return sizeof(a); }\r
96 inline unsigned int GetSerializeSize(signed char a,    int, int=0) { return sizeof(a); }\r
97 inline unsigned int GetSerializeSize(unsigned char a,  int, int=0) { return sizeof(a); }\r
98 inline unsigned int GetSerializeSize(signed short a,   int, int=0) { return sizeof(a); }\r
99 inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); }\r
100 inline unsigned int GetSerializeSize(signed int a,     int, int=0) { return sizeof(a); }\r
101 inline unsigned int GetSerializeSize(unsigned int a,   int, int=0) { return sizeof(a); }\r
102 inline unsigned int GetSerializeSize(signed long a,    int, int=0) { return sizeof(a); }\r
103 inline unsigned int GetSerializeSize(unsigned long a,  int, int=0) { return sizeof(a); }\r
104 inline unsigned int GetSerializeSize(int64 a,          int, int=0) { return sizeof(a); }\r
105 inline unsigned int GetSerializeSize(uint64 a,         int, int=0) { return sizeof(a); }\r
106 inline unsigned int GetSerializeSize(float a,          int, int=0) { return sizeof(a); }\r
107 inline unsigned int GetSerializeSize(double a,         int, int=0) { return sizeof(a); }\r
108 \r
109 template<typename Stream> inline void Serialize(Stream& s, char a,           int, int=0) { WRITEDATA(s, a); }\r
110 template<typename Stream> inline void Serialize(Stream& s, signed char a,    int, int=0) { WRITEDATA(s, a); }\r
111 template<typename Stream> inline void Serialize(Stream& s, unsigned char a,  int, int=0) { WRITEDATA(s, a); }\r
112 template<typename Stream> inline void Serialize(Stream& s, signed short a,   int, int=0) { WRITEDATA(s, a); }\r
113 template<typename Stream> inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); }\r
114 template<typename Stream> inline void Serialize(Stream& s, signed int a,     int, int=0) { WRITEDATA(s, a); }\r
115 template<typename Stream> inline void Serialize(Stream& s, unsigned int a,   int, int=0) { WRITEDATA(s, a); }\r
116 template<typename Stream> inline void Serialize(Stream& s, signed long a,    int, int=0) { WRITEDATA(s, a); }\r
117 template<typename Stream> inline void Serialize(Stream& s, unsigned long a,  int, int=0) { WRITEDATA(s, a); }\r
118 template<typename Stream> inline void Serialize(Stream& s, int64 a,          int, int=0) { WRITEDATA(s, a); }\r
119 template<typename Stream> inline void Serialize(Stream& s, uint64 a,         int, int=0) { WRITEDATA(s, a); }\r
120 template<typename Stream> inline void Serialize(Stream& s, float a,          int, int=0) { WRITEDATA(s, a); }\r
121 template<typename Stream> inline void Serialize(Stream& s, double a,         int, int=0) { WRITEDATA(s, a); }\r
122 \r
123 template<typename Stream> inline void Unserialize(Stream& s, char& a,           int, int=0) { READDATA(s, a); }\r
124 template<typename Stream> inline void Unserialize(Stream& s, signed char& a,    int, int=0) { READDATA(s, a); }\r
125 template<typename Stream> inline void Unserialize(Stream& s, unsigned char& a,  int, int=0) { READDATA(s, a); }\r
126 template<typename Stream> inline void Unserialize(Stream& s, signed short& a,   int, int=0) { READDATA(s, a); }\r
127 template<typename Stream> inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); }\r
128 template<typename Stream> inline void Unserialize(Stream& s, signed int& a,     int, int=0) { READDATA(s, a); }\r
129 template<typename Stream> inline void Unserialize(Stream& s, unsigned int& a,   int, int=0) { READDATA(s, a); }\r
130 template<typename Stream> inline void Unserialize(Stream& s, signed long& a,    int, int=0) { READDATA(s, a); }\r
131 template<typename Stream> inline void Unserialize(Stream& s, unsigned long& a,  int, int=0) { READDATA(s, a); }\r
132 template<typename Stream> inline void Unserialize(Stream& s, int64& a,          int, int=0) { READDATA(s, a); }\r
133 template<typename Stream> inline void Unserialize(Stream& s, uint64& a,         int, int=0) { READDATA(s, a); }\r
134 template<typename Stream> inline void Unserialize(Stream& s, float& a,          int, int=0) { READDATA(s, a); }\r
135 template<typename Stream> inline void Unserialize(Stream& s, double& a,         int, int=0) { READDATA(s, a); }\r
136 \r
137 inline unsigned int GetSerializeSize(bool a, int, int=0)                          { return sizeof(char); }\r
138 template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0)    { char f=a; WRITEDATA(s, f); }\r
139 template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; }\r
140 \r
141 \r
142 \r
143 \r
144 \r
145 \r
146 //\r
147 // Compact size\r
148 //  size <  253        -- 1 byte\r
149 //  size <= USHRT_MAX  -- 3 bytes  (253 + 2 bytes)\r
150 //  size <= UINT_MAX   -- 5 bytes  (254 + 4 bytes)\r
151 //  size >  UINT_MAX   -- 9 bytes  (255 + 8 bytes)\r
152 //\r
153 inline unsigned int GetSizeOfCompactSize(uint64 nSize)\r
154 {\r
155     if (nSize < UCHAR_MAX-2)     return sizeof(unsigned char);\r
156     else if (nSize <= USHRT_MAX) return sizeof(unsigned char) + sizeof(unsigned short);\r
157     else if (nSize <= UINT_MAX)  return sizeof(unsigned char) + sizeof(unsigned int);\r
158     else                         return sizeof(unsigned char) + sizeof(uint64);\r
159 }\r
160 \r
161 template<typename Stream>\r
162 void WriteCompactSize(Stream& os, uint64 nSize)\r
163 {\r
164     if (nSize < UCHAR_MAX-2)\r
165     {\r
166         unsigned char chSize = nSize;\r
167         WRITEDATA(os, chSize);\r
168     }\r
169     else if (nSize <= USHRT_MAX)\r
170     {\r
171         unsigned char chSize = UCHAR_MAX-2;\r
172         unsigned short xSize = nSize;\r
173         WRITEDATA(os, chSize);\r
174         WRITEDATA(os, xSize);\r
175     }\r
176     else if (nSize <= UINT_MAX)\r
177     {\r
178         unsigned char chSize = UCHAR_MAX-1;\r
179         unsigned int xSize = nSize;\r
180         WRITEDATA(os, chSize);\r
181         WRITEDATA(os, xSize);\r
182     }\r
183     else\r
184     {\r
185         unsigned char chSize = UCHAR_MAX;\r
186         WRITEDATA(os, chSize);\r
187         WRITEDATA(os, nSize);\r
188     }\r
189     return;\r
190 }\r
191 \r
192 template<typename Stream>\r
193 uint64 ReadCompactSize(Stream& is)\r
194 {\r
195     unsigned char chSize;\r
196     READDATA(is, chSize);\r
197     if (chSize < UCHAR_MAX-2)\r
198     {\r
199         return chSize;\r
200     }\r
201     else if (chSize == UCHAR_MAX-2)\r
202     {\r
203         unsigned short nSize;\r
204         READDATA(is, nSize);\r
205         return nSize;\r
206     }\r
207     else if (chSize == UCHAR_MAX-1)\r
208     {\r
209         unsigned int nSize;\r
210         READDATA(is, nSize);\r
211         return nSize;\r
212     }\r
213     else\r
214     {\r
215         uint64 nSize;\r
216         READDATA(is, nSize);\r
217         return nSize;\r
218     }\r
219 }\r
220 \r
221 \r
222 \r
223 //\r
224 // Wrapper for serializing arrays and POD\r
225 // There's a clever template way to make arrays serialize normally, but MSVC6 doesn't support it\r
226 //\r
227 #define FLATDATA(obj)   REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))\r
228 class CFlatData\r
229 {\r
230 protected:\r
231     char* pbegin;\r
232     char* pend;\r
233 public:\r
234     CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }\r
235     char* begin() { return pbegin; }\r
236     const char* begin() const { return pbegin; }\r
237     char* end() { return pend; }\r
238     const char* end() const { return pend; }\r
239 \r
240     unsigned int GetSerializeSize(int, int=0) const\r
241     {\r
242         return pend - pbegin;\r
243     }\r
244 \r
245     template<typename Stream>\r
246     void Serialize(Stream& s, int, int=0) const\r
247     {\r
248         s.write(pbegin, pend - pbegin);\r
249     }\r
250 \r
251     template<typename Stream>\r
252     void Unserialize(Stream& s, int, int=0)\r
253     {\r
254         s.read(pbegin, pend - pbegin);\r
255     }\r
256 };\r
257 \r
258 \r
259 \r
260 //\r
261 // string stored as a fixed length field\r
262 //\r
263 template<std::size_t LEN>\r
264 class CFixedFieldString\r
265 {\r
266 protected:\r
267     const string* pcstr;\r
268     string* pstr;\r
269 public:\r
270     explicit CFixedFieldString(const string& str) : pcstr(&str), pstr(NULL) { }\r
271     explicit CFixedFieldString(string& str) : pcstr(&str), pstr(&str) { }\r
272 \r
273     unsigned int GetSerializeSize(int, int=0) const\r
274     {\r
275         return LEN;\r
276     }\r
277 \r
278     template<typename Stream>\r
279     void Serialize(Stream& s, int, int=0) const\r
280     {\r
281         char pszBuf[LEN];\r
282         strncpy(pszBuf, pcstr->c_str(), LEN);\r
283         s.write(pszBuf, LEN);\r
284     }\r
285 \r
286     template<typename Stream>\r
287     void Unserialize(Stream& s, int, int=0)\r
288     {\r
289         if (pstr == NULL)\r
290             throw std::ios_base::failure("CFixedFieldString::Unserialize : trying to unserialize to const string");\r
291         char pszBuf[LEN+1];\r
292         s.read(pszBuf, LEN);\r
293         pszBuf[LEN] = '\0';\r
294         *pstr = pszBuf;\r
295     }\r
296 };\r
297 \r
298 \r
299 \r
300 \r
301 \r
302 //\r
303 // Forward declarations\r
304 //\r
305 \r
306 // string\r
307 template<typename C> unsigned int GetSerializeSize(const basic_string<C>& str, int, int=0);\r
308 template<typename Stream, typename C> void Serialize(Stream& os, const basic_string<C>& str, int, int=0);\r
309 template<typename Stream, typename C> void Unserialize(Stream& is, basic_string<C>& str, int, int=0);\r
310 \r
311 // vector\r
312 template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);\r
313 template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);\r
314 template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion=VERSION);\r
315 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&);\r
316 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&);\r
317 template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion=VERSION);\r
318 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&);\r
319 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&);\r
320 template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion=VERSION);\r
321 \r
322 // others derived from vector\r
323 extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion=VERSION);\r
324 template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion=VERSION);\r
325 template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion=VERSION);\r
326 \r
327 // pair\r
328 template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion=VERSION);\r
329 template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion=VERSION);\r
330 template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion=VERSION);\r
331 \r
332 // map\r
333 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);\r
334 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);\r
335 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);\r
336 \r
337 // set\r
338 template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);\r
339 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);\r
340 template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);\r
341 \r
342 \r
343 \r
344 \r
345 \r
346 //\r
347 // If none of the specialized versions above matched, default to calling member function.\r
348 // "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.\r
349 // The compiler will only cast int to long if none of the other templates matched.\r
350 // Thanks to Boost serialization for this idea.\r
351 //\r
352 template<typename T>\r
353 inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion=VERSION)\r
354 {\r
355     return a.GetSerializeSize((int)nType, nVersion);\r
356 }\r
357 \r
358 template<typename Stream, typename T>\r
359 inline void Serialize(Stream& os, const T& a, long nType, int nVersion=VERSION)\r
360 {\r
361     a.Serialize(os, (int)nType, nVersion);\r
362 }\r
363 \r
364 template<typename Stream, typename T>\r
365 inline void Unserialize(Stream& is, T& a, long nType, int nVersion=VERSION)\r
366 {\r
367     a.Unserialize(is, (int)nType, nVersion);\r
368 }\r
369 \r
370 \r
371 \r
372 \r
373 \r
374 //\r
375 // string\r
376 //\r
377 template<typename C>\r
378 unsigned int GetSerializeSize(const basic_string<C>& str, int, int)\r
379 {\r
380     return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]);\r
381 }\r
382 \r
383 template<typename Stream, typename C>\r
384 void Serialize(Stream& os, const basic_string<C>& str, int, int)\r
385 {\r
386     WriteCompactSize(os, str.size());\r
387     if (!str.empty())\r
388         os.write((char*)&str[0], str.size() * sizeof(str[0]));\r
389 }\r
390 \r
391 template<typename Stream, typename C>\r
392 void Unserialize(Stream& is, basic_string<C>& str, int, int)\r
393 {\r
394     unsigned int nSize = ReadCompactSize(is);\r
395     str.resize(nSize);\r
396     if (nSize != 0)\r
397         is.read((char*)&str[0], nSize * sizeof(str[0]));\r
398 }\r
399 \r
400 \r
401 \r
402 //\r
403 // vector\r
404 //\r
405 template<typename T, typename A>\r
406 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)\r
407 {\r
408     return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));\r
409 }\r
410 \r
411 template<typename T, typename A>\r
412 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)\r
413 {\r
414     unsigned int nSize = GetSizeOfCompactSize(v.size());\r
415     for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)\r
416         nSize += GetSerializeSize((*vi), nType, nVersion);\r
417     return nSize;\r
418 }\r
419 \r
420 template<typename T, typename A>\r
421 inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion)\r
422 {\r
423     return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental<T>());\r
424 }\r
425 \r
426 \r
427 template<typename Stream, typename T, typename A>\r
428 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)\r
429 {\r
430     WriteCompactSize(os, v.size());\r
431     if (!v.empty())\r
432         os.write((char*)&v[0], v.size() * sizeof(T));\r
433 }\r
434 \r
435 template<typename Stream, typename T, typename A>\r
436 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)\r
437 {\r
438     WriteCompactSize(os, v.size());\r
439     for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)\r
440         ::Serialize(os, (*vi), nType, nVersion);\r
441 }\r
442 \r
443 template<typename Stream, typename T, typename A>\r
444 inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion)\r
445 {\r
446     Serialize_impl(os, v, nType, nVersion, boost::is_fundamental<T>());\r
447 }\r
448 \r
449 \r
450 template<typename Stream, typename T, typename A>\r
451 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)\r
452 {\r
453     //unsigned int nSize = ReadCompactSize(is);\r
454     //v.resize(nSize);\r
455     //is.read((char*)&v[0], nSize * sizeof(T));\r
456 \r
457     // Limit size per read so bogus size value won't cause out of memory\r
458     v.clear();\r
459     unsigned int nSize = ReadCompactSize(is);\r
460     unsigned int i = 0;\r
461     while (i < nSize)\r
462     {\r
463         unsigned int blk = min(nSize - i, 1 + 4999999 / sizeof(T));\r
464         v.resize(i + blk);\r
465         is.read((char*)&v[i], blk * sizeof(T));\r
466         i += blk;\r
467     }\r
468 }\r
469 \r
470 template<typename Stream, typename T, typename A>\r
471 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)\r
472 {\r
473     //unsigned int nSize = ReadCompactSize(is);\r
474     //v.resize(nSize);\r
475     //for (std::vector<T, A>::iterator vi = v.begin(); vi != v.end(); ++vi)\r
476     //    Unserialize(is, (*vi), nType, nVersion);\r
477 \r
478     v.clear();\r
479     unsigned int nSize = ReadCompactSize(is);\r
480     unsigned int i = 0;\r
481     unsigned int nMid = 0;\r
482     while (nMid < nSize)\r
483     {\r
484         nMid += 5000000 / sizeof(T);\r
485         if (nMid > nSize)\r
486             nMid = nSize;\r
487         v.resize(nMid);\r
488         for (; i < nMid; i++)\r
489             Unserialize(is, v[i], nType, nVersion);\r
490     }\r
491 }\r
492 \r
493 template<typename Stream, typename T, typename A>\r
494 inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion)\r
495 {\r
496     Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental<T>());\r
497 }\r
498 \r
499 \r
500 \r
501 //\r
502 // others derived from vector\r
503 //\r
504 inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)\r
505 {\r
506     return GetSerializeSize((const vector<unsigned char>&)v, nType, nVersion);\r
507 }\r
508 \r
509 template<typename Stream>\r
510 void Serialize(Stream& os, const CScript& v, int nType, int nVersion)\r
511 {\r
512     Serialize(os, (const vector<unsigned char>&)v, nType, nVersion);\r
513 }\r
514 \r
515 template<typename Stream>\r
516 void Unserialize(Stream& is, CScript& v, int nType, int nVersion)\r
517 {\r
518     Unserialize(is, (vector<unsigned char>&)v, nType, nVersion);\r
519 }\r
520 \r
521 \r
522 \r
523 //\r
524 // pair\r
525 //\r
526 template<typename K, typename T>\r
527 unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)\r
528 {\r
529     return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion);\r
530 }\r
531 \r
532 template<typename Stream, typename K, typename T>\r
533 void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion)\r
534 {\r
535     Serialize(os, item.first, nType, nVersion);\r
536     Serialize(os, item.second, nType, nVersion);\r
537 }\r
538 \r
539 template<typename Stream, typename K, typename T>\r
540 void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)\r
541 {\r
542     Unserialize(is, item.first, nType, nVersion);\r
543     Unserialize(is, item.second, nType, nVersion);\r
544 }\r
545 \r
546 \r
547 \r
548 //\r
549 // map\r
550 //\r
551 template<typename K, typename T, typename Pred, typename A>\r
552 unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)\r
553 {\r
554     unsigned int nSize = GetSizeOfCompactSize(m.size());\r
555     for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)\r
556         nSize += GetSerializeSize((*mi), nType, nVersion);\r
557     return nSize;\r
558 }\r
559 \r
560 template<typename Stream, typename K, typename T, typename Pred, typename A>\r
561 void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion)\r
562 {\r
563     WriteCompactSize(os, m.size());\r
564     for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)\r
565         Serialize(os, (*mi), nType, nVersion);\r
566 }\r
567 \r
568 template<typename Stream, typename K, typename T, typename Pred, typename A>\r
569 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion)\r
570 {\r
571     m.clear();\r
572     unsigned int nSize = ReadCompactSize(is);\r
573     typename std::map<K, T, Pred, A>::iterator mi = m.begin();\r
574     for (unsigned int i = 0; i < nSize; i++)\r
575     {\r
576         pair<K, T> item;\r
577         Unserialize(is, item, nType, nVersion);\r
578         mi = m.insert(mi, item);\r
579     }\r
580 }\r
581 \r
582 \r
583 \r
584 //\r
585 // set\r
586 //\r
587 template<typename K, typename Pred, typename A>\r
588 unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)\r
589 {\r
590     unsigned int nSize = GetSizeOfCompactSize(m.size());\r
591     for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)\r
592         nSize += GetSerializeSize((*it), nType, nVersion);\r
593     return nSize;\r
594 }\r
595 \r
596 template<typename Stream, typename K, typename Pred, typename A>\r
597 void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion)\r
598 {\r
599     WriteCompactSize(os, m.size());\r
600     for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)\r
601         Serialize(os, (*it), nType, nVersion);\r
602 }\r
603 \r
604 template<typename Stream, typename K, typename Pred, typename A>\r
605 void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)\r
606 {\r
607     m.clear();\r
608     unsigned int nSize = ReadCompactSize(is);\r
609     typename std::set<K, Pred, A>::iterator it = m.begin();\r
610     for (unsigned int i = 0; i < nSize; i++)\r
611     {\r
612         K key;\r
613         Unserialize(is, key, nType, nVersion);\r
614         it = m.insert(it, key);\r
615     }\r
616 }\r
617 \r
618 \r
619 \r
620 //\r
621 // Support for IMPLEMENT_SERIALIZE and READWRITE macro\r
622 //\r
623 class CSerActionGetSerializeSize { };\r
624 class CSerActionSerialize { };\r
625 class CSerActionUnserialize { };\r
626 \r
627 template<typename Stream, typename T>\r
628 inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action)\r
629 {\r
630     return ::GetSerializeSize(obj, nType, nVersion);\r
631 }\r
632 \r
633 template<typename Stream, typename T>\r
634 inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)\r
635 {\r
636     ::Serialize(s, obj, nType, nVersion);\r
637     return 0;\r
638 }\r
639 \r
640 template<typename Stream, typename T>\r
641 inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)\r
642 {\r
643     ::Unserialize(s, obj, nType, nVersion);\r
644     return 0;\r
645 }\r
646 \r
647 struct ser_streamplaceholder\r
648 {\r
649     int nType;\r
650     int nVersion;\r
651 };\r
652 \r
653 \r
654 \r
655 \r
656 \r
657 \r
658 \r
659 \r
660 \r
661 //\r
662 // Allocator that clears its contents before deletion\r
663 //\r
664 template<typename T>\r
665 struct secure_allocator : public std::allocator<T>\r
666 {\r
667     // MSVC8 default copy constructor is broken\r
668     typedef std::allocator<T> base;\r
669     typedef typename base::size_type size_type;\r
670     typedef typename base::difference_type  difference_type;\r
671     typedef typename base::pointer pointer;\r
672     typedef typename base::const_pointer const_pointer;\r
673     typedef typename base::reference reference;\r
674     typedef typename base::const_reference const_reference;\r
675     typedef typename base::value_type value_type;\r
676     secure_allocator() throw() {}\r
677     secure_allocator(const secure_allocator& a) throw() : base(a) {}\r
678     ~secure_allocator() throw() {}\r
679     template<typename _Other> struct rebind\r
680     { typedef secure_allocator<_Other> other; };\r
681 \r
682     void deallocate(T* p, std::size_t n)\r
683     {\r
684         if (p != NULL)\r
685             memset(p, 0, sizeof(T) * n);\r
686         allocator<T>::deallocate(p, n);\r
687     }\r
688 };\r
689 \r
690 \r
691 \r
692 //\r
693 // Double ended buffer combining vector and stream-like interfaces.\r
694 // >> and << read and write unformatted data using the above serialization templates.\r
695 // Fills with data in linear time; some stringstream implementations take N^2 time.\r
696 //\r
697 class CDataStream\r
698 {\r
699 protected:\r
700     typedef vector<char, secure_allocator<char> > vector_type;\r
701     vector_type vch;\r
702     unsigned int nReadPos;\r
703     short state;\r
704     short exceptmask;\r
705 public:\r
706     int nType;\r
707     int nVersion;\r
708 \r
709     typedef vector_type::allocator_type   allocator_type;\r
710     typedef vector_type::size_type        size_type;\r
711     typedef vector_type::difference_type  difference_type;\r
712     typedef vector_type::reference        reference;\r
713     typedef vector_type::const_reference  const_reference;\r
714     typedef vector_type::value_type       value_type;\r
715     typedef vector_type::iterator         iterator;\r
716     typedef vector_type::const_iterator   const_iterator;\r
717     typedef vector_type::reverse_iterator reverse_iterator;\r
718 \r
719     explicit CDataStream(int nTypeIn=0, int nVersionIn=VERSION)\r
720     {\r
721         Init(nTypeIn, nVersionIn);\r
722     }\r
723 \r
724     CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=0, int nVersionIn=VERSION) : vch(pbegin, pend)\r
725     {\r
726         Init(nTypeIn, nVersionIn);\r
727     }\r
728 \r
729 #if !defined(_MSC_VER) || _MSC_VER >= 1300\r
730     CDataStream(const char* pbegin, const char* pend, int nTypeIn=0, int nVersionIn=VERSION) : vch(pbegin, pend)\r
731     {\r
732         Init(nTypeIn, nVersionIn);\r
733     }\r
734 #endif\r
735 \r
736     CDataStream(const vector_type& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())\r
737     {\r
738         Init(nTypeIn, nVersionIn);\r
739     }\r
740 \r
741     CDataStream(const vector<char>& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())\r
742     {\r
743         Init(nTypeIn, nVersionIn);\r
744     }\r
745 \r
746     CDataStream(const vector<unsigned char>& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0])\r
747     {\r
748         Init(nTypeIn, nVersionIn);\r
749     }\r
750 \r
751     void Init(int nTypeIn=0, int nVersionIn=VERSION)\r
752     {\r
753         nReadPos = 0;\r
754         nType = nTypeIn;\r
755         nVersion = nVersionIn;\r
756         state = 0;\r
757         exceptmask = ios::badbit | ios::failbit;\r
758     }\r
759 \r
760     CDataStream& operator+=(const CDataStream& b)\r
761     {\r
762         vch.insert(vch.end(), b.begin(), b.end());\r
763         return *this;\r
764     }\r
765 \r
766     friend CDataStream operator+(const CDataStream& a, const CDataStream& b)\r
767     {\r
768         CDataStream ret = a;\r
769         ret += b;\r
770         return (ret);\r
771     }\r
772 \r
773     string str() const\r
774     {\r
775         return (string(begin(), end()));\r
776     }\r
777 \r
778 \r
779     //\r
780     // Vector subset\r
781     //\r
782     const_iterator begin() const                     { return vch.begin() + nReadPos; }\r
783     iterator begin()                                 { return vch.begin() + nReadPos; }\r
784     const_iterator end() const                       { return vch.end(); }\r
785     iterator end()                                   { return vch.end(); }\r
786     size_type size() const                           { return vch.size() - nReadPos; }\r
787     bool empty() const                               { return vch.size() == nReadPos; }\r
788     void resize(size_type n, value_type c=0)         { vch.resize(n + nReadPos, c); }\r
789     void reserve(size_type n)                        { vch.reserve(n + nReadPos); }\r
790     const_reference operator[](size_type pos) const  { return vch[pos + nReadPos]; }\r
791     reference operator[](size_type pos)              { return vch[pos + nReadPos]; }\r
792     void clear()                                     { vch.clear(); nReadPos = 0; }\r
793     iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }\r
794     void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }\r
795 \r
796     void insert(iterator it, const_iterator first, const_iterator last)\r
797     {\r
798         if (it == vch.begin() + nReadPos && last - first <= nReadPos)\r
799         {\r
800             // special case for inserting at the front when there's room\r
801             nReadPos -= (last - first);\r
802             memcpy(&vch[nReadPos], &first[0], last - first);\r
803         }\r
804         else\r
805             vch.insert(it, first, last);\r
806     }\r
807 \r
808 #if !defined(_MSC_VER) || _MSC_VER >= 1300\r
809     void insert(iterator it, const char* first, const char* last)\r
810     {\r
811         if (it == vch.begin() + nReadPos && last - first <= nReadPos)\r
812         {\r
813             // special case for inserting at the front when there's room\r
814             nReadPos -= (last - first);\r
815             memcpy(&vch[nReadPos], &first[0], last - first);\r
816         }\r
817         else\r
818             vch.insert(it, first, last);\r
819     }\r
820 #endif\r
821 \r
822     iterator erase(iterator it)\r
823     {\r
824         if (it == vch.begin() + nReadPos)\r
825         {\r
826             // special case for erasing from the front\r
827             if (++nReadPos >= vch.size())\r
828             {\r
829                 // whenever we reach the end, we take the opportunity to clear the buffer\r
830                 nReadPos = 0;\r
831                 return vch.erase(vch.begin(), vch.end());\r
832             }\r
833             return vch.begin() + nReadPos;\r
834         }\r
835         else\r
836             return vch.erase(it);\r
837     }\r
838 \r
839     iterator erase(iterator first, iterator last)\r
840     {\r
841         if (first == vch.begin() + nReadPos)\r
842         {\r
843             // special case for erasing from the front\r
844             if (last == vch.end())\r
845             {\r
846                 nReadPos = 0;\r
847                 return vch.erase(vch.begin(), vch.end());\r
848             }\r
849             else\r
850             {\r
851                 nReadPos = (last - vch.begin());\r
852                 return last;\r
853             }\r
854         }\r
855         else\r
856             return vch.erase(first, last);\r
857     }\r
858 \r
859     inline void Compact()\r
860     {\r
861         vch.erase(vch.begin(), vch.begin() + nReadPos);\r
862         nReadPos = 0;\r
863     }\r
864 \r
865     bool Rewind(size_type n)\r
866     {\r
867         // Rewind by n characters if the buffer hasn't been compacted yet\r
868         if (n > nReadPos)\r
869             return false;\r
870         nReadPos -= n;\r
871         return true;\r
872     }\r
873 \r
874 \r
875     //\r
876     // Stream subset\r
877     //\r
878     void setstate(short bits, const char* psz)\r
879     {\r
880         state |= bits;\r
881         if (state & exceptmask)\r
882             throw std::ios_base::failure(psz);\r
883     }\r
884 \r
885     bool eof() const             { return size() == 0; }\r
886     bool fail() const            { return state & (ios::badbit | ios::failbit); }\r
887     bool good() const            { return !eof() && (state == 0); }\r
888     void clear(short n)          { state = n; }  // name conflict with vector clear()\r
889     short exceptions()           { return exceptmask; }\r
890     short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; }\r
891     CDataStream* rdbuf()         { return this; }\r
892     int in_avail()               { return size(); }\r
893 \r
894     void SetType(int n)          { nType = n; }\r
895     int GetType()                { return nType; }\r
896     void SetVersion(int n)       { nVersion = n; }\r
897     int GetVersion()             { return nVersion; }\r
898     void ReadVersion()           { *this >> nVersion; }\r
899     void WriteVersion()          { *this << nVersion; }\r
900 \r
901     CDataStream& read(char* pch, int nSize)\r
902     {\r
903         // Read from the beginning of the buffer\r
904         assert(nSize >= 0);\r
905         unsigned int nReadPosNext = nReadPos + nSize;\r
906         if (nReadPosNext >= vch.size())\r
907         {\r
908             if (nReadPosNext > vch.size())\r
909             {\r
910                 setstate(ios::failbit, "CDataStream::read() : end of data");\r
911                 memset(pch, 0, nSize);\r
912                 nSize = vch.size() - nReadPos;\r
913             }\r
914             memcpy(pch, &vch[nReadPos], nSize);\r
915             nReadPos = 0;\r
916             vch.clear();\r
917             return (*this);\r
918         }\r
919         memcpy(pch, &vch[nReadPos], nSize);\r
920         nReadPos = nReadPosNext;\r
921         return (*this);\r
922     }\r
923 \r
924     CDataStream& ignore(int nSize)\r
925     {\r
926         // Ignore from the beginning of the buffer\r
927         assert(nSize >= 0);\r
928         unsigned int nReadPosNext = nReadPos + nSize;\r
929         if (nReadPosNext >= vch.size())\r
930         {\r
931             if (nReadPosNext > vch.size())\r
932             {\r
933                 setstate(ios::failbit, "CDataStream::ignore() : end of data");\r
934                 nSize = vch.size() - nReadPos;\r
935             }\r
936             nReadPos = 0;\r
937             vch.clear();\r
938             return (*this);\r
939         }\r
940         nReadPos = nReadPosNext;\r
941         return (*this);\r
942     }\r
943 \r
944     CDataStream& write(const char* pch, int nSize)\r
945     {\r
946         // Write to the end of the buffer\r
947         assert(nSize >= 0);\r
948         vch.insert(vch.end(), pch, pch + nSize);\r
949         return (*this);\r
950     }\r
951 \r
952     template<typename Stream>\r
953     void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const\r
954     {\r
955         // Special case: stream << stream concatenates like stream += stream\r
956         if (!vch.empty())\r
957             s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));\r
958     }\r
959 \r
960     template<typename T>\r
961     unsigned int GetSerializeSize(const T& obj)\r
962     {\r
963         // Tells the size of the object if serialized to this stream\r
964         return ::GetSerializeSize(obj, nType, nVersion);\r
965     }\r
966 \r
967     template<typename T>\r
968     CDataStream& operator<<(const T& obj)\r
969     {\r
970         // Serialize to this stream\r
971         ::Serialize(*this, obj, nType, nVersion);\r
972         return (*this);\r
973     }\r
974 \r
975     template<typename T>\r
976     CDataStream& operator>>(T& obj)\r
977     {\r
978         // Unserialize from this stream\r
979         ::Unserialize(*this, obj, nType, nVersion);\r
980         return (*this);\r
981     }\r
982 };\r
983 \r
984 #ifdef TESTCDATASTREAM\r
985 // VC6sp6\r
986 // CDataStream:\r
987 // n=1000       0 seconds\r
988 // n=2000       0 seconds\r
989 // n=4000       0 seconds\r
990 // n=8000       0 seconds\r
991 // n=16000      0 seconds\r
992 // n=32000      0 seconds\r
993 // n=64000      1 seconds\r
994 // n=128000     1 seconds\r
995 // n=256000     2 seconds\r
996 // n=512000     4 seconds\r
997 // n=1024000    8 seconds\r
998 // n=2048000    16 seconds\r
999 // n=4096000    32 seconds\r
1000 // stringstream:\r
1001 // n=1000       1 seconds\r
1002 // n=2000       1 seconds\r
1003 // n=4000       13 seconds\r
1004 // n=8000       87 seconds\r
1005 // n=16000      400 seconds\r
1006 // n=32000      1660 seconds\r
1007 // n=64000      6749 seconds\r
1008 // n=128000     27241 seconds\r
1009 // n=256000     109804 seconds\r
1010 #include <iostream>\r
1011 int main(int argc, char *argv[])\r
1012 {\r
1013     vector<unsigned char> vch(0xcc, 250);\r
1014     printf("CDataStream:\n");\r
1015     for (int n = 1000; n <= 4500000; n *= 2)\r
1016     {\r
1017         CDataStream ss;\r
1018         time_t nStart = time(NULL);\r
1019         for (int i = 0; i < n; i++)\r
1020             ss.write((char*)&vch[0], vch.size());\r
1021         printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);\r
1022     }\r
1023     printf("stringstream:\n");\r
1024     for (int n = 1000; n <= 4500000; n *= 2)\r
1025     {\r
1026         stringstream ss;\r
1027         time_t nStart = time(NULL);\r
1028         for (int i = 0; i < n; i++)\r
1029             ss.write((char*)&vch[0], vch.size());\r
1030         printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);\r
1031     }\r
1032 }\r
1033 #endif\r
1034 \r
1035 \r
1036 \r
1037 \r
1038 \r
1039 \r
1040 \r
1041 \r
1042 \r
1043 \r
1044 //\r
1045 // Automatic closing wrapper for FILE*\r
1046 //  - Will automatically close the file when it goes out of scope if not null.\r
1047 //  - If you're returning the file pointer, return file.release().\r
1048 //  - If you need to close the file early, use file.fclose() instead of fclose(file).\r
1049 //\r
1050 class CAutoFile\r
1051 {\r
1052 protected:\r
1053     FILE* file;\r
1054     short state;\r
1055     short exceptmask;\r
1056 public:\r
1057     int nType;\r
1058     int nVersion;\r
1059 \r
1060     typedef FILE element_type;\r
1061 \r
1062     CAutoFile(FILE* filenew=NULL, int nTypeIn=SER_DISK, int nVersionIn=VERSION)\r
1063     {\r
1064         file = filenew;\r
1065         nType = nTypeIn;\r
1066         nVersion = nVersionIn;\r
1067         state = 0;\r
1068         exceptmask = ios::badbit | ios::failbit;\r
1069     }\r
1070 \r
1071     ~CAutoFile()\r
1072     {\r
1073         fclose();\r
1074     }\r
1075 \r
1076     void fclose()\r
1077     {\r
1078         if (file != NULL && file != stdin && file != stdout && file != stderr)\r
1079             ::fclose(file);\r
1080         file = NULL;\r
1081     }\r
1082 \r
1083     FILE* release()             { FILE* ret = file; file = NULL; return ret; }\r
1084     operator FILE*()            { return file; }\r
1085     FILE* operator->()          { return file; }\r
1086     FILE& operator*()           { return *file; }\r
1087     FILE** operator&()          { return &file; }\r
1088     FILE* operator=(FILE* pnew) { return file = pnew; }\r
1089     bool operator!()            { return (file == NULL); }\r
1090 \r
1091 \r
1092     //\r
1093     // Stream subset\r
1094     //\r
1095     void setstate(short bits, const char* psz)\r
1096     {\r
1097         state |= bits;\r
1098         if (state & exceptmask)\r
1099             throw std::ios_base::failure(psz);\r
1100     }\r
1101 \r
1102     bool fail() const            { return state & (ios::badbit | ios::failbit); }\r
1103     bool good() const            { return state == 0; }\r
1104     void clear(short n = 0)      { state = n; }\r
1105     short exceptions()           { return exceptmask; }\r
1106     short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; }\r
1107 \r
1108     void SetType(int n)          { nType = n; }\r
1109     int GetType()                { return nType; }\r
1110     void SetVersion(int n)       { nVersion = n; }\r
1111     int GetVersion()             { return nVersion; }\r
1112     void ReadVersion()           { *this >> nVersion; }\r
1113     void WriteVersion()          { *this << nVersion; }\r
1114 \r
1115     CAutoFile& read(char* pch, int nSize)\r
1116     {\r
1117         if (!file)\r
1118             throw std::ios_base::failure("CAutoFile::read : file handle is NULL");\r
1119         if (fread(pch, 1, nSize, file) != nSize)\r
1120             setstate(ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");\r
1121         return (*this);\r
1122     }\r
1123 \r
1124     CAutoFile& write(const char* pch, int nSize)\r
1125     {\r
1126         if (!file)\r
1127             throw std::ios_base::failure("CAutoFile::write : file handle is NULL");\r
1128         if (fwrite(pch, 1, nSize, file) != nSize)\r
1129             setstate(ios::failbit, "CAutoFile::write : write failed");\r
1130         return (*this);\r
1131     }\r
1132 \r
1133     template<typename T>\r
1134     unsigned int GetSerializeSize(const T& obj)\r
1135     {\r
1136         // Tells the size of the object if serialized to this stream\r
1137         return ::GetSerializeSize(obj, nType, nVersion);\r
1138     }\r
1139 \r
1140     template<typename T>\r
1141     CAutoFile& operator<<(const T& obj)\r
1142     {\r
1143         // Serialize to this stream\r
1144         if (!file)\r
1145             throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");\r
1146         ::Serialize(*this, obj, nType, nVersion);\r
1147         return (*this);\r
1148     }\r
1149 \r
1150     template<typename T>\r
1151     CAutoFile& operator>>(T& obj)\r
1152     {\r
1153         // Unserialize from this stream\r
1154         if (!file)\r
1155             throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");\r
1156         ::Unserialize(*this, obj, nType, nVersion);\r
1157         return (*this);\r
1158     }\r
1159 };\r
This page took 0.094944 seconds and 4 git commands to generate.