-
+ DDE46A79F37BB5606B2EE28D8F36B69299383A449927D558B87E9E23001785BF346DA518B184D015474881BAFAFEFE55677F2E78E03C60326188F4260E46F876
bitcoin/src/serialize.h
(0 . 0)(1 . 1380)
21124 // /****************************\
21125 // * EXPERIMENTAL BRANCH. *
21126 // * FOR LABORATORY USE ONLY. *
21127 // ********************************
21128 // ************
21129 // **************
21130 // ****************
21131 // **** **** ****
21132 // *** *** ***
21133 // *** *** ***
21134 // *** * * **
21135 // ******** ********
21136 // ******* ******
21137 // *** **
21138 // * ******* **
21139 // ** * * * * *
21140 // ** * * ***
21141 // **** * * * * ****
21142 // **** *** * * ** ***
21143 // **** ********* ******
21144 // ******* ***** *******
21145 // ********* ****** **
21146 // ** ****** ******
21147 // ** ******* **
21148 // ** ******* ***
21149 // **** ******** ************
21150 // ************ ************
21151 // ******** *******
21152 // ****** ****
21153 // *** ***
21154 // ********************************
21155 // Copyright (c) 2009-2010 Satoshi Nakamoto
21156 // Copyright (c) 2009-2012 The Bitcoin developers
21157 // Distributed under the MIT/X11 software license, see the accompanying
21158 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
21159 #ifndef BITCOIN_SERIALIZE_H
21160 #define BITCOIN_SERIALIZE_H
21161
21162 #include <string>
21163 #include <vector>
21164 #include <map>
21165 #include <set>
21166 #include <cassert>
21167 #include <climits>
21168 #include <cstring>
21169 #include <cstdio>
21170
21171 #include <boost/type_traits/is_fundamental.hpp>
21172 #include <boost/tuple/tuple.hpp>
21173 #include <boost/tuple/tuple_comparison.hpp>
21174 #include <boost/tuple/tuple_io.hpp>
21175
21176 #if defined(_MSC_VER) || defined(__BORLANDC__)
21177 typedef __int64 int64;
21178 typedef unsigned __int64 uint64;
21179 #else
21180 typedef long long int64;
21181 typedef unsigned long long uint64;
21182 #endif
21183 #if defined(_MSC_VER) && _MSC_VER < 1300
21184 #define for if (false) ; else for
21185 #endif
21186
21187 #ifdef WIN32
21188 #include <windows.h>
21189 // This is used to attempt to keep keying material out of swap
21190 // Note that VirtualLock does not provide this as a guarantee on Windows,
21191 // but, in practice, memory that has been VirtualLock'd almost never gets written to
21192 // the pagefile except in rare circumstances where memory is extremely low.
21193 #include <windows.h>
21194 #define mlock(p, n) VirtualLock((p), (n));
21195 #define munlock(p, n) VirtualUnlock((p), (n));
21196 #else
21197 #include <sys/mman.h>
21198 #include <limits.h>
21199 /* This comes from limits.h if it's not defined there set a sane default */
21200 #ifndef PAGESIZE
21201 #include <unistd.h>
21202 #define PAGESIZE sysconf(_SC_PAGESIZE)
21203 #endif
21204 #define mlock(a,b) \
21205 mlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
21206 (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
21207 #define munlock(a,b) \
21208 munlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
21209 (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
21210 #endif
21211
21212 class CScript;
21213 class CDataStream;
21214 class CAutoFile;
21215 static const unsigned int MAX_SIZE = 0x02000000;
21216
21217 static const int VERSION = 50300;
21218 static const char* pszSubVer = "";
21219 static const bool VERSION_IS_BETA = true;
21220
21221 // Used to bypass the rule against non-const reference to temporary
21222 // where it makes sense with wrappers such as CFlatData or CTxDB
21223 template<typename T>
21224 inline T& REF(const T& val)
21225 {
21226 return const_cast<T&>(val);
21227 }
21228
21229 /////////////////////////////////////////////////////////////////
21230 //
21231 // Templates for serializing to anything that looks like a stream,
21232 // i.e. anything that supports .read(char*, int) and .write(char*, int)
21233 //
21234
21235 enum
21236 {
21237 // primary actions
21238 SER_NETWORK = (1 << 0),
21239 SER_DISK = (1 << 1),
21240 SER_GETHASH = (1 << 2),
21241
21242 // modifiers
21243 SER_SKIPSIG = (1 << 16),
21244 SER_BLOCKHEADERONLY = (1 << 17),
21245 };
21246
21247 #define IMPLEMENT_SERIALIZE(statements) \
21248 unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const \
21249 { \
21250 CSerActionGetSerializeSize ser_action; \
21251 const bool fGetSize = true; \
21252 const bool fWrite = false; \
21253 const bool fRead = false; \
21254 unsigned int nSerSize = 0; \
21255 ser_streamplaceholder s; \
21256 assert(fGetSize||fWrite||fRead); /* suppress warning */ \
21257 s.nType = nType; \
21258 s.nVersion = nVersion; \
21259 {statements} \
21260 return nSerSize; \
21261 } \
21262 template<typename Stream> \
21263 void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const \
21264 { \
21265 CSerActionSerialize ser_action; \
21266 const bool fGetSize = false; \
21267 const bool fWrite = true; \
21268 const bool fRead = false; \
21269 unsigned int nSerSize = 0; \
21270 assert(fGetSize||fWrite||fRead); /* suppress warning */ \
21271 {statements} \
21272 } \
21273 template<typename Stream> \
21274 void Unserialize(Stream& s, int nType=0, int nVersion=VERSION) \
21275 { \
21276 CSerActionUnserialize ser_action; \
21277 const bool fGetSize = false; \
21278 const bool fWrite = false; \
21279 const bool fRead = true; \
21280 unsigned int nSerSize = 0; \
21281 assert(fGetSize||fWrite||fRead); /* suppress warning */ \
21282 {statements} \
21283 }
21284
21285 #define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
21286
21287
21288
21289
21290
21291
21292 //
21293 // Basic types
21294 //
21295 #define WRITEDATA(s, obj) s.write((char*)&(obj), sizeof(obj))
21296 #define READDATA(s, obj) s.read((char*)&(obj), sizeof(obj))
21297
21298 inline unsigned int GetSerializeSize(char a, int, int=0) { return sizeof(a); }
21299 inline unsigned int GetSerializeSize(signed char a, int, int=0) { return sizeof(a); }
21300 inline unsigned int GetSerializeSize(unsigned char a, int, int=0) { return sizeof(a); }
21301 inline unsigned int GetSerializeSize(signed short a, int, int=0) { return sizeof(a); }
21302 inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); }
21303 inline unsigned int GetSerializeSize(signed int a, int, int=0) { return sizeof(a); }
21304 inline unsigned int GetSerializeSize(unsigned int a, int, int=0) { return sizeof(a); }
21305 inline unsigned int GetSerializeSize(signed long a, int, int=0) { return sizeof(a); }
21306 inline unsigned int GetSerializeSize(unsigned long a, int, int=0) { return sizeof(a); }
21307 inline unsigned int GetSerializeSize(int64 a, int, int=0) { return sizeof(a); }
21308 inline unsigned int GetSerializeSize(uint64 a, int, int=0) { return sizeof(a); }
21309 inline unsigned int GetSerializeSize(float a, int, int=0) { return sizeof(a); }
21310 inline unsigned int GetSerializeSize(double a, int, int=0) { return sizeof(a); }
21311
21312 template<typename Stream> inline void Serialize(Stream& s, char a, int, int=0) { WRITEDATA(s, a); }
21313 template<typename Stream> inline void Serialize(Stream& s, signed char a, int, int=0) { WRITEDATA(s, a); }
21314 template<typename Stream> inline void Serialize(Stream& s, unsigned char a, int, int=0) { WRITEDATA(s, a); }
21315 template<typename Stream> inline void Serialize(Stream& s, signed short a, int, int=0) { WRITEDATA(s, a); }
21316 template<typename Stream> inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); }
21317 template<typename Stream> inline void Serialize(Stream& s, signed int a, int, int=0) { WRITEDATA(s, a); }
21318 template<typename Stream> inline void Serialize(Stream& s, unsigned int a, int, int=0) { WRITEDATA(s, a); }
21319 template<typename Stream> inline void Serialize(Stream& s, signed long a, int, int=0) { WRITEDATA(s, a); }
21320 template<typename Stream> inline void Serialize(Stream& s, unsigned long a, int, int=0) { WRITEDATA(s, a); }
21321 template<typename Stream> inline void Serialize(Stream& s, int64 a, int, int=0) { WRITEDATA(s, a); }
21322 template<typename Stream> inline void Serialize(Stream& s, uint64 a, int, int=0) { WRITEDATA(s, a); }
21323 template<typename Stream> inline void Serialize(Stream& s, float a, int, int=0) { WRITEDATA(s, a); }
21324 template<typename Stream> inline void Serialize(Stream& s, double a, int, int=0) { WRITEDATA(s, a); }
21325
21326 template<typename Stream> inline void Unserialize(Stream& s, char& a, int, int=0) { READDATA(s, a); }
21327 template<typename Stream> inline void Unserialize(Stream& s, signed char& a, int, int=0) { READDATA(s, a); }
21328 template<typename Stream> inline void Unserialize(Stream& s, unsigned char& a, int, int=0) { READDATA(s, a); }
21329 template<typename Stream> inline void Unserialize(Stream& s, signed short& a, int, int=0) { READDATA(s, a); }
21330 template<typename Stream> inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); }
21331 template<typename Stream> inline void Unserialize(Stream& s, signed int& a, int, int=0) { READDATA(s, a); }
21332 template<typename Stream> inline void Unserialize(Stream& s, unsigned int& a, int, int=0) { READDATA(s, a); }
21333 template<typename Stream> inline void Unserialize(Stream& s, signed long& a, int, int=0) { READDATA(s, a); }
21334 template<typename Stream> inline void Unserialize(Stream& s, unsigned long& a, int, int=0) { READDATA(s, a); }
21335 template<typename Stream> inline void Unserialize(Stream& s, int64& a, int, int=0) { READDATA(s, a); }
21336 template<typename Stream> inline void Unserialize(Stream& s, uint64& a, int, int=0) { READDATA(s, a); }
21337 template<typename Stream> inline void Unserialize(Stream& s, float& a, int, int=0) { READDATA(s, a); }
21338 template<typename Stream> inline void Unserialize(Stream& s, double& a, int, int=0) { READDATA(s, a); }
21339
21340 inline unsigned int GetSerializeSize(bool a, int, int=0) { return sizeof(char); }
21341 template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0) { char f=a; WRITEDATA(s, f); }
21342 template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; }
21343
21344
21345
21346
21347
21348
21349 //
21350 // Compact size
21351 // size < 253 -- 1 byte
21352 // size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)
21353 // size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
21354 // size > UINT_MAX -- 9 bytes (255 + 8 bytes)
21355 //
21356 inline unsigned int GetSizeOfCompactSize(uint64 nSize)
21357 {
21358 if (nSize < 253) return sizeof(unsigned char);
21359 else if (nSize <= USHRT_MAX) return sizeof(unsigned char) + sizeof(unsigned short);
21360 else if (nSize <= UINT_MAX) return sizeof(unsigned char) + sizeof(unsigned int);
21361 else return sizeof(unsigned char) + sizeof(uint64);
21362 }
21363
21364 template<typename Stream>
21365 void WriteCompactSize(Stream& os, uint64 nSize)
21366 {
21367 if (nSize < 253)
21368 {
21369 unsigned char chSize = nSize;
21370 WRITEDATA(os, chSize);
21371 }
21372 else if (nSize <= USHRT_MAX)
21373 {
21374 unsigned char chSize = 253;
21375 unsigned short xSize = nSize;
21376 WRITEDATA(os, chSize);
21377 WRITEDATA(os, xSize);
21378 }
21379 else if (nSize <= UINT_MAX)
21380 {
21381 unsigned char chSize = 254;
21382 unsigned int xSize = nSize;
21383 WRITEDATA(os, chSize);
21384 WRITEDATA(os, xSize);
21385 }
21386 else
21387 {
21388 unsigned char chSize = 255;
21389 uint64 xSize = nSize;
21390 WRITEDATA(os, chSize);
21391 WRITEDATA(os, xSize);
21392 }
21393 return;
21394 }
21395
21396 template<typename Stream>
21397 uint64 ReadCompactSize(Stream& is)
21398 {
21399 unsigned char chSize;
21400 READDATA(is, chSize);
21401 uint64 nSizeRet = 0;
21402 if (chSize < 253)
21403 {
21404 nSizeRet = chSize;
21405 }
21406 else if (chSize == 253)
21407 {
21408 unsigned short xSize;
21409 READDATA(is, xSize);
21410 nSizeRet = xSize;
21411 }
21412 else if (chSize == 254)
21413 {
21414 unsigned int xSize;
21415 READDATA(is, xSize);
21416 nSizeRet = xSize;
21417 }
21418 else
21419 {
21420 uint64 xSize;
21421 READDATA(is, xSize);
21422 nSizeRet = xSize;
21423 }
21424 if (nSizeRet > (uint64)MAX_SIZE)
21425 throw std::ios_base::failure("ReadCompactSize() : size too large");
21426 return nSizeRet;
21427 }
21428
21429
21430
21431 //
21432 // Wrapper for serializing arrays and POD
21433 // There's a clever template way to make arrays serialize normally, but MSVC6 doesn't support it
21434 //
21435 #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
21436 class CFlatData
21437 {
21438 protected:
21439 char* pbegin;
21440 char* pend;
21441 public:
21442 CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
21443 char* begin() { return pbegin; }
21444 const char* begin() const { return pbegin; }
21445 char* end() { return pend; }
21446 const char* end() const { return pend; }
21447
21448 unsigned int GetSerializeSize(int, int=0) const
21449 {
21450 return pend - pbegin;
21451 }
21452
21453 template<typename Stream>
21454 void Serialize(Stream& s, int, int=0) const
21455 {
21456 s.write(pbegin, pend - pbegin);
21457 }
21458
21459 template<typename Stream>
21460 void Unserialize(Stream& s, int, int=0)
21461 {
21462 s.read(pbegin, pend - pbegin);
21463 }
21464 };
21465
21466
21467
21468 //
21469 // string stored as a fixed length field
21470 //
21471 template<std::size_t LEN>
21472 class CFixedFieldString
21473 {
21474 protected:
21475 const std::string* pcstr;
21476 std::string* pstr;
21477 public:
21478 explicit CFixedFieldString(const std::string& str) : pcstr(&str), pstr(NULL) { }
21479 explicit CFixedFieldString(std::string& str) : pcstr(&str), pstr(&str) { }
21480
21481 unsigned int GetSerializeSize(int, int=0) const
21482 {
21483 return LEN;
21484 }
21485
21486 template<typename Stream>
21487 void Serialize(Stream& s, int, int=0) const
21488 {
21489 char pszBuf[LEN];
21490 strncpy(pszBuf, pcstr->c_str(), LEN);
21491 s.write(pszBuf, LEN);
21492 }
21493
21494 template<typename Stream>
21495 void Unserialize(Stream& s, int, int=0)
21496 {
21497 if (pstr == NULL)
21498 throw std::ios_base::failure("CFixedFieldString::Unserialize : trying to unserialize to const string");
21499 char pszBuf[LEN+1];
21500 s.read(pszBuf, LEN);
21501 pszBuf[LEN] = '\0';
21502 *pstr = pszBuf;
21503 }
21504 };
21505
21506
21507
21508
21509
21510 //
21511 // Forward declarations
21512 //
21513
21514 // string
21515 template<typename C> unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int=0);
21516 template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str, int, int=0);
21517 template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str, int, int=0);
21518
21519 // vector
21520 template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);
21521 template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);
21522 template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion=VERSION);
21523 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&);
21524 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&);
21525 template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion=VERSION);
21526 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&);
21527 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&);
21528 template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion=VERSION);
21529
21530 // others derived from vector
21531 extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion=VERSION);
21532 template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion=VERSION);
21533 template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion=VERSION);
21534
21535 // pair
21536 template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion=VERSION);
21537 template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion=VERSION);
21538 template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion=VERSION);
21539
21540 // 3 tuple
21541 template<typename T0, typename T1, typename T2> unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion=VERSION);
21542 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);
21543 template<typename Stream, typename T0, typename T1, typename T2> void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion=VERSION);
21544
21545 // 4 tuple
21546 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);
21547 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);
21548 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);
21549
21550 // map
21551 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);
21552 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);
21553 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);
21554
21555 // set
21556 template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
21557 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);
21558 template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
21559
21560
21561
21562
21563
21564 //
21565 // If none of the specialized versions above matched, default to calling member function.
21566 // "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
21567 // The compiler will only cast int to long if none of the other templates matched.
21568 // Thanks to Boost serialization for this idea.
21569 //
21570 template<typename T>
21571 inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion=VERSION)
21572 {
21573 return a.GetSerializeSize((int)nType, nVersion);
21574 }
21575
21576 template<typename Stream, typename T>
21577 inline void Serialize(Stream& os, const T& a, long nType, int nVersion=VERSION)
21578 {
21579 a.Serialize(os, (int)nType, nVersion);
21580 }
21581
21582 template<typename Stream, typename T>
21583 inline void Unserialize(Stream& is, T& a, long nType, int nVersion=VERSION)
21584 {
21585 a.Unserialize(is, (int)nType, nVersion);
21586 }
21587
21588
21589
21590
21591
21592 //
21593 // string
21594 //
21595 template<typename C>
21596 unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int)
21597 {
21598 return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]);
21599 }
21600
21601 template<typename Stream, typename C>
21602 void Serialize(Stream& os, const std::basic_string<C>& str, int, int)
21603 {
21604 WriteCompactSize(os, str.size());
21605 if (!str.empty())
21606 os.write((char*)&str[0], str.size() * sizeof(str[0]));
21607 }
21608
21609 template<typename Stream, typename C>
21610 void Unserialize(Stream& is, std::basic_string<C>& str, int, int)
21611 {
21612 unsigned int nSize = ReadCompactSize(is);
21613 str.resize(nSize);
21614 if (nSize != 0)
21615 is.read((char*)&str[0], nSize * sizeof(str[0]));
21616 }
21617
21618
21619
21620 //
21621 // vector
21622 //
21623 template<typename T, typename A>
21624 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
21625 {
21626 return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));
21627 }
21628
21629 template<typename T, typename A>
21630 unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
21631 {
21632 unsigned int nSize = GetSizeOfCompactSize(v.size());
21633 for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
21634 nSize += GetSerializeSize((*vi), nType, nVersion);
21635 return nSize;
21636 }
21637
21638 template<typename T, typename A>
21639 inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion)
21640 {
21641 return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental<T>());
21642 }
21643
21644
21645 template<typename Stream, typename T, typename A>
21646 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
21647 {
21648 WriteCompactSize(os, v.size());
21649 if (!v.empty())
21650 os.write((char*)&v[0], v.size() * sizeof(T));
21651 }
21652
21653 template<typename Stream, typename T, typename A>
21654 void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
21655 {
21656 WriteCompactSize(os, v.size());
21657 for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
21658 ::Serialize(os, (*vi), nType, nVersion);
21659 }
21660
21661 template<typename Stream, typename T, typename A>
21662 inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion)
21663 {
21664 Serialize_impl(os, v, nType, nVersion, boost::is_fundamental<T>());
21665 }
21666
21667
21668 template<typename Stream, typename T, typename A>
21669 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
21670 {
21671 //unsigned int nSize = ReadCompactSize(is);
21672 //v.resize(nSize);
21673 //is.read((char*)&v[0], nSize * sizeof(T));
21674
21675 // Limit size per read so bogus size value won't cause out of memory
21676 v.clear();
21677 unsigned int nSize = ReadCompactSize(is);
21678 unsigned int i = 0;
21679 while (i < nSize)
21680 {
21681 unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
21682 v.resize(i + blk);
21683 is.read((char*)&v[i], blk * sizeof(T));
21684 i += blk;
21685 }
21686 }
21687
21688 template<typename Stream, typename T, typename A>
21689 void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
21690 {
21691 //unsigned int nSize = ReadCompactSize(is);
21692 //v.resize(nSize);
21693 //for (std::vector<T, A>::iterator vi = v.begin(); vi != v.end(); ++vi)
21694 // Unserialize(is, (*vi), nType, nVersion);
21695
21696 v.clear();
21697 unsigned int nSize = ReadCompactSize(is);
21698 unsigned int i = 0;
21699 unsigned int nMid = 0;
21700 while (nMid < nSize)
21701 {
21702 nMid += 5000000 / sizeof(T);
21703 if (nMid > nSize)
21704 nMid = nSize;
21705 v.resize(nMid);
21706 for (; i < nMid; i++)
21707 Unserialize(is, v[i], nType, nVersion);
21708 }
21709 }
21710
21711 template<typename Stream, typename T, typename A>
21712 inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion)
21713 {
21714 Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental<T>());
21715 }
21716
21717
21718
21719 //
21720 // others derived from vector
21721 //
21722 inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)
21723 {
21724 return GetSerializeSize((const std::vector<unsigned char>&)v, nType, nVersion);
21725 }
21726
21727 template<typename Stream>
21728 void Serialize(Stream& os, const CScript& v, int nType, int nVersion)
21729 {
21730 Serialize(os, (const std::vector<unsigned char>&)v, nType, nVersion);
21731 }
21732
21733 template<typename Stream>
21734 void Unserialize(Stream& is, CScript& v, int nType, int nVersion)
21735 {
21736 Unserialize(is, (std::vector<unsigned char>&)v, nType, nVersion);
21737 }
21738
21739
21740
21741 //
21742 // pair
21743 //
21744 template<typename K, typename T>
21745 unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)
21746 {
21747 return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion);
21748 }
21749
21750 template<typename Stream, typename K, typename T>
21751 void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion)
21752 {
21753 Serialize(os, item.first, nType, nVersion);
21754 Serialize(os, item.second, nType, nVersion);
21755 }
21756
21757 template<typename Stream, typename K, typename T>
21758 void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
21759 {
21760 Unserialize(is, item.first, nType, nVersion);
21761 Unserialize(is, item.second, nType, nVersion);
21762 }
21763
21764
21765
21766 //
21767 // 3 tuple
21768 //
21769 template<typename T0, typename T1, typename T2>
21770 unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
21771 {
21772 unsigned int nSize = 0;
21773 nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion);
21774 nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion);
21775 nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion);
21776 return nSize;
21777 }
21778
21779 template<typename Stream, typename T0, typename T1, typename T2>
21780 void Serialize(Stream& os, const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
21781 {
21782 Serialize(os, boost::get<0>(item), nType, nVersion);
21783 Serialize(os, boost::get<1>(item), nType, nVersion);
21784 Serialize(os, boost::get<2>(item), nType, nVersion);
21785 }
21786
21787 template<typename Stream, typename T0, typename T1, typename T2>
21788 void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
21789 {
21790 Unserialize(is, boost::get<0>(item), nType, nVersion);
21791 Unserialize(is, boost::get<1>(item), nType, nVersion);
21792 Unserialize(is, boost::get<2>(item), nType, nVersion);
21793 }
21794
21795
21796
21797 //
21798 // 4 tuple
21799 //
21800 template<typename T0, typename T1, typename T2, typename T3>
21801 unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
21802 {
21803 unsigned int nSize = 0;
21804 nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion);
21805 nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion);
21806 nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion);
21807 nSize += GetSerializeSize(boost::get<3>(item), nType, nVersion);
21808 return nSize;
21809 }
21810
21811 template<typename Stream, typename T0, typename T1, typename T2, typename T3>
21812 void Serialize(Stream& os, const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
21813 {
21814 Serialize(os, boost::get<0>(item), nType, nVersion);
21815 Serialize(os, boost::get<1>(item), nType, nVersion);
21816 Serialize(os, boost::get<2>(item), nType, nVersion);
21817 Serialize(os, boost::get<3>(item), nType, nVersion);
21818 }
21819
21820 template<typename Stream, typename T0, typename T1, typename T2, typename T3>
21821 void Unserialize(Stream& is, boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
21822 {
21823 Unserialize(is, boost::get<0>(item), nType, nVersion);
21824 Unserialize(is, boost::get<1>(item), nType, nVersion);
21825 Unserialize(is, boost::get<2>(item), nType, nVersion);
21826 Unserialize(is, boost::get<3>(item), nType, nVersion);
21827 }
21828
21829
21830
21831 //
21832 // map
21833 //
21834 template<typename K, typename T, typename Pred, typename A>
21835 unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)
21836 {
21837 unsigned int nSize = GetSizeOfCompactSize(m.size());
21838 for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
21839 nSize += GetSerializeSize((*mi), nType, nVersion);
21840 return nSize;
21841 }
21842
21843 template<typename Stream, typename K, typename T, typename Pred, typename A>
21844 void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion)
21845 {
21846 WriteCompactSize(os, m.size());
21847 for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
21848 Serialize(os, (*mi), nType, nVersion);
21849 }
21850
21851 template<typename Stream, typename K, typename T, typename Pred, typename A>
21852 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion)
21853 {
21854 m.clear();
21855 unsigned int nSize = ReadCompactSize(is);
21856 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
21857 for (unsigned int i = 0; i < nSize; i++)
21858 {
21859 std::pair<K, T> item;
21860 Unserialize(is, item, nType, nVersion);
21861 mi = m.insert(mi, item);
21862 }
21863 }
21864
21865
21866
21867 //
21868 // set
21869 //
21870 template<typename K, typename Pred, typename A>
21871 unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)
21872 {
21873 unsigned int nSize = GetSizeOfCompactSize(m.size());
21874 for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
21875 nSize += GetSerializeSize((*it), nType, nVersion);
21876 return nSize;
21877 }
21878
21879 template<typename Stream, typename K, typename Pred, typename A>
21880 void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion)
21881 {
21882 WriteCompactSize(os, m.size());
21883 for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
21884 Serialize(os, (*it), nType, nVersion);
21885 }
21886
21887 template<typename Stream, typename K, typename Pred, typename A>
21888 void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
21889 {
21890 m.clear();
21891 unsigned int nSize = ReadCompactSize(is);
21892 typename std::set<K, Pred, A>::iterator it = m.begin();
21893 for (unsigned int i = 0; i < nSize; i++)
21894 {
21895 K key;
21896 Unserialize(is, key, nType, nVersion);
21897 it = m.insert(it, key);
21898 }
21899 }
21900
21901
21902
21903 //
21904 // Support for IMPLEMENT_SERIALIZE and READWRITE macro
21905 //
21906 class CSerActionGetSerializeSize { };
21907 class CSerActionSerialize { };
21908 class CSerActionUnserialize { };
21909
21910 template<typename Stream, typename T>
21911 inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action)
21912 {
21913 return ::GetSerializeSize(obj, nType, nVersion);
21914 }
21915
21916 template<typename Stream, typename T>
21917 inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
21918 {
21919 ::Serialize(s, obj, nType, nVersion);
21920 return 0;
21921 }
21922
21923 template<typename Stream, typename T>
21924 inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
21925 {
21926 ::Unserialize(s, obj, nType, nVersion);
21927 return 0;
21928 }
21929
21930 struct ser_streamplaceholder
21931 {
21932 int nType;
21933 int nVersion;
21934 };
21935
21936
21937
21938
21939
21940
21941
21942
21943
21944 //
21945 // Allocator that locks its contents from being paged
21946 // out of memory and clears its contents before deletion.
21947 //
21948 template<typename T>
21949 struct secure_allocator : public std::allocator<T>
21950 {
21951 // MSVC8 default copy constructor is broken
21952 typedef std::allocator<T> base;
21953 typedef typename base::size_type size_type;
21954 typedef typename base::difference_type difference_type;
21955 typedef typename base::pointer pointer;
21956 typedef typename base::const_pointer const_pointer;
21957 typedef typename base::reference reference;
21958 typedef typename base::const_reference const_reference;
21959 typedef typename base::value_type value_type;
21960 secure_allocator() throw() {}
21961 secure_allocator(const secure_allocator& a) throw() : base(a) {}
21962 template <typename U>
21963 secure_allocator(const secure_allocator<U>& a) throw() : base(a) {}
21964 ~secure_allocator() throw() {}
21965 template<typename _Other> struct rebind
21966 { typedef secure_allocator<_Other> other; };
21967
21968 T* allocate(std::size_t n, const void *hint = 0)
21969 {
21970 T *p;
21971 p = std::allocator<T>::allocate(n, hint);
21972 if (p != NULL)
21973 mlock(p, sizeof(T) * n);
21974 return p;
21975 }
21976
21977 void deallocate(T* p, std::size_t n)
21978 {
21979 if (p != NULL)
21980 {
21981 memset(p, 0, sizeof(T) * n);
21982 munlock(p, sizeof(T) * n);
21983 }
21984 std::allocator<T>::deallocate(p, n);
21985 }
21986 };
21987
21988
21989 //
21990 // Allocator that clears its contents before deletion.
21991 //
21992 template<typename T>
21993 struct zero_after_free_allocator : public std::allocator<T>
21994 {
21995 // MSVC8 default copy constructor is broken
21996 typedef std::allocator<T> base;
21997 typedef typename base::size_type size_type;
21998 typedef typename base::difference_type difference_type;
21999 typedef typename base::pointer pointer;
22000 typedef typename base::const_pointer const_pointer;
22001 typedef typename base::reference reference;
22002 typedef typename base::const_reference const_reference;
22003 typedef typename base::value_type value_type;
22004 zero_after_free_allocator() throw() {}
22005 zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {}
22006 template <typename U>
22007 zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a) {}
22008 ~zero_after_free_allocator() throw() {}
22009 template<typename _Other> struct rebind
22010 { typedef zero_after_free_allocator<_Other> other; };
22011
22012 void deallocate(T* p, std::size_t n)
22013 {
22014 if (p != NULL)
22015 memset(p, 0, sizeof(T) * n);
22016 std::allocator<T>::deallocate(p, n);
22017 }
22018 };
22019
22020
22021
22022 //
22023 // Double ended buffer combining vector and stream-like interfaces.
22024 // >> and << read and write unformatted data using the above serialization templates.
22025 // Fills with data in linear time; some stringstream implementations take N^2 time.
22026 //
22027 class CDataStream
22028 {
22029 protected:
22030 typedef std::vector<char, zero_after_free_allocator<char> > vector_type;
22031 vector_type vch;
22032 unsigned int nReadPos;
22033 short state;
22034 short exceptmask;
22035 public:
22036 int nType;
22037 int nVersion;
22038
22039 typedef vector_type::allocator_type allocator_type;
22040 typedef vector_type::size_type size_type;
22041 typedef vector_type::difference_type difference_type;
22042 typedef vector_type::reference reference;
22043 typedef vector_type::const_reference const_reference;
22044 typedef vector_type::value_type value_type;
22045 typedef vector_type::iterator iterator;
22046 typedef vector_type::const_iterator const_iterator;
22047 typedef vector_type::reverse_iterator reverse_iterator;
22048
22049 explicit CDataStream(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
22050 {
22051 Init(nTypeIn, nVersionIn);
22052 }
22053
22054 CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(pbegin, pend)
22055 {
22056 Init(nTypeIn, nVersionIn);
22057 }
22058
22059 #if !defined(_MSC_VER) || _MSC_VER >= 1300
22060 CDataStream(const char* pbegin, const char* pend, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(pbegin, pend)
22061 {
22062 Init(nTypeIn, nVersionIn);
22063 }
22064 #endif
22065
22066 CDataStream(const vector_type& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
22067 {
22068 Init(nTypeIn, nVersionIn);
22069 }
22070
22071 CDataStream(const std::vector<char>& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
22072 {
22073 Init(nTypeIn, nVersionIn);
22074 }
22075
22076 CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0])
22077 {
22078 Init(nTypeIn, nVersionIn);
22079 }
22080
22081 void Init(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
22082 {
22083 nReadPos = 0;
22084 nType = nTypeIn;
22085 nVersion = nVersionIn;
22086 state = 0;
22087 exceptmask = std::ios::badbit | std::ios::failbit;
22088 }
22089
22090 CDataStream& operator+=(const CDataStream& b)
22091 {
22092 vch.insert(vch.end(), b.begin(), b.end());
22093 return *this;
22094 }
22095
22096 friend CDataStream operator+(const CDataStream& a, const CDataStream& b)
22097 {
22098 CDataStream ret = a;
22099 ret += b;
22100 return (ret);
22101 }
22102
22103 std::string str() const
22104 {
22105 return (std::string(begin(), end()));
22106 }
22107
22108
22109 //
22110 // Vector subset
22111 //
22112 const_iterator begin() const { return vch.begin() + nReadPos; }
22113 iterator begin() { return vch.begin() + nReadPos; }
22114 const_iterator end() const { return vch.end(); }
22115 iterator end() { return vch.end(); }
22116 size_type size() const { return vch.size() - nReadPos; }
22117 bool empty() const { return vch.size() == nReadPos; }
22118 void resize(size_type n, value_type c=0) { vch.resize(n + nReadPos, c); }
22119 void reserve(size_type n) { vch.reserve(n + nReadPos); }
22120 const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; }
22121 reference operator[](size_type pos) { return vch[pos + nReadPos]; }
22122 void clear() { vch.clear(); nReadPos = 0; }
22123 iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }
22124 void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }
22125
22126 void insert(iterator it, const_iterator first, const_iterator last)
22127 {
22128 if (it == vch.begin() + nReadPos && last - first <= nReadPos)
22129 {
22130 // special case for inserting at the front when there's room
22131 nReadPos -= (last - first);
22132 memcpy(&vch[nReadPos], &first[0], last - first);
22133 }
22134 else
22135 vch.insert(it, first, last);
22136 }
22137
22138 void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last)
22139 {
22140 if (it == vch.begin() + nReadPos && last - first <= nReadPos)
22141 {
22142 // special case for inserting at the front when there's room
22143 nReadPos -= (last - first);
22144 memcpy(&vch[nReadPos], &first[0], last - first);
22145 }
22146 else
22147 vch.insert(it, first, last);
22148 }
22149
22150 #if !defined(_MSC_VER) || _MSC_VER >= 1300
22151 void insert(iterator it, const char* first, const char* last)
22152 {
22153 if (it == vch.begin() + nReadPos && last - first <= nReadPos)
22154 {
22155 // special case for inserting at the front when there's room
22156 nReadPos -= (last - first);
22157 memcpy(&vch[nReadPos], &first[0], last - first);
22158 }
22159 else
22160 vch.insert(it, first, last);
22161 }
22162 #endif
22163
22164 iterator erase(iterator it)
22165 {
22166 if (it == vch.begin() + nReadPos)
22167 {
22168 // special case for erasing from the front
22169 if (++nReadPos >= vch.size())
22170 {
22171 // whenever we reach the end, we take the opportunity to clear the buffer
22172 nReadPos = 0;
22173 return vch.erase(vch.begin(), vch.end());
22174 }
22175 return vch.begin() + nReadPos;
22176 }
22177 else
22178 return vch.erase(it);
22179 }
22180
22181 iterator erase(iterator first, iterator last)
22182 {
22183 if (first == vch.begin() + nReadPos)
22184 {
22185 // special case for erasing from the front
22186 if (last == vch.end())
22187 {
22188 nReadPos = 0;
22189 return vch.erase(vch.begin(), vch.end());
22190 }
22191 else
22192 {
22193 nReadPos = (last - vch.begin());
22194 return last;
22195 }
22196 }
22197 else
22198 return vch.erase(first, last);
22199 }
22200
22201 inline void Compact()
22202 {
22203 vch.erase(vch.begin(), vch.begin() + nReadPos);
22204 nReadPos = 0;
22205 }
22206
22207 bool Rewind(size_type n)
22208 {
22209 // Rewind by n characters if the buffer hasn't been compacted yet
22210 if (n > nReadPos)
22211 return false;
22212 nReadPos -= n;
22213 return true;
22214 }
22215
22216
22217 //
22218 // Stream subset
22219 //
22220 void setstate(short bits, const char* psz)
22221 {
22222 state |= bits;
22223 if (state & exceptmask)
22224 throw std::ios_base::failure(psz);
22225 }
22226
22227 bool eof() const { return size() == 0; }
22228 bool fail() const { return state & (std::ios::badbit | std::ios::failbit); }
22229 bool good() const { return !eof() && (state == 0); }
22230 void clear(short n) { state = n; } // name conflict with vector clear()
22231 short exceptions() { return exceptmask; }
22232 short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; }
22233 CDataStream* rdbuf() { return this; }
22234 int in_avail() { return size(); }
22235
22236 void SetType(int n) { nType = n; }
22237 int GetType() { return nType; }
22238 void SetVersion(int n) { nVersion = n; }
22239 int GetVersion() { return nVersion; }
22240 void ReadVersion() { *this >> nVersion; }
22241 void WriteVersion() { *this << nVersion; }
22242
22243 CDataStream& read(char* pch, int nSize)
22244 {
22245 // Read from the beginning of the buffer
22246 assert(nSize >= 0);
22247 unsigned int nReadPosNext = nReadPos + nSize;
22248 if (nReadPosNext >= vch.size())
22249 {
22250 if (nReadPosNext > vch.size())
22251 {
22252 setstate(std::ios::failbit, "CDataStream::read() : end of data");
22253 memset(pch, 0, nSize);
22254 nSize = vch.size() - nReadPos;
22255 }
22256 memcpy(pch, &vch[nReadPos], nSize);
22257 nReadPos = 0;
22258 vch.clear();
22259 return (*this);
22260 }
22261 memcpy(pch, &vch[nReadPos], nSize);
22262 nReadPos = nReadPosNext;
22263 return (*this);
22264 }
22265
22266 CDataStream& ignore(int nSize)
22267 {
22268 // Ignore from the beginning of the buffer
22269 assert(nSize >= 0);
22270 unsigned int nReadPosNext = nReadPos + nSize;
22271 if (nReadPosNext >= vch.size())
22272 {
22273 if (nReadPosNext > vch.size())
22274 {
22275 setstate(std::ios::failbit, "CDataStream::ignore() : end of data");
22276 nSize = vch.size() - nReadPos;
22277 }
22278 nReadPos = 0;
22279 vch.clear();
22280 return (*this);
22281 }
22282 nReadPos = nReadPosNext;
22283 return (*this);
22284 }
22285
22286 CDataStream& write(const char* pch, int nSize)
22287 {
22288 // Write to the end of the buffer
22289 assert(nSize >= 0);
22290 vch.insert(vch.end(), pch, pch + nSize);
22291 return (*this);
22292 }
22293
22294 template<typename Stream>
22295 void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
22296 {
22297 // Special case: stream << stream concatenates like stream += stream
22298 if (!vch.empty())
22299 s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));
22300 }
22301
22302 template<typename T>
22303 unsigned int GetSerializeSize(const T& obj)
22304 {
22305 // Tells the size of the object if serialized to this stream
22306 return ::GetSerializeSize(obj, nType, nVersion);
22307 }
22308
22309 template<typename T>
22310 CDataStream& operator<<(const T& obj)
22311 {
22312 // Serialize to this stream
22313 ::Serialize(*this, obj, nType, nVersion);
22314 return (*this);
22315 }
22316
22317 template<typename T>
22318 CDataStream& operator>>(T& obj)
22319 {
22320 // Unserialize from this stream
22321 ::Unserialize(*this, obj, nType, nVersion);
22322 return (*this);
22323 }
22324 };
22325
22326 #ifdef TESTCDATASTREAM
22327 // VC6sp6
22328 // CDataStream:
22329 // n=1000 0 seconds
22330 // n=2000 0 seconds
22331 // n=4000 0 seconds
22332 // n=8000 0 seconds
22333 // n=16000 0 seconds
22334 // n=32000 0 seconds
22335 // n=64000 1 seconds
22336 // n=128000 1 seconds
22337 // n=256000 2 seconds
22338 // n=512000 4 seconds
22339 // n=1024000 8 seconds
22340 // n=2048000 16 seconds
22341 // n=4096000 32 seconds
22342 // stringstream:
22343 // n=1000 1 seconds
22344 // n=2000 1 seconds
22345 // n=4000 13 seconds
22346 // n=8000 87 seconds
22347 // n=16000 400 seconds
22348 // n=32000 1660 seconds
22349 // n=64000 6749 seconds
22350 // n=128000 27241 seconds
22351 // n=256000 109804 seconds
22352 #include <iostream>
22353 int main(int argc, char *argv[])
22354 {
22355 vector<unsigned char> vch(0xcc, 250);
22356 printf("CDataStream:\n");
22357 for (int n = 1000; n <= 4500000; n *= 2)
22358 {
22359 CDataStream ss;
22360 time_t nStart = time(NULL);
22361 for (int i = 0; i < n; i++)
22362 ss.write((char*)&vch[0], vch.size());
22363 printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);
22364 }
22365 printf("stringstream:\n");
22366 for (int n = 1000; n <= 4500000; n *= 2)
22367 {
22368 stringstream ss;
22369 time_t nStart = time(NULL);
22370 for (int i = 0; i < n; i++)
22371 ss.write((char*)&vch[0], vch.size());
22372 printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);
22373 }
22374 }
22375 #endif
22376
22377
22378
22379
22380
22381
22382
22383
22384
22385
22386 //
22387 // Automatic closing wrapper for FILE*
22388 // - Will automatically close the file when it goes out of scope if not null.
22389 // - If you're returning the file pointer, return file.release().
22390 // - If you need to close the file early, use file.fclose() instead of fclose(file).
22391 //
22392 class CAutoFile
22393 {
22394 protected:
22395 FILE* file;
22396 short state;
22397 short exceptmask;
22398 public:
22399 int nType;
22400 int nVersion;
22401
22402 typedef FILE element_type;
22403
22404 CAutoFile(FILE* filenew=NULL, int nTypeIn=SER_DISK, int nVersionIn=VERSION)
22405 {
22406 file = filenew;
22407 nType = nTypeIn;
22408 nVersion = nVersionIn;
22409 state = 0;
22410 exceptmask = std::ios::badbit | std::ios::failbit;
22411 }
22412
22413 ~CAutoFile()
22414 {
22415 fclose();
22416 }
22417
22418 void fclose()
22419 {
22420 if (file != NULL && file != stdin && file != stdout && file != stderr)
22421 ::fclose(file);
22422 file = NULL;
22423 }
22424
22425 FILE* release() { FILE* ret = file; file = NULL; return ret; }
22426 operator FILE*() { return file; }
22427 FILE* operator->() { return file; }
22428 FILE& operator*() { return *file; }
22429 FILE** operator&() { return &file; }
22430 FILE* operator=(FILE* pnew) { return file = pnew; }
22431 bool operator!() { return (file == NULL); }
22432
22433
22434 //
22435 // Stream subset
22436 //
22437 void setstate(short bits, const char* psz)
22438 {
22439 state |= bits;
22440 if (state & exceptmask)
22441 throw std::ios_base::failure(psz);
22442 }
22443
22444 bool fail() const { return state & (std::ios::badbit | std::ios::failbit); }
22445 bool good() const { return state == 0; }
22446 void clear(short n = 0) { state = n; }
22447 short exceptions() { return exceptmask; }
22448 short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; }
22449
22450 void SetType(int n) { nType = n; }
22451 int GetType() { return nType; }
22452 void SetVersion(int n) { nVersion = n; }
22453 int GetVersion() { return nVersion; }
22454 void ReadVersion() { *this >> nVersion; }
22455 void WriteVersion() { *this << nVersion; }
22456
22457 CAutoFile& read(char* pch, int nSize)
22458 {
22459 if (!file)
22460 throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
22461 if (fread(pch, 1, nSize, file) != nSize)
22462 setstate(std::ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
22463 return (*this);
22464 }
22465
22466 CAutoFile& write(const char* pch, int nSize)
22467 {
22468 if (!file)
22469 throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
22470 if (fwrite(pch, 1, nSize, file) != nSize)
22471 setstate(std::ios::failbit, "CAutoFile::write : write failed");
22472 return (*this);
22473 }
22474
22475 template<typename T>
22476 unsigned int GetSerializeSize(const T& obj)
22477 {
22478 // Tells the size of the object if serialized to this stream
22479 return ::GetSerializeSize(obj, nType, nVersion);
22480 }
22481
22482 template<typename T>
22483 CAutoFile& operator<<(const T& obj)
22484 {
22485 // Serialize to this stream
22486 if (!file)
22487 throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
22488 ::Serialize(*this, obj, nType, nVersion);
22489 return (*this);
22490 }
22491
22492 template<typename T>
22493 CAutoFile& operator>>(T& obj)
22494 {
22495 // Unserialize from this stream
22496 if (!file)
22497 throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");
22498 ::Unserialize(*this, obj, nType, nVersion);
22499 return (*this);
22500 }
22501 };
22502
22503 #endif