40 using RLPs = std::vector<RLP>;
47 static const byte c_rlpMaxLengthBytes = 8;
48 static const byte c_rlpDataImmLenStart = 0x80;
49 static const byte c_rlpListStart = 0xc0;
51 static const byte c_rlpDataImmLenCount = c_rlpListStart - c_rlpDataImmLenStart - c_rlpMaxLengthBytes;
52 static const byte c_rlpDataIndLenZero = c_rlpDataImmLenStart + c_rlpDataImmLenCount - 1;
53 static const byte c_rlpListImmLenCount = 256 - c_rlpListStart - c_rlpMaxLengthBytes;
54 static const byte c_rlpListIndLenZero = c_rlpListStart + c_rlpListImmLenCount - 1;
56 template <
class T>
struct Converter {
static T convert(
RLP const&,
int) { BOOST_THROW_EXCEPTION(BadCast()); } };
74 Strict = ThrowOnFail | FailIfTooBig,
75 VeryStrict = ThrowOnFail | FailIfTooBig | FailIfTooSmall,
76 LaissezFaire = AllowNonCanon
100 explicit operator bool()
const {
return !isNull(); }
103 bool isNull()
const {
return m_data.size() == 0; }
106 bool isEmpty()
const {
return !isNull() && (m_data[0] == c_rlpDataImmLenStart || m_data[0] == c_rlpListStart); }
109 bool isData()
const {
return !isNull() && m_data[0] < c_rlpListStart; }
112 bool isList()
const {
return !isNull() && m_data[0] >= c_rlpListStart; }
118 size_t itemCount()
const {
return isList() ? items() : 0; }
119 size_t itemCountStrict()
const {
if (!isList()) BOOST_THROW_EXCEPTION(BadCast());
return items(); }
122 size_t size()
const {
return isData() ? length() : 0; }
123 size_t sizeStrict()
const {
if (!isData()) BOOST_THROW_EXCEPTION(BadCast());
return length(); }
132 bool operator==(
unsigned const& _i)
const {
return isInt() && toInt<unsigned>() == _i; }
133 bool operator!=(
unsigned const& _i)
const {
return isInt() && toInt<unsigned>() != _i; }
142 RLP operator[](
size_t _i)
const;
165 size_t m_remaining = 0;
175 template <
class T>
inline T convert(
int _flags)
const;
178 explicit operator std::string()
const {
return toString(); }
179 explicit operator bytes()
const {
return toBytes(); }
180 explicit operator RLPs()
const {
return toList(); }
181 explicit operator uint8_t()
const {
return toInt<uint8_t>(); }
182 explicit operator uint16_t()
const {
return toInt<uint16_t>(); }
183 explicit operator uint32_t()
const {
return toInt<uint32_t>(); }
184 explicit operator uint64_t()
const {
return toInt<uint64_t>(); }
185 explicit operator u160()
const {
return toInt<u160>(); }
186 explicit operator u256()
const {
return toInt<u256>(); }
187 explicit operator bigint()
const {
return toInt<bigint>(); }
188 template <
unsigned N>
explicit operator FixedHash<N>()
const {
return toHash<FixedHash<N>>(); }
189 template <
class T,
class U>
explicit operator std::pair<T, U>()
const {
return toPair<T, U>(); }
190 template <
class T>
explicit operator std::vector<T>()
const {
return toVector<T>(); }
191 template <
class T>
explicit operator std::set<T>()
const {
return toSet<T>(); }
192 template <
class T,
size_t N>
explicit operator std::array<T, N>()
const {
return toArray<T, N>(); }
195 bytes toBytes(
int _flags = LaissezFaire)
const {
if (!isData()) {
if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast());
else return bytes(); }
return bytes(payload().
data(), payload().
data() + length()); }
199 std::string
toString(
int _flags = LaissezFaire)
const {
if (!isData()) {
if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast());
else return std::string(); }
return payload().cropped(0, length()).toString(); }
204 std::vector<T>
toVector(
int _flags = LaissezFaire)
const 209 ret.reserve(itemCount());
210 for (
auto const& i: *
this)
211 ret.push_back(i.convert<
T>(_flags));
213 else if (_flags & ThrowOnFail)
214 BOOST_THROW_EXCEPTION(BadCast());
219 std::set<T>
toSet(
int _flags = LaissezFaire)
const 223 for (
auto const& i: *
this)
224 ret.insert(i.convert<
T>(_flags));
225 else if (_flags & ThrowOnFail)
226 BOOST_THROW_EXCEPTION(BadCast());
233 std::unordered_set<T> ret;
235 for (
auto const& i: *
this)
236 ret.insert(i.convert<
T>(_flags));
237 else if (_flags & ThrowOnFail)
238 BOOST_THROW_EXCEPTION(BadCast());
242 template <
class T,
class U>
243 std::pair<T, U>
toPair(
int _flags = Strict)
const 246 if (itemCountStrict() != 2)
248 if (_flags & ThrowOnFail)
249 BOOST_THROW_EXCEPTION(BadCast());
253 ret.first = (*this)[0].convert<
T>(_flags);
254 ret.second = (*this)[1].convert<U>(_flags);
258 template <
class T,
size_t N>
259 std::array<T, N>
toArray(
int _flags = LaissezFaire)
const 261 if (itemCountStrict() != N)
263 if (_flags & ThrowOnFail)
264 BOOST_THROW_EXCEPTION(BadCast());
266 return std::array<T, N>();
268 std::array<T, N> ret;
269 for (
size_t i = 0; i < N; ++i)
270 ret[i] =
operator[](i).convert<
T>(_flags);
275 template <
class _T =
unsigned> _T
toInt(
int _flags = Strict)
const 278 if ((!isInt() && !(_flags & AllowNonCanon)) || isList() || isNull())
280 if (_flags & ThrowOnFail)
281 BOOST_THROW_EXCEPTION(BadCast());
289 if (_flags & ThrowOnFail)
290 BOOST_THROW_EXCEPTION(BadCast());
295 return fromBigEndian<_T>(p);
298 template <
class _N> _N
toHash(
int _flags = Strict)
const 303 if (!isData() || (l >
_N::size && (_flags & FailIfTooBig)) || (l <
_N::size && (_flags & FailIfTooSmall)))
305 if (_flags & ThrowOnFail)
306 BOOST_THROW_EXCEPTION(BadCast());
312 size_t s = std::min<size_t>(
_N::size, l);
313 memcpy(ret.data() + _N::size - s, p.data(), s);
318 RLPs toList(
int _flags = Strict)
const;
321 bytesConstRef payload()
const {
auto l = length();
if (l > m_data.size()) BOOST_THROW_EXCEPTION(BadRLP());
return m_data.cropped(payloadOffset(), l); }
325 size_t actualSize()
const;
332 void requireGood()
const;
335 bool isSingleByte()
const {
return !isNull() && m_data[0] < c_rlpDataImmLenStart; }
338 unsigned lengthSize()
const {
if (isData() && m_data[0] > c_rlpDataIndLenZero)
return m_data[0] - c_rlpDataIndLenZero;
if (isList() && m_data[0] > c_rlpListIndLenZero)
return m_data[0] - c_rlpListIndLenZero;
return 0; }
341 size_t length()
const;
344 size_t payloadOffset()
const {
return isSingleByte() ? 0 : (1 + lengthSize()); }
347 size_t items()
const;
356 mutable size_t m_lastIndex = (size_t)-1;
357 mutable size_t m_lastEnd = 0;
365 template <>
struct Converter<uint16_t> {
static uint16_t
convert(
RLP const& _r,
int _flags) {
return _r.
toInt<uint16_t>(_flags); } };
366 template <>
struct Converter<uint32_t> {
static uint32_t
convert(
RLP const& _r,
int _flags) {
return _r.
toInt<uint32_t>(_flags); } };
367 template <>
struct Converter<uint64_t> {
static uint64_t
convert(
RLP const& _r,
int _flags) {
return _r.
toInt<uint64_t>(_flags); } };
372 template <
class T,
class U>
struct Converter<
std::pair<T, U>> {
static std::pair<T, U>
convert(
RLP const& _r,
int _flags) {
return _r.
toPair<
T, U>(_flags); } };
376 template <
class T,
size_t N>
struct Converter<
std::array<T, N>> {
static std::array<T, N>
convert(
RLP const& _r,
int _flags) {
return _r.
toArray<
T, N>(_flags); } };
390 explicit RLPStream(
size_t _listItems) { appendList(_listItems); }
409 template <
class _T>
RLPStream&
append(std::vector<_T>
const& _s) {
return appendVector(_s); }
410 template <
class _T>
RLPStream&
appendVector(std::vector<_T>
const& _s) { appendList(_s.size());
for (
auto const& i: _s) append(i);
return *
this; }
411 template <
class _T,
size_t S>
RLPStream&
append(std::array<_T, S>
const& _s) { appendList(_s.size());
for (
auto const& i: _s)
append(i);
return *
this; }
412 template <
class _T>
RLPStream&
append(std::set<_T>
const& _s) { appendList(_s.size());
for (
auto const& i: _s)
append(i);
return *
this; }
413 template <
class _T>
RLPStream&
append(std::unordered_set<_T>
const& _s) { appendList(_s.size());
for (
auto const& i: _s)
append(i);
return *
this; }
430 void clear() { m_out.clear(); m_listStack.clear(); }
442 void noteAppended(
size_t _itemCount = 1);
446 void pushCount(
size_t _count,
byte _offset);
449 template <
class _T>
void pushInt(_T _i,
size_t _br)
451 m_out.resize(m_out.size() + _br);
452 byte*
b = &m_out.back();
std::vector< std::pair< size_t, size_t > > m_listStack
bool operator!=(u256 const &_i) const
RLPStream & append(std::array< _T, S > const &_s)
RLPStream & append(std::string const &_s)
bool operator!=(unsigned const &_i) const
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
std::array< T, N > toArray(int _flags=LaissezFaire) const
std::set< T > toSet(int _flags=LaissezFaire) const
RLP(std::string const &_s, Strictness _st=VeryStrict)
Construct a node to read RLP data in the string.
static std::array< T, N > convert(RLP const &_r, int _flags)
bool isNull() const
No value.
static uint64_t convert(RLP const &_r, int _flags)
void swap(dev::eth::Watch &_a, dev::eth::Watch &_b)
bool isList() const
List value.
static u256 convert(RLP const &_r, int _flags)
static uint8_t convert(RLP const &_r, int _flags)
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
bytesConstRef data() const
The bare data of the RLP.
RLPStream & append(char const *_s)
bool operator!=(FixedHash< _N > const &_s) const
std::vector< T > toVector(int _flags=LaissezFaire) const
RLPStream & append(unsigned _s)
Append given datum to the byte stream.
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<>> bigint
bytes const & out() const
Read the byte stream.
static bigint convert(RLP const &_r, int _flags)
bytes m_out
Our output byte stream.
std::pair< T, U > toPair(int _flags=Strict) const
static bytes convert(RLP const &_r, int _flags)
static std::string convert(RLP const &_r, int _flags)
static FixedHash< N > convert(RLP const &_r, int _flags)
std::hash for asio::adress
std::string toString(string32 const &_s)
Make normal string from fixed-length string.
bool isData() const
String value.
RLP()
Construct a null node.
std::string toStringStrict() const
Converts to string.
static uint32_t convert(RLP const &_r, int _flags)
RLPStream & operator<<(T _data)
Shift operators for appending data items.
bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
bool operator==(unsigned const &_i) const
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 160, 160, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u160
static size_t sizeAsEncoded(bytesConstRef _data)
RLPStream & append(std::unordered_set< _T > const &_s)
bytesConstRef m_currentItem
RLPStream & appendList(RLPStream const &_s)
bytes RLPNull
The empty string in RLP format.
RLPStream & appendVector(std::vector< _T > const &_s)
RLPStream & append(std::set< _T > const &_s)
T convert(int _flags) const
RLPStream & append(RLP const &_rlp, size_t _itemCount=1)
Appends an arbitrary RLP fragment - this must be a single item unless _itemCount is given...
RLPStream & append(u160 _s)
unsigned lengthSize() const
_N toHash(int _flags=Strict) const
static std::pair< T, U > convert(RLP const &_r, int _flags)
bool operator!=(char const *_s) const
size_t itemCountStrict() const
bool operator==(u256 const &_i) const
bool operator==(char const *_s) const
Equality operators; does best-effort conversion and checks for equality.
bool operator==(FixedHash< _N > const &_h) const
bytesConstRef payload() const
std::vector< byte > bytes
RLPStream(size_t _listItems)
Initializes the RLPStream as a list of _listItems items.
vector_ref< byte const > bytesConstRef
bytes && invalidate()
Invalidate the object and steal the output byte stream.
static u160 convert(RLP const &_r, int _flags)
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
std::unordered_set< T > toUnorderedSet(int _flags=LaissezFaire) const
RLPStream & appendList(bytes const &_rlp)
RLPStream & appendRaw(bytes const &_rlp, size_t _itemCount=1)
static RLPs convert(RLP const &_r, int _flags)
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
bytesConstRef m_data
Our byte data.
bool operator==(iterator const &_cmp) const
RLPStream & append(u256 _s)
RLPs toList(int _flags=Strict) const
Converts to RLPs collection object. Useful if you need random access to sub items or will iterate ove...
bytes rlpList()
Export a list of items in RLP format, returning a byte array.
std::ostream & operator<<(std::ostream &_out, bytes const &_e)
bool operator==(bigint const &_i) const
bool operator==(std::string const &_s) const
void clear()
Clear the output stream so far.
RLPStream & append(std::vector< _T > const &_s)
Appends a sequence of data to the stream as a list.
size_t sizeStrict() const
static const unsigned maxSize
uint8_t const size_t const size
bool isSingleByte() const
Single-byte data payload.
RLPStream & append(FixedHash< N > _s, bool _compact=false, bool _allOrNothing=false)
void * memcpy(void *a, const void *b, size_t c)
Base class for all RLP exceptions.
size_t actualSize() const
bytesConstRef toBytesConstRef(int _flags=LaissezFaire) const
Converts to bytearray.
RLP(bytes const &_d, Strictness _s=VeryStrict)
Construct a node of value given in the bytes.
boost::error_info< struct tag_comment, std::string > errinfo_comment
static std::set< T > convert(RLP const &_r, int _flags)
Iterator class for iterating through items of RLP list.
std::string toString(int _flags=LaissezFaire) const
Converts to string.
RLP(byte const *_b, unsigned _s, Strictness _st=VeryStrict)
Construct a node to read RLP data in the bytes given.
RLP(bytes const &&)
Disable construction from rvalue.
static std::vector< T > convert(RLP const &_r, int _flags)
void pushInt(_T _i, size_t _br)
Push an integer as a raw big-endian byte-stream.
static T convert(RLP const &, int)
bool operator!=(iterator const &_cmp) const
iterator end() const
Iterator into end of sub-item list (valid only if we are a list).
size_t payloadOffset() const
void swapOut(bytes &_dest)
Swap the contents of the output stream out for some other byte array.
static uint16_t convert(RLP const &_r, int _flags)
RLPStream & append(bytes const &_s)
bool operator!=(std::string const &_s) const
iterator begin() const
Iterator into beginning of sub-item list (valid only if we are a list).
bool isEmpty() const
Contains a zero-length string or zero-length list.
RLPStream & append(std::pair< T, U > const &_s)
_T toInt(int _flags=Strict) const
Converts to int of type given; if isString(), decodes as big-endian bytestream.
Class for writing to an RLP bytestream.
RLPStream()
Initializes empty RLPStream.
Class for interpreting Recursive Linear-Prefix Data.
bytes toBytes(int _flags=LaissezFaire) const
Converts to bytearray.
static std::unordered_set< T > convert(RLP const &_r, int _flags)
void rlpListAux(RLPStream &_out, _T _t)
bool operator!=(bigint const &_i) const
bytes RLPEmptyList
The empty list in RLP format.