mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-09 19:37:27 -03:00
Allow CScript's operator<< to accept spans, not just vectors
Extracted existing serialization to append size & data in separate private methods to clarify that it does more than just a simple data insertion. * the C style casts were changed to static_cast * `unsigned char` and `uint8_t` were changed to value_type for forward compatibility * `data + sizeof(data)` was changed to `std::cend` * data insertion (in AppendData) relies on pointer arithmetic now to enable both `std::span<const value_type>` and `std::span<const std::byte>` operators * use uint32_t for data size instead of size_t * used span instead of raw pointers in the new methods Co-authored-by: Ryan Ofsky <ryan@ofsky.org> Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com>
This commit is contained in:
parent
c78d8ff4cb
commit
cac846c2fb
1 changed files with 36 additions and 25 deletions
|
@ -17,6 +17,7 @@
|
|||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <span>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
@ -412,6 +413,32 @@ bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator en
|
|||
/** Serialized script, used inside transaction inputs and outputs */
|
||||
class CScript : public CScriptBase
|
||||
{
|
||||
private:
|
||||
inline void AppendDataSize(const uint32_t size)
|
||||
{
|
||||
if (size < OP_PUSHDATA1) {
|
||||
insert(end(), static_cast<value_type>(size));
|
||||
} else if (size <= 0xff) {
|
||||
insert(end(), OP_PUSHDATA1);
|
||||
insert(end(), static_cast<value_type>(size));
|
||||
} else if (size <= 0xffff) {
|
||||
insert(end(), OP_PUSHDATA2);
|
||||
value_type data[2];
|
||||
WriteLE16(data, size);
|
||||
insert(end(), std::cbegin(data), std::cend(data));
|
||||
} else {
|
||||
insert(end(), OP_PUSHDATA4);
|
||||
value_type data[4];
|
||||
WriteLE32(data, size);
|
||||
insert(end(), std::cbegin(data), std::cend(data));
|
||||
}
|
||||
}
|
||||
|
||||
void AppendData(std::span<const value_type> data)
|
||||
{
|
||||
insert(end(), data.begin(), data.end());
|
||||
}
|
||||
|
||||
protected:
|
||||
CScript& push_int64(int64_t n)
|
||||
{
|
||||
|
@ -463,35 +490,19 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
CScript& operator<<(const std::vector<unsigned char>& b) LIFETIMEBOUND
|
||||
CScript& operator<<(std::span<const std::byte> b) LIFETIMEBOUND
|
||||
{
|
||||
if (b.size() < OP_PUSHDATA1)
|
||||
{
|
||||
insert(end(), (unsigned char)b.size());
|
||||
}
|
||||
else if (b.size() <= 0xff)
|
||||
{
|
||||
insert(end(), OP_PUSHDATA1);
|
||||
insert(end(), (unsigned char)b.size());
|
||||
}
|
||||
else if (b.size() <= 0xffff)
|
||||
{
|
||||
insert(end(), OP_PUSHDATA2);
|
||||
uint8_t _data[2];
|
||||
WriteLE16(_data, b.size());
|
||||
insert(end(), _data, _data + sizeof(_data));
|
||||
}
|
||||
else
|
||||
{
|
||||
insert(end(), OP_PUSHDATA4);
|
||||
uint8_t _data[4];
|
||||
WriteLE32(_data, b.size());
|
||||
insert(end(), _data, _data + sizeof(_data));
|
||||
}
|
||||
insert(end(), b.begin(), b.end());
|
||||
AppendDataSize(b.size());
|
||||
AppendData({reinterpret_cast<const value_type*>(b.data()), b.size()});
|
||||
return *this;
|
||||
}
|
||||
|
||||
// For compatibility reasons. In new code, prefer using std::byte instead of uint8_t.
|
||||
CScript& operator<<(std::span<const value_type> b) LIFETIMEBOUND
|
||||
{
|
||||
return *this << std::as_bytes(b);
|
||||
}
|
||||
|
||||
bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const
|
||||
{
|
||||
return GetScriptOp(pc, end(), opcodeRet, &vchRet);
|
||||
|
|
Loading…
Reference in a new issue