genesis                 1 
genesis                 2 
genesis                 3 
genesis                 4 
genesis                 5 #ifndef BITCOIN_SERIALIZE_H
genesis                 6 #define BITCOIN_SERIALIZE_H
genesis                 7 
genesis                 8 #include <string>
genesis                 9 #include <vector>
genesis                10 #include <map>
genesis                11 #include <set>
genesis                12 #include <cassert>
genesis                13 #include <climits>
genesis                14 #include <cstring>
genesis                15 #include <cstdio>
genesis                16 
genesis                17 #include <boost/type_traits/is_fundamental.hpp>
genesis                18 #include <boost/tuple/tuple.hpp>
genesis                19 #include <boost/tuple/tuple_comparison.hpp>
genesis                20 #include <boost/tuple/tuple_io.hpp>
genesis                21 
genesis                22 #if defined(_MSC_VER) || defined(__BORLANDC__)
genesis                23 typedef __int64  int64;
genesis                24 typedef unsigned __int64  uint64;
genesis                25 #else
genesis                26 typedef long long  int64;
genesis                27 typedef unsigned long long  uint64;
genesis                28 #endif
genesis                29 #if defined(_MSC_VER) && _MSC_VER < 1300
genesis                30 #define for  if (false) ; else for
genesis                31 #endif
genesis                32 
genesis                33 #ifdef WIN32
genesis                34 #include <windows.h>
genesis                35 
genesis                36 
genesis                37 
genesis                38 
genesis                39 #include <windows.h>
genesis                40 #define mlock(p, n) VirtualLock((p), (n));
genesis                41 #define munlock(p, n) VirtualUnlock((p), (n));
genesis                42 #else
genesis                43 #include <sys/mman.h>
genesis                44 #include <limits.h>
genesis                45 
genesis                46 #ifndef PAGESIZE
genesis                47 #include <unistd.h>
genesis                48 #define PAGESIZE sysconf(_SC_PAGESIZE)
genesis                49 #endif
genesis                50 #define mlock(a,b) \
genesis                51   mlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
genesis                52   (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
genesis                53 #define munlock(a,b) \
genesis                54   munlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
genesis                55   (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
genesis                56 #endif
genesis                57 
genesis                58 class CScript;
genesis                59 class CDataStream;
genesis                60 class CAutoFile;
genesis                61 static const unsigned int MAX_SIZE = 0x02000000;
genesis                62 
genesis                63 static const int VERSION = 50300;
genesis                64 static const char* pszSubVer = "";
genesis                65 static const bool VERSION_IS_BETA = true;
genesis                66 
genesis                67 
genesis                68 
genesis                69 template<typename T>
genesis                70 inline T& REF(const T& val)
genesis                71 {
genesis                72     return const_cast<T&>(val);
genesis                73 }
genesis                74 
genesis                75 
genesis                76 
genesis                77 
genesis                78 
genesis                79 
genesis                80 
genesis                81 enum
genesis                82 {
genesis                83     
genesis                84     SER_NETWORK         = (1 << 0),
genesis                85     SER_DISK            = (1 << 1),
genesis                86     SER_GETHASH         = (1 << 2),
genesis                87 
genesis                88     
genesis                89     SER_SKIPSIG         = (1 << 16),
genesis                90     SER_BLOCKHEADERONLY = (1 << 17),
genesis                91 };
genesis                92 
genesis                93 #define IMPLEMENT_SERIALIZE(statements)    \
genesis                94     unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const  \
genesis                95     {                                           \
genesis                96         CSerActionGetSerializeSize ser_action;  \
genesis                97         const bool fGetSize = true;             \
genesis                98         const bool fWrite = false;              \
genesis                99         const bool fRead = false;               \
genesis               100         unsigned int nSerSize = 0;              \
genesis               101         ser_streamplaceholder s;                \
genesis               102         assert(fGetSize||fWrite||fRead);  \
genesis               103         s.nType = nType;                        \
genesis               104         s.nVersion = nVersion;                  \
genesis               105         {statements}                            \
genesis               106         return nSerSize;                        \
genesis               107     }                                           \
genesis               108     template<typename Stream>                   \
genesis               109     void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const  \
genesis               110     {                                           \
genesis               111         CSerActionSerialize ser_action;         \
genesis               112         const bool fGetSize = false;            \
genesis               113         const bool fWrite = true;               \
genesis               114         const bool fRead = false;               \
genesis               115         unsigned int nSerSize = 0;              \
genesis               116         assert(fGetSize||fWrite||fRead);  \
genesis               117         {statements}                            \
genesis               118     }                                           \
genesis               119     template<typename Stream>                   \
genesis               120     void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)  \
genesis               121     {                                           \
genesis               122         CSerActionUnserialize ser_action;       \
genesis               123         const bool fGetSize = false;            \
genesis               124         const bool fWrite = false;              \
genesis               125         const bool fRead = true;                \
genesis               126         unsigned int nSerSize = 0;              \
genesis               127         assert(fGetSize||fWrite||fRead);  \
genesis               128         {statements}                            \
genesis               129     }
genesis               130 
genesis               131 #define READWRITE(obj)      (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
genesis               132 
genesis               133 
genesis               134 
genesis               135 
genesis               136 
genesis               137 
genesis               138 
genesis               139 
genesis               140 
genesis               141 #define WRITEDATA(s, obj)   s.write((char*)&(obj), sizeof(obj))
genesis               142 #define READDATA(s, obj)    s.read((char*)&(obj), sizeof(obj))
genesis               143 
genesis               144 inline unsigned int GetSerializeSize(char a,           int, int=0) { return sizeof(a); }
genesis               145 inline unsigned int GetSerializeSize(signed char a,    int, int=0) { return sizeof(a); }
genesis               146 inline unsigned int GetSerializeSize(unsigned char a,  int, int=0) { return sizeof(a); }
genesis               147 inline unsigned int GetSerializeSize(signed short a,   int, int=0) { return sizeof(a); }
genesis               148 inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); }
genesis               149 inline unsigned int GetSerializeSize(signed int a,     int, int=0) { return sizeof(a); }
genesis               150 inline unsigned int GetSerializeSize(unsigned int a,   int, int=0) { return sizeof(a); }
genesis               151 inline unsigned int GetSerializeSize(signed long a,    int, int=0) { return sizeof(a); }
genesis               152 inline unsigned int GetSerializeSize(unsigned long a,  int, int=0) { return sizeof(a); }
genesis               153 inline unsigned int GetSerializeSize(int64 a,          int, int=0) { return sizeof(a); }
genesis               154 inline unsigned int GetSerializeSize(uint64 a,         int, int=0) { return sizeof(a); }
genesis               155 inline unsigned int GetSerializeSize(float a,          int, int=0) { return sizeof(a); }
genesis               156 inline unsigned int GetSerializeSize(double a,         int, int=0) { return sizeof(a); }
genesis               157 
genesis               158 template<typename Stream> inline void Serialize(Stream& s, char a,           int, int=0) { WRITEDATA(s, a); }
genesis               159 template<typename Stream> inline void Serialize(Stream& s, signed char a,    int, int=0) { WRITEDATA(s, a); }
genesis               160 template<typename Stream> inline void Serialize(Stream& s, unsigned char a,  int, int=0) { WRITEDATA(s, a); }
genesis               161 template<typename Stream> inline void Serialize(Stream& s, signed short a,   int, int=0) { WRITEDATA(s, a); }
genesis               162 template<typename Stream> inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); }
genesis               163 template<typename Stream> inline void Serialize(Stream& s, signed int a,     int, int=0) { WRITEDATA(s, a); }
genesis               164 template<typename Stream> inline void Serialize(Stream& s, unsigned int a,   int, int=0) { WRITEDATA(s, a); }
genesis               165 template<typename Stream> inline void Serialize(Stream& s, signed long a,    int, int=0) { WRITEDATA(s, a); }
genesis               166 template<typename Stream> inline void Serialize(Stream& s, unsigned long a,  int, int=0) { WRITEDATA(s, a); }
genesis               167 template<typename Stream> inline void Serialize(Stream& s, int64 a,          int, int=0) { WRITEDATA(s, a); }
genesis               168 template<typename Stream> inline void Serialize(Stream& s, uint64 a,         int, int=0) { WRITEDATA(s, a); }
genesis               169 template<typename Stream> inline void Serialize(Stream& s, float a,          int, int=0) { WRITEDATA(s, a); }
genesis               170 template<typename Stream> inline void Serialize(Stream& s, double a,         int, int=0) { WRITEDATA(s, a); }
genesis               171 
genesis               172 template<typename Stream> inline void Unserialize(Stream& s, char& a,           int, int=0) { READDATA(s, a); }
genesis               173 template<typename Stream> inline void Unserialize(Stream& s, signed char& a,    int, int=0) { READDATA(s, a); }
genesis               174 template<typename Stream> inline void Unserialize(Stream& s, unsigned char& a,  int, int=0) { READDATA(s, a); }
genesis               175 template<typename Stream> inline void Unserialize(Stream& s, signed short& a,   int, int=0) { READDATA(s, a); }
genesis               176 template<typename Stream> inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); }
genesis               177 template<typename Stream> inline void Unserialize(Stream& s, signed int& a,     int, int=0) { READDATA(s, a); }
genesis               178 template<typename Stream> inline void Unserialize(Stream& s, unsigned int& a,   int, int=0) { READDATA(s, a); }
genesis               179 template<typename Stream> inline void Unserialize(Stream& s, signed long& a,    int, int=0) { READDATA(s, a); }
genesis               180 template<typename Stream> inline void Unserialize(Stream& s, unsigned long& a,  int, int=0) { READDATA(s, a); }
genesis               181 template<typename Stream> inline void Unserialize(Stream& s, int64& a,          int, int=0) { READDATA(s, a); }
genesis               182 template<typename Stream> inline void Unserialize(Stream& s, uint64& a,         int, int=0) { READDATA(s, a); }
genesis               183 template<typename Stream> inline void Unserialize(Stream& s, float& a,          int, int=0) { READDATA(s, a); }
genesis               184 template<typename Stream> inline void Unserialize(Stream& s, double& a,         int, int=0) { READDATA(s, a); }
genesis               185 
genesis               186 inline unsigned int GetSerializeSize(bool a, int, int=0)                          { return sizeof(char); }
genesis               187 template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0)    { char f=a; WRITEDATA(s, f); }
genesis               188 template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; }
genesis               189 
genesis               190 
genesis               191 
genesis               192 
genesis               193 
genesis               194 
genesis               195 
genesis               196 
genesis               197 
genesis               198 
genesis               199 
genesis               200 
genesis               201 
genesis               202 inline unsigned int GetSizeOfCompactSize(uint64 nSize)
genesis               203 {
genesis               204     if (nSize < 253)             return sizeof(unsigned char);
genesis               205     else if (nSize <= USHRT_MAX) return sizeof(unsigned char) + sizeof(unsigned short);
genesis               206     else if (nSize <= UINT_MAX)  return sizeof(unsigned char) + sizeof(unsigned int);
genesis               207     else                         return sizeof(unsigned char) + sizeof(uint64);
genesis               208 }
genesis               209 
genesis               210 template<typename Stream>
genesis               211 void WriteCompactSize(Stream& os, uint64 nSize)
genesis               212 {
genesis               213     if (nSize < 253)
genesis               214     {
genesis               215         unsigned char chSize = nSize;
genesis               216         WRITEDATA(os, chSize);
genesis               217     }
genesis               218     else if (nSize <= USHRT_MAX)
genesis               219     {
genesis               220         unsigned char chSize = 253;
genesis               221         unsigned short xSize = nSize;
genesis               222         WRITEDATA(os, chSize);
genesis               223         WRITEDATA(os, xSize);
genesis               224     }
genesis               225     else if (nSize <= UINT_MAX)
genesis               226     {
genesis               227         unsigned char chSize = 254;
genesis               228         unsigned int xSize = nSize;
genesis               229         WRITEDATA(os, chSize);
genesis               230         WRITEDATA(os, xSize);
genesis               231     }
genesis               232     else
genesis               233     {
genesis               234         unsigned char chSize = 255;
genesis               235         uint64 xSize = nSize;
genesis               236         WRITEDATA(os, chSize);
genesis               237         WRITEDATA(os, xSize);
genesis               238     }
genesis               239     return;
genesis               240 }
genesis               241 
genesis               242 template<typename Stream>
genesis               243 uint64 ReadCompactSize(Stream& is)
genesis               244 {
genesis               245     unsigned char chSize;
genesis               246     READDATA(is, chSize);
genesis               247     uint64 nSizeRet = 0;
genesis               248     if (chSize < 253)
genesis               249     {
genesis               250         nSizeRet = chSize;
genesis               251     }
genesis               252     else if (chSize == 253)
genesis               253     {
genesis               254         unsigned short xSize;
genesis               255         READDATA(is, xSize);
genesis               256         nSizeRet = xSize;
genesis               257     }
genesis               258     else if (chSize == 254)
genesis               259     {
genesis               260         unsigned int xSize;
genesis               261         READDATA(is, xSize);
genesis               262         nSizeRet = xSize;
genesis               263     }
genesis               264     else
genesis               265     {
genesis               266         uint64 xSize;
genesis               267         READDATA(is, xSize);
genesis               268         nSizeRet = xSize;
genesis               269     }
genesis               270     if (nSizeRet > (uint64)MAX_SIZE)
genesis               271         throw std::ios_base::failure("ReadCompactSize() : size too large");
genesis               272     return nSizeRet;
genesis               273 }
genesis               274 
genesis               275 
genesis               276 
genesis               277 
genesis               278 
genesis               279 
genesis               280 
genesis               281 #define FLATDATA(obj)   REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
genesis               282 class CFlatData
genesis               283 {
genesis               284 protected:
genesis               285     char* pbegin;
genesis               286     char* pend;
genesis               287 public:
genesis               288     CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
genesis               289     char* begin() { return pbegin; }
genesis               290     const char* begin() const { return pbegin; }
genesis               291     char* end() { return pend; }
genesis               292     const char* end() const { return pend; }
genesis               293 
genesis               294     unsigned int GetSerializeSize(int, int=0) const
genesis               295     {
genesis               296         return pend - pbegin;
genesis               297     }
genesis               298 
genesis               299     template<typename Stream>
genesis               300     void Serialize(Stream& s, int, int=0) const
genesis               301     {
genesis               302         s.write(pbegin, pend - pbegin);
genesis               303     }
genesis               304 
genesis               305     template<typename Stream>
genesis               306     void Unserialize(Stream& s, int, int=0)
genesis               307     {
genesis               308         s.read(pbegin, pend - pbegin);
genesis               309     }
genesis               310 };
genesis               311 
genesis               312 
genesis               313 
genesis               314 
genesis               315 
genesis               316 
genesis               317 template<std::size_t LEN>
genesis               318 class CFixedFieldString
genesis               319 {
genesis               320 protected:
genesis               321     const std::string* pcstr;
genesis               322     std::string* pstr;
genesis               323 public:
genesis               324     explicit CFixedFieldString(const std::string& str) : pcstr(&str), pstr(NULL) { }
genesis               325     explicit CFixedFieldString(std::string& str) : pcstr(&str), pstr(&str) { }
genesis               326 
genesis               327     unsigned int GetSerializeSize(int, int=0) const
genesis               328     {
genesis               329         return LEN;
genesis               330     }
genesis               331 
genesis               332     template<typename Stream>
genesis               333     void Serialize(Stream& s, int, int=0) const
genesis               334     {
genesis               335         char pszBuf[LEN];
genesis               336         strncpy(pszBuf, pcstr->c_str(), LEN);
genesis               337         s.write(pszBuf, LEN);
genesis               338     }
genesis               339 
genesis               340     template<typename Stream>
genesis               341     void Unserialize(Stream& s, int, int=0)
genesis               342     {
genesis               343         if (pstr == NULL)
genesis               344             throw std::ios_base::failure("CFixedFieldString::Unserialize : trying to unserialize to const string");
genesis               345         char pszBuf[LEN+1];
genesis               346         s.read(pszBuf, LEN);
genesis               347         pszBuf[LEN] = '\0';
genesis               348         *pstr = pszBuf;
genesis               349     }
genesis               350 };
genesis               351 
genesis               352 
genesis               353 
genesis               354 
genesis               355 
genesis               356 
genesis               357 
genesis               358 
genesis               359 
genesis               360 
genesis               361 template<typename C> unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int=0);
genesis               362 template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str, int, int=0);
genesis               363 template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str, int, int=0);
genesis               364 
genesis               365 
genesis               366 template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);
genesis               367 template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);
genesis               368 template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion=VERSION);
genesis               369 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&);
genesis               370 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&);
genesis               371 template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion=VERSION);
genesis               372 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&);
genesis               373 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&);
genesis               374 template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion=VERSION);
genesis               375 
genesis               376 
genesis               377 extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion=VERSION);
genesis               378 template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion=VERSION);
genesis               379 template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion=VERSION);
genesis               380 
genesis               381 
genesis               382 template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion=VERSION);
genesis               383 template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion=VERSION);
genesis               384 template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion=VERSION);
genesis               385 
genesis               386 
genesis               387 template<typename T0, typename T1, typename T2> unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion=VERSION);
genesis               388 template<typename Stream, typename T0, typename T1, typename T2> void Serialize(Stream& os, const boost::tuple<T0, T1, T2>& item, int nType, int nVersion=VERSION);
genesis               389 template<typename Stream, typename T0, typename T1, typename T2> void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion=VERSION);
genesis               390 
genesis               391 
genesis               392 template<typename T0, typename T1, typename T2, typename T3> unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion=VERSION);
genesis               393 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=VERSION);
genesis               394 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=VERSION);
genesis               395 
genesis               396 
genesis               397 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);
genesis               398 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);
genesis               399 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);
genesis               400 
genesis               401 
genesis               402 template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
genesis               403 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);
genesis               404 template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
genesis               405 
genesis               406 
genesis               407 
genesis               408 
genesis               409 
genesis               410 
genesis               411 
genesis               412 
genesis               413 
genesis               414 
genesis               415 
genesis               416 template<typename T>
genesis               417 inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion=VERSION)
genesis               418 {
genesis               419     return a.GetSerializeSize((int)nType, nVersion);
genesis               420 }
genesis               421 
genesis               422 template<typename Stream, typename T>
genesis               423 inline void Serialize(Stream& os, const T& a, long nType, int nVersion=VERSION)
genesis               424 {
genesis               425     a.Serialize(os, (int)nType, nVersion);
genesis               426 }
genesis               427 
genesis               428 template<typename Stream, typename T>
genesis               429 inline void Unserialize(Stream& is, T& a, long nType, int nVersion=VERSION)
genesis               430 {
genesis               431     a.Unserialize(is, (int)nType, nVersion);
genesis               432 }
genesis               433 
genesis               434 
genesis               435 
genesis               436 
genesis               437 
genesis               438 
genesis               439 
genesis               440 
genesis               441 template<typename C>
genesis               442 unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int)
genesis               443 {
genesis               444     return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]);
genesis               445 }
genesis               446 
genesis               447 template<typename Stream, typename C>
genesis               448 void Serialize(Stream& os, const std::basic_string<C>& str, int, int)
genesis               449 {
genesis               450     WriteCompactSize(os, str.size());
genesis               451     if (!str.empty())
genesis               452         os.write((char*)&str[0], str.size() * sizeof(str[0]));
genesis               453 }
genesis               454 
genesis               455 template<typename Stream, typename C>
genesis               456 void Unserialize(Stream& is, std::basic_string<C>& str, int, int)
genesis               457 {
genesis               458     unsigned int nSize = ReadCompactSize(is);
genesis               459     str.resize(nSize);
genesis               460     if (nSize != 0)
genesis               461         is.read((char*)&str[0], nSize * sizeof(str[0]));
genesis               462 }
genesis               463 
genesis               464 
genesis               465 
genesis               466 
genesis               467 
genesis               468 
genesis               469 template<typename T, typename A>
genesis               470 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
genesis               471 {
genesis               472     return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));
genesis               473 }
genesis               474 
genesis               475 template<typename T, typename A>
genesis               476 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
genesis               477 {
genesis               478     unsigned int nSize = GetSizeOfCompactSize(v.size());
genesis               479     for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
genesis               480         nSize += GetSerializeSize((*vi), nType, nVersion);
genesis               481     return nSize;
genesis               482 }
genesis               483 
genesis               484 template<typename T, typename A>
genesis               485 inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion)
genesis               486 {
genesis               487     return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental<T>());
genesis               488 }
genesis               489 
genesis               490 
genesis               491 template<typename Stream, typename T, typename A>
genesis               492 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
genesis               493 {
genesis               494     WriteCompactSize(os, v.size());
genesis               495     if (!v.empty())
genesis               496         os.write((char*)&v[0], v.size() * sizeof(T));
genesis               497 }
genesis               498 
genesis               499 template<typename Stream, typename T, typename A>
genesis               500 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
genesis               501 {
genesis               502     WriteCompactSize(os, v.size());
genesis               503     for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
genesis               504         ::Serialize(os, (*vi), nType, nVersion);
genesis               505 }
genesis               506 
genesis               507 template<typename Stream, typename T, typename A>
genesis               508 inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion)
genesis               509 {
genesis               510     Serialize_impl(os, v, nType, nVersion, boost::is_fundamental<T>());
genesis               511 }
genesis               512 
genesis               513 
genesis               514 template<typename Stream, typename T, typename A>
genesis               515 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
genesis               516 {
genesis               517     
genesis               518     
genesis               519     
genesis               520 
genesis               521     
genesis               522     v.clear();
genesis               523     unsigned int nSize = ReadCompactSize(is);
genesis               524     unsigned int i = 0;
genesis               525     while (i < nSize)
genesis               526     {
genesis               527         unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
genesis               528         v.resize(i + blk);
genesis               529         is.read((char*)&v[i], blk * sizeof(T));
genesis               530         i += blk;
genesis               531     }
genesis               532 }
genesis               533 
genesis               534 template<typename Stream, typename T, typename A>
genesis               535 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
genesis               536 {
genesis               537     
genesis               538     
genesis               539     
genesis               540     
genesis               541 
genesis               542     v.clear();
genesis               543     unsigned int nSize = ReadCompactSize(is);
genesis               544     unsigned int i = 0;
genesis               545     unsigned int nMid = 0;
genesis               546     while (nMid < nSize)
genesis               547     {
genesis               548         nMid += 5000000 / sizeof(T);
genesis               549         if (nMid > nSize)
genesis               550             nMid = nSize;
genesis               551         v.resize(nMid);
genesis               552         for (; i < nMid; i++)
genesis               553             Unserialize(is, v[i], nType, nVersion);
genesis               554     }
genesis               555 }
genesis               556 
genesis               557 template<typename Stream, typename T, typename A>
genesis               558 inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion)
genesis               559 {
genesis               560     Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental<T>());
genesis               561 }
genesis               562 
genesis               563 
genesis               564 
genesis               565 
genesis               566 
genesis               567 
genesis               568 inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)
genesis               569 {
genesis               570     return GetSerializeSize((const std::vector<unsigned char>&)v, nType, nVersion);
genesis               571 }
genesis               572 
genesis               573 template<typename Stream>
genesis               574 void Serialize(Stream& os, const CScript& v, int nType, int nVersion)
genesis               575 {
genesis               576     Serialize(os, (const std::vector<unsigned char>&)v, nType, nVersion);
genesis               577 }
genesis               578 
genesis               579 template<typename Stream>
genesis               580 void Unserialize(Stream& is, CScript& v, int nType, int nVersion)
genesis               581 {
genesis               582     Unserialize(is, (std::vector<unsigned char>&)v, nType, nVersion);
genesis               583 }
genesis               584 
genesis               585 
genesis               586 
genesis               587 
genesis               588 
genesis               589 
genesis               590 template<typename K, typename T>
genesis               591 unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)
genesis               592 {
genesis               593     return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion);
genesis               594 }
genesis               595 
genesis               596 template<typename Stream, typename K, typename T>
genesis               597 void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion)
genesis               598 {
genesis               599     Serialize(os, item.first, nType, nVersion);
genesis               600     Serialize(os, item.second, nType, nVersion);
genesis               601 }
genesis               602 
genesis               603 template<typename Stream, typename K, typename T>
genesis               604 void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
genesis               605 {
genesis               606     Unserialize(is, item.first, nType, nVersion);
genesis               607     Unserialize(is, item.second, nType, nVersion);
genesis               608 }
genesis               609 
genesis               610 
genesis               611 
genesis               612 
genesis               613 
genesis               614 
genesis               615 template<typename T0, typename T1, typename T2>
genesis               616 unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
genesis               617 {
genesis               618     unsigned int nSize = 0;
genesis               619     nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion);
genesis               620     nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion);
genesis               621     nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion);
genesis               622     return nSize;
genesis               623 }
genesis               624 
genesis               625 template<typename Stream, typename T0, typename T1, typename T2>
genesis               626 void Serialize(Stream& os, const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
genesis               627 {
genesis               628     Serialize(os, boost::get<0>(item), nType, nVersion);
genesis               629     Serialize(os, boost::get<1>(item), nType, nVersion);
genesis               630     Serialize(os, boost::get<2>(item), nType, nVersion);
genesis               631 }
genesis               632 
genesis               633 template<typename Stream, typename T0, typename T1, typename T2>
genesis               634 void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
genesis               635 {
genesis               636     Unserialize(is, boost::get<0>(item), nType, nVersion);
genesis               637     Unserialize(is, boost::get<1>(item), nType, nVersion);
genesis               638     Unserialize(is, boost::get<2>(item), nType, nVersion);
genesis               639 }
genesis               640 
genesis               641 
genesis               642 
genesis               643 
genesis               644 
genesis               645 
genesis               646 template<typename T0, typename T1, typename T2, typename T3>
genesis               647 unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
genesis               648 {
genesis               649     unsigned int nSize = 0;
genesis               650     nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion);
genesis               651     nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion);
genesis               652     nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion);
genesis               653     nSize += GetSerializeSize(boost::get<3>(item), nType, nVersion);
genesis               654     return nSize;
genesis               655 }
genesis               656 
genesis               657 template<typename Stream, typename T0, typename T1, typename T2, typename T3>
genesis               658 void Serialize(Stream& os, const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
genesis               659 {
genesis               660     Serialize(os, boost::get<0>(item), nType, nVersion);
genesis               661     Serialize(os, boost::get<1>(item), nType, nVersion);
genesis               662     Serialize(os, boost::get<2>(item), nType, nVersion);
genesis               663     Serialize(os, boost::get<3>(item), nType, nVersion);
genesis               664 }
genesis               665 
genesis               666 template<typename Stream, typename T0, typename T1, typename T2, typename T3>
genesis               667 void Unserialize(Stream& is, boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
genesis               668 {
genesis               669     Unserialize(is, boost::get<0>(item), nType, nVersion);
genesis               670     Unserialize(is, boost::get<1>(item), nType, nVersion);
genesis               671     Unserialize(is, boost::get<2>(item), nType, nVersion);
genesis               672     Unserialize(is, boost::get<3>(item), nType, nVersion);
genesis               673 }
genesis               674 
genesis               675 
genesis               676 
genesis               677 
genesis               678 
genesis               679 
genesis               680 template<typename K, typename T, typename Pred, typename A>
genesis               681 unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)
genesis               682 {
genesis               683     unsigned int nSize = GetSizeOfCompactSize(m.size());
genesis               684     for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
genesis               685         nSize += GetSerializeSize((*mi), nType, nVersion);
genesis               686     return nSize;
genesis               687 }
genesis               688 
genesis               689 template<typename Stream, typename K, typename T, typename Pred, typename A>
genesis               690 void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion)
genesis               691 {
genesis               692     WriteCompactSize(os, m.size());
genesis               693     for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
genesis               694         Serialize(os, (*mi), nType, nVersion);
genesis               695 }
genesis               696 
genesis               697 template<typename Stream, typename K, typename T, typename Pred, typename A>
genesis               698 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion)
genesis               699 {
genesis               700     m.clear();
genesis               701     unsigned int nSize = ReadCompactSize(is);
genesis               702     typename std::map<K, T, Pred, A>::iterator mi = m.begin();
genesis               703     for (unsigned int i = 0; i < nSize; i++)
genesis               704     {
genesis               705         std::pair<K, T> item;
genesis               706         Unserialize(is, item, nType, nVersion);
genesis               707         mi = m.insert(mi, item);
genesis               708     }
genesis               709 }
genesis               710 
genesis               711 
genesis               712 
genesis               713 
genesis               714 
genesis               715 
genesis               716 template<typename K, typename Pred, typename A>
genesis               717 unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)
genesis               718 {
genesis               719     unsigned int nSize = GetSizeOfCompactSize(m.size());
genesis               720     for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
genesis               721         nSize += GetSerializeSize((*it), nType, nVersion);
genesis               722     return nSize;
genesis               723 }
genesis               724 
genesis               725 template<typename Stream, typename K, typename Pred, typename A>
genesis               726 void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion)
genesis               727 {
genesis               728     WriteCompactSize(os, m.size());
genesis               729     for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
genesis               730         Serialize(os, (*it), nType, nVersion);
genesis               731 }
genesis               732 
genesis               733 template<typename Stream, typename K, typename Pred, typename A>
genesis               734 void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
genesis               735 {
genesis               736     m.clear();
genesis               737     unsigned int nSize = ReadCompactSize(is);
genesis               738     typename std::set<K, Pred, A>::iterator it = m.begin();
genesis               739     for (unsigned int i = 0; i < nSize; i++)
genesis               740     {
genesis               741         K key;
genesis               742         Unserialize(is, key, nType, nVersion);
genesis               743         it = m.insert(it, key);
genesis               744     }
genesis               745 }
genesis               746 
genesis               747 
genesis               748 
genesis               749 
genesis               750 
genesis               751 
genesis               752 class CSerActionGetSerializeSize { };
genesis               753 class CSerActionSerialize { };
genesis               754 class CSerActionUnserialize { };
genesis               755 
genesis               756 template<typename Stream, typename T>
genesis               757 inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action)
genesis               758 {
genesis               759     return ::GetSerializeSize(obj, nType, nVersion);
genesis               760 }
genesis               761 
genesis               762 template<typename Stream, typename T>
genesis               763 inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
genesis               764 {
genesis               765     ::Serialize(s, obj, nType, nVersion);
genesis               766     return 0;
genesis               767 }
genesis               768 
genesis               769 template<typename Stream, typename T>
genesis               770 inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
genesis               771 {
genesis               772     ::Unserialize(s, obj, nType, nVersion);
genesis               773     return 0;
genesis               774 }
genesis               775 
genesis               776 struct ser_streamplaceholder
genesis               777 {
genesis               778     int nType;
genesis               779     int nVersion;
genesis               780 };
genesis               781 
genesis               782 
genesis               783 
genesis               784 
genesis               785 
genesis               786 
genesis               787 
genesis               788 
genesis               789 
genesis               790 
genesis               791 
genesis               792 
genesis               793 
genesis               794 template<typename T>
genesis               795 struct secure_allocator : public std::allocator<T>
genesis               796 {
genesis               797     
genesis               798     typedef std::allocator<T> base;
genesis               799     typedef typename base::size_type size_type;
genesis               800     typedef typename base::difference_type  difference_type;
genesis               801     typedef typename base::pointer pointer;
genesis               802     typedef typename base::const_pointer const_pointer;
genesis               803     typedef typename base::reference reference;
genesis               804     typedef typename base::const_reference const_reference;
genesis               805     typedef typename base::value_type value_type;
genesis               806     secure_allocator() throw() {}
genesis               807     secure_allocator(const secure_allocator& a) throw() : base(a) {}
genesis               808     template <typename U>
genesis               809     secure_allocator(const secure_allocator<U>& a) throw() : base(a) {}
genesis               810     ~secure_allocator() throw() {}
genesis               811     template<typename _Other> struct rebind
genesis               812     { typedef secure_allocator<_Other> other; };
genesis               813 
genesis               814     T* allocate(std::size_t n, const void *hint = 0)
genesis               815     {
genesis               816         T *p;
genesis               817         p = std::allocator<T>::allocate(n, hint);
genesis               818         if (p != NULL)
genesis               819             mlock(p, sizeof(T) * n);
genesis               820         return p;
genesis               821     }
genesis               822 
genesis               823     void deallocate(T* p, std::size_t n)
genesis               824     {
genesis               825         if (p != NULL)
genesis               826         {
genesis               827             memset(p, 0, sizeof(T) * n);
genesis               828             munlock(p, sizeof(T) * n);
genesis               829         }
genesis               830         std::allocator<T>::deallocate(p, n);
genesis               831     }
genesis               832 };
genesis               833 
genesis               834 
genesis               835 
genesis               836 
genesis               837 
genesis               838 template<typename T>
genesis               839 struct zero_after_free_allocator : public std::allocator<T>
genesis               840 {
genesis               841     
genesis               842     typedef std::allocator<T> base;
genesis               843     typedef typename base::size_type size_type;
genesis               844     typedef typename base::difference_type  difference_type;
genesis               845     typedef typename base::pointer pointer;
genesis               846     typedef typename base::const_pointer const_pointer;
genesis               847     typedef typename base::reference reference;
genesis               848     typedef typename base::const_reference const_reference;
genesis               849     typedef typename base::value_type value_type;
genesis               850     zero_after_free_allocator() throw() {}
genesis               851     zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {}
genesis               852     template <typename U>
genesis               853     zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a) {}
genesis               854     ~zero_after_free_allocator() throw() {}
genesis               855     template<typename _Other> struct rebind
genesis               856     { typedef zero_after_free_allocator<_Other> other; };
genesis               857 
genesis               858     void deallocate(T* p, std::size_t n)
genesis               859     {
genesis               860         if (p != NULL)
genesis               861             memset(p, 0, sizeof(T) * n);
genesis               862         std::allocator<T>::deallocate(p, n);
genesis               863     }
genesis               864 };
genesis               865 
genesis               866 
genesis               867 
genesis               868 
genesis               869 
genesis               870 
genesis               871 
genesis               872 
genesis               873 class CDataStream
genesis               874 {
genesis               875 protected:
genesis               876     typedef std::vector<char, zero_after_free_allocator<char> > vector_type;
genesis               877     vector_type vch;
genesis               878     unsigned int nReadPos;
genesis               879     short state;
genesis               880     short exceptmask;
genesis               881 public:
genesis               882     int nType;
genesis               883     int nVersion;
genesis               884 
genesis               885     typedef vector_type::allocator_type   allocator_type;
genesis               886     typedef vector_type::size_type        size_type;
genesis               887     typedef vector_type::difference_type  difference_type;
genesis               888     typedef vector_type::reference        reference;
genesis               889     typedef vector_type::const_reference  const_reference;
genesis               890     typedef vector_type::value_type       value_type;
genesis               891     typedef vector_type::iterator         iterator;
genesis               892     typedef vector_type::const_iterator   const_iterator;
genesis               893     typedef vector_type::reverse_iterator reverse_iterator;
genesis               894 
genesis               895     explicit CDataStream(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
genesis               896     {
genesis               897         Init(nTypeIn, nVersionIn);
genesis               898     }
genesis               899 
genesis               900     CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(pbegin, pend)
genesis               901     {
genesis               902         Init(nTypeIn, nVersionIn);
genesis               903     }
genesis               904 
genesis               905 #if !defined(_MSC_VER) || _MSC_VER >= 1300
genesis               906     CDataStream(const char* pbegin, const char* pend, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(pbegin, pend)
genesis               907     {
genesis               908         Init(nTypeIn, nVersionIn);
genesis               909     }
genesis               910 #endif
genesis               911 
genesis               912     CDataStream(const vector_type& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
genesis               913     {
genesis               914         Init(nTypeIn, nVersionIn);
genesis               915     }
genesis               916 
genesis               917     CDataStream(const std::vector<char>& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
genesis               918     {
genesis               919         Init(nTypeIn, nVersionIn);
genesis               920     }
genesis               921 
genesis               922     CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0])
genesis               923     {
genesis               924         Init(nTypeIn, nVersionIn);
genesis               925     }
genesis               926 
genesis               927     void Init(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
genesis               928     {
genesis               929         nReadPos = 0;
genesis               930         nType = nTypeIn;
genesis               931         nVersion = nVersionIn;
genesis               932         state = 0;
genesis               933         exceptmask = std::ios::badbit | std::ios::failbit;
genesis               934     }
genesis               935 
genesis               936     CDataStream& operator+=(const CDataStream& b)
genesis               937     {
genesis               938         vch.insert(vch.end(), b.begin(), b.end());
genesis               939         return *this;
genesis               940     }
genesis               941 
genesis               942     friend CDataStream operator+(const CDataStream& a, const CDataStream& b)
genesis               943     {
genesis               944         CDataStream ret = a;
genesis               945         ret += b;
genesis               946         return (ret);
genesis               947     }
genesis               948 
genesis               949     std::string str() const
genesis               950     {
genesis               951         return (std::string(begin(), end()));
genesis               952     }
genesis               953 
genesis               954 
genesis               955     
genesis               956     
genesis               957     
genesis               958     const_iterator begin() const                     { return vch.begin() + nReadPos; }
genesis               959     iterator begin()                                 { return vch.begin() + nReadPos; }
genesis               960     const_iterator end() const                       { return vch.end(); }
genesis               961     iterator end()                                   { return vch.end(); }
genesis               962     size_type size() const                           { return vch.size() - nReadPos; }
genesis               963     bool empty() const                               { return vch.size() == nReadPos; }
genesis               964     void resize(size_type n, value_type c=0)         { vch.resize(n + nReadPos, c); }
genesis               965     void reserve(size_type n)                        { vch.reserve(n + nReadPos); }
genesis               966     const_reference operator[](size_type pos) const  { return vch[pos + nReadPos]; }
genesis               967     reference operator[](size_type pos)              { return vch[pos + nReadPos]; }
genesis               968     void clear()                                     { vch.clear(); nReadPos = 0; }
genesis               969     iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }
genesis               970     void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }
genesis               971 
genesis               972     void insert(iterator it, const_iterator first, const_iterator last)
genesis               973     {
genesis               974         if (it == vch.begin() + nReadPos && last - first <= nReadPos)
genesis               975         {
genesis               976             
genesis               977             nReadPos -= (last - first);
genesis               978             memcpy(&vch[nReadPos], &first[0], last - first);
genesis               979         }
genesis               980         else
genesis               981             vch.insert(it, first, last);
genesis               982     }
genesis               983 
genesis               984     void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last)
genesis               985     {
genesis               986         if (it == vch.begin() + nReadPos && last - first <= nReadPos)
genesis               987         {
genesis               988             
genesis               989             nReadPos -= (last - first);
genesis               990             memcpy(&vch[nReadPos], &first[0], last - first);
genesis               991         }
genesis               992         else
genesis               993             vch.insert(it, first, last);
genesis               994     }
genesis               995 
genesis               996 #if !defined(_MSC_VER) || _MSC_VER >= 1300
genesis               997     void insert(iterator it, const char* first, const char* last)
genesis               998     {
genesis               999         if (it == vch.begin() + nReadPos && last - first <= nReadPos)
genesis              1000         {
genesis              1001             
genesis              1002             nReadPos -= (last - first);
genesis              1003             memcpy(&vch[nReadPos], &first[0], last - first);
genesis              1004         }
genesis              1005         else
genesis              1006             vch.insert(it, first, last);
genesis              1007     }
genesis              1008 #endif
genesis              1009 
genesis              1010     iterator erase(iterator it)
genesis              1011     {
genesis              1012         if (it == vch.begin() + nReadPos)
genesis              1013         {
genesis              1014             
genesis              1015             if (++nReadPos >= vch.size())
genesis              1016             {
genesis              1017                 
genesis              1018                 nReadPos = 0;
genesis              1019                 return vch.erase(vch.begin(), vch.end());
genesis              1020             }
genesis              1021             return vch.begin() + nReadPos;
genesis              1022         }
genesis              1023         else
genesis              1024             return vch.erase(it);
genesis              1025     }
genesis              1026 
genesis              1027     iterator erase(iterator first, iterator last)
genesis              1028     {
genesis              1029         if (first == vch.begin() + nReadPos)
genesis              1030         {
genesis              1031             
genesis              1032             if (last == vch.end())
genesis              1033             {
genesis              1034                 nReadPos = 0;
genesis              1035                 return vch.erase(vch.begin(), vch.end());
genesis              1036             }
genesis              1037             else
genesis              1038             {
genesis              1039                 nReadPos = (last - vch.begin());
genesis              1040                 return last;
genesis              1041             }
genesis              1042         }
genesis              1043         else
genesis              1044             return vch.erase(first, last);
genesis              1045     }
genesis              1046 
genesis              1047     inline void Compact()
genesis              1048     {
genesis              1049         vch.erase(vch.begin(), vch.begin() + nReadPos);
genesis              1050         nReadPos = 0;
genesis              1051     }
genesis              1052 
genesis              1053     bool Rewind(size_type n)
genesis              1054     {
genesis              1055         
genesis              1056         if (n > nReadPos)
genesis              1057             return false;
genesis              1058         nReadPos -= n;
genesis              1059         return true;
genesis              1060     }
genesis              1061 
genesis              1062 
genesis              1063     
genesis              1064     
genesis              1065     
genesis              1066     void setstate(short bits, const char* psz)
genesis              1067     {
genesis              1068         state |= bits;
genesis              1069         if (state & exceptmask)
genesis              1070             throw std::ios_base::failure(psz);
genesis              1071     }
genesis              1072 
genesis              1073     bool eof() const             { return size() == 0; }
genesis              1074     bool fail() const            { return state & (std::ios::badbit | std::ios::failbit); }
genesis              1075     bool good() const            { return !eof() && (state == 0); }
genesis              1076     void clear(short n)          { state = n; }  
genesis              1077     short exceptions()           { return exceptmask; }
genesis              1078     short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; }
genesis              1079     CDataStream* rdbuf()         { return this; }
genesis              1080     int in_avail()               { return size(); }
genesis              1081 
genesis              1082     void SetType(int n)          { nType = n; }
genesis              1083     int GetType()                { return nType; }
genesis              1084     void SetVersion(int n)       { nVersion = n; }
genesis              1085     int GetVersion()             { return nVersion; }
genesis              1086     void ReadVersion()           { *this >> nVersion; }
genesis              1087     void WriteVersion()          { *this << nVersion; }
genesis              1088 
genesis              1089     CDataStream& read(char* pch, int nSize)
genesis              1090     {
genesis              1091         
genesis              1092         assert(nSize >= 0);
genesis              1093         unsigned int nReadPosNext = nReadPos + nSize;
genesis              1094         if (nReadPosNext >= vch.size())
genesis              1095         {
genesis              1096             if (nReadPosNext > vch.size())
genesis              1097             {
genesis              1098                 setstate(std::ios::failbit, "CDataStream::read() : end of data");
genesis              1099                 memset(pch, 0, nSize);
genesis              1100                 nSize = vch.size() - nReadPos;
genesis              1101             }
genesis              1102             memcpy(pch, &vch[nReadPos], nSize);
genesis              1103             nReadPos = 0;
genesis              1104             vch.clear();
genesis              1105             return (*this);
genesis              1106         }
genesis              1107         memcpy(pch, &vch[nReadPos], nSize);
genesis              1108         nReadPos = nReadPosNext;
genesis              1109         return (*this);
genesis              1110     }
genesis              1111 
genesis              1112     CDataStream& ignore(int nSize)
genesis              1113     {
genesis              1114         
genesis              1115         assert(nSize >= 0);
genesis              1116         unsigned int nReadPosNext = nReadPos + nSize;
genesis              1117         if (nReadPosNext >= vch.size())
genesis              1118         {
genesis              1119             if (nReadPosNext > vch.size())
genesis              1120             {
genesis              1121                 setstate(std::ios::failbit, "CDataStream::ignore() : end of data");
genesis              1122                 nSize = vch.size() - nReadPos;
genesis              1123             }
genesis              1124             nReadPos = 0;
genesis              1125             vch.clear();
genesis              1126             return (*this);
genesis              1127         }
genesis              1128         nReadPos = nReadPosNext;
genesis              1129         return (*this);
genesis              1130     }
genesis              1131 
genesis              1132     CDataStream& write(const char* pch, int nSize)
genesis              1133     {
genesis              1134         
genesis              1135         assert(nSize >= 0);
genesis              1136         vch.insert(vch.end(), pch, pch + nSize);
genesis              1137         return (*this);
genesis              1138     }
genesis              1139 
genesis              1140     template<typename Stream>
genesis              1141     void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
genesis              1142     {
genesis              1143         
genesis              1144         if (!vch.empty())
genesis              1145             s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));
genesis              1146     }
genesis              1147 
genesis              1148     template<typename T>
genesis              1149     unsigned int GetSerializeSize(const T& obj)
genesis              1150     {
genesis              1151         
genesis              1152         return ::GetSerializeSize(obj, nType, nVersion);
genesis              1153     }
genesis              1154 
genesis              1155     template<typename T>
genesis              1156     CDataStream& operator<<(const T& obj)
genesis              1157     {
genesis              1158         
genesis              1159         ::Serialize(*this, obj, nType, nVersion);
genesis              1160         return (*this);
genesis              1161     }
genesis              1162 
genesis              1163     template<typename T>
genesis              1164     CDataStream& operator>>(T& obj)
genesis              1165     {
genesis              1166         
genesis              1167         ::Unserialize(*this, obj, nType, nVersion);
genesis              1168         return (*this);
genesis              1169     }
genesis              1170 };
genesis              1171 
genesis              1172 #ifdef TESTCDATASTREAM
genesis              1173 
genesis              1174 
genesis              1175 
genesis              1176 
genesis              1177 
genesis              1178 
genesis              1179 
genesis              1180 
genesis              1181 
genesis              1182 
genesis              1183 
genesis              1184 
genesis              1185 
genesis              1186 
genesis              1187 
genesis              1188 
genesis              1189 
genesis              1190 
genesis              1191 
genesis              1192 
genesis              1193 
genesis              1194 
genesis              1195 
genesis              1196 
genesis              1197 
genesis              1198 #include <iostream>
genesis              1199 int main(int argc, char *argv[])
genesis              1200 {
genesis              1201     vector<unsigned char> vch(0xcc, 250);
genesis              1202     printf("CDataStream:\n");
genesis              1203     for (int n = 1000; n <= 4500000; n *= 2)
genesis              1204     {
genesis              1205         CDataStream ss;
genesis              1206         time_t nStart = time(NULL);
genesis              1207         for (int i = 0; i < n; i++)
genesis              1208             ss.write((char*)&vch[0], vch.size());
genesis              1209         printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);
genesis              1210     }
genesis              1211     printf("stringstream:\n");
genesis              1212     for (int n = 1000; n <= 4500000; n *= 2)
genesis              1213     {
genesis              1214         stringstream ss;
genesis              1215         time_t nStart = time(NULL);
genesis              1216         for (int i = 0; i < n; i++)
genesis              1217             ss.write((char*)&vch[0], vch.size());
genesis              1218         printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);
genesis              1219     }
genesis              1220 }
genesis              1221 #endif
genesis              1222 
genesis              1223 
genesis              1224 
genesis              1225 
genesis              1226 
genesis              1227 
genesis              1228 
genesis              1229 
genesis              1230 
genesis              1231 
genesis              1232 
genesis              1233 
genesis              1234 
genesis              1235 
genesis              1236 
genesis              1237 
genesis              1238 class CAutoFile
genesis              1239 {
genesis              1240 protected:
genesis              1241     FILE* file;
genesis              1242     short state;
genesis              1243     short exceptmask;
genesis              1244 public:
genesis              1245     int nType;
genesis              1246     int nVersion;
genesis              1247 
genesis              1248     typedef FILE element_type;
genesis              1249 
genesis              1250     CAutoFile(FILE* filenew=NULL, int nTypeIn=SER_DISK, int nVersionIn=VERSION)
genesis              1251     {
genesis              1252         file = filenew;
genesis              1253         nType = nTypeIn;
genesis              1254         nVersion = nVersionIn;
genesis              1255         state = 0;
genesis              1256         exceptmask = std::ios::badbit | std::ios::failbit;
genesis              1257     }
genesis              1258 
genesis              1259     ~CAutoFile()
genesis              1260     {
genesis              1261         fclose();
genesis              1262     }
genesis              1263 
genesis              1264     void fclose()
genesis              1265     {
genesis              1266         if (file != NULL && file != stdin && file != stdout && file != stderr)
genesis              1267             ::fclose(file);
genesis              1268         file = NULL;
genesis              1269     }
genesis              1270 
genesis              1271     FILE* release()             { FILE* ret = file; file = NULL; return ret; }
genesis              1272     operator FILE*()            { return file; }
genesis              1273     FILE* operator->()          { return file; }
genesis              1274     FILE& operator*()           { return *file; }
genesis              1275     FILE** operator&()          { return &file; }
genesis              1276     FILE* operator=(FILE* pnew) { return file = pnew; }
genesis              1277     bool operator!()            { return (file == NULL); }
genesis              1278 
genesis              1279 
genesis              1280     
genesis              1281     
genesis              1282     
genesis              1283     void setstate(short bits, const char* psz)
genesis              1284     {
genesis              1285         state |= bits;
genesis              1286         if (state & exceptmask)
genesis              1287             throw std::ios_base::failure(psz);
genesis              1288     }
genesis              1289 
genesis              1290     bool fail() const            { return state & (std::ios::badbit | std::ios::failbit); }
genesis              1291     bool good() const            { return state == 0; }
genesis              1292     void clear(short n = 0)      { state = n; }
genesis              1293     short exceptions()           { return exceptmask; }
genesis              1294     short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; }
genesis              1295 
genesis              1296     void SetType(int n)          { nType = n; }
genesis              1297     int GetType()                { return nType; }
genesis              1298     void SetVersion(int n)       { nVersion = n; }
genesis              1299     int GetVersion()             { return nVersion; }
genesis              1300     void ReadVersion()           { *this >> nVersion; }
genesis              1301     void WriteVersion()          { *this << nVersion; }
genesis              1302 
genesis              1303     CAutoFile& read(char* pch, int nSize)
genesis              1304     {
genesis              1305         if (!file)
genesis              1306             throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
genesis              1307         if (fread(pch, 1, nSize, file) != nSize)
genesis              1308             setstate(std::ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
genesis              1309         return (*this);
genesis              1310     }
genesis              1311 
genesis              1312     CAutoFile& write(const char* pch, int nSize)
genesis              1313     {
genesis              1314         if (!file)
genesis              1315             throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
genesis              1316         if (fwrite(pch, 1, nSize, file) != nSize)
genesis              1317             setstate(std::ios::failbit, "CAutoFile::write : write failed");
genesis              1318         return (*this);
genesis              1319     }
genesis              1320 
genesis              1321     template<typename T>
genesis              1322     unsigned int GetSerializeSize(const T& obj)
genesis              1323     {
genesis              1324         
genesis              1325         return ::GetSerializeSize(obj, nType, nVersion);
genesis              1326     }
genesis              1327 
genesis              1328     template<typename T>
genesis              1329     CAutoFile& operator<<(const T& obj)
genesis              1330     {
genesis              1331         
genesis              1332         if (!file)
genesis              1333             throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
genesis              1334         ::Serialize(*this, obj, nType, nVersion);
genesis              1335         return (*this);
genesis              1336     }
genesis              1337 
genesis              1338     template<typename T>
genesis              1339     CAutoFile& operator>>(T& obj)
genesis              1340     {
genesis              1341         
genesis              1342         if (!file)
genesis              1343             throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");
genesis              1344         ::Unserialize(*this, obj, nType, nVersion);
genesis              1345         return (*this);
genesis              1346     }
genesis              1347 };
genesis              1348 
genesis              1349 #endif