mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-29 15:35:50 +00:00
STVar: optimized storage for STObject (RIPD-825):
This introduces the STVar container, capable of holding any STBase-derived class and implementing a "small string" optimization. STObject is changed to store std::vector<STVar> instead of boost::ptr_vector<STBase>. This eliminates a significant number of needless dynamic memory allocations and deallocations during transaction processing when ledger entries are deserialized. It comes at the expense of larger overall storage requirements for STObject.
This commit is contained in:
@@ -2940,6 +2940,12 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\protocol\impl\STVar.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ripple\protocol\impl\STVar.h">
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\protocol\impl\STVector256.cpp">
|
<ClCompile Include="..\..\src\ripple\protocol\impl\STVector256.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
|
|||||||
@@ -3471,6 +3471,12 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\protocol\impl\STValidation.cpp">
|
<ClCompile Include="..\..\src\ripple\protocol\impl\STValidation.cpp">
|
||||||
<Filter>ripple\protocol\impl</Filter>
|
<Filter>ripple\protocol\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\protocol\impl\STVar.cpp">
|
||||||
|
<Filter>ripple\protocol\impl</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ripple\protocol\impl\STVar.h">
|
||||||
|
<Filter>ripple\protocol\impl</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\protocol\impl\STVector256.cpp">
|
<ClCompile Include="..\..\src\ripple\protocol\impl\STVector256.cpp">
|
||||||
<Filter>ripple\protocol\impl</Filter>
|
<Filter>ripple\protocol\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -513,22 +513,22 @@ void LedgerEntrySet::calcRawMeta (Serializer& s, TER result, std::uint32_t index
|
|||||||
{
|
{
|
||||||
// go through the original node for modified fields saved on modification
|
// go through the original node for modified fields saved on modification
|
||||||
if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))
|
if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))
|
||||||
prevs.addObject (obj);
|
prevs.emplace_back (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prevs.empty ())
|
if (!prevs.empty ())
|
||||||
mSet.getAffectedNode (it.first).addObject (prevs);
|
mSet.getAffectedNode (it.first).emplace_back (std::move(prevs));
|
||||||
|
|
||||||
STObject finals (sfFinalFields);
|
STObject finals (sfFinalFields);
|
||||||
for (auto const& obj : *curNode)
|
for (auto const& obj : *curNode)
|
||||||
{
|
{
|
||||||
// go through the final node for final fields
|
// go through the final node for final fields
|
||||||
if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_DeleteFinal))
|
if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_DeleteFinal))
|
||||||
finals.addObject (obj);
|
finals.emplace_back (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!finals.empty ())
|
if (!finals.empty ())
|
||||||
mSet.getAffectedNode (it.first).addObject (finals);
|
mSet.getAffectedNode (it.first).emplace_back (std::move(finals));
|
||||||
}
|
}
|
||||||
else if (type == &sfModifiedNode)
|
else if (type == &sfModifiedNode)
|
||||||
{
|
{
|
||||||
@@ -542,22 +542,22 @@ void LedgerEntrySet::calcRawMeta (Serializer& s, TER result, std::uint32_t index
|
|||||||
{
|
{
|
||||||
// search the original node for values saved on modify
|
// search the original node for values saved on modify
|
||||||
if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))
|
if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))
|
||||||
prevs.addObject (obj);
|
prevs.emplace_back (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prevs.empty ())
|
if (!prevs.empty ())
|
||||||
mSet.getAffectedNode (it.first).addObject (prevs);
|
mSet.getAffectedNode (it.first).emplace_back (std::move(prevs));
|
||||||
|
|
||||||
STObject finals (sfFinalFields);
|
STObject finals (sfFinalFields);
|
||||||
for (auto const& obj : *curNode)
|
for (auto const& obj : *curNode)
|
||||||
{
|
{
|
||||||
// search the final node for values saved always
|
// search the final node for values saved always
|
||||||
if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_ChangeNew))
|
if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_ChangeNew))
|
||||||
finals.addObject (obj);
|
finals.emplace_back (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!finals.empty ())
|
if (!finals.empty ())
|
||||||
mSet.getAffectedNode (it.first).addObject (finals);
|
mSet.getAffectedNode (it.first).emplace_back (std::move(finals));
|
||||||
}
|
}
|
||||||
else if (type == &sfCreatedNode) // if created, thread to owner(s)
|
else if (type == &sfCreatedNode) // if created, thread to owner(s)
|
||||||
{
|
{
|
||||||
@@ -572,11 +572,11 @@ void LedgerEntrySet::calcRawMeta (Serializer& s, TER result, std::uint32_t index
|
|||||||
{
|
{
|
||||||
// save non-default values
|
// save non-default values
|
||||||
if (!obj.isDefault () && obj.getFName ().shouldMeta (SField::sMD_Create | SField::sMD_Always))
|
if (!obj.isDefault () && obj.getFName ().shouldMeta (SField::sMD_Create | SField::sMD_Always))
|
||||||
news.addObject (obj);
|
news.emplace_back (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!news.empty ())
|
if (!news.empty ())
|
||||||
mSet.getAffectedNode (it.first).addObject (news);
|
mSet.getAffectedNode (it.first).emplace_back (std::move(news));
|
||||||
}
|
}
|
||||||
else assert (false);
|
else assert (false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,25 +29,22 @@ namespace ripple {
|
|||||||
// VFALCO TODO rename class to TransactionMeta
|
// VFALCO TODO rename class to TransactionMeta
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
TransactionMetaSet::TransactionMetaSet (uint256 const& txid, std::uint32_t ledger, T const& data,
|
TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
|
||||||
CtorHelper) :
|
std::uint32_t ledger, T const& data, CtorHelper)
|
||||||
mTransactionID (txid), mLedger (ledger), mNodes (sfAffectedNodes, 32)
|
: mTransactionID (txid)
|
||||||
|
, mLedger (ledger)
|
||||||
|
, mNodes (sfAffectedNodes, 32)
|
||||||
{
|
{
|
||||||
Serializer s (data);
|
Serializer s (data);
|
||||||
SerialIter sit (s);
|
SerialIter sit (s);
|
||||||
|
|
||||||
std::unique_ptr<STBase> pobj = STObject::deserialize (sit, sfMetadata);
|
STObject obj(sit, sfMetadata);
|
||||||
STObject* obj = static_cast<STObject*> (pobj.get ());
|
mResult = obj.getFieldU8 (sfTransactionResult);
|
||||||
|
mIndex = obj.getFieldU32 (sfTransactionIndex);
|
||||||
|
mNodes = * dynamic_cast<STArray*> (&obj.getField (sfAffectedNodes));
|
||||||
|
|
||||||
if (!obj)
|
if (obj.isFieldPresent (sfDeliveredAmount))
|
||||||
throw std::runtime_error ("bad metadata");
|
setDeliveredAmount (obj.getFieldAmount (sfDeliveredAmount));
|
||||||
|
|
||||||
mResult = obj->getFieldU8 (sfTransactionResult);
|
|
||||||
mIndex = obj->getFieldU32 (sfTransactionIndex);
|
|
||||||
mNodes = * dynamic_cast<STArray*> (&obj->getField (sfAffectedNodes));
|
|
||||||
|
|
||||||
if (obj->isFieldPresent (sfDeliveredAmount))
|
|
||||||
setDeliveredAmount (obj->getFieldAmount (sfDeliveredAmount));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
|
TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
|
||||||
@@ -125,7 +122,7 @@ std::vector<RippleAddress> TransactionMetaSet::getAffectedAccounts ()
|
|||||||
|
|
||||||
if (inner)
|
if (inner)
|
||||||
{
|
{
|
||||||
for (auto const& field : inner->peekData ())
|
for (auto const& field : *inner)
|
||||||
{
|
{
|
||||||
const STAccount* sa = dynamic_cast<const STAccount*> (&field);
|
const STAccount* sa = dynamic_cast<const STAccount*> (&field);
|
||||||
|
|
||||||
@@ -242,7 +239,7 @@ STObject TransactionMetaSet::getAsObject () const
|
|||||||
assert (mResult != 255);
|
assert (mResult != 255);
|
||||||
metaData.setFieldU8 (sfTransactionResult, mResult);
|
metaData.setFieldU8 (sfTransactionResult, mResult);
|
||||||
metaData.setFieldU32 (sfTransactionIndex, mIndex);
|
metaData.setFieldU32 (sfTransactionIndex, mIndex);
|
||||||
metaData.addObject (mNodes);
|
metaData.emplace_back (mNodes);
|
||||||
if (hasDeliveredAmount ())
|
if (hasDeliveredAmount ())
|
||||||
metaData.setFieldAmount (sfDeliveredAmount, getDeliveredAmount ());
|
metaData.setFieldAmount (sfDeliveredAmount, getDeliveredAmount ());
|
||||||
return metaData;
|
return metaData;
|
||||||
|
|||||||
@@ -44,9 +44,19 @@ public:
|
|||||||
{
|
{
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
static std::unique_ptr<STBase> deserialize (SerialIter& sit, SField::ref name)
|
|
||||||
|
STAccount (SerialIter& sit, SField::ref name);
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const override
|
||||||
{
|
{
|
||||||
return std::unique_ptr<STBase> (construct (sit, name));
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializedTypeID getSType () const override
|
SerializedTypeID getSType () const override
|
||||||
@@ -76,12 +86,6 @@ public:
|
|||||||
|
|
||||||
bool isValueH160 () const;
|
bool isValueH160 () const;
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STAccount>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static STAccount* construct (SerialIter&, SField::ref);
|
static STAccount* construct (SerialIter&, SField::ref);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace ripple {
|
|||||||
// Wire form:
|
// Wire form:
|
||||||
// High 8 bits are (offset+142), legal range is, 80 to 22 inclusive
|
// High 8 bits are (offset+142), legal range is, 80 to 22 inclusive
|
||||||
// Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive
|
// Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive
|
||||||
class STAmount final
|
class STAmount
|
||||||
: public STBase
|
: public STBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -73,6 +73,8 @@ public:
|
|||||||
|
|
||||||
struct unchecked { };
|
struct unchecked { };
|
||||||
|
|
||||||
|
STAmount(SerialIter& sit, SField::ref name);
|
||||||
|
|
||||||
// Calls canonicalize
|
// Calls canonicalize
|
||||||
STAmount (SField::ref name, Issue const& issue,
|
STAmount (SField::ref name, Issue const& issue,
|
||||||
mantissa_type mantissa, exponent_type exponent,
|
mantissa_type mantissa, exponent_type exponent,
|
||||||
@@ -104,6 +106,18 @@ public:
|
|||||||
|
|
||||||
STAmount (Issue const& issue, int mantissa, int exponent = 0);
|
STAmount (Issue const& issue, int mantissa, int exponent = 0);
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -119,18 +133,6 @@ public:
|
|||||||
STAmount
|
STAmount
|
||||||
createFromInt64 (SField::ref n, std::int64_t v);
|
createFromInt64 (SField::ref n, std::int64_t v);
|
||||||
|
|
||||||
static
|
|
||||||
std::unique_ptr <STBase>
|
|
||||||
deserialize (
|
|
||||||
SerialIter& sit, SField::ref name)
|
|
||||||
{
|
|
||||||
return construct (sit, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
STAmount
|
|
||||||
deserialize (SerialIter&);
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Observers
|
// Observers
|
||||||
@@ -289,12 +291,6 @@ public:
|
|||||||
return (mValue == 0) && mIsNative;
|
return (mValue == 0) && mIsNative;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STAmount>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void canonicalize();
|
void canonicalize();
|
||||||
void set (std::int64_t v);
|
void set (std::int64_t v);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <ripple/basics/CountedObject.h>
|
#include <ripple/basics/CountedObject.h>
|
||||||
#include <ripple/protocol/STObject.h>
|
#include <ripple/protocol/STObject.h>
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -30,149 +29,94 @@ class STArray final
|
|||||||
: public STBase
|
: public STBase
|
||||||
, public CountedObject <STArray>
|
, public CountedObject <STArray>
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
using list_type = std::vector<STObject>;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
reserveSize = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
list_type v_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Read-only iteration
|
||||||
|
class Items;
|
||||||
|
|
||||||
static char const* getCountedObjectName () { return "STArray"; }
|
static char const* getCountedObjectName () { return "STArray"; }
|
||||||
|
|
||||||
typedef boost::ptr_vector<STObject> vector;
|
using size_type = list_type::size_type;
|
||||||
|
using iterator = list_type::iterator;
|
||||||
|
using const_iterator = list_type::const_iterator;
|
||||||
|
|
||||||
typedef vector::iterator iterator;
|
STArray();
|
||||||
typedef vector::const_iterator const_iterator;
|
STArray (STArray&&);
|
||||||
typedef vector::reverse_iterator reverse_iterator;
|
STArray (STArray const&) = default;
|
||||||
typedef vector::const_reverse_iterator const_reverse_iterator;
|
STArray (SField::ref f, int n);
|
||||||
typedef vector::size_type size_type;
|
STArray (SerialIter& sit, SField::ref f);
|
||||||
|
explicit STArray (int n);
|
||||||
|
explicit STArray (SField::ref f);
|
||||||
|
STArray& operator= (STArray const&) = default;
|
||||||
|
STArray& operator= (STArray&&);
|
||||||
|
|
||||||
public:
|
STBase*
|
||||||
STArray () = default;
|
copy (std::size_t n, void* buf) const override
|
||||||
|
|
||||||
explicit
|
|
||||||
STArray (int n)
|
|
||||||
{
|
{
|
||||||
value.reserve (n);
|
return emplace(n, buf, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit
|
STBase*
|
||||||
STArray (SField::ref f)
|
move (std::size_t n, void* buf) override
|
||||||
: STBase (f)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
STArray (SField::ref f, int n)
|
|
||||||
: STBase (f)
|
|
||||||
{
|
{
|
||||||
value.reserve (n);
|
return emplace(n, buf, std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
STArray (SField::ref f, const vector& v)
|
|
||||||
: STBase (f), value (v)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
explicit
|
|
||||||
STArray (vector & v)
|
|
||||||
: value (v)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual ~STArray () = default;
|
|
||||||
|
|
||||||
static
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
deserialize (SerialIter & sit, SField::ref name);
|
|
||||||
|
|
||||||
const vector& getValue () const
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector& getValue ()
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// VFALCO NOTE as long as we're married to boost why not use
|
|
||||||
// boost::iterator_facade?
|
|
||||||
//
|
|
||||||
// vector-like functions
|
|
||||||
void push_back (const STObject & object)
|
void push_back (const STObject & object)
|
||||||
{
|
{
|
||||||
value.push_back (object.oClone ().release ());
|
v_.push_back(object);
|
||||||
}
|
|
||||||
STObject& operator[] (int j)
|
|
||||||
{
|
|
||||||
return value[j];
|
|
||||||
}
|
|
||||||
const STObject& operator[] (int j) const
|
|
||||||
{
|
|
||||||
return value[j];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator begin ()
|
iterator begin ()
|
||||||
{
|
{
|
||||||
return value.begin ();
|
return v_.begin ();
|
||||||
}
|
|
||||||
const_iterator begin () const
|
|
||||||
{
|
|
||||||
return value.begin ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator end ()
|
iterator end ()
|
||||||
{
|
{
|
||||||
return value.end ();
|
return v_.end ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const_iterator begin () const
|
||||||
|
{
|
||||||
|
return v_.begin ();
|
||||||
|
}
|
||||||
|
|
||||||
const_iterator end () const
|
const_iterator end () const
|
||||||
{
|
{
|
||||||
return value.end ();
|
return v_.end ();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type size () const
|
size_type size () const
|
||||||
{
|
{
|
||||||
return value.size ();
|
return v_.size ();
|
||||||
}
|
|
||||||
reverse_iterator rbegin ()
|
|
||||||
{
|
|
||||||
return value.rbegin ();
|
|
||||||
}
|
|
||||||
const_reverse_iterator rbegin () const
|
|
||||||
{
|
|
||||||
return value.rbegin ();
|
|
||||||
}
|
|
||||||
reverse_iterator rend ()
|
|
||||||
{
|
|
||||||
return value.rend ();
|
|
||||||
}
|
|
||||||
const_reverse_iterator rend () const
|
|
||||||
{
|
|
||||||
return value.rend ();
|
|
||||||
}
|
|
||||||
iterator erase (iterator pos)
|
|
||||||
{
|
|
||||||
return value.erase (pos);
|
|
||||||
}
|
|
||||||
STObject& front ()
|
|
||||||
{
|
|
||||||
return value.front ();
|
|
||||||
}
|
|
||||||
const STObject& front () const
|
|
||||||
{
|
|
||||||
return value.front ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STObject& back ()
|
STObject& back ()
|
||||||
{
|
{
|
||||||
return value.back ();
|
return v_.back ();
|
||||||
}
|
|
||||||
const STObject& back () const
|
|
||||||
{
|
|
||||||
return value.back ();
|
|
||||||
}
|
|
||||||
void pop_back ()
|
|
||||||
{
|
|
||||||
value.pop_back ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty () const
|
bool empty () const
|
||||||
{
|
{
|
||||||
return value.empty ();
|
return v_.empty ();
|
||||||
}
|
}
|
||||||
void clear ()
|
void clear ()
|
||||||
{
|
{
|
||||||
value.clear ();
|
v_.clear ();
|
||||||
}
|
}
|
||||||
void swap (STArray & a) noexcept
|
void swap (STArray & a) noexcept
|
||||||
{
|
{
|
||||||
value.swap (a.value);
|
v_.swap (a.v_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string getFullText () const override;
|
virtual std::string getFullText () const override;
|
||||||
@@ -185,11 +129,11 @@ public:
|
|||||||
|
|
||||||
bool operator== (const STArray & s) const
|
bool operator== (const STArray & s) const
|
||||||
{
|
{
|
||||||
return value == s.value;
|
return v_ == s.v_;
|
||||||
}
|
}
|
||||||
bool operator!= (const STArray & s) const
|
bool operator!= (const STArray & s) const
|
||||||
{
|
{
|
||||||
return value != s.value;
|
return v_ != s.v_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual SerializedTypeID getSType () const override
|
virtual SerializedTypeID getSType () const override
|
||||||
@@ -199,17 +143,8 @@ public:
|
|||||||
virtual bool isEquivalent (const STBase & t) const override;
|
virtual bool isEquivalent (const STBase & t) const override;
|
||||||
virtual bool isDefault () const override
|
virtual bool isDefault () const override
|
||||||
{
|
{
|
||||||
return value.empty ();
|
return v_.empty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STArray>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
vector value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
#include <beast/cxx14/memory.h> // <memory>
|
#include <beast/cxx14/memory.h> // <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
#include <utility>
|
||||||
|
#include <beast/cxx14/type_traits.h> // <type_traits>
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
// VFALCO TODO fix this restriction on copy assignment.
|
// VFALCO TODO fix this restriction on copy assignment.
|
||||||
@@ -70,6 +71,20 @@ public:
|
|||||||
bool operator== (const STBase& t) const;
|
bool operator== (const STBase& t) const;
|
||||||
bool operator!= (const STBase& t) const;
|
bool operator!= (const STBase& t) const;
|
||||||
|
|
||||||
|
virtual
|
||||||
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const
|
||||||
|
{
|
||||||
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf)
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
|
}
|
||||||
|
|
||||||
template <class D>
|
template <class D>
|
||||||
D&
|
D&
|
||||||
downcast()
|
downcast()
|
||||||
@@ -130,27 +145,23 @@ public:
|
|||||||
void
|
void
|
||||||
addFieldID (Serializer& s) const;
|
addFieldID (Serializer& s) const;
|
||||||
|
|
||||||
static
|
|
||||||
std::unique_ptr <STBase>
|
|
||||||
deserialize (SField::ref name);
|
|
||||||
|
|
||||||
virtual
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const
|
|
||||||
{
|
|
||||||
return std::make_unique<STBase>(*fName);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SField::ptr fName;
|
SField::ptr fName;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
static
|
||||||
|
STBase*
|
||||||
|
emplace(std::size_t n, void* buf, T&& val)
|
||||||
|
{
|
||||||
|
using U = std::decay_t<T>;
|
||||||
|
if (sizeof(U) > n)
|
||||||
|
return new U(std::forward<T>(val));
|
||||||
|
return new(buf) U(std::forward<T>(val));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
STBase* new_clone (const STBase& s);
|
|
||||||
|
|
||||||
void delete_clone (const STBase* s);
|
|
||||||
|
|
||||||
std::ostream& operator<< (std::ostream& out, const STBase& t);
|
std::ostream& operator<< (std::ostream& out, const STBase& t);
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -57,11 +57,21 @@ public:
|
|||||||
bitString_.SetHex (v);
|
bitString_.SetHex (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
STBitString (SerialIter& sit, SField::ref name)
|
||||||
std::unique_ptr<STBase>
|
: STBitString(name, sit.getBitString<Bits>())
|
||||||
deserialize (SerialIter& sit, SField::ref name)
|
|
||||||
{
|
{
|
||||||
return std::make_unique<STBitString> (name, sit.getBitString<Bits> ());
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializedTypeID
|
SerializedTypeID
|
||||||
@@ -111,12 +121,6 @@ public:
|
|||||||
return bitString_ == zero;
|
return bitString_ == zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STBitString>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BitString bitString_;
|
BitString bitString_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -72,11 +72,16 @@ public:
|
|||||||
|
|
||||||
STBlob (SerialIter&, SField::ref name = sfGeneric);
|
STBlob (SerialIter&, SField::ref name = sfGeneric);
|
||||||
|
|
||||||
static
|
STBase*
|
||||||
std::unique_ptr<STBase>
|
copy (std::size_t n, void* buf) const override
|
||||||
deserialize (SerialIter& sit, SField::ref name)
|
|
||||||
{
|
{
|
||||||
return std::make_unique<STBlob> (name, sit.getVLBuffer ());
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t
|
std::size_t
|
||||||
@@ -150,12 +155,6 @@ public:
|
|||||||
return value_.empty ();
|
return value_.empty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STBlob>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Buffer value_;
|
Buffer value_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,9 +40,19 @@ public:
|
|||||||
: STBase (n), value_ (v)
|
: STBase (n), value_ (v)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
static
|
STInteger(SerialIter& sit, SField::ref name);
|
||||||
std::unique_ptr<STBase>
|
|
||||||
deserialize (SerialIter& sit, SField::ref name);
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
|
}
|
||||||
|
|
||||||
SerializedTypeID
|
SerializedTypeID
|
||||||
getSType () const override;
|
getSType () const override;
|
||||||
@@ -92,12 +102,6 @@ public:
|
|||||||
return v && (value_ == v->value_);
|
return v && (value_ == v->value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STInteger>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Integer value_;
|
Integer value_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,6 +41,18 @@ public:
|
|||||||
STLedgerEntry (LedgerEntryType type, uint256 const& index);
|
STLedgerEntry (LedgerEntryType type, uint256 const& index);
|
||||||
STLedgerEntry (const STObject & object, uint256 const& index);
|
STLedgerEntry (const STObject & object, uint256 const& index);
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
|
}
|
||||||
|
|
||||||
SerializedTypeID getSType () const override
|
SerializedTypeID getSType () const override
|
||||||
{
|
{
|
||||||
return STI_LEDGERENTRY;
|
return STI_LEDGERENTRY;
|
||||||
@@ -94,12 +106,6 @@ public:
|
|||||||
std::uint32_t & prevLedgerID);
|
std::uint32_t & prevLedgerID);
|
||||||
std::vector<uint256> getOwners (); // nodes notified if this node is deleted
|
std::vector<uint256> getOwners (); // nodes notified if this node is deleted
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STLedgerEntry>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Make STObject comply with the template for this SLE type
|
/** Make STObject comply with the template for this SLE type
|
||||||
Can throw
|
Can throw
|
||||||
|
|||||||
@@ -25,7 +25,15 @@
|
|||||||
#include <ripple/protocol/STPathSet.h>
|
#include <ripple/protocol/STPathSet.h>
|
||||||
#include <ripple/protocol/STVector256.h>
|
#include <ripple/protocol/STVector256.h>
|
||||||
#include <ripple/protocol/SOTemplate.h>
|
#include <ripple/protocol/SOTemplate.h>
|
||||||
|
#include <ripple/protocol/impl/STVar.h>
|
||||||
|
#include <boost/iterator/transform_iterator.hpp>
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <beast/streams/debug_ostream.h>
|
||||||
|
#include <beast/utility/static_initializer.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -35,50 +43,98 @@ class STObject
|
|||||||
: public STBase
|
: public STBase
|
||||||
, public CountedObject <STObject>
|
, public CountedObject <STObject>
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
struct Transform
|
||||||
|
{
|
||||||
|
using argument_type = detail::STVar;
|
||||||
|
using result_type = STBase;
|
||||||
|
|
||||||
|
STBase const&
|
||||||
|
operator() (detail::STVar const& e) const
|
||||||
|
{
|
||||||
|
return e.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
reserveSize = 20
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Log
|
||||||
|
{
|
||||||
|
std::mutex mutex_;
|
||||||
|
std::unordered_map<
|
||||||
|
std::size_t, std::size_t> map_;
|
||||||
|
|
||||||
|
~Log()
|
||||||
|
{
|
||||||
|
beast::debug_ostream os;
|
||||||
|
for(auto const& e : map_)
|
||||||
|
os << e.first << "," << e.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
operator() (std::size_t n)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
auto const result = map_.emplace(n, 1);
|
||||||
|
if (! result.second)
|
||||||
|
++result.first->second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using list_type = std::vector<detail::STVar>;
|
||||||
|
|
||||||
|
list_type v_;
|
||||||
|
SOTemplate const* mType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using iterator = boost::transform_iterator<
|
||||||
|
Transform, STObject::list_type::const_iterator>;
|
||||||
|
|
||||||
static char const* getCountedObjectName () { return "STObject"; }
|
static char const* getCountedObjectName () { return "STObject"; }
|
||||||
|
|
||||||
STObject () : mType (nullptr)
|
STObject(STObject&&);
|
||||||
|
STObject(STObject const&) = default;
|
||||||
|
STObject (const SOTemplate & type, SField::ref name);
|
||||||
|
STObject (const SOTemplate & type, SerialIter & sit, SField::ref name);
|
||||||
|
STObject (SField::ref name, boost::ptr_vector<STBase>& data);
|
||||||
|
STObject (SerialIter& sit, SField::ref name);
|
||||||
|
STObject& operator= (STObject const&) = default;
|
||||||
|
STObject& operator= (STObject&& other);
|
||||||
|
|
||||||
|
explicit STObject (SField::ref name);
|
||||||
|
|
||||||
|
virtual ~STObject();
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const override
|
||||||
{
|
{
|
||||||
;
|
return emplace(n, buf, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit STObject (SField::ref name)
|
STBase*
|
||||||
: STBase (name), mType (nullptr)
|
move (std::size_t n, void* buf) override
|
||||||
{
|
{
|
||||||
;
|
return emplace(n, buf, std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
STObject (const SOTemplate & type, SField::ref name)
|
iterator begin() const
|
||||||
: STBase (name)
|
|
||||||
{
|
{
|
||||||
set (type);
|
return iterator(v_.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
STObject (
|
iterator end() const
|
||||||
const SOTemplate & type, SerialIter & sit, SField::ref name)
|
|
||||||
: STBase (name)
|
|
||||||
{
|
{
|
||||||
set (sit);
|
return iterator(v_.end());
|
||||||
setType (type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STObject (SField::ref name, boost::ptr_vector<STBase>& data)
|
bool empty() const
|
||||||
: STBase (name), mType (nullptr)
|
|
||||||
{
|
{
|
||||||
mData.swap (data);
|
return v_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr <STObject> oClone () const
|
|
||||||
{
|
|
||||||
return std::make_unique <STObject> (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~STObject () { }
|
|
||||||
|
|
||||||
static std::unique_ptr<STBase>
|
|
||||||
deserialize (SerialIter & sit, SField::ref name);
|
|
||||||
|
|
||||||
bool setType (const SOTemplate & type);
|
bool setType (const SOTemplate & type);
|
||||||
bool isValidForType ();
|
bool isValidForType ();
|
||||||
bool isFieldAllowed (SField::ref);
|
bool isFieldAllowed (SField::ref);
|
||||||
@@ -97,7 +153,7 @@ public:
|
|||||||
virtual bool isEquivalent (const STBase & t) const override;
|
virtual bool isEquivalent (const STBase & t) const override;
|
||||||
virtual bool isDefault () const override
|
virtual bool isDefault () const override
|
||||||
{
|
{
|
||||||
return mData.empty ();
|
return v_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void add (Serializer & s) const override
|
virtual void add (Serializer & s) const override
|
||||||
@@ -123,49 +179,17 @@ public:
|
|||||||
// TODO(tom): options should be an enum.
|
// TODO(tom): options should be an enum.
|
||||||
virtual Json::Value getJson (int options) const override;
|
virtual Json::Value getJson (int options) const override;
|
||||||
|
|
||||||
int addObject (const STBase & t)
|
template <class... Args>
|
||||||
|
std::size_t
|
||||||
|
emplace_back(Args&&... args)
|
||||||
{
|
{
|
||||||
mData.push_back (t.duplicate ().release ());
|
v_.emplace_back(std::forward<Args>(args)...);
|
||||||
return mData.size () - 1;
|
return v_.size() - 1;
|
||||||
}
|
|
||||||
int giveObject (std::unique_ptr<STBase> t)
|
|
||||||
{
|
|
||||||
mData.push_back (t.release ());
|
|
||||||
return mData.size () - 1;
|
|
||||||
}
|
|
||||||
int giveObject (STBase * t)
|
|
||||||
{
|
|
||||||
mData.push_back (t);
|
|
||||||
return mData.size () - 1;
|
|
||||||
}
|
|
||||||
const boost::ptr_vector<STBase>& peekData () const
|
|
||||||
{
|
|
||||||
return mData;
|
|
||||||
}
|
|
||||||
boost::ptr_vector<STBase>& peekData ()
|
|
||||||
{
|
|
||||||
return mData;
|
|
||||||
}
|
|
||||||
STBase& front ()
|
|
||||||
{
|
|
||||||
return mData.front ();
|
|
||||||
}
|
|
||||||
const STBase& front () const
|
|
||||||
{
|
|
||||||
return mData.front ();
|
|
||||||
}
|
|
||||||
STBase& back ()
|
|
||||||
{
|
|
||||||
return mData.back ();
|
|
||||||
}
|
|
||||||
const STBase& back () const
|
|
||||||
{
|
|
||||||
return mData.back ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int getCount () const
|
int getCount () const
|
||||||
{
|
{
|
||||||
return mData.size ();
|
return v_.size ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setFlag (std::uint32_t);
|
bool setFlag (std::uint32_t);
|
||||||
@@ -178,19 +202,19 @@ public:
|
|||||||
|
|
||||||
const STBase& peekAtIndex (int offset) const
|
const STBase& peekAtIndex (int offset) const
|
||||||
{
|
{
|
||||||
return mData[offset];
|
return v_[offset].get();
|
||||||
}
|
}
|
||||||
STBase& getIndex (int offset)
|
STBase& getIndex(int offset)
|
||||||
{
|
{
|
||||||
return mData[offset];
|
return v_[offset].get();
|
||||||
}
|
}
|
||||||
const STBase* peekAtPIndex (int offset) const
|
const STBase* peekAtPIndex (int offset) const
|
||||||
{
|
{
|
||||||
return & (mData[offset]);
|
return &v_[offset].get();
|
||||||
}
|
}
|
||||||
STBase* getPIndex (int offset)
|
STBase* getPIndex (int offset)
|
||||||
{
|
{
|
||||||
return & (mData[offset]);
|
return &v_[offset].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getFieldIndex (SField::ref field) const;
|
int getFieldIndex (SField::ref field) const;
|
||||||
@@ -270,51 +294,6 @@ public:
|
|||||||
bool delField (SField::ref field);
|
bool delField (SField::ref field);
|
||||||
void delField (int index);
|
void delField (int index);
|
||||||
|
|
||||||
static std::unique_ptr <STBase>
|
|
||||||
makeDefaultObject (SerializedTypeID id, SField::ref name);
|
|
||||||
|
|
||||||
// VFALCO TODO remove the 'depth' parameter
|
|
||||||
static std::unique_ptr<STBase> makeDeserializedObject (
|
|
||||||
SerializedTypeID id,
|
|
||||||
SField::ref name,
|
|
||||||
SerialIter&,
|
|
||||||
int depth);
|
|
||||||
|
|
||||||
static std::unique_ptr<STBase>
|
|
||||||
makeNonPresentObject (SField::ref name)
|
|
||||||
{
|
|
||||||
return makeDefaultObject (STI_NOTPRESENT, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::unique_ptr<STBase> makeDefaultObject (SField::ref name)
|
|
||||||
{
|
|
||||||
return makeDefaultObject (name.fieldType, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// field iterator stuff
|
|
||||||
typedef boost::ptr_vector<STBase>::iterator iterator;
|
|
||||||
typedef boost::ptr_vector<STBase>::const_iterator const_iterator;
|
|
||||||
iterator begin ()
|
|
||||||
{
|
|
||||||
return mData.begin ();
|
|
||||||
}
|
|
||||||
iterator end ()
|
|
||||||
{
|
|
||||||
return mData.end ();
|
|
||||||
}
|
|
||||||
const_iterator begin () const
|
|
||||||
{
|
|
||||||
return mData.begin ();
|
|
||||||
}
|
|
||||||
const_iterator end () const
|
|
||||||
{
|
|
||||||
return mData.end ();
|
|
||||||
}
|
|
||||||
bool empty () const
|
|
||||||
{
|
|
||||||
return mData.empty ();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasMatchingEntry (const STBase&);
|
bool hasMatchingEntry (const STBase&);
|
||||||
|
|
||||||
bool operator== (const STObject & o) const;
|
bool operator== (const STObject & o) const;
|
||||||
@@ -323,12 +302,6 @@ public:
|
|||||||
return ! (*this == o);
|
return ! (*this == o);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STObject>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Implementation for getting (most) fields that return by value.
|
// Implementation for getting (most) fields that return by value.
|
||||||
//
|
//
|
||||||
@@ -425,10 +398,6 @@ private:
|
|||||||
|
|
||||||
(*cf) = value;
|
(*cf) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
boost::ptr_vector<STBase> mData;
|
|
||||||
const SOTemplate* mType;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -237,14 +237,18 @@ public:
|
|||||||
: STBase (n)
|
: STBase (n)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
static
|
STPathSet (SerialIter& sit, SField::ref name);
|
||||||
std::unique_ptr<STBase>
|
|
||||||
deserialize (SerialIter& sit, SField::ref name);
|
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
STBase*
|
||||||
duplicate () const override
|
copy (std::size_t n, void* buf) const override
|
||||||
{
|
{
|
||||||
return std::make_unique<STPathSet>(*this);
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -56,6 +56,18 @@ public:
|
|||||||
// Only called from ripple::RPC::transactionSign - can we eliminate this?
|
// Only called from ripple::RPC::transactionSign - can we eliminate this?
|
||||||
explicit STTx (STObject const& object);
|
explicit STTx (STObject const& object);
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
|
}
|
||||||
|
|
||||||
// STObject functions
|
// STObject functions
|
||||||
SerializedTypeID getSType () const override
|
SerializedTypeID getSType () const override
|
||||||
{
|
{
|
||||||
@@ -143,12 +155,6 @@ public:
|
|||||||
char status,
|
char status,
|
||||||
std::string const& escapedMetaData) const;
|
std::string const& escapedMetaData) const;
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STTx>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TxType tx_type_;
|
TxType tx_type_;
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,18 @@ public:
|
|||||||
STValidation (uint256 const& ledgerHash, std::uint32_t signTime,
|
STValidation (uint256 const& ledgerHash, std::uint32_t signTime,
|
||||||
const RippleAddress & raPub, bool isFull);
|
const RippleAddress & raPub, bool isFull);
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
|
}
|
||||||
|
|
||||||
uint256 getLedgerHash () const;
|
uint256 getLedgerHash () const;
|
||||||
std::uint32_t getSignTime () const;
|
std::uint32_t getSignTime () const;
|
||||||
std::uint32_t getFlags () const;
|
std::uint32_t getFlags () const;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
class STVector256 final
|
class STVector256
|
||||||
: public STBase
|
: public STBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -41,6 +41,20 @@ public:
|
|||||||
: mValue (vector)
|
: mValue (vector)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
STVector256 (SerialIter& sit, SField::ref name);
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
copy (std::size_t n, void* buf) const override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBase*
|
||||||
|
move (std::size_t n, void* buf) override
|
||||||
|
{
|
||||||
|
return emplace(n, buf, std::move(*this));
|
||||||
|
}
|
||||||
|
|
||||||
SerializedTypeID
|
SerializedTypeID
|
||||||
getSType () const override
|
getSType () const override
|
||||||
{
|
{
|
||||||
@@ -50,10 +64,6 @@ public:
|
|||||||
void
|
void
|
||||||
add (Serializer& s) const override;
|
add (Serializer& s) const override;
|
||||||
|
|
||||||
static
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
deserialize (SerialIter& sit, SField::ref name);
|
|
||||||
|
|
||||||
Json::Value
|
Json::Value
|
||||||
getJson (int) const override;
|
getJson (int) const override;
|
||||||
|
|
||||||
@@ -72,12 +82,6 @@ public:
|
|||||||
mValue = v.mValue;
|
mValue = v.mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
duplicate () const override
|
|
||||||
{
|
|
||||||
return std::make_unique<STVector256>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieve a copy of the vector we contain */
|
/** Retrieve a copy of the vector we contain */
|
||||||
explicit
|
explicit
|
||||||
operator std::vector<uint256> () const
|
operator std::vector<uint256> () const
|
||||||
|
|||||||
@@ -22,6 +22,11 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
|
STAccount::STAccount (SerialIter& sit, SField::ref name)
|
||||||
|
: STAccount(name, sit.getVLBuffer())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::string STAccount::getText () const
|
std::string STAccount::getText () const
|
||||||
{
|
{
|
||||||
Account u;
|
Account u;
|
||||||
|
|||||||
@@ -42,6 +42,82 @@ STAmount const saOne (noIssue(), 1u);
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
STAmount::STAmount(SerialIter& sit, SField::ref name)
|
||||||
|
: STBase(name)
|
||||||
|
{
|
||||||
|
std::uint64_t value = sit.get64 ();
|
||||||
|
|
||||||
|
// native
|
||||||
|
if ((value & cNotNative) == 0)
|
||||||
|
{
|
||||||
|
// positive
|
||||||
|
if ((value & cPosNative) != 0)
|
||||||
|
{
|
||||||
|
mValue = value & ~cPosNative;
|
||||||
|
mOffset = 0;
|
||||||
|
mIsNative = true;
|
||||||
|
mIsNegative = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// negative
|
||||||
|
if (value == 0)
|
||||||
|
throw std::runtime_error ("negative zero is not canonical");
|
||||||
|
|
||||||
|
mValue = value;
|
||||||
|
mOffset = 0;
|
||||||
|
mIsNative = true;
|
||||||
|
mIsNegative = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Issue issue;
|
||||||
|
issue.currency.copyFrom (sit.get160 ());
|
||||||
|
|
||||||
|
if (isXRP (issue.currency))
|
||||||
|
throw std::runtime_error ("invalid native currency");
|
||||||
|
|
||||||
|
issue.account.copyFrom (sit.get160 ());
|
||||||
|
|
||||||
|
if (isXRP (issue.account))
|
||||||
|
throw std::runtime_error ("invalid native account");
|
||||||
|
|
||||||
|
// 10 bits for the offset, sign and "not native" flag
|
||||||
|
int offset = static_cast<int> (value >> (64 - 10));
|
||||||
|
|
||||||
|
value &= ~ (1023ull << (64 - 10));
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
bool isNegative = (offset & 256) == 0;
|
||||||
|
offset = (offset & 255) - 97; // center the range
|
||||||
|
|
||||||
|
if (value < cMinValue ||
|
||||||
|
value > cMaxValue ||
|
||||||
|
offset < cMinOffset ||
|
||||||
|
offset > cMaxOffset)
|
||||||
|
{
|
||||||
|
throw std::runtime_error ("invalid currency value");
|
||||||
|
}
|
||||||
|
|
||||||
|
mIssue = issue;
|
||||||
|
mValue = value;
|
||||||
|
mOffset = offset;
|
||||||
|
mIsNegative = isNegative;
|
||||||
|
canonicalize();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset != 512)
|
||||||
|
throw std::runtime_error ("invalid currency value");
|
||||||
|
|
||||||
|
mIssue = issue;
|
||||||
|
mValue = 0;
|
||||||
|
mOffset = 0;
|
||||||
|
mIsNegative = false;
|
||||||
|
canonicalize();
|
||||||
|
}
|
||||||
|
|
||||||
STAmount::STAmount (SField::ref name, Issue const& issue,
|
STAmount::STAmount (SField::ref name, Issue const& issue,
|
||||||
mantissa_type mantissa, exponent_type exponent,
|
mantissa_type mantissa, exponent_type exponent,
|
||||||
bool native, bool negative)
|
bool native, bool negative)
|
||||||
@@ -140,58 +216,7 @@ STAmount::STAmount (Issue const& issue,
|
|||||||
std::unique_ptr<STAmount>
|
std::unique_ptr<STAmount>
|
||||||
STAmount::construct (SerialIter& sit, SField::ref name)
|
STAmount::construct (SerialIter& sit, SField::ref name)
|
||||||
{
|
{
|
||||||
std::uint64_t value = sit.get64 ();
|
return std::make_unique<STAmount>(sit, name);
|
||||||
|
|
||||||
// native
|
|
||||||
if ((value & cNotNative) == 0)
|
|
||||||
{
|
|
||||||
// positive
|
|
||||||
if ((value & cPosNative) != 0)
|
|
||||||
return std::make_unique<STAmount> (name, value & ~cPosNative, false);
|
|
||||||
|
|
||||||
// negative
|
|
||||||
if (value == 0)
|
|
||||||
throw std::runtime_error ("negative zero is not canonical");
|
|
||||||
|
|
||||||
return std::make_unique<STAmount> (name, value, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Issue issue;
|
|
||||||
issue.currency.copyFrom (sit.get160 ());
|
|
||||||
|
|
||||||
if (isXRP (issue.currency))
|
|
||||||
throw std::runtime_error ("invalid native currency");
|
|
||||||
|
|
||||||
issue.account.copyFrom (sit.get160 ());
|
|
||||||
|
|
||||||
if (isXRP (issue.account))
|
|
||||||
throw std::runtime_error ("invalid native account");
|
|
||||||
|
|
||||||
// 10 bits for the offset, sign and "not native" flag
|
|
||||||
int offset = static_cast<int> (value >> (64 - 10));
|
|
||||||
|
|
||||||
value &= ~ (1023ull << (64 - 10));
|
|
||||||
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
bool isNegative = (offset & 256) == 0;
|
|
||||||
offset = (offset & 255) - 97; // center the range
|
|
||||||
|
|
||||||
if (value < cMinValue ||
|
|
||||||
value > cMaxValue ||
|
|
||||||
offset < cMinOffset ||
|
|
||||||
offset > cMaxOffset)
|
|
||||||
{
|
|
||||||
throw std::runtime_error ("invalid currency value");
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_unique<STAmount> (name, issue, value, offset, isNegative);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset != 512)
|
|
||||||
throw std::runtime_error ("invalid currency value");
|
|
||||||
|
|
||||||
return std::make_unique<STAmount> (name, issue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount
|
STAmount
|
||||||
@@ -202,16 +227,6 @@ STAmount::createFromInt64 (SField::ref name, std::int64_t value)
|
|||||||
: STAmount (name, static_cast<std::uint64_t> (-value), true);
|
: STAmount (name, static_cast<std::uint64_t> (-value), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount STAmount::deserialize (SerialIter& it)
|
|
||||||
{
|
|
||||||
auto s = construct (it, sfGeneric);
|
|
||||||
|
|
||||||
if (!s)
|
|
||||||
throw std::runtime_error("Deserialization error");
|
|
||||||
|
|
||||||
return STAmount (*s);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Operators
|
// Operators
|
||||||
|
|||||||
@@ -24,12 +24,47 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
STArray::STArray()
|
||||||
STArray::deserialize (SerialIter& sit, SField::ref field)
|
|
||||||
{
|
{
|
||||||
std::unique_ptr <STArray> ret (std::make_unique <STArray> (field));
|
// VFALCO NOTE We need to determine if this is
|
||||||
vector& value (ret->getValue ());
|
// the right thing to do, and consider
|
||||||
|
// making it optional.
|
||||||
|
//v_.reserve(reserveSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
STArray::STArray (STArray&& other)
|
||||||
|
: STBase(other.getFName())
|
||||||
|
, v_(std::move(other.v_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
STArray& STArray::operator= (STArray&& other)
|
||||||
|
{
|
||||||
|
setFName(other.getFName());
|
||||||
|
v_ = std::move(other.v_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
STArray::STArray (int n)
|
||||||
|
{
|
||||||
|
v_.reserve(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
STArray::STArray (SField::ref f)
|
||||||
|
: STBase (f)
|
||||||
|
{
|
||||||
|
v_.reserve(reserveSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
STArray::STArray (SField::ref f, int n)
|
||||||
|
: STBase (f)
|
||||||
|
{
|
||||||
|
v_.reserve(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
STArray::STArray (SerialIter& sit, SField::ref f)
|
||||||
|
: STBase(f)
|
||||||
|
{
|
||||||
while (!sit.empty ())
|
while (!sit.empty ())
|
||||||
{
|
{
|
||||||
int type, field;
|
int type, field;
|
||||||
@@ -45,7 +80,7 @@ STArray::deserialize (SerialIter& sit, SField::ref field)
|
|||||||
throw std::runtime_error ("Illegal terminator in array");
|
throw std::runtime_error ("Illegal terminator in array");
|
||||||
}
|
}
|
||||||
|
|
||||||
SField::ref fn = SField::getField (type, field);
|
SField::ref const fn = SField::getField (type, field);
|
||||||
|
|
||||||
if (fn.isInvalid ())
|
if (fn.isInvalid ())
|
||||||
{
|
{
|
||||||
@@ -60,10 +95,9 @@ STArray::deserialize (SerialIter& sit, SField::ref field)
|
|||||||
throw std::runtime_error ("Non-object in array");
|
throw std::runtime_error ("Non-object in array");
|
||||||
}
|
}
|
||||||
|
|
||||||
value.push_back (new STObject (fn));
|
v_.emplace_back(fn);
|
||||||
value.rbegin ()->set (sit, 1);
|
v_.back().set (sit, 1);
|
||||||
}
|
}
|
||||||
return std::move (ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string STArray::getFullText () const
|
std::string STArray::getFullText () const
|
||||||
@@ -71,12 +105,12 @@ std::string STArray::getFullText () const
|
|||||||
std::string r = "[";
|
std::string r = "[";
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (STObject const& o : value)
|
for (auto const& obj : v_)
|
||||||
{
|
{
|
||||||
if (!first)
|
if (!first)
|
||||||
r += ",";
|
r += ",";
|
||||||
|
|
||||||
r += o.getFullText ();
|
r += obj.getFullText ();
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +123,7 @@ std::string STArray::getText () const
|
|||||||
std::string r = "[";
|
std::string r = "[";
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (STObject const& o : value)
|
for (STObject const& o : v_)
|
||||||
{
|
{
|
||||||
if (!first)
|
if (!first)
|
||||||
r += ",";
|
r += ",";
|
||||||
@@ -106,7 +140,7 @@ Json::Value STArray::getJson (int p) const
|
|||||||
{
|
{
|
||||||
Json::Value v = Json::arrayValue;
|
Json::Value v = Json::arrayValue;
|
||||||
int index = 1;
|
int index = 1;
|
||||||
for (auto const& object: value)
|
for (auto const& object: v_)
|
||||||
{
|
{
|
||||||
if (object.getSType () != STI_NOTPRESENT)
|
if (object.getSType () != STI_NOTPRESENT)
|
||||||
{
|
{
|
||||||
@@ -122,7 +156,7 @@ Json::Value STArray::getJson (int p) const
|
|||||||
|
|
||||||
void STArray::add (Serializer& s) const
|
void STArray::add (Serializer& s) const
|
||||||
{
|
{
|
||||||
for (STObject const& object : value)
|
for (STObject const& object : v_)
|
||||||
{
|
{
|
||||||
object.addFieldID (s);
|
object.addFieldID (s);
|
||||||
object.add (s);
|
object.add (s);
|
||||||
@@ -141,12 +175,12 @@ bool STArray::isEquivalent (const STBase& t) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value == v->value;
|
return v_ == v->v_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void STArray::sort (bool (*compare) (const STObject&, const STObject&))
|
void STArray::sort (bool (*compare) (const STObject&, const STObject&))
|
||||||
{
|
{
|
||||||
value.sort (compare);
|
std::sort(v_.begin(), v_.end(), compare);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -145,28 +145,8 @@ STBase::addFieldID (Serializer& s) const
|
|||||||
s.addFieldID (fName->fieldType, fName->fieldValue);
|
s.addFieldID (fName->fieldType, fName->fieldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr <STBase>
|
|
||||||
STBase::deserialize (SField::ref name)
|
|
||||||
{
|
|
||||||
return std::make_unique<STBase>(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
STBase*
|
|
||||||
new_clone (const STBase& s)
|
|
||||||
{
|
|
||||||
STBase* const copy (s.duplicate ().release ());
|
|
||||||
assert (typeid (*copy) == typeid (s));
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
delete_clone (const STBase* s)
|
|
||||||
{
|
|
||||||
boost::checked_delete (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<< (std::ostream& out, const STBase& t)
|
operator<< (std::ostream& out, const STBase& t)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,6 +28,12 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
STInteger<unsigned char>::STInteger(SerialIter& sit, SField::ref name)
|
||||||
|
: STInteger(name, sit.get8())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
SerializedTypeID
|
SerializedTypeID
|
||||||
STUInt8::getSType () const
|
STUInt8::getSType () const
|
||||||
@@ -35,13 +41,6 @@ STUInt8::getSType () const
|
|||||||
return STI_UINT8;
|
return STI_UINT8;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
STUInt8::deserialize (SerialIter& sit, SField::ref name)
|
|
||||||
{
|
|
||||||
return std::make_unique <STUInt8> (name, sit.get8 ());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::string
|
std::string
|
||||||
STUInt8::getText () const
|
STUInt8::getText () const
|
||||||
@@ -77,6 +76,12 @@ STUInt8::getJson (int) const
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<>
|
||||||
|
STInteger<std::uint16_t>::STInteger(SerialIter& sit, SField::ref name)
|
||||||
|
: STInteger(name, sit.get16())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
SerializedTypeID
|
SerializedTypeID
|
||||||
STUInt16::getSType () const
|
STUInt16::getSType () const
|
||||||
@@ -84,13 +89,6 @@ STUInt16::getSType () const
|
|||||||
return STI_UINT16;
|
return STI_UINT16;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
STUInt16::deserialize (SerialIter& sit, SField::ref name)
|
|
||||||
{
|
|
||||||
return std::make_unique <STUInt16> (name, sit.get16 ());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::string
|
std::string
|
||||||
STUInt16::getText () const
|
STUInt16::getText () const
|
||||||
@@ -143,6 +141,12 @@ STUInt16::getJson (int) const
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<>
|
||||||
|
STInteger<std::uint32_t>::STInteger(SerialIter& sit, SField::ref name)
|
||||||
|
: STInteger(name, sit.get32())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
SerializedTypeID
|
SerializedTypeID
|
||||||
STUInt32::getSType () const
|
STUInt32::getSType () const
|
||||||
@@ -150,13 +154,6 @@ STUInt32::getSType () const
|
|||||||
return STI_UINT32;
|
return STI_UINT32;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
STUInt32::deserialize (SerialIter& sit, SField::ref name)
|
|
||||||
{
|
|
||||||
return std::make_unique <STUInt32> (name, sit.get32 ());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::string
|
std::string
|
||||||
STUInt32::getText () const
|
STUInt32::getText () const
|
||||||
@@ -173,6 +170,12 @@ STUInt32::getJson (int) const
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<>
|
||||||
|
STInteger<std::uint64_t>::STInteger(SerialIter& sit, SField::ref name)
|
||||||
|
: STInteger(name, sit.get64())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
SerializedTypeID
|
SerializedTypeID
|
||||||
STUInt64::getSType () const
|
STUInt64::getSType () const
|
||||||
@@ -180,13 +183,6 @@ STUInt64::getSType () const
|
|||||||
return STI_UINT64;
|
return STI_UINT64;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
STUInt64::deserialize (SerialIter& sit, SField::ref name)
|
|
||||||
{
|
|
||||||
return std::make_unique <STUInt64> (name, sit.get64 ());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::string
|
std::string
|
||||||
STUInt64::getText () const
|
STUInt64::getText () const
|
||||||
|
|||||||
@@ -31,222 +31,150 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
STObject::~STObject()
|
||||||
STObject::makeDefaultObject (SerializedTypeID id, SField::ref name)
|
|
||||||
{
|
{
|
||||||
assert ((id == STI_NOTPRESENT) || (id == name.fieldType));
|
#if 0
|
||||||
|
// Turn this on to get a histogram on exit
|
||||||
switch (id)
|
static beast::static_initializer<Log> log;
|
||||||
{
|
(*log)(v_.size());
|
||||||
case STI_NOTPRESENT:
|
#endif
|
||||||
return std::make_unique <STBase> (name);
|
|
||||||
|
|
||||||
case STI_UINT8:
|
|
||||||
return std::make_unique <STUInt8> (name);
|
|
||||||
|
|
||||||
case STI_UINT16:
|
|
||||||
return std::make_unique <STUInt16> (name);
|
|
||||||
|
|
||||||
case STI_UINT32:
|
|
||||||
return std::make_unique <STUInt32> (name);
|
|
||||||
|
|
||||||
case STI_UINT64:
|
|
||||||
return std::make_unique <STUInt64> (name);
|
|
||||||
|
|
||||||
case STI_AMOUNT:
|
|
||||||
return std::make_unique <STAmount> (name);
|
|
||||||
|
|
||||||
case STI_HASH128:
|
|
||||||
return std::make_unique <STHash128> (name);
|
|
||||||
|
|
||||||
case STI_HASH160:
|
|
||||||
return std::make_unique <STHash160> (name);
|
|
||||||
|
|
||||||
case STI_HASH256:
|
|
||||||
return std::make_unique <STHash256> (name);
|
|
||||||
|
|
||||||
case STI_VECTOR256:
|
|
||||||
return std::make_unique <STVector256> (name);
|
|
||||||
|
|
||||||
case STI_VL:
|
|
||||||
return std::make_unique <STBlob> (name);
|
|
||||||
|
|
||||||
case STI_ACCOUNT:
|
|
||||||
return std::make_unique <STAccount> (name);
|
|
||||||
|
|
||||||
case STI_PATHSET:
|
|
||||||
return std::make_unique <STPathSet> (name);
|
|
||||||
|
|
||||||
case STI_OBJECT:
|
|
||||||
return std::make_unique <STObject> (name);
|
|
||||||
|
|
||||||
case STI_ARRAY:
|
|
||||||
return std::make_unique <STArray> (name);
|
|
||||||
|
|
||||||
default:
|
|
||||||
WriteLog (lsFATAL, STObject) <<
|
|
||||||
"Object type: " << beast::lexicalCast <std::string> (id);
|
|
||||||
assert (false);
|
|
||||||
throw std::runtime_error ("Unknown object type");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VFALCO TODO Remove the 'depth' parameter
|
STObject::STObject(STObject&& other)
|
||||||
std::unique_ptr<STBase>
|
: STBase(other.getFName())
|
||||||
STObject::makeDeserializedObject (SerializedTypeID id, SField::ref name,
|
, v_(std::move(other.v_))
|
||||||
SerialIter& sit, int depth)
|
, mType(other.mType)
|
||||||
{
|
{
|
||||||
switch (id)
|
}
|
||||||
{
|
|
||||||
case STI_NOTPRESENT:
|
|
||||||
return STBase::deserialize (name);
|
|
||||||
|
|
||||||
case STI_UINT8:
|
STObject::STObject (SField::ref name)
|
||||||
return STUInt8::deserialize (sit, name);
|
: STBase (name)
|
||||||
|
, mType (nullptr)
|
||||||
|
{
|
||||||
|
// VFALCO TODO See if this is the right thing to do
|
||||||
|
//v_.reserve(reserveSize);
|
||||||
|
}
|
||||||
|
|
||||||
case STI_UINT16:
|
STObject::STObject (SOTemplate const& type,
|
||||||
return STUInt16::deserialize (sit, name);
|
SField::ref name)
|
||||||
|
: STBase (name)
|
||||||
|
{
|
||||||
|
set (type);
|
||||||
|
}
|
||||||
|
|
||||||
case STI_UINT32:
|
STObject::STObject (SOTemplate const& type,
|
||||||
return STUInt32::deserialize (sit, name);
|
SerialIter & sit, SField::ref name)
|
||||||
|
: STBase (name)
|
||||||
|
{
|
||||||
|
v_.reserve(type.peek().size());
|
||||||
|
set (sit);
|
||||||
|
setType (type);
|
||||||
|
}
|
||||||
|
|
||||||
case STI_UINT64:
|
STObject::STObject (SField::ref name,
|
||||||
return STUInt64::deserialize (sit, name);
|
boost::ptr_vector<STBase>& data)
|
||||||
|
: STBase (name)
|
||||||
|
, mType (nullptr)
|
||||||
|
{
|
||||||
|
v_.reserve(data.size());
|
||||||
|
for (auto const& b : data)
|
||||||
|
v_.emplace_back(b);
|
||||||
|
}
|
||||||
|
|
||||||
case STI_AMOUNT:
|
STObject::STObject (SerialIter& sit, SField::ref name)
|
||||||
return STAmount::deserialize (sit, name);
|
: STBase(name)
|
||||||
|
, mType(nullptr)
|
||||||
|
{
|
||||||
|
set(sit, 0);
|
||||||
|
}
|
||||||
|
|
||||||
case STI_HASH128:
|
STObject&
|
||||||
return STHash128::deserialize (sit, name);
|
STObject::operator= (STObject&& other)
|
||||||
|
{
|
||||||
case STI_HASH160:
|
setFName(other.getFName());
|
||||||
return STHash160::deserialize (sit, name);
|
mType = other.mType;
|
||||||
|
v_ = std::move(other.v_);
|
||||||
case STI_HASH256:
|
return *this;
|
||||||
return STHash256::deserialize (sit, name);
|
|
||||||
|
|
||||||
case STI_VECTOR256:
|
|
||||||
return STVector256::deserialize (sit, name);
|
|
||||||
|
|
||||||
case STI_VL:
|
|
||||||
return STBlob::deserialize (sit, name);
|
|
||||||
|
|
||||||
case STI_ACCOUNT:
|
|
||||||
return STAccount::deserialize (sit, name);
|
|
||||||
|
|
||||||
case STI_PATHSET:
|
|
||||||
return STPathSet::deserialize (sit, name);
|
|
||||||
|
|
||||||
case STI_ARRAY:
|
|
||||||
return STArray::deserialize (sit, name);
|
|
||||||
|
|
||||||
case STI_OBJECT:
|
|
||||||
return STObject::deserialize (sit, name);
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw std::runtime_error ("Unknown object type");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void STObject::set (const SOTemplate& type)
|
void STObject::set (const SOTemplate& type)
|
||||||
{
|
{
|
||||||
mData.clear ();
|
v_.clear();
|
||||||
|
v_.reserve(type.peek().size());
|
||||||
mType = &type;
|
mType = &type;
|
||||||
|
|
||||||
for (SOTemplate::value_type const& elem : type.peek ())
|
for (auto const& elem : type.peek())
|
||||||
{
|
{
|
||||||
if (elem->flags != SOE_REQUIRED)
|
if (elem->flags != SOE_REQUIRED)
|
||||||
giveObject (makeNonPresentObject (elem->e_field));
|
v_.emplace_back(detail::nonPresentObject, elem->e_field);
|
||||||
else
|
else
|
||||||
giveObject (makeDefaultObject (elem->e_field));
|
v_.emplace_back(detail::defaultObject, elem->e_field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool STObject::setType (const SOTemplate& type)
|
bool STObject::setType (const SOTemplate& type)
|
||||||
{
|
{
|
||||||
boost::ptr_vector<STBase> newData (type.peek ().size ());
|
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
|
|
||||||
mType = &type;
|
mType = &type;
|
||||||
|
decltype(v_) v;
|
||||||
STBase** array = mData.c_array();
|
v.reserve(type.peek().size());
|
||||||
std::size_t count = mData.size ();
|
for (auto const& e : type.peek())
|
||||||
|
|
||||||
for (auto const& elem : type.peek ())
|
|
||||||
{
|
{
|
||||||
// Loop through all the fields in the template
|
auto const iter = std::find_if(
|
||||||
bool match = false;
|
v_.begin(), v_.end(), [&](detail::STVar const& b)
|
||||||
|
{ return b.get().getFName() == e->e_field; });
|
||||||
for (std::size_t i = 0; i < count; ++i)
|
if (iter != v_.end())
|
||||||
if ((array[i] != nullptr) &&
|
|
||||||
(array[i]->getFName () == elem->e_field))
|
|
||||||
{
|
|
||||||
// matching entry in the object, move to new vector
|
|
||||||
match = true;
|
|
||||||
|
|
||||||
if ((elem->flags == SOE_DEFAULT) && array[i]->isDefault ())
|
|
||||||
{
|
|
||||||
WriteLog (lsWARNING, STObject) <<
|
|
||||||
"setType( " << getFName ().getName () <<
|
|
||||||
") invalid default " << elem->e_field.fieldName;
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
newData.push_back (array[i]);
|
|
||||||
array[i] = nullptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!match)
|
|
||||||
{
|
{
|
||||||
// no match found in the object for an entry in the template
|
if ((e->flags == SOE_DEFAULT) && iter->get().isDefault())
|
||||||
if (elem->flags == SOE_REQUIRED)
|
|
||||||
{
|
{
|
||||||
WriteLog (lsWARNING, STObject) <<
|
WriteLog (lsWARNING, STObject) <<
|
||||||
"setType( " << getFName ().getName () <<
|
"setType( " << getFName ().getName () <<
|
||||||
") invalid missing " << elem->e_field.fieldName;
|
") invalid default " << e->e_field.fieldName;
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
|
v.emplace_back(std::move(*iter));
|
||||||
// Make a default object
|
v_.erase(iter);
|
||||||
newData.push_back (makeNonPresentObject (elem->e_field).release ());
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (e->flags == SOE_REQUIRED)
|
||||||
|
{
|
||||||
|
WriteLog (lsWARNING, STObject) <<
|
||||||
|
"setType( " << getFName ().getName () <<
|
||||||
|
") invalid missing " << e->e_field.fieldName;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
v.emplace_back(detail::nonPresentObject, e->e_field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto const& e : v_)
|
||||||
for (std::size_t i = 0; i < count; ++i)
|
|
||||||
{
|
{
|
||||||
// Anything left over in the object must be discardable
|
// Anything left over in the object must be discardable
|
||||||
if ((array[i] != nullptr) && !array[i]->getFName ().isDiscardable ())
|
if (! e->getFName().isDiscardable())
|
||||||
{
|
{
|
||||||
WriteLog (lsWARNING, STObject) <<
|
WriteLog (lsWARNING, STObject) <<
|
||||||
"setType( " << getFName ().getName () <<
|
"setType( " << getFName ().getName () <<
|
||||||
") invalid leftover " << array[i]->getFName ().getName ();
|
") invalid leftover " << e->getFName ().getName ();
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap the template matching data in for the old data,
|
// Swap the template matching data in for the old data,
|
||||||
// freeing any leftover junk
|
// freeing any leftover junk
|
||||||
mData.swap (newData);
|
v_.swap(v);
|
||||||
|
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool STObject::isValidForType ()
|
bool STObject::isValidForType ()
|
||||||
{
|
{
|
||||||
boost::ptr_vector<STBase>::iterator it = mData.begin ();
|
auto it = v_.begin();
|
||||||
|
for (SOTemplate::value_type const& elem : mType->peek())
|
||||||
for (SOTemplate::value_type const& elem : mType->peek ())
|
|
||||||
{
|
{
|
||||||
if (it == mData.end ())
|
if (it == v_.end())
|
||||||
return false;
|
return false;
|
||||||
|
if (elem->e_field != it->get().getFName())
|
||||||
if (elem->e_field != it->getFName ())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,9 +191,7 @@ bool STObject::set (SerialIter& sit, int depth)
|
|||||||
{
|
{
|
||||||
bool reachedEndOfObject = false;
|
bool reachedEndOfObject = false;
|
||||||
|
|
||||||
// Empty the destination buffer
|
v_.clear();
|
||||||
//
|
|
||||||
mData.clear ();
|
|
||||||
|
|
||||||
// Consume data in the pipe until we run out or reach the end
|
// Consume data in the pipe until we run out or reach the end
|
||||||
//
|
//
|
||||||
@@ -302,24 +228,13 @@ bool STObject::set (SerialIter& sit, int depth)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unflatten the field
|
// Unflatten the field
|
||||||
//
|
v_.emplace_back(sit, fn);
|
||||||
giveObject (
|
|
||||||
makeDeserializedObject (fn.fieldType, fn, sit, depth + 1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return reachedEndOfObject;
|
return reachedEndOfObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
|
||||||
STObject::deserialize (SerialIter& sit, SField::ref name)
|
|
||||||
{
|
|
||||||
std::unique_ptr <STObject> object (std::make_unique <STObject> (name));
|
|
||||||
object->set (sit, 1);
|
|
||||||
return std::move (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool STObject::hasMatchingEntry (const STBase& t)
|
bool STObject::hasMatchingEntry (const STBase& t)
|
||||||
{
|
{
|
||||||
const STBase* o = peekAtPField (t.getFName ());
|
const STBase* o = peekAtPField (t.getFName ());
|
||||||
@@ -342,16 +257,16 @@ std::string STObject::getFullText () const
|
|||||||
}
|
}
|
||||||
else ret = "{";
|
else ret = "{";
|
||||||
|
|
||||||
for (STBase const& elem : mData)
|
for (auto const& elem : v_)
|
||||||
{
|
{
|
||||||
if (elem.getSType () != STI_NOTPRESENT)
|
if (elem->getSType () != STI_NOTPRESENT)
|
||||||
{
|
{
|
||||||
if (!first)
|
if (!first)
|
||||||
ret += ", ";
|
ret += ", ";
|
||||||
else
|
else
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
ret += elem.getFullText ();
|
ret += elem->getFullText ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,32 +276,30 @@ std::string STObject::getFullText () const
|
|||||||
|
|
||||||
void STObject::add (Serializer& s, bool withSigningFields) const
|
void STObject::add (Serializer& s, bool withSigningFields) const
|
||||||
{
|
{
|
||||||
std::map<int, const STBase*> fields;
|
std::map<int, STBase const*> fields;
|
||||||
|
for (auto const& e : v_)
|
||||||
for (STBase const& elem : mData)
|
|
||||||
{
|
{
|
||||||
// pick out the fields and sort them
|
// pick out the fields and sort them
|
||||||
if ((elem.getSType () != STI_NOTPRESENT) &&
|
if ((e->getSType() != STI_NOTPRESENT) &&
|
||||||
elem.getFName ().shouldInclude (withSigningFields))
|
e->getFName().shouldInclude (withSigningFields))
|
||||||
{
|
{
|
||||||
fields.insert (std::make_pair (elem.getFName ().fieldCode, &elem));
|
fields.insert (std::make_pair (
|
||||||
|
e->getFName().fieldCode, &e.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& mapEntry : fields)
|
// insert sorted
|
||||||
|
for (auto const& e : fields)
|
||||||
{
|
{
|
||||||
// insert them in sorted order
|
auto const field = e.second;
|
||||||
const STBase* field = mapEntry.second;
|
|
||||||
|
|
||||||
// When we serialize an object inside another object,
|
// When we serialize an object inside another object,
|
||||||
// the type associated by rule with this field name
|
// the type associated by rule with this field name
|
||||||
// must be OBJECT, or the object cannot be deserialized
|
// must be OBJECT, or the object cannot be deserialized
|
||||||
assert ((field->getSType() != STI_OBJECT) ||
|
assert ((field->getSType() != STI_OBJECT) ||
|
||||||
(field->getFName().fieldType == STI_OBJECT));
|
(field->getFName().fieldType == STI_OBJECT));
|
||||||
|
|
||||||
field->addFieldID (s);
|
field->addFieldID (s);
|
||||||
field->add (s);
|
field->add (s);
|
||||||
|
|
||||||
if (dynamic_cast<const STArray*> (field) != nullptr)
|
if (dynamic_cast<const STArray*> (field) != nullptr)
|
||||||
s.addFieldID (STI_ARRAY, 1);
|
s.addFieldID (STI_ARRAY, 1);
|
||||||
else if (dynamic_cast<const STObject*> (field) != nullptr)
|
else if (dynamic_cast<const STObject*> (field) != nullptr)
|
||||||
@@ -398,15 +311,15 @@ std::string STObject::getText () const
|
|||||||
{
|
{
|
||||||
std::string ret = "{";
|
std::string ret = "{";
|
||||||
bool first = false;
|
bool first = false;
|
||||||
for (STBase const& elem : mData)
|
for (auto const& elem : v_)
|
||||||
{
|
{
|
||||||
if (!first)
|
if (! first)
|
||||||
{
|
{
|
||||||
ret += ", ";
|
ret += ", ";
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret += elem.getText ();
|
ret += elem->getText ();
|
||||||
}
|
}
|
||||||
ret += "}";
|
ret += "}";
|
||||||
return ret;
|
return ret;
|
||||||
@@ -423,23 +336,23 @@ bool STObject::isEquivalent (const STBase& t) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef boost::ptr_vector<STBase>::const_iterator const_iter;
|
auto it1 = v_.begin (), end1 = v_.end ();
|
||||||
const_iter it1 = mData.begin (), end1 = mData.end ();
|
auto it2 = v->v_.begin (), end2 = v->v_.end ();
|
||||||
const_iter it2 = v->mData.begin (), end2 = v->mData.end ();
|
|
||||||
|
|
||||||
while ((it1 != end1) && (it2 != end2))
|
while ((it1 != end1) && (it2 != end2))
|
||||||
{
|
{
|
||||||
if ((it1->getSType () != it2->getSType ()) || !it1->isEquivalent (*it2))
|
if ((it1->get().getSType () != it2->get().getSType ()) ||
|
||||||
|
!it1->get().isEquivalent (it2->get()))
|
||||||
{
|
{
|
||||||
if (it1->getSType () != it2->getSType ())
|
if (it1->get().getSType () != it2->get().getSType ())
|
||||||
{
|
{
|
||||||
WriteLog (lsDEBUG, STObject) << "notEquiv type " <<
|
WriteLog (lsDEBUG, STObject) << "notEquiv type " <<
|
||||||
it1->getFullText() << " != " << it2->getFullText();
|
it1->get().getFullText() << " != " << it2->get().getFullText();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WriteLog (lsDEBUG, STObject) << "notEquiv " <<
|
WriteLog (lsDEBUG, STObject) << "notEquiv " <<
|
||||||
it1->getFullText() << " != " << it2->getFullText();
|
it1->get().getFullText() << " != " << it2->get().getFullText();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -473,11 +386,10 @@ int STObject::getFieldIndex (SField::ref field) const
|
|||||||
return mType->getIndex (field);
|
return mType->getIndex (field);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (STBase const& elem : mData)
|
for (auto const& elem : v_)
|
||||||
{
|
{
|
||||||
if (elem.getFName () == field)
|
if (elem->getFName () == field)
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -505,7 +417,7 @@ STBase& STObject::getField (SField::ref field)
|
|||||||
|
|
||||||
SField::ref STObject::getFieldSType (int index) const
|
SField::ref STObject::getFieldSType (int index) const
|
||||||
{
|
{
|
||||||
return mData[index].getFName ();
|
return v_[index]->getFName ();
|
||||||
}
|
}
|
||||||
|
|
||||||
const STBase* STObject::peekAtPField (SField::ref field) const
|
const STBase* STObject::peekAtPField (SField::ref field) const
|
||||||
@@ -525,7 +437,7 @@ STBase* STObject::getPField (SField::ref field, bool createOkay)
|
|||||||
if (index == -1)
|
if (index == -1)
|
||||||
{
|
{
|
||||||
if (createOkay && isFree ())
|
if (createOkay && isFree ())
|
||||||
return getPIndex (giveObject (makeDefaultObject (field)));
|
return getPIndex(emplace_back(detail::defaultObject, field));
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -607,7 +519,7 @@ STBase* STObject::makeFieldPresent (SField::ref field)
|
|||||||
if (!isFree ())
|
if (!isFree ())
|
||||||
throw std::runtime_error ("Field not found");
|
throw std::runtime_error ("Field not found");
|
||||||
|
|
||||||
return getPIndex (giveObject (makeNonPresentObject (field)));
|
return getPIndex (emplace_back(detail::nonPresentObject, field));
|
||||||
}
|
}
|
||||||
|
|
||||||
STBase* f = getPIndex (index);
|
STBase* f = getPIndex (index);
|
||||||
@@ -615,7 +527,8 @@ STBase* STObject::makeFieldPresent (SField::ref field)
|
|||||||
if (f->getSType () != STI_NOTPRESENT)
|
if (f->getSType () != STI_NOTPRESENT)
|
||||||
return f;
|
return f;
|
||||||
|
|
||||||
mData.replace (index, makeDefaultObject (f->getFName ()).release ());
|
v_[index] = detail::STVar(
|
||||||
|
detail::defaultObject, f->getFName());
|
||||||
return getPIndex (index);
|
return getPIndex (index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,8 +543,8 @@ void STObject::makeFieldAbsent (SField::ref field)
|
|||||||
|
|
||||||
if (f.getSType () == STI_NOTPRESENT)
|
if (f.getSType () == STI_NOTPRESENT)
|
||||||
return;
|
return;
|
||||||
|
v_[index] = detail::STVar(
|
||||||
mData.replace (index, makeNonPresentObject (f.getFName ()).release ());
|
detail::nonPresentObject, f.getFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool STObject::delField (SField::ref field)
|
bool STObject::delField (SField::ref field)
|
||||||
@@ -647,7 +560,7 @@ bool STObject::delField (SField::ref field)
|
|||||||
|
|
||||||
void STObject::delField (int index)
|
void STObject::delField (int index)
|
||||||
{
|
{
|
||||||
mData.erase (mData.begin () + index);
|
v_.erase (v_.begin () + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string STObject::getFieldString (SField::ref field) const
|
std::string STObject::getFieldString (SField::ref field) const
|
||||||
@@ -771,14 +684,14 @@ STObject::set (std::unique_ptr<STBase> v)
|
|||||||
getFieldIndex(v->getFName());
|
getFieldIndex(v->getFName());
|
||||||
if (i != -1)
|
if (i != -1)
|
||||||
{
|
{
|
||||||
mData.replace(i, v.release());
|
v_[i] = std::move(*v);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (! isFree())
|
if (! isFree())
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"missing field in templated STObject");
|
"missing field in templated STObject");
|
||||||
mData.push_back(v.release());
|
v_.emplace_back(std::move(*v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -862,14 +775,14 @@ Json::Value STObject::getJson (int options) const
|
|||||||
|
|
||||||
// TODO(tom): this variable is never changed...?
|
// TODO(tom): this variable is never changed...?
|
||||||
int index = 1;
|
int index = 1;
|
||||||
for (auto const& it: mData)
|
for (auto const& elem : v_)
|
||||||
{
|
{
|
||||||
if (it.getSType () != STI_NOTPRESENT)
|
if (elem->getSType () != STI_NOTPRESENT)
|
||||||
{
|
{
|
||||||
auto const& n = it.getFName ();
|
auto const& n = elem->getFName ();
|
||||||
auto key = n.hasName () ? std::string(n.getJsonName ()) :
|
auto key = n.hasName () ? std::string(n.getJsonName ()) :
|
||||||
std::to_string (index);
|
std::to_string (index);
|
||||||
ret[key] = it.getJson (options);
|
ret[key] = elem->getJson (options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -880,15 +793,15 @@ bool STObject::operator== (const STObject& obj) const
|
|||||||
// This is not particularly efficient, and only compares data elements
|
// This is not particularly efficient, and only compares data elements
|
||||||
// with binary representations
|
// with binary representations
|
||||||
int matches = 0;
|
int matches = 0;
|
||||||
for (STBase const& t1 : mData)
|
for (auto const& t1 : v_)
|
||||||
{
|
{
|
||||||
if ((t1.getSType () != STI_NOTPRESENT) && t1.getFName ().isBinary ())
|
if ((t1->getSType () != STI_NOTPRESENT) && t1->getFName ().isBinary ())
|
||||||
{
|
{
|
||||||
// each present field must have a matching field
|
// each present field must have a matching field
|
||||||
bool match = false;
|
bool match = false;
|
||||||
for (STBase const& t2 : obj.mData)
|
for (auto const& t2 : obj.v_)
|
||||||
{
|
{
|
||||||
if (t1.getFName () == t2.getFName ())
|
if (t1->getFName () == t2->getFName ())
|
||||||
{
|
{
|
||||||
if (t2 != t1)
|
if (t2 != t1)
|
||||||
return false;
|
return false;
|
||||||
@@ -903,16 +816,16 @@ bool STObject::operator== (const STObject& obj) const
|
|||||||
{
|
{
|
||||||
WriteLog (lsTRACE, STObject) <<
|
WriteLog (lsTRACE, STObject) <<
|
||||||
"STObject::operator==: no match for " <<
|
"STObject::operator==: no match for " <<
|
||||||
t1.getFName ().getName ();
|
t1->getFName ().getName ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int fields = 0;
|
int fields = 0;
|
||||||
for (STBase const& t2 : obj.mData)
|
for (auto const& t2 : obj.v_)
|
||||||
{
|
{
|
||||||
if ((t2.getSType () != STI_NOTPRESENT) && t2.getFName ().isBinary ())
|
if ((t2->getSType () != STI_NOTPRESENT) && t2->getFName ().isBinary ())
|
||||||
++fields;
|
++fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,14 +50,11 @@ STPathElement::get_hash (STPathElement const& element)
|
|||||||
return (hash_account ^ hash_currency ^ hash_issuer);
|
return (hash_account ^ hash_currency ^ hash_issuer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
STPathSet::STPathSet (SerialIter& sit, SField::ref name)
|
||||||
STPathSet::deserialize (SerialIter& sit, SField::ref name)
|
: STBase(name)
|
||||||
{
|
{
|
||||||
std::vector<STPathElement> path;
|
std::vector<STPathElement> path;
|
||||||
|
for(;;)
|
||||||
auto pathset = std::make_unique <STPathSet> (name);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
int iType = sit.get8 ();
|
int iType = sit.get8 ();
|
||||||
|
|
||||||
@@ -71,13 +68,11 @@ STPathSet::deserialize (SerialIter& sit, SField::ref name)
|
|||||||
throw std::runtime_error ("empty path");
|
throw std::runtime_error ("empty path");
|
||||||
}
|
}
|
||||||
|
|
||||||
pathset->push_back (path);
|
push_back (path);
|
||||||
path.clear ();
|
path.clear ();
|
||||||
|
|
||||||
if (iType == STPathElement::typeNone)
|
if (iType == STPathElement::typeNone)
|
||||||
{
|
return;
|
||||||
return std::move (pathset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (iType & ~STPathElement::typeAll)
|
else if (iType & ~STPathElement::typeAll)
|
||||||
{
|
{
|
||||||
@@ -108,7 +103,6 @@ STPathSet::deserialize (SerialIter& sit, SField::ref name)
|
|||||||
path.emplace_back (account, currency, issuer, hasCurrency);
|
path.emplace_back (account, currency, issuer, hasCurrency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ STTx::getMentionedAccounts () const
|
|||||||
{
|
{
|
||||||
std::vector<RippleAddress> accounts;
|
std::vector<RippleAddress> accounts;
|
||||||
|
|
||||||
for (auto const& it : peekData ())
|
for (auto const& it : *this)
|
||||||
{
|
{
|
||||||
if (auto sa = dynamic_cast<STAccount const*> (&it))
|
if (auto sa = dynamic_cast<STAccount const*> (&it))
|
||||||
{
|
{
|
||||||
|
|||||||
183
src/ripple/protocol/impl/STVar.cpp
Normal file
183
src/ripple/protocol/impl/STVar.cpp
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/protocol/STAccount.h>
|
||||||
|
#include <ripple/protocol/STAmount.h>
|
||||||
|
#include <ripple/protocol/STArray.h>
|
||||||
|
#include <ripple/protocol/STBase.h>
|
||||||
|
#include <ripple/protocol/STBitString.h>
|
||||||
|
#include <ripple/protocol/STBlob.h>
|
||||||
|
#include <ripple/protocol/STInteger.h>
|
||||||
|
#include <ripple/protocol/STObject.h>
|
||||||
|
#include <ripple/protocol/STPathSet.h>
|
||||||
|
#include <ripple/protocol/STVector256.h>
|
||||||
|
#include <ripple/protocol/impl/STVar.h>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
defaultObject_t defaultObject;
|
||||||
|
nonPresentObject_t nonPresentObject;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
STVar::Log::~Log()
|
||||||
|
{
|
||||||
|
beast::debug_ostream os;
|
||||||
|
for(auto const& e : map_)
|
||||||
|
os << e.first << "," << e.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
STVar::Log::operator() (std::size_t n)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
auto const result = map_.emplace(n, 1);
|
||||||
|
if (! result.second)
|
||||||
|
++result.first->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
STVar::~STVar()
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar::STVar (STVar const& other)
|
||||||
|
: p_(nullptr)
|
||||||
|
{
|
||||||
|
if (other.p_ != nullptr)
|
||||||
|
p_ = other.p_->copy(
|
||||||
|
sizeof(d_), &d_);
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar::STVar (STVar&& other)
|
||||||
|
{
|
||||||
|
if (other.on_heap())
|
||||||
|
{
|
||||||
|
p_ = other.p_;
|
||||||
|
other.p_ = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_ = other.p_->move(
|
||||||
|
sizeof(d_), &d_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar&
|
||||||
|
STVar::operator= (STVar const& rhs)
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
p_ = nullptr;
|
||||||
|
if (rhs.p_)
|
||||||
|
p_ = rhs.p_->copy(
|
||||||
|
sizeof(d_), &d_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar&
|
||||||
|
STVar::operator= (STVar&& rhs)
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
if (rhs.on_heap())
|
||||||
|
{
|
||||||
|
p_ = rhs.p_;
|
||||||
|
rhs.p_ = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_ = nullptr;
|
||||||
|
p_ = rhs.p_->move(
|
||||||
|
sizeof(d_), &d_);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar::STVar (defaultObject_t, SField::ref name)
|
||||||
|
: STVar(name.fieldType, name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar::STVar (nonPresentObject_t, SField::ref name)
|
||||||
|
: STVar(STI_NOTPRESENT, name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar::STVar (SerialIter& sit, SField::ref name)
|
||||||
|
{
|
||||||
|
switch (name.fieldType)
|
||||||
|
{
|
||||||
|
case STI_NOTPRESENT: construct<STBase>(name); return;
|
||||||
|
case STI_UINT8: construct<STUInt8>(sit, name); return;
|
||||||
|
case STI_UINT16: construct<STUInt16>(sit, name); return;
|
||||||
|
case STI_UINT32: construct<STUInt32>(sit, name); return;
|
||||||
|
case STI_UINT64: construct<STUInt64>(sit, name); return;
|
||||||
|
case STI_AMOUNT: construct<STAmount>(sit, name); return;
|
||||||
|
case STI_HASH128: construct<STHash128>(sit, name); return;
|
||||||
|
case STI_HASH160: construct<STHash160>(sit, name); return;
|
||||||
|
case STI_HASH256: construct<STHash256>(sit, name); return;
|
||||||
|
case STI_VECTOR256: construct<STVector256>(sit, name); return;
|
||||||
|
case STI_VL: construct<STBlob>(sit, name); return;
|
||||||
|
case STI_ACCOUNT: construct<STAccount>(sit, name); return;
|
||||||
|
case STI_PATHSET: construct<STPathSet>(sit, name); return;
|
||||||
|
case STI_OBJECT: construct<STObject>(sit, name); return;
|
||||||
|
case STI_ARRAY: construct<STArray>(sit, name); return;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error ("Unknown object type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar::STVar (SerializedTypeID id, SField::ref name)
|
||||||
|
{
|
||||||
|
assert ((id == STI_NOTPRESENT) || (id == name.fieldType));
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case STI_NOTPRESENT: construct<STBase>(name); return;
|
||||||
|
case STI_UINT8: construct<STUInt8>(name); return;
|
||||||
|
case STI_UINT16: construct<STUInt16>(name); return;
|
||||||
|
case STI_UINT32: construct<STUInt32>(name); return;
|
||||||
|
case STI_UINT64: construct<STUInt64>(name); return;
|
||||||
|
case STI_AMOUNT: construct<STAmount>(name); return;
|
||||||
|
case STI_HASH128: construct<STHash128>(name); return;
|
||||||
|
case STI_HASH160: construct<STHash160>(name); return;
|
||||||
|
case STI_HASH256: construct<STHash256>(name); return;
|
||||||
|
case STI_VECTOR256: construct<STVector256>(name); return;
|
||||||
|
case STI_VL: construct<STBlob>(name); return;
|
||||||
|
case STI_ACCOUNT: construct<STAccount>(name); return;
|
||||||
|
case STI_PATHSET: construct<STPathSet>(name); return;
|
||||||
|
case STI_OBJECT: construct<STObject>(name); return;
|
||||||
|
case STI_ARRAY: construct<STArray>(name); return;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error ("Unknown object type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
STVar::destroy()
|
||||||
|
{
|
||||||
|
if (on_heap())
|
||||||
|
delete p_;
|
||||||
|
else
|
||||||
|
p_->~STBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // ripple
|
||||||
133
src/ripple/protocol/impl/STVar.h
Normal file
133
src/ripple/protocol/impl/STVar.h
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLE_PROTOCOL_STVAR_H_INCLUDED
|
||||||
|
#define RIPPLE_PROTOCOL_STVAR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <ripple/protocol/Serializer.h>
|
||||||
|
#include <ripple/protocol/SField.h>
|
||||||
|
#include <ripple/protocol/STBase.h>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <utility>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
#include <beast/streams/debug_ostream.h>
|
||||||
|
#include <beast/utility/static_initializer.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
struct defaultObject_t { };
|
||||||
|
struct nonPresentObject_t { };
|
||||||
|
|
||||||
|
extern defaultObject_t defaultObject;
|
||||||
|
extern nonPresentObject_t nonPresentObject;
|
||||||
|
|
||||||
|
// "variant" that can hold any type of serialized object
|
||||||
|
// and includes a small-object allocation optimization.
|
||||||
|
class STVar
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::aligned_storage<72>::type d_;
|
||||||
|
STBase* p_ = nullptr;
|
||||||
|
|
||||||
|
struct Log
|
||||||
|
{
|
||||||
|
std::mutex mutex_;
|
||||||
|
std::unordered_map<
|
||||||
|
std::size_t, std::size_t> map_;
|
||||||
|
|
||||||
|
~Log();
|
||||||
|
void operator() (std::size_t n);
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
~STVar();
|
||||||
|
STVar (STVar const& other);
|
||||||
|
STVar (STVar&& other);
|
||||||
|
STVar& operator= (STVar const& rhs);
|
||||||
|
STVar& operator= (STVar&& rhs);
|
||||||
|
|
||||||
|
STVar (STBase&& t)
|
||||||
|
{
|
||||||
|
p_ = t.move(sizeof(d_), &d_);
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar (STBase const& t)
|
||||||
|
{
|
||||||
|
p_ = t.copy(sizeof(d_), &d_);
|
||||||
|
}
|
||||||
|
|
||||||
|
STVar (defaultObject_t, SField::ref name);
|
||||||
|
STVar (nonPresentObject_t, SField::ref name);
|
||||||
|
STVar (SerialIter& sit, SField::ref name);
|
||||||
|
|
||||||
|
STBase& get() { return *p_; }
|
||||||
|
STBase& operator*() { return get(); }
|
||||||
|
STBase* operator->() { return &get(); }
|
||||||
|
STBase const& get() const { return *p_; }
|
||||||
|
STBase const& operator*() const { return get(); }
|
||||||
|
STBase const* operator->() const { return &get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
STVar (SerializedTypeID id, SField::ref name);
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
template <class T, class... Args>
|
||||||
|
void
|
||||||
|
construct(Args&&... args)
|
||||||
|
{
|
||||||
|
if(sizeof(T) > sizeof(d_))
|
||||||
|
p_ = new T(
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
else
|
||||||
|
p_ = new(&d_) T(
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
on_heap() const
|
||||||
|
{
|
||||||
|
return static_cast<void const*>(p_) !=
|
||||||
|
static_cast<void const*>(&d_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
operator== (STVar const& lhs, STVar const& rhs)
|
||||||
|
{
|
||||||
|
return lhs.get().isEquivalent(rhs.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
operator!= (STVar const& lhs, STVar const& rhs)
|
||||||
|
{
|
||||||
|
return ! (lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // ripple
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -25,31 +25,22 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
std::unique_ptr<STBase>
|
STVector256::STVector256(SerialIter& sit, SField::ref name)
|
||||||
STVector256::deserialize (SerialIter& sit, SField::ref name)
|
: STBase(name)
|
||||||
{
|
{
|
||||||
auto vec = std::make_unique<STVector256> (name);
|
|
||||||
|
|
||||||
Blob data = sit.getVL ();
|
Blob data = sit.getVL ();
|
||||||
|
|
||||||
auto const count = data.size () / (256 / 8);
|
auto const count = data.size () / (256 / 8);
|
||||||
|
mValue.reserve (count);
|
||||||
vec->mValue.reserve (count);
|
|
||||||
|
|
||||||
Blob::iterator begin = data.begin ();
|
Blob::iterator begin = data.begin ();
|
||||||
unsigned int uStart = 0;
|
unsigned int uStart = 0;
|
||||||
|
|
||||||
for (unsigned int i = 0; i != count; i++)
|
for (unsigned int i = 0; i != count; i++)
|
||||||
{
|
{
|
||||||
unsigned int uEnd = uStart + (256 / 8);
|
unsigned int uEnd = uStart + (256 / 8);
|
||||||
|
// This next line could be optimized to construct a default
|
||||||
// This next line could be optimized to construct a default uint256
|
// uint256 in the vector and then copy into it
|
||||||
// in the vector and then copy into it
|
mValue.push_back (uint256 (Blob (begin + uStart, begin + uEnd)));
|
||||||
vec->mValue.push_back (uint256 (Blob (begin + uStart, begin + uEnd)));
|
|
||||||
uStart = uEnd;
|
uStart = uEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::move (vec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public:
|
|||||||
s.add (ser);
|
s.add (ser);
|
||||||
|
|
||||||
SerialIter sit (ser);
|
SerialIter sit (ser);
|
||||||
return STAmount::deserialize (sit);
|
return STAmount(sit, sfGeneric);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include <ripple/protocol/impl/STPathSet.cpp>
|
#include <ripple/protocol/impl/STPathSet.cpp>
|
||||||
#include <ripple/protocol/impl/STTx.cpp>
|
#include <ripple/protocol/impl/STTx.cpp>
|
||||||
#include <ripple/protocol/impl/STValidation.cpp>
|
#include <ripple/protocol/impl/STValidation.cpp>
|
||||||
|
#include <ripple/protocol/impl/STVar.cpp>
|
||||||
#include <ripple/protocol/impl/STVector256.cpp>
|
#include <ripple/protocol/impl/STVector256.cpp>
|
||||||
|
|
||||||
#include <ripple/protocol/tests/BuildInfo.test.cpp>
|
#include <ripple/protocol/tests/BuildInfo.test.cpp>
|
||||||
|
|||||||
Reference in New Issue
Block a user