Browse Source

All tests passed for 2-way RLP.

cl-refactor
Gav Wood 11 years ago
parent
commit
29ce98f7c9
  1. 59
      RLP.h
  2. 67
      main.cpp

59
RLP.h

@ -25,6 +25,9 @@ public:
/// Construct a node of value given in the bytes.
explicit RLP(fConstBytes _d): m_data(_d) {}
/// Construct a node of value given in the bytes.
explicit RLP(bytes const& _d): m_data(const_cast<bytes*>(&_d)) {} // a bit horrible, but we know we won't be altering the data. TODO: allow vector<T> const* to be passed to foreign<T const>.
/// Construct a node to read RLP data in the bytes given.
RLP(byte const* _b, uint _s): m_data(fConstBytes(_b, _s)) {}
@ -64,6 +67,26 @@ public:
/// @returns the number of characters in the string, or zero if it isn't a string.
uint stringSize() const { return isString() ? items() : 0; }
bool operator==(char const* _s) const { return isString() && toString() == _s; }
bool operator==(std::string const& _s) const { return isString() && toString() == _s; }
bool operator==(uint const& _i) const { return toSlimInt() == _i; }
bool operator==(u256 const& _i) const { return toFatInt() == _i; }
bool operator==(bigint const& _i) const { return toBigInt() == _i; }
RLP operator[](uint _i) const
{
if (!isList() || itemCount() <= _i)
return RLP();
fConstBytes d = payload();
for (uint64_t i = 0; i < _i; ++i, d = d.cropped(RLP(d).size())) {}
return RLP(d);
}
explicit operator std::string() const { return toString(); }
explicit operator RLPs() const { return toList(); }
explicit operator uint() const { return toSlimInt(); }
explicit operator u256() const { return toFatInt(); }
explicit operator bigint() const { return toBigInt(); }
std::string toString() const
{
if (!isString())
@ -78,9 +101,10 @@ public:
if (isDirectValueInt())
return m_data[0];
_T ret = 0;
auto s = intSize();
auto s = intSize() - intLengthSize();
uint o = intLengthSize() + 1;
for (uint i = 0; i < s; ++i)
ret = (ret << 8) | m_data[i + 1];
ret = (ret << 8) | m_data[i + o];
return ret;
}
@ -174,7 +198,7 @@ public:
else
pushCount(_s.size(), 0x40);
uint os = m_out.size();
m_out.resize(m_out.size() + _s.size());
m_out.resize(os + _s.size());
memcpy(m_out.data() + os, _s.data(), _s.size());
}
@ -189,10 +213,12 @@ public:
RLPStream operator<<(uint _i) { append(_i); return *this; }
RLPStream operator<<(u256 _i) { append(_i); return *this; }
RLPStream operator<<(bigint _i) { append(_i); return *this; }
RLPStream operator<<(char const* _s) { append(std::string(_s)); return *this; }
RLPStream operator<<(std::string const& _s) { append(_s); return *this; }
RLPStream operator<<(RLPList _l) { appendList(_l.count); return *this; }
bytes const& out() const { return m_out; }
std::string str() const { return std::string((char const*)m_out.data(), (char const*)(m_out.data() + m_out.size())); }
private:
void appendNumeric(uint _i)
@ -203,8 +229,7 @@ private:
{
auto br = bytesRequired(_i);
m_out.push_back(br + 0x17); // max 8 bytes.
for (int i = br - 1; i >= 0; --i)
m_out.push_back((_i >> i) & 0xff);
pushInt(_i, br);
}
}
@ -216,8 +241,7 @@ private:
{
auto br = bytesRequired(_i);
m_out.push_back(br + 0x17); // max 8 bytes.
for (int i = br - 1; i >= 0; --i)
m_out.push_back((byte)(_i >> i));
pushInt(_i, br);
}
}
@ -234,20 +258,25 @@ private:
{
auto brbr = bytesRequired(br);
m_out.push_back(0x37 + brbr);
for (int i = brbr - 1; i >= 0; --i)
m_out.push_back((br >> i) & 0xff);
}
for (uint i = 0; i < br; ++i)
{
bigint u = (_i >> (br - 1 - i));
m_out.push_back((uint)u);
pushInt(br, brbr);
}
pushInt(_i, br);
}
}
template <class _T> void pushInt(_T _i, uint _br)
{
m_out.resize(m_out.size() + _br);
byte* b = &m_out.back();
for (; _i; _i >>= 8)
*(b--) = (byte)_i;
}
void pushCount(uint _count, byte _base)
{
m_out.push_back(bytesRequired(_count) + 0x37 + _base); // max 8 bytes.
auto br = bytesRequired(_count);
m_out.push_back(br + 0x37 + _base); // max 8 bytes.
pushInt(_count, br);
}
template <class _T> static uint bytesRequired(_T _i)

67
main.cpp

@ -12,35 +12,74 @@ std::string asHex(std::string const& _data)
return ret.str();
}
std::string asHex(bytes const& _data)
{
std::ostringstream ret;
for (auto i: _data)
ret << hex << setfill('0') << setw(2) << (int)i;
return ret.str();
}
template <class _T> void rlpListAux(RLPStream& _out, _T _t)
{
_out << _t;
}
template <class _T, class ... _Ts> void rlpListAux(RLPStream& _out, _T _t, _Ts ... _ts)
{
_out << _t;
rlpListAux(_out, _ts...);
}
template <class _T> std::string rlp(_T _t)
{
RLPStream out;
out << _t;
return out.str();
}
template <class ... _Ts> std::string rlpList(_Ts ... _ts)
{
RLPStream out;
out << RLPList(sizeof ...(_Ts));
rlpListAux(out, _ts...);
return out.str();
}
int main()
{
// int of value 15
assert(toString(RLP("\x0f")) == "15");
// 2-item list
assert(toString(RLP("\x43""dog")) == "\"dog\"");
assert(RLP("\x0f") == 15);
assert(rlp(15) == "\x0f");
// 3-character string
assert(toString(RLP("\x82\x0f\x43""dog")) == "[ 15, \"dog\" ]");
assert(RLP("\x43""dog") == "dog");
assert(rlp("dog") == "\x43""dog");
// 2-item list
RLP twoItemList("\x82\x0f\x43""dog");
assert(twoItemList.itemCount() == 2 && twoItemList[0] == 15 && twoItemList[1] == "dog");
assert(rlpList(15, "dog") == "\x82\x0f\x43""dog");
// 1-byte (8-bit) int
assert(toString(RLP("\x18\x45")) == "69");
assert(RLP("\x18\x45") == 69);
assert(rlp(69) == "\x18\x45");
// 2-byte (16-bit) int
assert(toString(RLP("\x19\x01\x01")) == "257");
assert(RLP("\x19\x01\x01") == 257);
assert(rlp(257) == "\x19\x01\x01");
// 32-byte (256-bit) int
ostringstream o1;
o1 << hex << RLP("\x37\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f");
assert(o1.str() == "100102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
assert(RLP("\x37\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f") == bigint("0x100102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
assert(rlp(bigint("0x100102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")) == "\x37\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f");
// 33-byte (264-bit) int
ostringstream o2;
o2 << hex << RLP("\x38\x21\x20\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f");
assert(o2.str() == "2120100102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
assert(RLP("\x38\x21\x20\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f") == bigint("0x20100102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"));
assert(rlp(bigint("0x20100102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")) == "\x38\x21\x20\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f");
// 56-character string.
assert(toString(RLP("\x78\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit")) == "\"Lorem ipsum dolor sit amet, consectetur adipisicing elit\"");
assert(RLP("\x78\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit") == "Lorem ipsum dolor sit amet, consectetur adipisicing elit");
assert(rlp("Lorem ipsum dolor sit amet, consectetur adipisicing elit") == "\x78\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit");
/*
* Hex-prefix Notation. First nibble has flags: oddness = 2^0 & termination = 2^1

Loading…
Cancel
Save