Merge #12740: Add native support for serializing char arrays without FLATDATA
a7c45bc
Add native support for serializing char arrays without FLATDATA (Pieter Wuille)
Pull request description:
Support is added to serialize arrays of type `char` or `unsigned char` directly, without any wrappers. All invocations of the `FLATDATA` wrappers that are obsoleted by this are removed.
This includes a patch by @ryanofsky to make `char` casting type safe.
The serialization of `CSubNet` is changed to serialize a `bool` directly rather than though `FLATDATA`. This makes the serialization independent of the size of the bool type (and will use 1 byte everywhere).
This is a small change taken from #10785.
Tree-SHA512: a41f61ca5fdc2fadb2d0e1702351a58a23841d551f505292a9542602cdb19f90d8944b8df14b872810a56bd201648fa4c0e958f3e9427fe829886284e85b9bfd
This commit is contained in:
commit
8203c4c42e
8 changed files with 40 additions and 26 deletions
|
@ -22,8 +22,8 @@ bool SerializeDB(Stream& stream, const Data& data)
|
|||
// Write and commit header, data
|
||||
try {
|
||||
CHashWriter hasher(SER_DISK, CLIENT_VERSION);
|
||||
stream << FLATDATA(Params().MessageStart()) << data;
|
||||
hasher << FLATDATA(Params().MessageStart()) << data;
|
||||
stream << Params().MessageStart() << data;
|
||||
hasher << Params().MessageStart() << data;
|
||||
stream << hasher.GetHash();
|
||||
} catch (const std::exception& e) {
|
||||
return error("%s: Serialize or I/O error - %s", __func__, e.what());
|
||||
|
@ -66,7 +66,7 @@ bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
|
|||
CHashVerifier<Stream> verifier(&stream);
|
||||
// de-serialize file header (network specific magic number) and ..
|
||||
unsigned char pchMsgTmp[4];
|
||||
verifier >> FLATDATA(pchMsgTmp);
|
||||
verifier >> pchMsgTmp;
|
||||
// ... verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
|
||||
return error("%s: Invalid network magic number", __func__);
|
||||
|
|
|
@ -93,7 +93,7 @@ class CNetAddr
|
|||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(FLATDATA(ip));
|
||||
READWRITE(ip);
|
||||
}
|
||||
|
||||
friend class CSubNet;
|
||||
|
@ -131,8 +131,8 @@ class CSubNet
|
|||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(network);
|
||||
READWRITE(FLATDATA(netmask));
|
||||
READWRITE(FLATDATA(valid));
|
||||
READWRITE(netmask);
|
||||
READWRITE(valid);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -166,7 +166,7 @@ class CService : public CNetAddr
|
|||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(FLATDATA(ip));
|
||||
READWRITE(ip);
|
||||
unsigned short portN = htons(port);
|
||||
READWRITE(FLATDATA(portN));
|
||||
if (ser_action.ForRead())
|
||||
|
|
|
@ -48,10 +48,10 @@ public:
|
|||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(FLATDATA(pchMessageStart));
|
||||
READWRITE(FLATDATA(pchCommand));
|
||||
READWRITE(pchMessageStart);
|
||||
READWRITE(pchCommand);
|
||||
READWRITE(nMessageSize);
|
||||
READWRITE(FLATDATA(pchChecksum));
|
||||
READWRITE(pchChecksum);
|
||||
}
|
||||
|
||||
char pchMessageStart[MESSAGE_START_SIZE];
|
||||
|
|
|
@ -59,6 +59,12 @@ inline T* NCONST_PTR(const T* val)
|
|||
return const_cast<T*>(val);
|
||||
}
|
||||
|
||||
//! Safely convert odd char pointer types to standard ones.
|
||||
inline char* CharCast(char* c) { return c; }
|
||||
inline char* CharCast(unsigned char* c) { return (char*)c; }
|
||||
inline const char* CharCast(const char* c) { return c; }
|
||||
inline const char* CharCast(const unsigned char* c) { return (const char*)c; }
|
||||
|
||||
/*
|
||||
* Lowest-level serialization and conversion.
|
||||
* @note Sizes of these types are verified in the tests
|
||||
|
@ -177,6 +183,8 @@ template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_wri
|
|||
template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
|
||||
template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
|
||||
template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
|
||||
template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(a, N); }
|
||||
template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(CharCast(a), N); }
|
||||
|
||||
template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
|
||||
template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
|
||||
|
@ -189,6 +197,8 @@ template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a =
|
|||
template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
|
||||
template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
|
||||
template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
|
||||
template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(a, N); }
|
||||
template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(CharCast(a), N); }
|
||||
|
||||
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; }
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
|
||||
{
|
||||
CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
|
||||
ssPeersIn << FLATDATA(Params().MessageStart());
|
||||
ssPeersIn << Params().MessageStart();
|
||||
ssPeersIn << _addrman;
|
||||
std::string str = ssPeersIn.str();
|
||||
std::vector<unsigned char> vchData(str.begin(), str.end());
|
||||
|
@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
|
|||
BOOST_CHECK(addrman1.size() == 0);
|
||||
try {
|
||||
unsigned char pchMsgTmp[4];
|
||||
ssPeers1 >> FLATDATA(pchMsgTmp);
|
||||
ssPeers1 >> pchMsgTmp;
|
||||
ssPeers1 >> addrman1;
|
||||
} catch (const std::exception& e) {
|
||||
exceptionThrown = true;
|
||||
|
@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
|
|||
BOOST_CHECK(addrman1.size() == 0);
|
||||
try {
|
||||
unsigned char pchMsgTmp[4];
|
||||
ssPeers1 >> FLATDATA(pchMsgTmp);
|
||||
ssPeers1 >> pchMsgTmp;
|
||||
ssPeers1 >> addrman1;
|
||||
} catch (const std::exception& e) {
|
||||
exceptionThrown = true;
|
||||
|
|
|
@ -19,11 +19,15 @@ protected:
|
|||
int intval;
|
||||
bool boolval;
|
||||
std::string stringval;
|
||||
const char* charstrval;
|
||||
char charstrval[16];
|
||||
CTransactionRef txval;
|
||||
public:
|
||||
CSerializeMethodsTestSingle() = default;
|
||||
CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, CTransaction txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), charstrval(charstrvalin), txval(MakeTransactionRef(txvalin)){}
|
||||
CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, CTransaction txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), txval(MakeTransactionRef(txvalin))
|
||||
{
|
||||
memcpy(charstrval, charstrvalin, sizeof(charstrval));
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
|
@ -31,7 +35,7 @@ public:
|
|||
READWRITE(intval);
|
||||
READWRITE(boolval);
|
||||
READWRITE(stringval);
|
||||
READWRITE(FLATDATA(charstrval));
|
||||
READWRITE(charstrval);
|
||||
READWRITE(txval);
|
||||
}
|
||||
|
||||
|
@ -53,7 +57,7 @@ public:
|
|||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(intval, boolval, stringval, FLATDATA(charstrval), txval);
|
||||
READWRITE(intval, boolval, stringval, charstrval, txval);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -344,7 +348,7 @@ BOOST_AUTO_TEST_CASE(class_methods)
|
|||
int intval(100);
|
||||
bool boolval(true);
|
||||
std::string stringval("testing");
|
||||
const char* charstrval("testing charstr");
|
||||
const char charstrval[16] = "testing charstr";
|
||||
CMutableTransaction txval;
|
||||
CSerializeMethodsTestSingle methodtest1(intval, boolval, stringval, charstrval, txval);
|
||||
CSerializeMethodsTestMany methodtest2(intval, boolval, stringval, charstrval, txval);
|
||||
|
@ -360,7 +364,7 @@ BOOST_AUTO_TEST_CASE(class_methods)
|
|||
BOOST_CHECK(methodtest2 == methodtest3);
|
||||
BOOST_CHECK(methodtest3 == methodtest4);
|
||||
|
||||
CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, FLATDATA(charstrval), txval);
|
||||
CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, charstrval, txval);
|
||||
ss2 >> methodtest3;
|
||||
BOOST_CHECK(methodtest3 == methodtest4);
|
||||
}
|
||||
|
|
|
@ -57,16 +57,16 @@ BOOST_AUTO_TEST_CASE(streams_vector_writer)
|
|||
BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
|
||||
vch.clear();
|
||||
|
||||
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, FLATDATA(bytes));
|
||||
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
|
||||
BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
|
||||
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, FLATDATA(bytes));
|
||||
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
|
||||
BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
|
||||
vch.clear();
|
||||
|
||||
vch.resize(4, 8);
|
||||
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, FLATDATA(bytes), b);
|
||||
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
|
||||
BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
|
||||
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, FLATDATA(bytes), b);
|
||||
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
|
||||
BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
|
||||
vch.clear();
|
||||
}
|
||||
|
|
|
@ -1078,7 +1078,7 @@ static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMes
|
|||
|
||||
// Write index header
|
||||
unsigned int nSize = GetSerializeSize(fileout, block);
|
||||
fileout << FLATDATA(messageStart) << nSize;
|
||||
fileout << messageStart << nSize;
|
||||
|
||||
// Write block
|
||||
long fileOutPos = ftell(fileout.Get());
|
||||
|
@ -1442,7 +1442,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint
|
|||
|
||||
// Write index header
|
||||
unsigned int nSize = GetSerializeSize(fileout, blockundo);
|
||||
fileout << FLATDATA(messageStart) << nSize;
|
||||
fileout << messageStart << nSize;
|
||||
|
||||
// Write undo data
|
||||
long fileOutPos = ftell(fileout.Get());
|
||||
|
@ -4284,7 +4284,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
|
|||
unsigned char buf[CMessageHeader::MESSAGE_START_SIZE];
|
||||
blkdat.FindByte(chainparams.MessageStart()[0]);
|
||||
nRewind = blkdat.GetPos()+1;
|
||||
blkdat >> FLATDATA(buf);
|
||||
blkdat >> buf;
|
||||
if (memcmp(buf, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE))
|
||||
continue;
|
||||
// read size
|
||||
|
|
Loading…
Add table
Reference in a new issue