aboutsummaryrefslogtreecommitdiff
path: root/src/serialize.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/serialize.h')
-rw-r--r--src/serialize.h112
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;
}