mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
Implement CFixedVarIntsBitSet and CAutoBitSet
This commit is contained in:
parent
76a58f5a48
commit
49de417265
101
src/serialize.h
101
src/serialize.h
@ -206,6 +206,8 @@ template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a =
|
|||||||
template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
|
template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
|
||||||
template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }
|
template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }
|
||||||
|
|
||||||
|
template <typename T> size_t GetSerializeSize(const T& t, int nType, int nVersion = 0);
|
||||||
|
template <typename S, typename T> size_t GetSerializeSize(const S& s, const T& t);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -359,6 +361,8 @@ I ReadVarInt(Stream& is)
|
|||||||
#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
|
#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
|
||||||
#define FIXEDBITSET(obj, size) REF(CFixedBitSet(REF(obj), (size)))
|
#define FIXEDBITSET(obj, size) REF(CFixedBitSet(REF(obj), (size)))
|
||||||
#define DYNBITSET(obj) REF(CDynamicBitSet(REF(obj)))
|
#define DYNBITSET(obj) REF(CDynamicBitSet(REF(obj)))
|
||||||
|
#define FIXEDVARINTSBITSET(obj, size) REF(CFixedVarIntsBitSet(REF(obj), (size)))
|
||||||
|
#define AUTOBITSET(obj, size) REF(CAutoBitSet(REF(obj), (size)))
|
||||||
#define VARINT(obj) REF(WrapVarInt(REF(obj)))
|
#define VARINT(obj) REF(WrapVarInt(REF(obj)))
|
||||||
#define COMPACTSIZE(obj) REF(CCompactSize(REF(obj)))
|
#define COMPACTSIZE(obj) REF(CCompactSize(REF(obj)))
|
||||||
#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))
|
#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))
|
||||||
@ -464,6 +468,101 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a fixed size bitset as a series of VarInts. Each VarInt is an offset from the last entry and the sum of the
|
||||||
|
* last entry and the offset gives an index into the bitset for a set bit. The series of VarInts ends with a 0.
|
||||||
|
*/
|
||||||
|
class CFixedVarIntsBitSet
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::vector<bool>& vec;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CFixedVarIntsBitSet(std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
|
||||||
|
|
||||||
|
template<typename Stream>
|
||||||
|
void Serialize(Stream& s) const
|
||||||
|
{
|
||||||
|
int32_t last = -1;
|
||||||
|
for (int32_t i = 0; i < (int32_t)vec.size(); i++) {
|
||||||
|
if (vec[i]) {
|
||||||
|
WriteVarInt<Stream, uint32_t>(s, (uint32_t)(i - last));
|
||||||
|
last = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WriteVarInt(s, 0); // stopper
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream>
|
||||||
|
void Unserialize(Stream& s)
|
||||||
|
{
|
||||||
|
vec.assign(size, false);
|
||||||
|
|
||||||
|
int32_t last = -1;
|
||||||
|
while(true) {
|
||||||
|
uint32_t offset = ReadVarInt<Stream, uint32_t>(s);
|
||||||
|
if (offset == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int32_t idx = last + offset;
|
||||||
|
if (idx >= size) {
|
||||||
|
throw std::ios_base::failure("out of bounds index");
|
||||||
|
}
|
||||||
|
if (last != -1 && idx <= last) {
|
||||||
|
throw std::ios_base::failure("offset overflow");
|
||||||
|
}
|
||||||
|
vec[idx] = true;
|
||||||
|
last = idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes either as a CFixedBitSet or CFixedVarIntsBitSet, depending on which would give a smaller size
|
||||||
|
*/
|
||||||
|
class CAutoBitSet
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::vector<bool>& vec;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CAutoBitSet(std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
|
||||||
|
|
||||||
|
template<typename Stream>
|
||||||
|
void Serialize(Stream& s) const
|
||||||
|
{
|
||||||
|
assert(vec.size() == size);
|
||||||
|
|
||||||
|
size_t size1 = ::GetSerializeSize(s, CFixedBitSet(vec, size));
|
||||||
|
size_t size2 = ::GetSerializeSize(s, CFixedVarIntsBitSet(vec, size));
|
||||||
|
|
||||||
|
if (size1 < size2) {
|
||||||
|
ser_writedata8(s, 0);
|
||||||
|
s << FIXEDBITSET(vec, vec.size());
|
||||||
|
} else {
|
||||||
|
ser_writedata8(s, 1);
|
||||||
|
s << FIXEDVARINTSBITSET(vec, vec.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream>
|
||||||
|
void Unserialize(Stream& s)
|
||||||
|
{
|
||||||
|
uint8_t isVarInts = ser_readdata8(s);
|
||||||
|
if (isVarInts != 0 && isVarInts != 1) {
|
||||||
|
throw std::ios_base::failure("invalid value for isVarInts byte");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isVarInts) {
|
||||||
|
s >> FIXEDBITSET(vec, size);
|
||||||
|
} else {
|
||||||
|
s >> FIXEDVARINTSBITSET(vec, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename I>
|
template<typename I>
|
||||||
class CVarInt
|
class CVarInt
|
||||||
{
|
{
|
||||||
@ -1093,7 +1192,7 @@ inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
size_t GetSerializeSize(const T& t, int nType, int nVersion = 0)
|
size_t GetSerializeSize(const T& t, int nType, int nVersion)
|
||||||
{
|
{
|
||||||
return (CSizeComputer(nType, nVersion) << t).size();
|
return (CSizeComputer(nType, nVersion) << t).size();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user