raw
genesis                 1 // Copyright (c) 2009-2010 Satoshi Nakamoto
genesis 2 // Copyright (c) 2009-2012 The Bitcoin developers
genesis 3 // Distributed under the MIT/X11 software license, see the accompanying
genesis 4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
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 // This is used to attempt to keep keying material out of swap
genesis 36 // Note that VirtualLock does not provide this as a guarantee on Windows,
genesis 37 // but, in practice, memory that has been VirtualLock'd almost never gets written to
genesis 38 // the pagefile except in rare circumstances where memory is extremely low.
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 /* This comes from limits.h if it's not defined there set a sane default */
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 // Used to bypass the rule against non-const reference to temporary
genesis 68 // where it makes sense with wrappers such as CFlatData or CTxDB
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 // Templates for serializing to anything that looks like a stream,
genesis 78 // i.e. anything that supports .read(char*, int) and .write(char*, int)
genesis 79 //
genesis 80
genesis 81 enum
genesis 82 {
genesis 83 // primary actions
genesis 84 SER_NETWORK = (1 << 0),
genesis 85 SER_DISK = (1 << 1),
genesis 86 SER_GETHASH = (1 << 2),
genesis 87
genesis 88 // modifiers
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); /* suppress warning */ \
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); /* suppress warning */ \
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); /* suppress warning */ \
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 // Basic types
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 // Compact size
genesis 197 // size < 253 -- 1 byte
genesis 198 // size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)
genesis 199 // size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
genesis 200 // size > UINT_MAX -- 9 bytes (255 + 8 bytes)
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 // Wrapper for serializing arrays and POD
genesis 279 // There's a clever template way to make arrays serialize normally, but MSVC6 doesn't support it
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 // string stored as a fixed length field
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 // Forward declarations
genesis 358 //
genesis 359
genesis 360 // string
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 // vector
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 // others derived from vector
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 // pair
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 // 3 tuple
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 // 4 tuple
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 // map
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 // set
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 // If none of the specialized versions above matched, default to calling member function.
genesis 412 // "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
genesis 413 // The compiler will only cast int to long if none of the other templates matched.
genesis 414 // Thanks to Boost serialization for this idea.
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 // string
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 // vector
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 //unsigned int nSize = ReadCompactSize(is);
genesis 518 //v.resize(nSize);
genesis 519 //is.read((char*)&v[0], nSize * sizeof(T));
genesis 520
genesis 521 // Limit size per read so bogus size value won't cause out of memory
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 //unsigned int nSize = ReadCompactSize(is);
genesis 538 //v.resize(nSize);
genesis 539 //for (std::vector<T, A>::iterator vi = v.begin(); vi != v.end(); ++vi)
genesis 540 // Unserialize(is, (*vi), nType, nVersion);
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 // others derived from vector
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 // pair
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 // 3 tuple
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 // 4 tuple
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 // map
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 // set
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 // Support for IMPLEMENT_SERIALIZE and READWRITE macro
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 // Allocator that locks its contents from being paged
genesis 792 // out of memory and clears its contents before deletion.
genesis 793 //
genesis 794 template<typename T>
genesis 795 struct secure_allocator : public std::allocator<T>
genesis 796 {
genesis 797 // MSVC8 default copy constructor is broken
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 // Allocator that clears its contents before deletion.
genesis 837 //
genesis 838 template<typename T>
genesis 839 struct zero_after_free_allocator : public std::allocator<T>
genesis 840 {
genesis 841 // MSVC8 default copy constructor is broken
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 // Double ended buffer combining vector and stream-like interfaces.
genesis 870 // >> and << read and write unformatted data using the above serialization templates.
genesis 871 // Fills with data in linear time; some stringstream implementations take N^2 time.
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 // Vector subset
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 // special case for inserting at the front when there's room
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 // special case for inserting at the front when there's room
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 // special case for inserting at the front when there's room
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 // special case for erasing from the front
genesis 1015 if (++nReadPos >= vch.size())
genesis 1016 {
genesis 1017 // whenever we reach the end, we take the opportunity to clear the buffer
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 // special case for erasing from the front
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 // Rewind by n characters if the buffer hasn't been compacted yet
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 // Stream subset
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; } // name conflict with vector clear()
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 // Read from the beginning of the buffer
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 // Ignore from the beginning of the buffer
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 // Write to the end of the buffer
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 // Special case: stream << stream concatenates like stream += stream
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 // Tells the size of the object if serialized to this stream
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 // Serialize to this stream
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 // Unserialize from this stream
genesis 1167 ::Unserialize(*this, obj, nType, nVersion);
genesis 1168 return (*this);
genesis 1169 }
genesis 1170 };
genesis 1171
genesis 1172 #ifdef TESTCDATASTREAM
genesis 1173 // VC6sp6
genesis 1174 // CDataStream:
genesis 1175 // n=1000 0 seconds
genesis 1176 // n=2000 0 seconds
genesis 1177 // n=4000 0 seconds
genesis 1178 // n=8000 0 seconds
genesis 1179 // n=16000 0 seconds
genesis 1180 // n=32000 0 seconds
genesis 1181 // n=64000 1 seconds
genesis 1182 // n=128000 1 seconds
genesis 1183 // n=256000 2 seconds
genesis 1184 // n=512000 4 seconds
genesis 1185 // n=1024000 8 seconds
genesis 1186 // n=2048000 16 seconds
genesis 1187 // n=4096000 32 seconds
genesis 1188 // stringstream:
genesis 1189 // n=1000 1 seconds
genesis 1190 // n=2000 1 seconds
genesis 1191 // n=4000 13 seconds
genesis 1192 // n=8000 87 seconds
genesis 1193 // n=16000 400 seconds
genesis 1194 // n=32000 1660 seconds
genesis 1195 // n=64000 6749 seconds
genesis 1196 // n=128000 27241 seconds
genesis 1197 // n=256000 109804 seconds
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 // Automatic closing wrapper for FILE*
genesis 1234 // - Will automatically close the file when it goes out of scope if not null.
genesis 1235 // - If you're returning the file pointer, return file.release().
genesis 1236 // - If you need to close the file early, use file.fclose() instead of fclose(file).
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 // Stream subset
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 // Tells the size of the object if serialized to this stream
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 // Serialize to this stream
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 // Unserialize from this stream
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