mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
Merge #12886: Introduce Span type and use it instead of FLATDATA
9272d70
Support serializing Span<unsigned char> and use that instead of FLATDATA (Pieter Wuille)833bc08
Add Slice: a (pointer, size) array view that acts like a container (Pieter Wuille) Pull request description: Introduce a new data type `Span`, which is an encapsulated pointer + size (like C++20's `std::span` or LevelDB's `Slice`), and represents a view to a sequence of objects laid out continuously in memory. The immediate use case is replacing the remaining `FLATDATA` invocations. Instead of those, we support serializing/deserializing unsigned char `Span`s (treating them as arrays). A longer term goal for `Span`s is making the script execution operate on them rather than on `CScript` itself. This will allow separate storage mechanisms for scripts. Tree-SHA512: 7b0da3c802e5df367f223275004d16b04262804c007b7c73fda927176f0a9c3b2ef3225fa842cb73500b0df73175ec1419f1f5239de2402e21dd9ae8e5d05233
This commit is contained in:
parent
ec71097801
commit
4bb1132438
@ -509,6 +509,7 @@ libdash_consensus_a_SOURCES = \
|
||||
script/script_error.cpp \
|
||||
script/script_error.h \
|
||||
serialize.h \
|
||||
span.h \
|
||||
streams.h \
|
||||
tinyformat.h \
|
||||
uint256.cpp \
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <primitives/transaction.h>
|
||||
#include <script/script.h>
|
||||
#include <serialize.h>
|
||||
#include <span.h>
|
||||
|
||||
class CKeyID;
|
||||
class CPubKey;
|
||||
@ -59,12 +60,12 @@ public:
|
||||
void Serialize(Stream &s) const {
|
||||
std::vector<unsigned char> compr;
|
||||
if (Compress(compr)) {
|
||||
s << CFlatData(compr);
|
||||
s << MakeSpan(compr);
|
||||
return;
|
||||
}
|
||||
unsigned int nSize = script.size() + nSpecialScripts;
|
||||
s << VARINT(nSize);
|
||||
s << CFlatData(script);
|
||||
s << MakeSpan(script);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
@ -73,7 +74,7 @@ public:
|
||||
s >> VARINT(nSize);
|
||||
if (nSize < nSpecialScripts) {
|
||||
std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
|
||||
s >> CFlatData(vch);
|
||||
s >> MakeSpan(vch);
|
||||
Decompress(nSize, vch);
|
||||
return;
|
||||
}
|
||||
@ -84,7 +85,7 @@ public:
|
||||
s.ignore(nSize);
|
||||
} else {
|
||||
script.resize(nSize);
|
||||
s >> CFlatData(script);
|
||||
s >> MakeSpan(script);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <compat.h>
|
||||
#include <serialize.h>
|
||||
#include <span.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
@ -171,10 +172,13 @@ class CService : public CNetAddr
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(ip);
|
||||
|
||||
// TODO: introduce native support for BE serialization in serialize.h
|
||||
unsigned short portN = htons(port);
|
||||
READWRITE(FLATDATA(portN));
|
||||
if (ser_action.ForRead())
|
||||
READWRITE(Span<unsigned char>((unsigned char*)&portN, 2));
|
||||
if (ser_action.ForRead()) {
|
||||
port = ntohs(portN);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <prevector.h>
|
||||
#include <span.h>
|
||||
|
||||
static const unsigned int MAX_SIZE = 0x02000000;
|
||||
|
||||
@ -44,7 +45,7 @@ constexpr deserialize_type deserialize {};
|
||||
|
||||
/**
|
||||
* Used to bypass the rule against non-const reference to temporary
|
||||
* where it makes sense with wrappers such as CFlatData or CTxDB
|
||||
* where it makes sense with wrappers.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T& REF(const T& val)
|
||||
@ -206,6 +207,8 @@ template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_wri
|
||||
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 Serialize(Stream& s, const Span<const unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
|
||||
template<typename Stream> inline void Serialize(Stream& s, const Span<unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
|
||||
|
||||
#ifndef CHAR_EQUALS_INT8
|
||||
template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
|
||||
@ -222,6 +225,7 @@ template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a =
|
||||
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 Unserialize(Stream& s, Span<unsigned char>& span) { s.read(CharCast(span.data()), span.size()); }
|
||||
|
||||
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; }
|
||||
@ -385,7 +389,6 @@ I ReadVarInt(Stream& is)
|
||||
}
|
||||
}
|
||||
|
||||
#define FLATDATA(obj) CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))
|
||||
#define FIXEDBITSET(obj, size) CFixedBitSet(REF(obj), (size))
|
||||
#define DYNBITSET(obj) CDynamicBitSet(REF(obj))
|
||||
#define FIXEDVARINTSBITSET(obj, size) CFixedVarIntsBitSet(REF(obj), (size))
|
||||
@ -394,46 +397,6 @@ I ReadVarInt(Stream& is)
|
||||
#define COMPACTSIZE(obj) CCompactSize(REF(obj))
|
||||
#define LIMITED_STRING(obj,n) LimitedString< n >(REF(obj))
|
||||
|
||||
/**
|
||||
* Wrapper for serializing arrays and POD.
|
||||
*/
|
||||
class CFlatData
|
||||
{
|
||||
protected:
|
||||
char* pbegin;
|
||||
char* pend;
|
||||
public:
|
||||
CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
|
||||
template <class T, class TAl>
|
||||
explicit CFlatData(std::vector<T,TAl> &v)
|
||||
{
|
||||
pbegin = (char*)v.data();
|
||||
pend = (char*)(v.data() + v.size());
|
||||
}
|
||||
template <unsigned int N, typename T, typename S, typename D>
|
||||
explicit CFlatData(prevector<N, T, S, D> &v)
|
||||
{
|
||||
pbegin = (char*)v.data();
|
||||
pend = (char*)(v.data() + v.size());
|
||||
}
|
||||
char* begin() { return pbegin; }
|
||||
const char* begin() const { return pbegin; }
|
||||
char* end() { return pend; }
|
||||
const char* end() const { return pend; }
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const
|
||||
{
|
||||
s.write(pbegin, pend - pbegin);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s)
|
||||
{
|
||||
s.read(pbegin, pend - pbegin);
|
||||
}
|
||||
};
|
||||
|
||||
class CFixedBitSet
|
||||
{
|
||||
protected:
|
||||
|
40
src/span.h
Normal file
40
src/span.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_SPAN_H
|
||||
#define BITCOIN_SPAN_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
|
||||
/** A Span is an object that can refer to a contiguous sequence of objects.
|
||||
*
|
||||
* It implements a subset of C++20's std::span.
|
||||
*/
|
||||
template<typename C>
|
||||
class Span
|
||||
{
|
||||
C* m_data;
|
||||
std::ptrdiff_t m_size;
|
||||
|
||||
public:
|
||||
constexpr Span() noexcept : m_data(nullptr), m_size(0) {}
|
||||
constexpr Span(C* data, std::ptrdiff_t size) noexcept : m_data(data), m_size(size) {}
|
||||
|
||||
constexpr C* data() const noexcept { return m_data; }
|
||||
constexpr std::ptrdiff_t size() const noexcept { return m_size; }
|
||||
};
|
||||
|
||||
/** Create a span to a container exposing data() and size().
|
||||
*
|
||||
* This correctly deals with constness: the returned Span's element type will be
|
||||
* whatever data() returns a pointer to. If either the passed container is const,
|
||||
* or its element type is const, the resulting span will have a const element type.
|
||||
*
|
||||
* std::span will have a constructor that implements this functionality directly.
|
||||
*/
|
||||
template<typename V>
|
||||
constexpr Span<typename std::remove_pointer<decltype(std::declval<V>().data())>::type> MakeSpan(V& v) { return Span<typename std::remove_pointer<decltype(std::declval<V>().data())>::type>(v.data(), v.size()); }
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user