обновление библиотек
[novacoin.git] / src / serialize.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #ifndef BITCOIN_SERIALIZE_H
6 #define BITCOIN_SERIALIZE_H
7
8 #include <string>
9 #include <vector>
10 #include <map>
11 #include <set>
12 #include <cassert>
13 #include <limits>
14 #include <cstring>
15 #include <cstdio>
16
17 #ifndef Q_MOC_RUN
18 #include <boost/type_traits/is_fundamental.hpp>
19 #include <boost/tuple/tuple.hpp>
20 #include <boost/tuple/tuple_comparison.hpp>
21 #include <boost/tuple/tuple_io.hpp>
22 #endif
23
24 #include "allocators.h"
25 #include "version.h"
26
27 #ifdef _MSC_VER
28 #undef max
29 #endif
30
31 typedef long long  int64;
32 typedef unsigned long long  uint64;
33
34 class CScript;
35 class CDataStream;
36 class CAutoFile;
37 static const unsigned int MAX_SIZE = 0x02000000;
38
39 // Used to bypass the rule against non-const reference to temporary
40 // where it makes sense with wrappers such as CFlatData or CTxDB
41 template<typename T>
42 inline T& REF(const T& val)
43 {
44     return const_cast<T&>(val);
45 }
46
47 /////////////////////////////////////////////////////////////////
48 //
49 // Templates for serializing to anything that looks like a stream,
50 // i.e. anything that supports .read(char*, int) and .write(char*, int)
51 //
52
53 enum
54 {
55     // primary actions
56     SER_NETWORK         = (1 << 0),
57     SER_DISK            = (1 << 1),
58     SER_GETHASH         = (1 << 2),
59
60          // modifiers
61          SER_SKIPSIG = (1 << 16),
62          SER_BLOCKHEADERONLY = (1 << 17),
63
64 };
65
66 #ifdef _MSC_VER
67 #define IMPLEMENT_SERIALIZE(statements)    \
68     unsigned int GetSerializeSize(int nType, int nVersion) const  \
69     {                                           \
70         CSerActionGetSerializeSize ser_action;  \
71         const bool fGetSize = true;             \
72         const bool fWrite = false;              \
73         const bool fRead = false;               \
74         unsigned int nSerSize = 0;              \
75         ser_streamplaceholder s;                \
76         assert(fGetSize||fWrite||fRead); /* suppress warning */ \
77         s.nType = nType;                        \
78         s.nVersion = nVersion;                  \
79         std::map<int, int>  mapUnkIds;          \
80         {statements}                            \
81         return nSerSize;                        \
82     }                                           \
83     template<typename Stream>                   \
84     void Serialize(Stream& s, int nType, int nVersion) const  \
85     {                                           \
86         CSerActionSerialize ser_action;         \
87         const bool fGetSize = false;            \
88         const bool fWrite = true;               \
89         const bool fRead = false;               \
90         unsigned int nSerSize = 0;              \
91         assert(fGetSize||fWrite||fRead); /* suppress warning */ \
92     std::map<int, int>  mapUnkIds;  \
93         {statements}                            \
94     }                                           \
95     template<typename Stream>                   \
96     void Unserialize(Stream& s, int nType, int nVersion)  \
97     {                                           \
98         CSerActionUnserialize ser_action;       \
99         const bool fGetSize = false;            \
100         const bool fWrite = false;              \
101         const bool fRead = true;                \
102         unsigned int nSerSize = 0;              \
103     std::map<int, int>  mapUnkIds;  \
104         assert(fGetSize||fWrite||fRead); /* suppress warning */ \
105         {statements}                            \
106     }
107
108 #else
109
110 #define IMPLEMENT_SERIALIZE(statements)    \
111     unsigned int GetSerializeSize(int nType, int nVersion) const  \
112     {                                           \
113         CSerActionGetSerializeSize ser_action;  \
114         const bool fGetSize = true;             \
115         const bool fWrite = false;              \
116         const bool fRead = false;               \
117         unsigned int nSerSize = 0;              \
118         ser_streamplaceholder s;                \
119         assert(fGetSize||fWrite||fRead); /* suppress warning */ \
120         s.nType = nType;                        \
121         s.nVersion = nVersion;                  \
122         {statements}                            \
123         return nSerSize;                        \
124     }                                           \
125     template<typename Stream>                   \
126     void Serialize(Stream& s, int nType, int nVersion) const  \
127     {                                           \
128         CSerActionSerialize ser_action;         \
129         const bool fGetSize = false;            \
130         const bool fWrite = true;               \
131         const bool fRead = false;               \
132         unsigned int nSerSize = 0;              \
133         assert(fGetSize||fWrite||fRead); /* suppress warning */ \
134         {statements}                            \
135     }                                           \
136     template<typename Stream>                   \
137     void Unserialize(Stream& s, int nType, int nVersion)  \
138     {                                           \
139         CSerActionUnserialize ser_action;       \
140         const bool fGetSize = false;            \
141         const bool fWrite = false;              \
142         const bool fRead = true;                \
143         unsigned int nSerSize = 0;              \
144         assert(fGetSize||fWrite||fRead); /* suppress warning */ \
145         {statements}                            \
146     }
147
148 #endif
149
150 #define READWRITE(obj)      (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
151
152
153
154
155
156
157 //
158 // Basic types
159 //
160 #define WRITEDATA(s, obj)   s.write((char*)&(obj), sizeof(obj))
161 #define READDATA(s, obj)    s.read((char*)&(obj), sizeof(obj))
162
163 inline unsigned int GetSerializeSize(char a,           int, int=0) { return sizeof(a); }
164 inline unsigned int GetSerializeSize(signed char a,    int, int=0) { return sizeof(a); }
165 inline unsigned int GetSerializeSize(unsigned char a,  int, int=0) { return sizeof(a); }
166 inline unsigned int GetSerializeSize(signed short a,   int, int=0) { return sizeof(a); }
167 inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); }
168 inline unsigned int GetSerializeSize(signed int a,     int, int=0) { return sizeof(a); }
169 inline unsigned int GetSerializeSize(unsigned int a,   int, int=0) { return sizeof(a); }
170 inline unsigned int GetSerializeSize(signed long a,    int, int=0) { return sizeof(a); }
171 inline unsigned int GetSerializeSize(unsigned long a,  int, int=0) { return sizeof(a); }
172 inline unsigned int GetSerializeSize(int64 a,          int, int=0) { return sizeof(a); }
173 inline unsigned int GetSerializeSize(uint64 a,         int, int=0) { return sizeof(a); }
174 inline unsigned int GetSerializeSize(float a,          int, int=0) { return sizeof(a); }
175 inline unsigned int GetSerializeSize(double a,         int, int=0) { return sizeof(a); }
176
177 template<typename Stream> inline void Serialize(Stream& s, char a,           int, int=0) { WRITEDATA(s, a); }
178 template<typename Stream> inline void Serialize(Stream& s, signed char a,    int, int=0) { WRITEDATA(s, a); }
179 template<typename Stream> inline void Serialize(Stream& s, unsigned char a,  int, int=0) { WRITEDATA(s, a); }
180 template<typename Stream> inline void Serialize(Stream& s, signed short a,   int, int=0) { WRITEDATA(s, a); }
181 template<typename Stream> inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); }
182 template<typename Stream> inline void Serialize(Stream& s, signed int a,     int, int=0) { WRITEDATA(s, a); }
183 template<typename Stream> inline void Serialize(Stream& s, unsigned int a,   int, int=0) { WRITEDATA(s, a); }
184 template<typename Stream> inline void Serialize(Stream& s, signed long a,    int, int=0) { WRITEDATA(s, a); }
185 template<typename Stream> inline void Serialize(Stream& s, unsigned long a,  int, int=0) { WRITEDATA(s, a); }
186 template<typename Stream> inline void Serialize(Stream& s, int64 a,          int, int=0) { WRITEDATA(s, a); }
187 template<typename Stream> inline void Serialize(Stream& s, uint64 a,         int, int=0) { WRITEDATA(s, a); }
188 template<typename Stream> inline void Serialize(Stream& s, float a,          int, int=0) { WRITEDATA(s, a); }
189 template<typename Stream> inline void Serialize(Stream& s, double a,         int, int=0) { WRITEDATA(s, a); }
190
191 template<typename Stream> inline void Unserialize(Stream& s, char& a,           int, int=0) { READDATA(s, a); }
192 template<typename Stream> inline void Unserialize(Stream& s, signed char& a,    int, int=0) { READDATA(s, a); }
193 template<typename Stream> inline void Unserialize(Stream& s, unsigned char& a,  int, int=0) { READDATA(s, a); }
194 template<typename Stream> inline void Unserialize(Stream& s, signed short& a,   int, int=0) { READDATA(s, a); }
195 template<typename Stream> inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); }
196 template<typename Stream> inline void Unserialize(Stream& s, signed int& a,     int, int=0) { READDATA(s, a); }
197 template<typename Stream> inline void Unserialize(Stream& s, unsigned int& a,   int, int=0) { READDATA(s, a); }
198 template<typename Stream> inline void Unserialize(Stream& s, signed long& a,    int, int=0) { READDATA(s, a); }
199 template<typename Stream> inline void Unserialize(Stream& s, unsigned long& a,  int, int=0) { READDATA(s, a); }
200 template<typename Stream> inline void Unserialize(Stream& s, int64& a,          int, int=0) { READDATA(s, a); }
201 template<typename Stream> inline void Unserialize(Stream& s, uint64& a,         int, int=0) { READDATA(s, a); }
202 template<typename Stream> inline void Unserialize(Stream& s, float& a,          int, int=0) { READDATA(s, a); }
203 template<typename Stream> inline void Unserialize(Stream& s, double& a,         int, int=0) { READDATA(s, a); }
204
205 inline unsigned int GetSerializeSize(bool a, int, int=0)                          { return sizeof(char); }
206 template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0)    { char f=a; WRITEDATA(s, f); }
207 template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; }
208
209
210
211
212
213
214 //
215 // Compact size
216 //  size <  253        -- 1 byte
217 //  size <= USHRT_MAX  -- 3 bytes  (253 + 2 bytes)
218 //  size <= UINT_MAX   -- 5 bytes  (254 + 4 bytes)
219 //  size >  UINT_MAX   -- 9 bytes  (255 + 8 bytes)
220 //
221 inline unsigned int GetSizeOfCompactSize(uint64 nSize)
222 {
223     if (nSize < 253)             return sizeof(unsigned char);
224     else if (nSize <= std::numeric_limits<unsigned short>::max()) return sizeof(unsigned char) + sizeof(unsigned short);
225     else if (nSize <= std::numeric_limits<unsigned int>::max())  return sizeof(unsigned char) + sizeof(unsigned int);
226     else                         return sizeof(unsigned char) + sizeof(uint64);
227 }
228
229 template<typename Stream>
230 void WriteCompactSize(Stream& os, uint64 nSize)
231 {
232     if (nSize < 253)
233     {
234         unsigned char chSize = nSize;
235         WRITEDATA(os, chSize);
236     }
237     else if (nSize <= std::numeric_limits<unsigned short>::max())
238     {
239         unsigned char chSize = 253;
240         unsigned short xSize = nSize;
241         WRITEDATA(os, chSize);
242         WRITEDATA(os, xSize);
243     }
244     else if (nSize <= std::numeric_limits<unsigned int>::max())
245     {
246         unsigned char chSize = 254;
247         unsigned int xSize = nSize;
248         WRITEDATA(os, chSize);
249         WRITEDATA(os, xSize);
250     }
251     else
252     {
253         unsigned char chSize = 255;
254         uint64 xSize = nSize;
255         WRITEDATA(os, chSize);
256         WRITEDATA(os, xSize);
257     }
258     return;
259 }
260
261 template<typename Stream>
262 uint64 ReadCompactSize(Stream& is)
263 {
264     unsigned char chSize;
265     READDATA(is, chSize);
266     uint64 nSizeRet = 0;
267     if (chSize < 253)
268     {
269         nSizeRet = chSize;
270     }
271     else if (chSize == 253)
272     {
273         unsigned short xSize;
274         READDATA(is, xSize);
275         nSizeRet = xSize;
276     }
277     else if (chSize == 254)
278     {
279         unsigned int xSize;
280         READDATA(is, xSize);
281         nSizeRet = xSize;
282     }
283     else
284     {
285         uint64 xSize;
286         READDATA(is, xSize);
287         nSizeRet = xSize;
288     }
289     if (nSizeRet > (uint64)MAX_SIZE)
290         throw std::ios_base::failure("ReadCompactSize() : size too large");
291     return nSizeRet;
292 }
293
294 // Variable-length integers: bytes are a MSB base-128 encoding of the number.
295 // The high bit in each byte signifies whether another digit follows. To make
296 // the encoding is one-to-one, one is subtracted from all but the last digit.
297 // Thus, the byte sequence a[] with length len, where all but the last byte
298 // has bit 128 set, encodes the number:
299 //
300 //   (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
301 //
302 // Properties:
303 // * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
304 // * Every integer has exactly one encoding
305 // * Encoding does not depend on size of original integer type
306 // * No redundancy: every (infinite) byte sequence corresponds to a list
307 //   of encoded integers.
308 //
309 // 0:         [0x00]  256:        [0x81 0x00]
310 // 1:         [0x01]  16383:      [0xFE 0x7F]
311 // 127:       [0x7F]  16384:      [0xFF 0x00]
312 // 128:  [0x80 0x00]  16511: [0x80 0xFF 0x7F]
313 // 255:  [0x80 0x7F]  65535: [0x82 0xFD 0x7F]
314 // 2^32:           [0x8E 0xFE 0xFE 0xFF 0x00]
315
316 template<typename I>
317 inline unsigned int GetSizeOfVarInt(I n)
318 {
319     int nRet = 0;
320     while(true) {
321         nRet++;
322         if (n <= 0x7F)
323             break;
324         n = (n >> 7) - 1;
325     }
326     return nRet;
327 }
328
329 template<typename Stream, typename I>
330 void WriteVarInt(Stream& os, I n)
331 {
332     unsigned char tmp[(sizeof(n)*8+6)/7];
333     int len=0;
334     while(true) {
335         tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
336         if (n <= 0x7F)
337             break;
338         n = (n >> 7) - 1;
339         len++;
340     }
341     do {
342         WRITEDATA(os, tmp[len]);
343     } while(len--);
344 }
345
346 template<typename Stream, typename I>
347 I ReadVarInt(Stream& is)
348 {
349     I n = 0;
350     while(true) {
351         unsigned char chData;
352         READDATA(is, chData);
353         n = (n << 7) | (chData & 0x7F);
354         if (chData & 0x80)
355             n++;
356         else
357             return n;
358     }
359 }
360
361 #define FLATDATA(obj)  REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
362 #define VARINT(obj)    REF(WrapVarInt(REF(obj)))
363
364 /** Wrapper for serializing arrays and POD.
365  */
366 class CFlatData
367 {
368 protected:
369     char* pbegin;
370     char* pend;
371 public:
372     CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
373     char* begin() { return pbegin; }
374     const char* begin() const { return pbegin; }
375     char* end() { return pend; }
376     const char* end() const { return pend; }
377
378     unsigned int GetSerializeSize(int, int=0) const
379     {
380         return pend - pbegin;
381     }
382
383     template<typename Stream>
384     void Serialize(Stream& s, int, int=0) const
385     {
386         s.write(pbegin, pend - pbegin);
387     }
388
389     template<typename Stream>
390     void Unserialize(Stream& s, int, int=0)
391     {
392         s.read(pbegin, pend - pbegin);
393     }
394 };
395
396 template<typename I>
397 class CVarInt
398 {
399 protected:
400     I &n;
401 public:
402     CVarInt(I& nIn) : n(nIn) { }
403
404     unsigned int GetSerializeSize(int, int) const {
405         return GetSizeOfVarInt<I>(n);
406     }
407
408     template<typename Stream>
409     void Serialize(Stream &s, int, int) const {
410         WriteVarInt<Stream,I>(s, n);
411     }
412
413     template<typename Stream>
414     void Unserialize(Stream& s, int, int) {
415         n = ReadVarInt<Stream,I>(s);
416     }
417 };
418
419 template<typename I>
420 CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
421
422 //
423 // Forward declarations
424 //
425
426 // string
427 template<typename C> unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int=0);
428 template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str, int, int=0);
429 template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str, int, int=0);
430
431 // vector
432 template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);
433 template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);
434 template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion);
435 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&);
436 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&);
437 template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion);
438 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&);
439 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&);
440 template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion);
441
442 // others derived from vector
443 extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion);
444 template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion);
445 template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion);
446
447 // pair
448 template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion);
449 template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion);
450 template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion);
451
452 // 3 tuple
453 template<typename T0, typename T1, typename T2> unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion);
454 template<typename Stream, typename T0, typename T1, typename T2> void Serialize(Stream& os, const boost::tuple<T0, T1, T2>& item, int nType, int nVersion);
455 template<typename Stream, typename T0, typename T1, typename T2> void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion);
456
457 // 4 tuple
458 template<typename T0, typename T1, typename T2, typename T3> unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion);
459 template<typename Stream, typename T0, typename T1, typename T2, typename T3> void Serialize(Stream& os, const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion);
460 template<typename Stream, typename T0, typename T1, typename T2, typename T3> void Unserialize(Stream& is, boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion);
461
462 // map
463 template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion);
464 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);
465 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);
466
467 // set
468 template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion);
469 template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion);
470 template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion);
471
472
473
474
475
476 //
477 // If none of the specialized versions above matched, default to calling member function.
478 // "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
479 // The compiler will only cast int to long if none of the other templates matched.
480 // Thanks to Boost serialization for this idea.
481 //
482 template<typename T>
483 inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion)
484 {
485     return a.GetSerializeSize((int)nType, nVersion);
486 }
487
488 template<typename Stream, typename T>
489 inline void Serialize(Stream& os, const T& a, long nType, int nVersion)
490 {
491     a.Serialize(os, (int)nType, nVersion);
492 }
493
494 template<typename Stream, typename T>
495 inline void Unserialize(Stream& is, T& a, long nType, int nVersion)
496 {
497     a.Unserialize(is, (int)nType, nVersion);
498 }
499
500
501
502
503
504 //
505 // string
506 //
507 template<typename C>
508 unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int)
509 {
510     return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]);
511 }
512
513 template<typename Stream, typename C>
514 void Serialize(Stream& os, const std::basic_string<C>& str, int, int)
515 {
516     WriteCompactSize(os, str.size());
517     if (!str.empty())
518         os.write((char*)&str[0], str.size() * sizeof(str[0]));
519 }
520
521 template<typename Stream, typename C>
522 void Unserialize(Stream& is, std::basic_string<C>& str, int, int)
523 {
524     unsigned int nSize = ReadCompactSize(is);
525     str.resize(nSize);
526     if (nSize != 0)
527         is.read((char*)&str[0], nSize * sizeof(str[0]));
528 }
529
530
531
532 //
533 // vector
534 //
535 template<typename T, typename A>
536 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
537 {
538     return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));
539 }
540
541 template<typename T, typename A>
542 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
543 {
544     unsigned int nSize = GetSizeOfCompactSize(v.size());
545     for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
546         nSize += GetSerializeSize((*vi), nType, nVersion);
547     return nSize;
548 }
549
550 template<typename T, typename A>
551 inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion)
552 {
553     return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental<T>());
554 }
555
556
557 template<typename Stream, typename T, typename A>
558 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
559 {
560     WriteCompactSize(os, v.size());
561     if (!v.empty())
562         os.write((char*)&v[0], v.size() * sizeof(T));
563 }
564
565 template<typename Stream, typename T, typename A>
566 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
567 {
568     WriteCompactSize(os, v.size());
569     for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
570         ::Serialize(os, (*vi), nType, nVersion);
571 }
572
573 template<typename Stream, typename T, typename A>
574 inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion)
575 {
576     Serialize_impl(os, v, nType, nVersion, boost::is_fundamental<T>());
577 }
578
579
580 template<typename Stream, typename T, typename A>
581 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
582 {
583     // Limit size per read so bogus size value won't cause out of memory
584     v.clear();
585     unsigned int nSize = ReadCompactSize(is);
586     unsigned int i = 0;
587     while (i < nSize)
588     {
589         unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
590         v.resize(i + blk);
591         is.read((char*)&v[i], blk * sizeof(T));
592         i += blk;
593     }
594 }
595
596 template<typename Stream, typename T, typename A>
597 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
598 {
599     v.clear();
600     unsigned int nSize = ReadCompactSize(is);
601     unsigned int i = 0;
602     unsigned int nMid = 0;
603     while (nMid < nSize)
604     {
605         nMid += 5000000 / sizeof(T);
606         if (nMid > nSize)
607             nMid = nSize;
608         v.resize(nMid);
609         for (; i < nMid; i++)
610             Unserialize(is, v[i], nType, nVersion);
611     }
612 }
613
614 template<typename Stream, typename T, typename A>
615 inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion)
616 {
617     Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental<T>());
618 }
619
620
621
622 //
623 // others derived from vector
624 //
625 inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)
626 {
627     return GetSerializeSize((const std::vector<unsigned char>&)v, nType, nVersion);
628 }
629
630 template<typename Stream>
631 void Serialize(Stream& os, const CScript& v, int nType, int nVersion)
632 {
633     Serialize(os, (const std::vector<unsigned char>&)v, nType, nVersion);
634 }
635
636 template<typename Stream>
637 void Unserialize(Stream& is, CScript& v, int nType, int nVersion)
638 {
639     Unserialize(is, (std::vector<unsigned char>&)v, nType, nVersion);
640 }
641
642
643
644 //
645 // pair
646 //
647 template<typename K, typename T>
648 unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)
649 {
650     return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion);
651 }
652
653 template<typename Stream, typename K, typename T>
654 void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion)
655 {
656     Serialize(os, item.first, nType, nVersion);
657     Serialize(os, item.second, nType, nVersion);
658 }
659
660 template<typename Stream, typename K, typename T>
661 void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
662 {
663     Unserialize(is, item.first, nType, nVersion);
664     Unserialize(is, item.second, nType, nVersion);
665 }
666
667
668
669 //
670 // 3 tuple
671 //
672 template<typename T0, typename T1, typename T2>
673 unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
674 {
675     unsigned int nSize = 0;
676     nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion);
677     nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion);
678     nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion);
679     return nSize;
680 }
681
682 template<typename Stream, typename T0, typename T1, typename T2>
683 void Serialize(Stream& os, const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
684 {
685     Serialize(os, boost::get<0>(item), nType, nVersion);
686     Serialize(os, boost::get<1>(item), nType, nVersion);
687     Serialize(os, boost::get<2>(item), nType, nVersion);
688 }
689
690 template<typename Stream, typename T0, typename T1, typename T2>
691 void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
692 {
693     Unserialize(is, boost::get<0>(item), nType, nVersion);
694     Unserialize(is, boost::get<1>(item), nType, nVersion);
695     Unserialize(is, boost::get<2>(item), nType, nVersion);
696 }
697
698
699
700 //
701 // 4 tuple
702 //
703 template<typename T0, typename T1, typename T2, typename T3>
704 unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
705 {
706     unsigned int nSize = 0;
707     nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion);
708     nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion);
709     nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion);
710     nSize += GetSerializeSize(boost::get<3>(item), nType, nVersion);
711     return nSize;
712 }
713
714 template<typename Stream, typename T0, typename T1, typename T2, typename T3>
715 void Serialize(Stream& os, const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
716 {
717     Serialize(os, boost::get<0>(item), nType, nVersion);
718     Serialize(os, boost::get<1>(item), nType, nVersion);
719     Serialize(os, boost::get<2>(item), nType, nVersion);
720     Serialize(os, boost::get<3>(item), nType, nVersion);
721 }
722
723 template<typename Stream, typename T0, typename T1, typename T2, typename T3>
724 void Unserialize(Stream& is, boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
725 {
726     Unserialize(is, boost::get<0>(item), nType, nVersion);
727     Unserialize(is, boost::get<1>(item), nType, nVersion);
728     Unserialize(is, boost::get<2>(item), nType, nVersion);
729     Unserialize(is, boost::get<3>(item), nType, nVersion);
730 }
731
732
733
734 //
735 // map
736 //
737 template<typename K, typename T, typename Pred, typename A>
738 unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)
739 {
740     unsigned int nSize = GetSizeOfCompactSize(m.size());
741     for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
742         nSize += GetSerializeSize((*mi), nType, nVersion);
743     return nSize;
744 }
745
746 template<typename Stream, typename K, typename T, typename Pred, typename A>
747 void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion)
748 {
749     WriteCompactSize(os, m.size());
750     for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
751         Serialize(os, (*mi), nType, nVersion);
752 }
753
754 template<typename Stream, typename K, typename T, typename Pred, typename A>
755 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion)
756 {
757     m.clear();
758     unsigned int nSize = ReadCompactSize(is);
759     typename std::map<K, T, Pred, A>::iterator mi = m.begin();
760     for (unsigned int i = 0; i < nSize; i++)
761     {
762         std::pair<K, T> item;
763         Unserialize(is, item, nType, nVersion);
764         mi = m.insert(mi, item);
765     }
766 }
767
768
769
770 //
771 // set
772 //
773 template<typename K, typename Pred, typename A>
774 unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)
775 {
776     unsigned int nSize = GetSizeOfCompactSize(m.size());
777     for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
778         nSize += GetSerializeSize((*it), nType, nVersion);
779     return nSize;
780 }
781
782 template<typename Stream, typename K, typename Pred, typename A>
783 void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion)
784 {
785     WriteCompactSize(os, m.size());
786     for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
787         Serialize(os, (*it), nType, nVersion);
788 }
789
790 template<typename Stream, typename K, typename Pred, typename A>
791 void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
792 {
793     m.clear();
794     unsigned int nSize = ReadCompactSize(is);
795     typename std::set<K, Pred, A>::iterator it = m.begin();
796     for (unsigned int i = 0; i < nSize; i++)
797     {
798         K key;
799         Unserialize(is, key, nType, nVersion);
800         it = m.insert(it, key);
801     }
802 }
803
804
805
806 //
807 // Support for IMPLEMENT_SERIALIZE and READWRITE macro
808 //
809 class CSerActionGetSerializeSize { };
810 class CSerActionSerialize { };
811 class CSerActionUnserialize { };
812
813 template<typename Stream, typename T>
814 inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action)
815 {
816     return ::GetSerializeSize(obj, nType, nVersion);
817 }
818
819 template<typename Stream, typename T>
820 inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
821 {
822     ::Serialize(s, obj, nType, nVersion);
823     return 0;
824 }
825
826 template<typename Stream, typename T>
827 inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
828 {
829     ::Unserialize(s, obj, nType, nVersion);
830     return 0;
831 }
832
833 struct ser_streamplaceholder
834 {
835     int nType;
836     int nVersion;
837 };
838
839
840
841
842
843
844
845
846
847
848
849 typedef std::vector<char, zero_after_free_allocator<char> > CSerializeData;
850
851 /** Double ended buffer combining vector and stream-like interfaces.
852  *
853  * >> and << read and write unformatted data using the above serialization templates.
854  * Fills with data in linear time; some stringstream implementations take N^2 time.
855  */
856 class CDataStream
857 {
858 protected:
859     typedef CSerializeData vector_type;
860     vector_type vch;
861     unsigned int nReadPos;
862     short state;
863     short exceptmask;
864 public:
865     int nType;
866     int nVersion;
867
868     typedef vector_type::allocator_type   allocator_type;
869     typedef vector_type::size_type        size_type;
870     typedef vector_type::difference_type  difference_type;
871     typedef vector_type::reference        reference;
872     typedef vector_type::const_reference  const_reference;
873     typedef vector_type::value_type       value_type;
874     typedef vector_type::iterator         iterator;
875     typedef vector_type::const_iterator   const_iterator;
876     typedef vector_type::reverse_iterator reverse_iterator;
877
878     explicit CDataStream(int nTypeIn, int nVersionIn)
879     {
880         Init(nTypeIn, nVersionIn);
881     }
882
883     CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
884     {
885         Init(nTypeIn, nVersionIn);
886     }
887
888 #if !defined(_MSC_VER) || _MSC_VER >= 1300
889     CDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
890     {
891         Init(nTypeIn, nVersionIn);
892     }
893 #endif
894
895     CDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
896     {
897         Init(nTypeIn, nVersionIn);
898     }
899
900     CDataStream(const std::vector<char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
901     {
902         Init(nTypeIn, nVersionIn);
903     }
904
905     CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
906     {
907         Init(nTypeIn, nVersionIn);
908     }
909
910     void Init(int nTypeIn, int nVersionIn)
911     {
912         nReadPos = 0;
913         nType = nTypeIn;
914         nVersion = nVersionIn;
915         state = 0;
916         exceptmask = std::ios::badbit | std::ios::failbit;
917     }
918
919     CDataStream& operator+=(const CDataStream& b)
920     {
921         vch.insert(vch.end(), b.begin(), b.end());
922         return *this;
923     }
924
925     friend CDataStream operator+(const CDataStream& a, const CDataStream& b)
926     {
927         CDataStream ret = a;
928         ret += b;
929         return (ret);
930     }
931
932     std::string str() const
933     {
934         return (std::string(begin(), end()));
935     }
936
937
938     //
939     // Vector subset
940     //
941     const_iterator begin() const                     { return vch.begin() + nReadPos; }
942     iterator begin()                                 { return vch.begin() + nReadPos; }
943     const_iterator end() const                       { return vch.end(); }
944     iterator end()                                   { return vch.end(); }
945     size_type size() const                           { return vch.size() - nReadPos; }
946     bool empty() const                               { return vch.size() == nReadPos; }
947     void resize(size_type n, value_type c=0)         { vch.resize(n + nReadPos, c); }
948     void reserve(size_type n)                        { vch.reserve(n + nReadPos); }
949     const_reference operator[](size_type pos) const  { return vch[pos + nReadPos]; }
950     reference operator[](size_type pos)              { return vch[pos + nReadPos]; }
951     void clear()                                     { vch.clear(); nReadPos = 0; }
952     iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }
953     void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }
954
955 #ifdef _MSC_VER
956     void insert(iterator it, const_iterator first, const_iterator last)
957     {
958         assert(last - first >= 0);
959         if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
960         {
961             // special case for inserting at the front when there's room
962             nReadPos -= (last - first);
963             memcpy(&vch[nReadPos], &first[0], last - first);
964         }
965         else
966             vch.insert(it, first, last);
967     }
968 #endif
969
970 #ifndef _MSC_VER
971     void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last)
972     {
973         assert(last - first >= 0);
974         if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
975         {
976             // special case for inserting at the front when there's room
977             nReadPos -= (last - first);
978             memcpy(&vch[nReadPos], &first[0], last - first);
979         }
980         else
981             vch.insert(it, first, last);
982     }
983 #endif
984
985 #if !defined(_MSC_VER) || _MSC_VER >= 1300
986     void insert(iterator it, const char* first, const char* last)
987     {
988         assert(last - first >= 0);
989         if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
990         {
991             // special case for inserting at the front when there's room
992             nReadPos -= (last - first);
993             memcpy(&vch[nReadPos], &first[0], last - first);
994         }
995         else
996             vch.insert(it, first, last);
997     }
998 #endif
999
1000     iterator erase(iterator it)
1001     {
1002         if (it == vch.begin() + nReadPos)
1003         {
1004             // special case for erasing from the front
1005             if (++nReadPos >= vch.size())
1006             {
1007                 // whenever we reach the end, we take the opportunity to clear the buffer
1008                 nReadPos = 0;
1009                 return vch.erase(vch.begin(), vch.end());
1010             }
1011             return vch.begin() + nReadPos;
1012         }
1013         else
1014             return vch.erase(it);
1015     }
1016
1017     iterator erase(iterator first, iterator last)
1018     {
1019         if (first == vch.begin() + nReadPos)
1020         {
1021             // special case for erasing from the front
1022             if (last == vch.end())
1023             {
1024                 nReadPos = 0;
1025                 return vch.erase(vch.begin(), vch.end());
1026             }
1027             else
1028             {
1029                 nReadPos = (last - vch.begin());
1030                 return last;
1031             }
1032         }
1033         else
1034             return vch.erase(first, last);
1035     }
1036
1037     inline void Compact()
1038     {
1039         vch.erase(vch.begin(), vch.begin() + nReadPos);
1040         nReadPos = 0;
1041     }
1042
1043     bool Rewind(size_type n)
1044     {
1045         // Rewind by n characters if the buffer hasn't been compacted yet
1046         if (n > nReadPos)
1047             return false;
1048         nReadPos -= n;
1049         return true;
1050     }
1051
1052
1053     //
1054     // Stream subset
1055     //
1056     void setstate(short bits, const char* psz)
1057     {
1058         state |= bits;
1059         if (state & exceptmask)
1060             throw std::ios_base::failure(psz);
1061     }
1062
1063     bool eof() const             { return size() == 0; }
1064     bool fail() const            { return state & (std::ios::badbit | std::ios::failbit); }
1065     bool good() const            { return !eof() && (state == 0); }
1066     void clear(short n)          { state = n; }  // name conflict with vector clear()
1067     short exceptions()           { return exceptmask; }
1068     short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; }
1069     CDataStream* rdbuf()         { return this; }
1070     int in_avail()               { return size(); }
1071
1072     void SetType(int n)          { nType = n; }
1073     int GetType()                { return nType; }
1074     void SetVersion(int n)       { nVersion = n; }
1075     int GetVersion()             { return nVersion; }
1076     void ReadVersion()           { *this >> nVersion; }
1077     void WriteVersion()          { *this << nVersion; }
1078
1079     CDataStream& read(char* pch, int nSize)
1080     {
1081         // Read from the beginning of the buffer
1082         assert(nSize >= 0);
1083         unsigned int nReadPosNext = nReadPos + nSize;
1084         if (nReadPosNext >= vch.size())
1085         {
1086             if (nReadPosNext > vch.size())
1087             {
1088                 setstate(std::ios::failbit, "CDataStream::read() : end of data");
1089                 memset(pch, 0, nSize);
1090                 nSize = vch.size() - nReadPos;
1091             }
1092             memcpy(pch, &vch[nReadPos], nSize);
1093             nReadPos = 0;
1094             vch.clear();
1095             return (*this);
1096         }
1097         memcpy(pch, &vch[nReadPos], nSize);
1098         nReadPos = nReadPosNext;
1099         return (*this);
1100     }
1101
1102     CDataStream& ignore(int nSize)
1103     {
1104         // Ignore from the beginning of the buffer
1105         assert(nSize >= 0);
1106         unsigned int nReadPosNext = nReadPos + nSize;
1107         if (nReadPosNext >= vch.size())
1108         {
1109             if (nReadPosNext > vch.size())
1110             {
1111                 setstate(std::ios::failbit, "CDataStream::ignore() : end of data");
1112                 nSize = vch.size() - nReadPos;
1113             }
1114             nReadPos = 0;
1115             vch.clear();
1116             return (*this);
1117         }
1118         nReadPos = nReadPosNext;
1119         return (*this);
1120     }
1121
1122     CDataStream& write(const char* pch, int nSize)
1123     {
1124         // Write to the end of the buffer
1125         assert(nSize >= 0);
1126         vch.insert(vch.end(), pch, pch + nSize);
1127         return (*this);
1128     }
1129
1130     template<typename Stream>
1131     void Serialize(Stream& s, int nType, int nVersion) const
1132     {
1133         // Special case: stream << stream concatenates like stream += stream
1134         if (!vch.empty())
1135             s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));
1136     }
1137
1138     template<typename T>
1139     unsigned int GetSerializeSize(const T& obj)
1140     {
1141         // Tells the size of the object if serialized to this stream
1142         return ::GetSerializeSize(obj, nType, nVersion);
1143     }
1144
1145     template<typename T>
1146     CDataStream& operator<<(const T& obj)
1147     {
1148         // Serialize to this stream
1149         ::Serialize(*this, obj, nType, nVersion);
1150         return (*this);
1151     }
1152
1153     template<typename T>
1154     CDataStream& operator>>(T& obj)
1155     {
1156         // Unserialize from this stream
1157         ::Unserialize(*this, obj, nType, nVersion);
1158         return (*this);
1159     }
1160
1161     void GetAndClear(CSerializeData &data) {
1162         vch.swap(data);
1163         CSerializeData().swap(vch);
1164     }
1165 };
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176 /** RAII wrapper for FILE*.
1177  *
1178  * Will automatically close the file when it goes out of scope if not null.
1179  * If you're returning the file pointer, return file.release().
1180  * If you need to close the file early, use file.fclose() instead of fclose(file).
1181  */
1182 class CAutoFile
1183 {
1184 protected:
1185     FILE* file;
1186     short state;
1187     short exceptmask;
1188 public:
1189     int nType;
1190     int nVersion;
1191
1192     CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn)
1193     {
1194         file = filenew;
1195         nType = nTypeIn;
1196         nVersion = nVersionIn;
1197         state = 0;
1198         exceptmask = std::ios::badbit | std::ios::failbit;
1199     }
1200
1201     ~CAutoFile()
1202     {
1203         fclose();
1204     }
1205
1206     void fclose()
1207     {
1208         if (file != NULL && file != stdin && file != stdout && file != stderr)
1209             ::fclose(file);
1210         file = NULL;
1211     }
1212
1213     FILE* release()             { FILE* ret = file; file = NULL; return ret; }
1214     operator FILE*()            { return file; }
1215     FILE* operator->()          { return file; }
1216     FILE& operator*()           { return *file; }
1217     FILE** operator&()          { return &file; }
1218     FILE* operator=(FILE* pnew) { return file = pnew; }
1219     bool operator!()            { return (file == NULL); }
1220
1221
1222     //
1223     // Stream subset
1224     //
1225     void setstate(short bits, const char* psz)
1226     {
1227         state |= bits;
1228         if (state & exceptmask)
1229             throw std::ios_base::failure(psz);
1230     }
1231
1232     bool fail() const            { return state & (std::ios::badbit | std::ios::failbit); }
1233     bool good() const            { return state == 0; }
1234     void clear(short n = 0)      { state = n; }
1235     short exceptions()           { return exceptmask; }
1236     short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; }
1237
1238     void SetType(int n)          { nType = n; }
1239     int GetType()                { return nType; }
1240     void SetVersion(int n)       { nVersion = n; }
1241     int GetVersion()             { return nVersion; }
1242     void ReadVersion()           { *this >> nVersion; }
1243     void WriteVersion()          { *this << nVersion; }
1244
1245     CAutoFile& read(char* pch, size_t nSize)
1246     {
1247         if (!file)
1248             throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
1249         if (fread(pch, 1, nSize, file) != nSize)
1250             setstate(std::ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
1251         return (*this);
1252     }
1253
1254     CAutoFile& write(const char* pch, size_t nSize)
1255     {
1256         if (!file)
1257             throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
1258         if (fwrite(pch, 1, nSize, file) != nSize)
1259             setstate(std::ios::failbit, "CAutoFile::write : write failed");
1260         return (*this);
1261     }
1262
1263     template<typename T>
1264     unsigned int GetSerializeSize(const T& obj)
1265     {
1266         // Tells the size of the object if serialized to this stream
1267         return ::GetSerializeSize(obj, nType, nVersion);
1268     }
1269
1270     template<typename T>
1271     CAutoFile& operator<<(const T& obj)
1272     {
1273         // Serialize to this stream
1274         if (!file)
1275             throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
1276         ::Serialize(*this, obj, nType, nVersion);
1277         return (*this);
1278     }
1279
1280     template<typename T>
1281     CAutoFile& operator>>(T& obj)
1282     {
1283         // Unserialize from this stream
1284         if (!file)
1285             throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");
1286         ::Unserialize(*this, obj, nType, nVersion);
1287         return (*this);
1288     }
1289 };
1290
1291 /** Wrapper around a FILE* that implements a ring buffer to
1292  *  deserialize from. It guarantees the ability to rewind
1293  *  a given number of bytes. */
1294 class CBufferedFile
1295 {
1296 private:
1297     FILE *src;          // source file
1298     uint64 nSrcPos;     // how many bytes have been read from source
1299     uint64 nReadPos;    // how many bytes have been read from this
1300     uint64 nReadLimit;  // up to which position we're allowed to read
1301     uint64 nRewind;     // how many bytes we guarantee to rewind
1302     std::vector<char> vchBuf; // the buffer
1303
1304     short state;
1305     short exceptmask;
1306
1307 protected:
1308     void setstate(short bits, const char *psz) {
1309         state |= bits;
1310         if (state & exceptmask)
1311             throw std::ios_base::failure(psz);
1312     }
1313
1314     // read data from the source to fill the buffer
1315     bool Fill() {
1316         unsigned int pos = nSrcPos % vchBuf.size();
1317         unsigned int readNow = vchBuf.size() - pos;
1318         unsigned int nAvail = vchBuf.size() - (nSrcPos - nReadPos) - nRewind;
1319         if (nAvail < readNow)
1320             readNow = nAvail;
1321         if (readNow == 0)
1322             return false;
1323         size_t read = fread((void*)&vchBuf[pos], 1, readNow, src);
1324         if (read == 0) {
1325             setstate(std::ios_base::failbit, feof(src) ? "CBufferedFile::Fill : end of file" : "CBufferedFile::Fill : fread failed");
1326             return false;
1327         } else {
1328             nSrcPos += read;
1329             return true;
1330         }
1331     }
1332
1333 public:
1334     int nType;
1335     int nVersion;
1336
1337     CBufferedFile(FILE *fileIn, uint64 nBufSize, uint64 nRewindIn, int nTypeIn, int nVersionIn) :
1338         src(fileIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0),
1339         state(0), exceptmask(std::ios_base::badbit | std::ios_base::failbit), nType(nTypeIn), nVersion(nVersionIn) {
1340     }
1341
1342     // check whether no error occurred
1343     bool good() const {
1344         return state == 0;
1345     }
1346
1347     // check whether we're at the end of the source file
1348     bool eof() const {
1349         return nReadPos == nSrcPos && feof(src);
1350     }
1351
1352     // read a number of bytes
1353     CBufferedFile& read(char *pch, size_t nSize) {
1354         if (nSize + nReadPos > nReadLimit)
1355             throw std::ios_base::failure("Read attempted past buffer limit");
1356         if (nSize + nRewind > vchBuf.size())
1357             throw std::ios_base::failure("Read larger than buffer size");
1358         while (nSize > 0) {
1359             if (nReadPos == nSrcPos)
1360                 Fill();
1361             unsigned int pos = nReadPos % vchBuf.size();
1362             size_t nNow = nSize;
1363             if (nNow + pos > vchBuf.size())
1364                 nNow = vchBuf.size() - pos;
1365             if (nNow + nReadPos > nSrcPos)
1366                 nNow = nSrcPos - nReadPos;
1367             memcpy(pch, &vchBuf[pos], nNow);
1368             nReadPos += nNow;
1369             pch += nNow;
1370             nSize -= nNow;
1371         }
1372         return (*this);
1373     }
1374
1375     // return the current reading position
1376     uint64 GetPos() {
1377         return nReadPos;
1378     }
1379
1380     // rewind to a given reading position
1381     bool SetPos(uint64 nPos) {
1382         nReadPos = nPos;
1383         if (nReadPos + nRewind < nSrcPos) {
1384             nReadPos = nSrcPos - nRewind;
1385             return false;
1386         } else if (nReadPos > nSrcPos) {
1387             nReadPos = nSrcPos;
1388             return false;
1389         } else {
1390             return true;
1391         }
1392     }
1393
1394     bool Seek(uint64 nPos) {
1395         long nLongPos = nPos;
1396         if (nPos != (uint64)nLongPos)
1397             return false;
1398         if (fseek(src, nLongPos, SEEK_SET))
1399             return false;
1400         nLongPos = ftell(src);
1401         nSrcPos = nLongPos;
1402         nReadPos = nLongPos;
1403         state = 0;
1404         return true;
1405     }
1406
1407     // prevent reading beyond a certain position
1408     // no argument removes the limit
1409     bool SetLimit(uint64 nPos = (uint64)(-1)) {
1410         if (nPos < nReadPos)
1411             return false;
1412         nReadLimit = nPos;
1413         return true;
1414     }
1415
1416     template<typename T>
1417     CBufferedFile& operator>>(T& obj) {
1418         // Unserialize from this stream
1419         ::Unserialize(*this, obj, nType, nVersion);
1420         return (*this);
1421     }
1422
1423     // search for a given byte in the stream, and remain positioned on it
1424     void FindByte(char ch) {
1425         while (true) {
1426             if (nReadPos == nSrcPos)
1427                 Fill();
1428             if (vchBuf[nReadPos % vchBuf.size()] == ch)
1429                 break;
1430             nReadPos++;
1431         }
1432     }
1433 };
1434
1435 #endif