X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fserialize.h;h=c0471bbd3ebb69a90a788b428d405b82fd3ec9ad;hb=fffc7f103e43c9ca096461481364cff01bf17e3c;hp=f579c5864e97e4b54aa1b7e1a2e6149759c8397b;hpb=532b9005ab4fc02db3db424b4631fe395e0b9071;p=novacoin.git diff --git a/src/serialize.h b/src/serialize.h index f579c58..c0471bb 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -13,12 +13,10 @@ #include #include #include +#include +#include #ifndef Q_MOC_RUN -#include -#include -#include -#include #endif #if defined __USE_MINGW_ANSI_STDIO @@ -56,13 +54,12 @@ enum SER_DISK = (1 << 1), SER_GETHASH = (1 << 2), - // modifiers - SER_SKIPSIG = (1 << 16), - SER_BLOCKHEADERONLY = (1 << 17), + // modifiers + SER_SKIPSIG = (1 << 16), + SER_BLOCKHEADERONLY = (1 << 17) }; -#ifdef _MSC_VER #define IMPLEMENT_SERIALIZE(statements) \ unsigned int GetSerializeSize(int nType, int nVersion) const \ { \ @@ -75,7 +72,6 @@ enum assert(fGetSize||fWrite||fRead); /* suppress warning */ \ s.nType = nType; \ s.nVersion = nVersion; \ - std::map mapUnkIds; \ {statements} \ return nSerSize; \ } \ @@ -88,7 +84,6 @@ enum const bool fRead = false; \ unsigned int nSerSize = 0; \ assert(fGetSize||fWrite||fRead); /* suppress warning */ \ - std::map mapUnkIds; \ {statements} \ } \ template \ @@ -99,60 +94,15 @@ enum const bool fWrite = false; \ const bool fRead = true; \ unsigned int nSerSize = 0; \ - std::map mapUnkIds; \ assert(fGetSize||fWrite||fRead); /* suppress warning */ \ {statements} \ } -#else - -#define IMPLEMENT_SERIALIZE(statements) \ - unsigned int GetSerializeSize(int nType, int nVersion) const \ - { \ - CSerActionGetSerializeSize ser_action; \ - const bool fGetSize = true; \ - const bool fWrite = false; \ - const bool fRead = false; \ - unsigned int nSerSize = 0; \ - ser_streamplaceholder s; \ - assert(fGetSize||fWrite||fRead); /* suppress warning */ \ - s.nType = nType; \ - s.nVersion = nVersion; \ - {statements} \ - return nSerSize; \ - } \ - template \ - void Serialize(Stream& s, int nType, int nVersion) const \ - { \ - CSerActionSerialize ser_action; \ - const bool fGetSize = false; \ - const bool fWrite = true; \ - const bool fRead = false; \ - unsigned int nSerSize = 0; \ - assert(fGetSize||fWrite||fRead); /* suppress warning */ \ - {statements} \ - } \ - template \ - void Unserialize(Stream& s, int nType, int nVersion) \ - { \ - CSerActionUnserialize ser_action; \ - const bool fGetSize = false; \ - const bool fWrite = false; \ - const bool fRead = true; \ - unsigned int nSerSize = 0; \ - assert(fGetSize||fWrite||fRead); /* suppress warning */ \ - {statements} \ - } - -#endif - #define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action)) - - // // Basic types // @@ -208,87 +158,29 @@ template inline void Unserialize(Stream& s, bool& a, int, int=0 - - // // Compact size -// size < 253 -- 1 byte -// size <= USHRT_MAX -- 3 bytes (253 + 2 bytes) -// size <= UINT_MAX -- 5 bytes (254 + 4 bytes) -// size > UINT_MAX -- 9 bytes (255 + 8 bytes) +// size < 253 -- 1 byte +// size <= UINT16_MAX -- 3 bytes (253 + 2 bytes) +// size <= UINT32_MAX -- 5 bytes (254 + 4 bytes) +// size > UINT32_MAX -- 9 bytes (255 + 8 bytes) // -inline unsigned int GetSizeOfCompactSize(uint64_t nSize) +inline uint32_t GetSizeOfCompactSize(uint64_t nSize) { - if (nSize < 253) return sizeof(unsigned char); - else if (nSize <= std::numeric_limits::max()) return sizeof(unsigned char) + sizeof(unsigned short); - else if (nSize <= std::numeric_limits::max()) return sizeof(unsigned char) + sizeof(unsigned int); - else return sizeof(unsigned char) + sizeof(uint64_t); + if (nSize < 0xfd) + return 1; + if (nSize <= std::numeric_limits::max()) + return 3; + if (nSize <= std::numeric_limits::max()) + return 5; + return 9; } template -void WriteCompactSize(Stream& os, uint64_t nSize) -{ - if (nSize < 253) - { - unsigned char chSize = (unsigned char)nSize; - WRITEDATA(os, chSize); - } - else if (nSize <= std::numeric_limits::max()) - { - unsigned char chSize = 253; - unsigned short xSize = (unsigned short)nSize; - WRITEDATA(os, chSize); - WRITEDATA(os, xSize); - } - else if (nSize <= std::numeric_limits::max()) - { - unsigned char chSize = 254; - unsigned int xSize = (unsigned int)nSize; - WRITEDATA(os, chSize); - WRITEDATA(os, xSize); - } - else - { - unsigned char chSize = 255; - uint64_t xSize = nSize; - WRITEDATA(os, chSize); - WRITEDATA(os, xSize); - } - return; -} +void WriteCompactSize(Stream& os, uint64_t nSize); template -uint64_t ReadCompactSize(Stream& is) -{ - unsigned char chSize; - READDATA(is, chSize); - uint64_t nSizeRet = 0; - if (chSize < 253) - { - nSizeRet = chSize; - } - else if (chSize == 253) - { - unsigned short xSize; - READDATA(is, xSize); - nSizeRet = xSize; - } - else if (chSize == 254) - { - unsigned int xSize; - READDATA(is, xSize); - nSizeRet = xSize; - } - else - { - uint64_t xSize; - READDATA(is, xSize); - nSizeRet = xSize; - } - if (nSizeRet > (uint64_t)MAX_SIZE) - throw std::ios_base::failure("ReadCompactSize() : size too large"); - return nSizeRet; -} +uint64_t ReadCompactSize(Stream& is); // Variable-length integers: bytes are a MSB base-128 encoding of the number. // The high bit in each byte signifies whether another digit follows. To make @@ -316,7 +208,7 @@ template inline unsigned int GetSizeOfVarInt(I n) { int nRet = 0; - while(true) { + for ( ; ; ) { nRet++; if (n <= 0x7F) break; @@ -330,7 +222,7 @@ void WriteVarInt(Stream& os, I n) { unsigned char tmp[(sizeof(n)*8+6)/7]; int len=0; - while(true) { + for ( ; ; ) { tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00); if (n <= 0x7F) break; @@ -346,7 +238,7 @@ template I ReadVarInt(Stream& is) { I n = 0; - while(true) { + for ( ; ; ) { unsigned char chData; READDATA(is, chData); n = (n << 7) | (chData & 0x7F); @@ -428,14 +320,14 @@ template void Serialize(Stream& os, const std::basi template void Unserialize(Stream& is, std::basic_string& str, int, int=0); // vector -template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::true_type&); -template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::false_type&); +template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const std::true_type&); +template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const std::false_type&); template inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion); -template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::true_type&); -template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::false_type&); +template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const std::true_type&); +template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const std::false_type&); template inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion); -template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::true_type&); -template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::false_type&); +template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const std::true_type&); +template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const std::false_type&); template inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion); // others derived from vector @@ -449,14 +341,9 @@ template void Serialize(Stream& os, con template void Unserialize(Stream& is, std::pair& item, int nType, int nVersion); // 3 tuple -template unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion); -template void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion); -template void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion); - -// 4 tuple -template unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion); -template void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion); -template void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion); +template unsigned int GetSerializeSize(const std::tuple& item, int nType, int nVersion); +template void Serialize(Stream& os, const std::tuple& item, int nType, int nVersion); +template void Unserialize(Stream& is, std::tuple& item, int nType, int nVersion); // map template unsigned int GetSerializeSize(const std::map& m, int nType, int nVersion); @@ -471,7 +358,6 @@ template void Unserializ - // // If none of the specialized versions above matched, default to calling member function. // "int nType" is changed to "long nType" to keep from getting an ambiguous overload error. @@ -499,7 +385,6 @@ inline void Unserialize(Stream& is, T& a, long nType, int nVersion) - // // string // @@ -532,13 +417,13 @@ void Unserialize(Stream& is, std::basic_string& str, int, int) // vector // template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::true_type&) +unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const std::true_type&) { return (unsigned int)(GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T)); } template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::false_type&) +unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const std::false_type&) { unsigned int nSize = GetSizeOfCompactSize(v.size()); for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) @@ -549,12 +434,12 @@ unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nV template inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion) { - return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental()); + return GetSerializeSize_impl(v, nType, nVersion, std::is_fundamental()); } template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::true_type&) +void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const std::true_type&) { WriteCompactSize(os, v.size()); if (!v.empty()) @@ -562,7 +447,7 @@ void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVers } template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::false_type&) +void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const std::false_type&) { WriteCompactSize(os, v.size()); for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) @@ -572,12 +457,12 @@ void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVers template inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion) { - Serialize_impl(os, v, nType, nVersion, boost::is_fundamental()); + Serialize_impl(os, v, nType, nVersion, std::is_fundamental()); } template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::true_type&) +void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const std::true_type&) { // Limit size per read so bogus size value won't cause out of memory v.clear(); @@ -593,7 +478,7 @@ void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, } template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::false_type&) +void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const std::false_type&) { v.clear(); unsigned int nSize = (unsigned int)(ReadCompactSize(is)); @@ -613,7 +498,7 @@ void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, template inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion) { - Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental()); + Unserialize_impl(is, v, nType, nVersion, std::is_fundamental()); } @@ -669,63 +554,29 @@ void Unserialize(Stream& is, std::pair& item, int nType, int nVersion) // 3 tuple // template -unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion) +unsigned int GetSerializeSize(const std::tuple& item, int nType, int nVersion) { unsigned int nSize = 0; - nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion); + nSize += GetSerializeSize(std::get<0>(item), nType, nVersion); + nSize += GetSerializeSize(std::get<1>(item), nType, nVersion); + nSize += GetSerializeSize(std::get<2>(item), nType, nVersion); return nSize; } template -void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion) +void Serialize(Stream& os, const std::tuple& item, int nType, int nVersion) { - Serialize(os, boost::get<0>(item), nType, nVersion); - Serialize(os, boost::get<1>(item), nType, nVersion); - Serialize(os, boost::get<2>(item), nType, nVersion); + Serialize(os, std::get<0>(item), nType, nVersion); + Serialize(os, std::get<1>(item), nType, nVersion); + Serialize(os, std::get<2>(item), nType, nVersion); } template -void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion) -{ - Unserialize(is, boost::get<0>(item), nType, nVersion); - Unserialize(is, boost::get<1>(item), nType, nVersion); - Unserialize(is, boost::get<2>(item), nType, nVersion); -} - - - -// -// 4 tuple -// -template -unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion) -{ - unsigned int nSize = 0; - nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<3>(item), nType, nVersion); - return nSize; -} - -template -void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion) -{ - Serialize(os, boost::get<0>(item), nType, nVersion); - Serialize(os, boost::get<1>(item), nType, nVersion); - Serialize(os, boost::get<2>(item), nType, nVersion); - Serialize(os, boost::get<3>(item), nType, nVersion); -} - -template -void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion) +void Unserialize(Stream& is, std::tuple& item, int nType, int nVersion) { - Unserialize(is, boost::get<0>(item), nType, nVersion); - Unserialize(is, boost::get<1>(item), nType, nVersion); - Unserialize(is, boost::get<2>(item), nType, nVersion); - Unserialize(is, boost::get<3>(item), nType, nVersion); + Unserialize(is, std::get<0>(item), nType, nVersion); + Unserialize(is, std::get<1>(item), nType, nVersion); + Unserialize(is, std::get<2>(item), nType, nVersion); } @@ -838,13 +689,6 @@ struct ser_streamplaceholder - - - - - - - typedef std::vector > CSerializeData; /** Double ended buffer combining vector and stream-like interfaces. @@ -884,12 +728,10 @@ public: Init(nTypeIn, nVersionIn); } -#if !defined(_MSC_VER) || _MSC_VER >= 1300 CDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend) { Init(nTypeIn, nVersionIn); } -#endif CDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) { @@ -951,22 +793,6 @@ public: iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); } void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); } -#ifdef _MSC_VER - void insert(iterator it, const_iterator first, const_iterator last) - { - assert(last - first >= 0); - if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) - { - // special case for inserting at the front when there's room - nReadPos -= (unsigned int)(last - first); - memcpy(&vch[nReadPos], &first[0], last - first); - } - else - vch.insert(it, first, last); - } -#endif - -#ifndef _MSC_VER void insert(iterator it, std::vector::const_iterator first, std::vector::const_iterator last) { assert(last - first >= 0); @@ -979,9 +805,7 @@ public: else vch.insert(it, first, last); } -#endif -#if !defined(_MSC_VER) || _MSC_VER >= 1300 void insert(iterator it, const char* first, const char* last) { assert(last - first >= 0); @@ -994,7 +818,6 @@ public: else vch.insert(it, first, last); } -#endif iterator erase(iterator it) { @@ -1039,26 +862,12 @@ public: nReadPos = 0; } - bool Rewind(size_type n) - { - // Rewind by n characters if the buffer hasn't been compacted yet - if (n > nReadPos) - return false; - nReadPos -= (unsigned int)n; - return true; - } - + bool Rewind(size_type n); // // Stream subset // - void setstate(short bits, const char* psz) - { - state |= bits; - if (state & exceptmask) - throw std::ios_base::failure(psz); - } - + void setstate(short bits, const char* psz); bool eof() const { return size() == 0; } bool fail() const { return (state & (std::ios::badbit | std::ios::failbit)) != 0; } bool good() const { return !eof() && (state == 0); } @@ -1075,56 +884,9 @@ public: void ReadVersion() { *this >> nVersion; } void WriteVersion() { *this << nVersion; } - CDataStream& read(char* pch, int nSize) - { - // Read from the beginning of the buffer - assert(nSize >= 0); - unsigned int nReadPosNext = nReadPos + nSize; - if (nReadPosNext >= vch.size()) - { - if (nReadPosNext > vch.size()) - { - setstate(std::ios::failbit, "CDataStream::read() : end of data"); - memset(pch, 0, nSize); - nSize = (int)(vch.size() - nReadPos); - } - memcpy(pch, &vch[nReadPos], nSize); - nReadPos = 0; - vch.clear(); - return (*this); - } - memcpy(pch, &vch[nReadPos], nSize); - nReadPos = nReadPosNext; - return (*this); - } - - CDataStream& ignore(int nSize) - { - // Ignore from the beginning of the buffer - assert(nSize >= 0); - unsigned int nReadPosNext = nReadPos + nSize; - if (nReadPosNext >= vch.size()) - { - if (nReadPosNext > vch.size()) - { - setstate(std::ios::failbit, "CDataStream::ignore() : end of data"); - nSize = (int)(vch.size() - nReadPos); - } - nReadPos = 0; - vch.clear(); - return (*this); - } - nReadPos = nReadPosNext; - return (*this); - } - - CDataStream& write(const char* pch, int nSize) - { - // Write to the end of the buffer - assert(nSize >= 0); - vch.insert(vch.end(), pch, pch + nSize); - return (*this); - } + CDataStream& read(char* pch, int nSize); + CDataStream& ignore(int nSize); + CDataStream& write(const char* pch, int nSize); template void Serialize(Stream& s, int nType, int nVersion) const @@ -1157,27 +919,15 @@ public: return (*this); } - void GetAndClear(CSerializeData &data) { - vch.swap(data); - CSerializeData().swap(vch); - } + void GetAndClear(CSerializeData &data); }; - - - - - - - - -/** RAII wrapper for FILE*. - * - * Will automatically close the file when it goes out of scope if not null. - * If you're returning the file pointer, return file.release(). - * If you need to close the file early, use file.fclose() instead of fclose(file). - */ +// RAII wrapper for FILE*. +// +// Will automatically close the file when it goes out of scope if not null. +// If you're returning the file pointer, return file.release(). +// If you need to close the file early, use file.fclose() instead of fclose(file). class CAutoFile { protected: @@ -1188,26 +938,9 @@ public: int nType; int nVersion; - CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) - { - file = filenew; - nType = nTypeIn; - nVersion = nVersionIn; - state = 0; - exceptmask = std::ios::badbit | std::ios::failbit; - } - - ~CAutoFile() - { - fclose(); - } - - void fclose() - { - if (file != NULL && file != stdin && file != stdout && file != stderr) - ::fclose(file); - file = NULL; - } + CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn); + ~CAutoFile(); + void fclose(); FILE* release() { FILE* ret = file; file = NULL; return ret; } operator FILE*() { return file; } @@ -1221,13 +954,7 @@ public: // // Stream subset // - void setstate(short bits, const char* psz) - { - state |= bits; - if (state & exceptmask) - throw std::ios_base::failure(psz); - } - + void setstate(short bits, const char* psz); bool fail() const { return (state & (std::ios::badbit | std::ios::failbit)) != 0; } bool good() const { return state == 0; } void clear(short n = 0) { state = n; } @@ -1241,23 +968,8 @@ public: void ReadVersion() { *this >> nVersion; } void WriteVersion() { *this << nVersion; } - CAutoFile& read(char* pch, size_t nSize) - { - if (!file) - throw std::ios_base::failure("CAutoFile::read : file handle is NULL"); - if (fread(pch, 1, nSize, file) != nSize) - setstate(std::ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed"); - return (*this); - } - - CAutoFile& write(const char* pch, size_t nSize) - { - if (!file) - throw std::ios_base::failure("CAutoFile::write : file handle is NULL"); - if (fwrite(pch, 1, nSize, file) != nSize) - setstate(std::ios::failbit, "CAutoFile::write : write failed"); - return (*this); - } + CAutoFile& read(char* pch, size_t nSize); + CAutoFile& write(const char* pch, size_t nSize); template unsigned int GetSerializeSize(const T& obj) @@ -1287,9 +999,9 @@ public: } }; -/** Wrapper around a FILE* that implements a ring buffer to - * deserialize from. It guarantees the ability to rewind - * a given number of bytes. */ +// Wrapper around a FILE* that implements a ring buffer to +// deserialize from. It guarantees the ability to rewind +// a given number of bytes. class CBufferedFile { private: @@ -1304,113 +1016,29 @@ private: short exceptmask; protected: - void setstate(short bits, const char *psz) { - state |= bits; - if (state & exceptmask) - throw std::ios_base::failure(psz); - } - + void setstate(short bits, const char *psz); // read data from the source to fill the buffer - bool Fill() { - unsigned int pos = (unsigned int)(nSrcPos % vchBuf.size()); - unsigned int readNow = (unsigned int)(vchBuf.size() - pos); - unsigned int nAvail = (unsigned int)(vchBuf.size() - (nSrcPos - nReadPos) - nRewind); - if (nAvail < readNow) - readNow = nAvail; - if (readNow == 0) - return false; - size_t read = fread((void*)&vchBuf[pos], 1, readNow, src); - if (read == 0) { - setstate(std::ios_base::failbit, feof(src) ? "CBufferedFile::Fill : end of file" : "CBufferedFile::Fill : fread failed"); - return false; - } else { - nSrcPos += read; - return true; - } - } + bool Fill(); public: int nType; int nVersion; - CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) : - src(fileIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0), - state(0), exceptmask(std::ios_base::badbit | std::ios_base::failbit), nType(nTypeIn), nVersion(nVersionIn) { - } - + CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn); // check whether no error occurred - bool good() const { - return state == 0; - } - + bool good() const; // check whether we're at the end of the source file - bool eof() const { - return nReadPos == nSrcPos && feof(src); - } - + bool eof() const; // read a number of bytes - CBufferedFile& read(char *pch, size_t nSize) { - if (nSize + nReadPos > nReadLimit) - throw std::ios_base::failure("Read attempted past buffer limit"); - if (nSize + nRewind > vchBuf.size()) - throw std::ios_base::failure("Read larger than buffer size"); - while (nSize > 0) { - if (nReadPos == nSrcPos) - Fill(); - unsigned int pos = (unsigned int)(nReadPos % vchBuf.size()); - size_t nNow = nSize; - if (nNow + pos > vchBuf.size()) - nNow = vchBuf.size() - pos; - if (nNow + nReadPos > nSrcPos) - nNow = nSrcPos - nReadPos; - memcpy(pch, &vchBuf[pos], nNow); - nReadPos += nNow; - pch += nNow; - nSize -= nNow; - } - return (*this); - } - + CBufferedFile& read(char *pch, size_t nSize); // return the current reading position - uint64_t GetPos() { - return nReadPos; - } - + uint64_t GetPos(); // rewind to a given reading position - bool SetPos(uint64_t nPos) { - nReadPos = nPos; - if (nReadPos + nRewind < nSrcPos) { - nReadPos = nSrcPos - nRewind; - return false; - } else if (nReadPos > nSrcPos) { - nReadPos = nSrcPos; - return false; - } else { - return true; - } - } - - bool Seek(uint64_t nPos) { - long nLongPos = (long)nPos; - if (nPos != (uint64_t)nLongPos) - return false; - if (fseek(src, nLongPos, SEEK_SET)) - return false; - nLongPos = ftell(src); - nSrcPos = nLongPos; - nReadPos = nLongPos; - state = 0; - return true; - } - + bool SetPos(uint64_t nPos); + bool Seek(uint64_t nPos); // prevent reading beyond a certain position // no argument removes the limit - bool SetLimit(uint64_t nPos = (uint64_t)(-1)) { - if (nPos < nReadPos) - return false; - nReadLimit = nPos; - return true; - } + bool SetLimit(uint64_t nPos = std::numeric_limits::max()); template CBufferedFile& operator>>(T& obj) { @@ -1420,15 +1048,7 @@ public: } // search for a given byte in the stream, and remain positioned on it - void FindByte(char ch) { - while (true) { - if (nReadPos == nSrcPos) - Fill(); - if (vchBuf[nReadPos % vchBuf.size()] == ch) - break; - nReadPos++; - } - } + void FindByte(char ch); }; #endif