diff options
Diffstat (limited to 'src/serialize.h')
-rw-r--r-- | src/serialize.h | 112 |
1 files changed, 47 insertions, 65 deletions
diff --git a/src/serialize.h b/src/serialize.h index f876efd9b5..17cb724bee 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -68,7 +68,7 @@ inline const T* end_ptr(const std::vector<T,TAl>& v) ///////////////////////////////////////////////////////////////// // // Templates for serializing to anything that looks like a stream, -// i.e. anything that supports .read(char*, int) and .write(char*, int) +// i.e. anything that supports .read(char*, size_t) and .write(char*, size_t) // enum @@ -334,8 +334,9 @@ I ReadVarInt(Stream& is) } } -#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) -#define VARINT(obj) REF(WrapVarInt(REF(obj))) +#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) +#define VARINT(obj) REF(WrapVarInt(REF(obj))) +#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj))) /** Wrapper for serializing arrays and POD. */ @@ -398,6 +399,40 @@ public: } }; +template<size_t Limit> +class LimitedString +{ +protected: + std::string& string; +public: + LimitedString(std::string& string) : string(string) {} + + template<typename Stream> + void Unserialize(Stream& s, int, int=0) + { + size_t size = ReadCompactSize(s); + if (size > Limit) { + throw std::ios_base::failure("String length limit exceeded"); + } + string.resize(size); + if (size != 0) + s.read((char*)&string[0], size); + } + + template<typename Stream> + void Serialize(Stream& s, int, int=0) const + { + WriteCompactSize(s, string.size()); + if (!string.empty()) + s.write((char*)&string[0], string.size()); + } + + unsigned int GetSerializeSize(int, int=0) const + { + return GetSizeOfCompactSize(string.size()) + string.size(); + } +}; + template<typename I> CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); } @@ -841,7 +876,7 @@ public: CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {} - CSizeComputer& write(const char *psz, int nSize) + CSizeComputer& write(const char *psz, size_t nSize) { this->nSize += nSize; return *this; @@ -870,8 +905,6 @@ protected: typedef CSerializeData vector_type; vector_type vch; unsigned int nReadPos; - short state; - short exceptmask; public: int nType; int nVersion; @@ -923,8 +956,6 @@ public: nReadPos = 0; nType = nTypeIn; nVersion = nVersionIn; - state = 0; - exceptmask = std::ios::badbit | std::ios::failbit; } CDataStream& operator+=(const CDataStream& b) @@ -1047,19 +1078,7 @@ public: // // Stream subset // - void setstate(short bits, const char* psz) - { - state |= bits; - if (state & exceptmask) - throw std::ios_base::failure(psz); - } - bool eof() const { return size() == 0; } - bool fail() const { return state & (std::ios::badbit | std::ios::failbit); } - bool good() const { return !eof() && (state == 0); } - void clear(short n) { state = n; } // name conflict with vector clear() - short exceptions() { return exceptmask; } - short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; } CDataStream* rdbuf() { return this; } int in_avail() { return size(); } @@ -1070,18 +1089,15 @@ public: void ReadVersion() { *this >> nVersion; } void WriteVersion() { *this << nVersion; } - CDataStream& read(char* pch, int nSize) + CDataStream& read(char* pch, size_t 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 = vch.size() - nReadPos; + throw std::ios_base::failure("CDataStream::read() : end of data"); } memcpy(pch, &vch[nReadPos], nSize); nReadPos = 0; @@ -1101,7 +1117,7 @@ public: if (nReadPosNext >= vch.size()) { if (nReadPosNext > vch.size()) - setstate(std::ios::failbit, "CDataStream::ignore() : end of data"); + throw std::ios_base::failure("CDataStream::ignore() : end of data"); nReadPos = 0; vch.clear(); return (*this); @@ -1110,10 +1126,9 @@ public: return (*this); } - CDataStream& write(const char* pch, int nSize) + CDataStream& write(const char* pch, size_t nSize) { // Write to the end of the buffer - assert(nSize >= 0); vch.insert(vch.end(), pch, pch + nSize); return (*this); } @@ -1174,8 +1189,6 @@ class CAutoFile { protected: FILE* file; - short state; - short exceptmask; public: int nType; int nVersion; @@ -1185,8 +1198,6 @@ public: file = filenew; nType = nTypeIn; nVersion = nVersionIn; - state = 0; - exceptmask = std::ios::badbit | std::ios::failbit; } ~CAutoFile() @@ -1213,19 +1224,6 @@ public: // // Stream subset // - void setstate(short bits, const char* psz) - { - state |= bits; - if (state & exceptmask) - throw std::ios_base::failure(psz); - } - - bool fail() const { return state & (std::ios::badbit | std::ios::failbit); } - bool good() const { return state == 0; } - void clear(short n = 0) { state = n; } - short exceptions() { return exceptmask; } - short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; } - void SetType(int n) { nType = n; } int GetType() { return nType; } void SetVersion(int n) { nVersion = n; } @@ -1238,7 +1236,7 @@ public: 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"); + throw std::ios_base::failure(feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed"); return (*this); } @@ -1247,7 +1245,7 @@ public: 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"); + throw std::ios_base::failure("CAutoFile::write : write failed"); return (*this); } @@ -1292,16 +1290,7 @@ private: uint64_t nRewind; // how many bytes we guarantee to rewind std::vector<char> vchBuf; // the buffer - short state; - short exceptmask; - protected: - void setstate(short bits, const char *psz) { - state |= bits; - if (state & exceptmask) - throw std::ios_base::failure(psz); - } - // read data from the source to fill the buffer bool Fill() { unsigned int pos = nSrcPos % vchBuf.size(); @@ -1313,8 +1302,7 @@ protected: 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; + throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill : end of file" : "CBufferedFile::Fill : fread failed"); } else { nSrcPos += read; return true; @@ -1327,12 +1315,7 @@ public: 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) { - } - - // check whether no error occurred - bool good() const { - return state == 0; + nType(nTypeIn), nVersion(nVersionIn) { } // check whether we're at the end of the source file @@ -1391,7 +1374,6 @@ public: nLongPos = ftell(src); nSrcPos = nLongPos; nReadPos = nLongPos; - state = 0; return true; } |