diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj
index 05060f72fa..4c15666f0f 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj
+++ b/Builds/VisualStudio2013/RippleD.vcxproj
@@ -2940,6 +2940,12 @@
True
True
+
+ True
+ True
+
+
+
True
True
diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters
index a229870570..bf37a52627 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters
@@ -3471,6 +3471,12 @@
ripple\protocol\impl
+
+ ripple\protocol\impl
+
+
+ ripple\protocol\impl
+
ripple\protocol\impl
diff --git a/src/ripple/app/ledger/LedgerEntrySet.cpp b/src/ripple/app/ledger/LedgerEntrySet.cpp
index 030890d8ee..02f9190788 100644
--- a/src/ripple/app/ledger/LedgerEntrySet.cpp
+++ b/src/ripple/app/ledger/LedgerEntrySet.cpp
@@ -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
if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))
- prevs.addObject (obj);
+ prevs.emplace_back (obj);
}
if (!prevs.empty ())
- mSet.getAffectedNode (it.first).addObject (prevs);
+ mSet.getAffectedNode (it.first).emplace_back (std::move(prevs));
STObject finals (sfFinalFields);
for (auto const& obj : *curNode)
{
// go through the final node for final fields
if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_DeleteFinal))
- finals.addObject (obj);
+ finals.emplace_back (obj);
}
if (!finals.empty ())
- mSet.getAffectedNode (it.first).addObject (finals);
+ mSet.getAffectedNode (it.first).emplace_back (std::move(finals));
}
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
if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))
- prevs.addObject (obj);
+ prevs.emplace_back (obj);
}
if (!prevs.empty ())
- mSet.getAffectedNode (it.first).addObject (prevs);
+ mSet.getAffectedNode (it.first).emplace_back (std::move(prevs));
STObject finals (sfFinalFields);
for (auto const& obj : *curNode)
{
// search the final node for values saved always
if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_ChangeNew))
- finals.addObject (obj);
+ finals.emplace_back (obj);
}
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)
{
@@ -572,11 +572,11 @@ void LedgerEntrySet::calcRawMeta (Serializer& s, TER result, std::uint32_t index
{
// save non-default values
if (!obj.isDefault () && obj.getFName ().shouldMeta (SField::sMD_Create | SField::sMD_Always))
- news.addObject (obj);
+ news.emplace_back (obj);
}
if (!news.empty ())
- mSet.getAffectedNode (it.first).addObject (news);
+ mSet.getAffectedNode (it.first).emplace_back (std::move(news));
}
else assert (false);
}
diff --git a/src/ripple/app/tx/TransactionMeta.cpp b/src/ripple/app/tx/TransactionMeta.cpp
index 07e32d0048..6bfd6860c0 100644
--- a/src/ripple/app/tx/TransactionMeta.cpp
+++ b/src/ripple/app/tx/TransactionMeta.cpp
@@ -29,25 +29,22 @@ namespace ripple {
// VFALCO TODO rename class to TransactionMeta
template
-TransactionMetaSet::TransactionMetaSet (uint256 const& txid, std::uint32_t ledger, T const& data,
- CtorHelper) :
- mTransactionID (txid), mLedger (ledger), mNodes (sfAffectedNodes, 32)
+TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
+ std::uint32_t ledger, T const& data, CtorHelper)
+ : mTransactionID (txid)
+ , mLedger (ledger)
+ , mNodes (sfAffectedNodes, 32)
{
Serializer s (data);
SerialIter sit (s);
- std::unique_ptr pobj = STObject::deserialize (sit, sfMetadata);
- STObject* obj = static_cast (pobj.get ());
+ STObject obj(sit, sfMetadata);
+ mResult = obj.getFieldU8 (sfTransactionResult);
+ mIndex = obj.getFieldU32 (sfTransactionIndex);
+ mNodes = * dynamic_cast (&obj.getField (sfAffectedNodes));
- if (!obj)
- throw std::runtime_error ("bad metadata");
-
- mResult = obj->getFieldU8 (sfTransactionResult);
- mIndex = obj->getFieldU32 (sfTransactionIndex);
- mNodes = * dynamic_cast (&obj->getField (sfAffectedNodes));
-
- if (obj->isFieldPresent (sfDeliveredAmount))
- setDeliveredAmount (obj->getFieldAmount (sfDeliveredAmount));
+ if (obj.isFieldPresent (sfDeliveredAmount))
+ setDeliveredAmount (obj.getFieldAmount (sfDeliveredAmount));
}
TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
@@ -125,7 +122,7 @@ std::vector TransactionMetaSet::getAffectedAccounts ()
if (inner)
{
- for (auto const& field : inner->peekData ())
+ for (auto const& field : *inner)
{
const STAccount* sa = dynamic_cast (&field);
@@ -242,7 +239,7 @@ STObject TransactionMetaSet::getAsObject () const
assert (mResult != 255);
metaData.setFieldU8 (sfTransactionResult, mResult);
metaData.setFieldU32 (sfTransactionIndex, mIndex);
- metaData.addObject (mNodes);
+ metaData.emplace_back (mNodes);
if (hasDeliveredAmount ())
metaData.setFieldAmount (sfDeliveredAmount, getDeliveredAmount ());
return metaData;
diff --git a/src/ripple/protocol/STAccount.h b/src/ripple/protocol/STAccount.h
index 4034f53712..91f4af33cc 100644
--- a/src/ripple/protocol/STAccount.h
+++ b/src/ripple/protocol/STAccount.h
@@ -44,9 +44,19 @@ public:
{
;
}
- static std::unique_ptr 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 (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
@@ -76,12 +86,6 @@ public:
bool isValueH160 () const;
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
private:
static STAccount* construct (SerialIter&, SField::ref);
};
diff --git a/src/ripple/protocol/STAmount.h b/src/ripple/protocol/STAmount.h
index a91acccc87..c879476789 100644
--- a/src/ripple/protocol/STAmount.h
+++ b/src/ripple/protocol/STAmount.h
@@ -38,7 +38,7 @@ namespace ripple {
// Wire form:
// 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
-class STAmount final
+class STAmount
: public STBase
{
public:
@@ -73,6 +73,8 @@ public:
struct unchecked { };
+ STAmount(SerialIter& sit, SField::ref name);
+
// Calls canonicalize
STAmount (SField::ref name, Issue const& issue,
mantissa_type mantissa, exponent_type exponent,
@@ -104,6 +106,18 @@ public:
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:
@@ -119,18 +133,6 @@ public:
STAmount
createFromInt64 (SField::ref n, std::int64_t v);
- static
- std::unique_ptr
- deserialize (
- SerialIter& sit, SField::ref name)
- {
- return construct (sit, name);
- }
-
- static
- STAmount
- deserialize (SerialIter&);
-
//--------------------------------------------------------------------------
//
// Observers
@@ -289,12 +291,6 @@ public:
return (mValue == 0) && mIsNative;
}
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
void canonicalize();
void set (std::int64_t v);
};
diff --git a/src/ripple/protocol/STArray.h b/src/ripple/protocol/STArray.h
index bb333f25d6..2c1f19f6ea 100644
--- a/src/ripple/protocol/STArray.h
+++ b/src/ripple/protocol/STArray.h
@@ -22,7 +22,6 @@
#include
#include
-#include
namespace ripple {
@@ -30,149 +29,94 @@ class STArray final
: public STBase
, public CountedObject
{
+private:
+ using list_type = std::vector;
+
+ enum
+ {
+ reserveSize = 8
+ };
+
+ list_type v_;
+
public:
+ // Read-only iteration
+ class Items;
+
static char const* getCountedObjectName () { return "STArray"; }
- typedef boost::ptr_vector vector;
+ using size_type = list_type::size_type;
+ using iterator = list_type::iterator;
+ using const_iterator = list_type::const_iterator;
- typedef vector::iterator iterator;
- typedef vector::const_iterator const_iterator;
- typedef vector::reverse_iterator reverse_iterator;
- typedef vector::const_reverse_iterator const_reverse_iterator;
- typedef vector::size_type size_type;
+ STArray();
+ STArray (STArray&&);
+ STArray (STArray const&) = default;
+ STArray (SField::ref f, int n);
+ STArray (SerialIter& sit, SField::ref f);
+ explicit STArray (int n);
+ explicit STArray (SField::ref f);
+ STArray& operator= (STArray const&) = default;
+ STArray& operator= (STArray&&);
-public:
- STArray () = default;
-
- explicit
- STArray (int n)
+ STBase*
+ copy (std::size_t n, void* buf) const override
{
- value.reserve (n);
+ return emplace(n, buf, *this);
}
- explicit
- STArray (SField::ref f)
- : STBase (f)
- { }
-
- STArray (SField::ref f, int n)
- : STBase (f)
+ STBase*
+ move (std::size_t n, void* buf) override
{
- 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
- 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)
{
- value.push_back (object.oClone ().release ());
- }
- STObject& operator[] (int j)
- {
- return value[j];
- }
- const STObject& operator[] (int j) const
- {
- return value[j];
+ v_.push_back(object);
}
+
iterator begin ()
{
- return value.begin ();
- }
- const_iterator begin () const
- {
- return value.begin ();
+ return v_.begin ();
}
+
iterator end ()
{
- return value.end ();
+ return v_.end ();
}
+
+ const_iterator begin () const
+ {
+ return v_.begin ();
+ }
+
const_iterator end () const
{
- return value.end ();
+ return v_.end ();
}
+
size_type size () const
{
- return value.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 ();
+ return v_.size ();
}
+
STObject& back ()
{
- return value.back ();
- }
- const STObject& back () const
- {
- return value.back ();
- }
- void pop_back ()
- {
- value.pop_back ();
+ return v_.back ();
}
+
bool empty () const
{
- return value.empty ();
+ return v_.empty ();
}
void clear ()
{
- value.clear ();
+ v_.clear ();
}
void swap (STArray & a) noexcept
{
- value.swap (a.value);
+ v_.swap (a.v_);
}
virtual std::string getFullText () const override;
@@ -185,11 +129,11 @@ public:
bool operator== (const STArray & s) const
{
- return value == s.value;
+ return v_ == s.v_;
}
bool operator!= (const STArray & s) const
{
- return value != s.value;
+ return v_ != s.v_;
}
virtual SerializedTypeID getSType () const override
@@ -199,17 +143,8 @@ public:
virtual bool isEquivalent (const STBase & t) const override;
virtual bool isDefault () const override
{
- return value.empty ();
+ return v_.empty ();
}
-
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
-private:
- vector value;
};
} // ripple
diff --git a/src/ripple/protocol/STBase.h b/src/ripple/protocol/STBase.h
index 097a57cd5b..75328584af 100644
--- a/src/ripple/protocol/STBase.h
+++ b/src/ripple/protocol/STBase.h
@@ -26,7 +26,8 @@
#include //
#include
#include
-
+#include
+#include //
namespace ripple {
// 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;
+ 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
D&
downcast()
@@ -130,27 +145,23 @@ public:
void
addFieldID (Serializer& s) const;
- static
- std::unique_ptr
- deserialize (SField::ref name);
-
- virtual
- std::unique_ptr
- duplicate () const
- {
- return std::make_unique(*fName);
- }
-
protected:
SField::ptr fName;
+
+ template
+ static
+ STBase*
+ emplace(std::size_t n, void* buf, T&& val)
+ {
+ using U = std::decay_t;
+ if (sizeof(U) > n)
+ return new U(std::forward(val));
+ return new(buf) U(std::forward(val));
+ }
};
//------------------------------------------------------------------------------
-STBase* new_clone (const STBase& s);
-
-void delete_clone (const STBase* s);
-
std::ostream& operator<< (std::ostream& out, const STBase& t);
} // ripple
diff --git a/src/ripple/protocol/STBitString.h b/src/ripple/protocol/STBitString.h
index ff2f3604c1..0d9512f809 100644
--- a/src/ripple/protocol/STBitString.h
+++ b/src/ripple/protocol/STBitString.h
@@ -57,11 +57,21 @@ public:
bitString_.SetHex (v);
}
- static
- std::unique_ptr
- deserialize (SerialIter& sit, SField::ref name)
+ STBitString (SerialIter& sit, SField::ref name)
+ : STBitString(name, sit.getBitString())
{
- return std::make_unique (name, sit.getBitString ());
+ }
+
+ 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
@@ -111,12 +121,6 @@ public:
return bitString_ == zero;
}
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
private:
BitString bitString_;
};
diff --git a/src/ripple/protocol/STBlob.h b/src/ripple/protocol/STBlob.h
index fb79841f7c..c92f57be44 100644
--- a/src/ripple/protocol/STBlob.h
+++ b/src/ripple/protocol/STBlob.h
@@ -72,11 +72,16 @@ public:
STBlob (SerialIter&, SField::ref name = sfGeneric);
- static
- std::unique_ptr
- deserialize (SerialIter& sit, SField::ref name)
+ STBase*
+ copy (std::size_t n, void* buf) const override
{
- return std::make_unique (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
@@ -150,12 +155,6 @@ public:
return value_.empty ();
}
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
private:
Buffer value_;
};
diff --git a/src/ripple/protocol/STInteger.h b/src/ripple/protocol/STInteger.h
index d6874a0f6d..c73e855058 100644
--- a/src/ripple/protocol/STInteger.h
+++ b/src/ripple/protocol/STInteger.h
@@ -40,9 +40,19 @@ public:
: STBase (n), value_ (v)
{ }
- static
- std::unique_ptr
- deserialize (SerialIter& sit, SField::ref name);
+ STInteger(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
getSType () const override;
@@ -92,12 +102,6 @@ public:
return v && (value_ == v->value_);
}
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
private:
Integer value_;
};
diff --git a/src/ripple/protocol/STLedgerEntry.h b/src/ripple/protocol/STLedgerEntry.h
index 1b99220f41..9c31a2b408 100644
--- a/src/ripple/protocol/STLedgerEntry.h
+++ b/src/ripple/protocol/STLedgerEntry.h
@@ -41,6 +41,18 @@ public:
STLedgerEntry (LedgerEntryType type, 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
{
return STI_LEDGERENTRY;
@@ -94,12 +106,6 @@ public:
std::uint32_t & prevLedgerID);
std::vector getOwners (); // nodes notified if this node is deleted
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
private:
/** Make STObject comply with the template for this SLE type
Can throw
diff --git a/src/ripple/protocol/STObject.h b/src/ripple/protocol/STObject.h
index 221e12b301..cfaa519808 100644
--- a/src/ripple/protocol/STObject.h
+++ b/src/ripple/protocol/STObject.h
@@ -25,7 +25,15 @@
#include
#include
#include
+#include
+#include
#include
+#include
+
+#include
+#include
+#include
+#include
namespace ripple {
@@ -35,50 +43,98 @@ class STObject
: public STBase
, public CountedObject
{
+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 lock(mutex_);
+ auto const result = map_.emplace(n, 1);
+ if (! result.second)
+ ++result.first->second;
+ }
+ };
+
+ using list_type = std::vector;
+
+ list_type v_;
+ SOTemplate const* mType;
+
public:
+ using iterator = boost::transform_iterator<
+ Transform, STObject::list_type::const_iterator>;
+
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& 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 (name), mType (nullptr)
+ STBase*
+ move (std::size_t n, void* buf) override
{
- ;
+ return emplace(n, buf, std::move(*this));
}
- STObject (const SOTemplate & type, SField::ref name)
- : STBase (name)
+ iterator begin() const
{
- set (type);
+ return iterator(v_.begin());
}
- STObject (
- const SOTemplate & type, SerialIter & sit, SField::ref name)
- : STBase (name)
+ iterator end() const
{
- set (sit);
- setType (type);
+ return iterator(v_.end());
}
- STObject (SField::ref name, boost::ptr_vector& data)
- : STBase (name), mType (nullptr)
+ bool empty() const
{
- mData.swap (data);
+ return v_.empty();
}
- std::unique_ptr oClone () const
- {
- return std::make_unique (*this);
- }
-
- virtual ~STObject () { }
-
- static std::unique_ptr
- deserialize (SerialIter & sit, SField::ref name);
-
bool setType (const SOTemplate & type);
bool isValidForType ();
bool isFieldAllowed (SField::ref);
@@ -97,7 +153,7 @@ public:
virtual bool isEquivalent (const STBase & t) const override;
virtual bool isDefault () const override
{
- return mData.empty ();
+ return v_.empty();
}
virtual void add (Serializer & s) const override
@@ -123,49 +179,17 @@ public:
// TODO(tom): options should be an enum.
virtual Json::Value getJson (int options) const override;
- int addObject (const STBase & t)
+ template
+ std::size_t
+ emplace_back(Args&&... args)
{
- mData.push_back (t.duplicate ().release ());
- return mData.size () - 1;
- }
- int giveObject (std::unique_ptr 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& peekData () const
- {
- return mData;
- }
- boost::ptr_vector& 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 ();
+ v_.emplace_back(std::forward(args)...);
+ return v_.size() - 1;
}
int getCount () const
{
- return mData.size ();
+ return v_.size ();
}
bool setFlag (std::uint32_t);
@@ -178,19 +202,19 @@ public:
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
{
- return & (mData[offset]);
+ return &v_[offset].get();
}
STBase* getPIndex (int offset)
{
- return & (mData[offset]);
+ return &v_[offset].get();
}
int getFieldIndex (SField::ref field) const;
@@ -270,51 +294,6 @@ public:
bool delField (SField::ref field);
void delField (int index);
- static std::unique_ptr
- makeDefaultObject (SerializedTypeID id, SField::ref name);
-
- // VFALCO TODO remove the 'depth' parameter
- static std::unique_ptr makeDeserializedObject (
- SerializedTypeID id,
- SField::ref name,
- SerialIter&,
- int depth);
-
- static std::unique_ptr
- makeNonPresentObject (SField::ref name)
- {
- return makeDefaultObject (STI_NOTPRESENT, name);
- }
-
- static std::unique_ptr makeDefaultObject (SField::ref name)
- {
- return makeDefaultObject (name.fieldType, name);
- }
-
- // field iterator stuff
- typedef boost::ptr_vector::iterator iterator;
- typedef boost::ptr_vector::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 operator== (const STObject & o) const;
@@ -323,12 +302,6 @@ public:
return ! (*this == o);
}
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
private:
// Implementation for getting (most) fields that return by value.
//
@@ -425,10 +398,6 @@ private:
(*cf) = value;
}
-
-private:
- boost::ptr_vector mData;
- const SOTemplate* mType;
};
} // ripple
diff --git a/src/ripple/protocol/STPathSet.h b/src/ripple/protocol/STPathSet.h
index 43211d93a8..f2d9ff474e 100644
--- a/src/ripple/protocol/STPathSet.h
+++ b/src/ripple/protocol/STPathSet.h
@@ -237,14 +237,18 @@ public:
: STBase (n)
{ }
- static
- std::unique_ptr
- deserialize (SerialIter& sit, SField::ref name);
+ STPathSet (SerialIter& sit, SField::ref name);
- std::unique_ptr
- duplicate () const override
+ STBase*
+ copy (std::size_t n, void* buf) const override
{
- return std::make_unique(*this);
+ return emplace(n, buf, *this);
+ }
+
+ STBase*
+ move (std::size_t n, void* buf) override
+ {
+ return emplace(n, buf, std::move(*this));
}
void
diff --git a/src/ripple/protocol/STTx.h b/src/ripple/protocol/STTx.h
index 03699d4fe9..3c4999664b 100644
--- a/src/ripple/protocol/STTx.h
+++ b/src/ripple/protocol/STTx.h
@@ -56,6 +56,18 @@ public:
// Only called from ripple::RPC::transactionSign - can we eliminate this?
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
SerializedTypeID getSType () const override
{
@@ -143,12 +155,6 @@ public:
char status,
std::string const& escapedMetaData) const;
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
private:
TxType tx_type_;
diff --git a/src/ripple/protocol/STValidation.h b/src/ripple/protocol/STValidation.h
index 42bc1d7a7f..818b95877b 100644
--- a/src/ripple/protocol/STValidation.h
+++ b/src/ripple/protocol/STValidation.h
@@ -52,6 +52,18 @@ public:
STValidation (uint256 const& ledgerHash, std::uint32_t signTime,
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;
std::uint32_t getSignTime () const;
std::uint32_t getFlags () const;
diff --git a/src/ripple/protocol/STVector256.h b/src/ripple/protocol/STVector256.h
index 20c83d2646..30bd1ee3ef 100644
--- a/src/ripple/protocol/STVector256.h
+++ b/src/ripple/protocol/STVector256.h
@@ -27,7 +27,7 @@
namespace ripple {
-class STVector256 final
+class STVector256
: public STBase
{
public:
@@ -41,6 +41,20 @@ public:
: 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
getSType () const override
{
@@ -50,10 +64,6 @@ public:
void
add (Serializer& s) const override;
- static
- std::unique_ptr
- deserialize (SerialIter& sit, SField::ref name);
-
Json::Value
getJson (int) const override;
@@ -72,12 +82,6 @@ public:
mValue = v.mValue;
}
- std::unique_ptr
- duplicate () const override
- {
- return std::make_unique(*this);
- }
-
/** Retrieve a copy of the vector we contain */
explicit
operator std::vector () const
diff --git a/src/ripple/protocol/impl/STAccount.cpp b/src/ripple/protocol/impl/STAccount.cpp
index c47cd49487..0a50efc729 100644
--- a/src/ripple/protocol/impl/STAccount.cpp
+++ b/src/ripple/protocol/impl/STAccount.cpp
@@ -22,6 +22,11 @@
namespace ripple {
+STAccount::STAccount (SerialIter& sit, SField::ref name)
+ : STAccount(name, sit.getVLBuffer())
+{
+}
+
std::string STAccount::getText () const
{
Account u;
diff --git a/src/ripple/protocol/impl/STAmount.cpp b/src/ripple/protocol/impl/STAmount.cpp
index 4cf5167716..c35f92806e 100644
--- a/src/ripple/protocol/impl/STAmount.cpp
+++ b/src/ripple/protocol/impl/STAmount.cpp
@@ -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 (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,
mantissa_type mantissa, exponent_type exponent,
bool native, bool negative)
@@ -140,58 +216,7 @@ STAmount::STAmount (Issue const& issue,
std::unique_ptr
STAmount::construct (SerialIter& sit, SField::ref name)
{
- std::uint64_t value = sit.get64 ();
-
- // native
- if ((value & cNotNative) == 0)
- {
- // positive
- if ((value & cPosNative) != 0)
- return std::make_unique (name, value & ~cPosNative, false);
-
- // negative
- if (value == 0)
- throw std::runtime_error ("negative zero is not canonical");
-
- return std::make_unique (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 (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 (name, issue, value, offset, isNegative);
- }
-
- if (offset != 512)
- throw std::runtime_error ("invalid currency value");
-
- return std::make_unique (name, issue);
+ return std::make_unique(sit, name);
}
STAmount
@@ -202,16 +227,6 @@ STAmount::createFromInt64 (SField::ref name, std::int64_t value)
: STAmount (name, static_cast (-value), true);
}
-STAmount STAmount::deserialize (SerialIter& it)
-{
- auto s = construct (it, sfGeneric);
-
- if (!s)
- throw std::runtime_error("Deserialization error");
-
- return STAmount (*s);
-}
-
//------------------------------------------------------------------------------
//
// Operators
diff --git a/src/ripple/protocol/impl/STArray.cpp b/src/ripple/protocol/impl/STArray.cpp
index 73525afd64..d943fca691 100644
--- a/src/ripple/protocol/impl/STArray.cpp
+++ b/src/ripple/protocol/impl/STArray.cpp
@@ -24,12 +24,47 @@
namespace ripple {
-std::unique_ptr
-STArray::deserialize (SerialIter& sit, SField::ref field)
+STArray::STArray()
{
- std::unique_ptr ret (std::make_unique (field));
- vector& value (ret->getValue ());
+ // VFALCO NOTE We need to determine if this is
+ // 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 ())
{
int type, field;
@@ -45,7 +80,7 @@ STArray::deserialize (SerialIter& sit, SField::ref field)
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 ())
{
@@ -60,10 +95,9 @@ STArray::deserialize (SerialIter& sit, SField::ref field)
throw std::runtime_error ("Non-object in array");
}
- value.push_back (new STObject (fn));
- value.rbegin ()->set (sit, 1);
+ v_.emplace_back(fn);
+ v_.back().set (sit, 1);
}
- return std::move (ret);
}
std::string STArray::getFullText () const
@@ -71,12 +105,12 @@ std::string STArray::getFullText () const
std::string r = "[";
bool first = true;
- for (STObject const& o : value)
+ for (auto const& obj : v_)
{
if (!first)
r += ",";
- r += o.getFullText ();
+ r += obj.getFullText ();
first = false;
}
@@ -89,7 +123,7 @@ std::string STArray::getText () const
std::string r = "[";
bool first = true;
- for (STObject const& o : value)
+ for (STObject const& o : v_)
{
if (!first)
r += ",";
@@ -106,7 +140,7 @@ Json::Value STArray::getJson (int p) const
{
Json::Value v = Json::arrayValue;
int index = 1;
- for (auto const& object: value)
+ for (auto const& object: v_)
{
if (object.getSType () != STI_NOTPRESENT)
{
@@ -122,7 +156,7 @@ Json::Value STArray::getJson (int p) const
void STArray::add (Serializer& s) const
{
- for (STObject const& object : value)
+ for (STObject const& object : v_)
{
object.addFieldID (s);
object.add (s);
@@ -141,12 +175,12 @@ bool STArray::isEquivalent (const STBase& t) const
return false;
}
- return value == v->value;
+ return v_ == v->v_;
}
void STArray::sort (bool (*compare) (const STObject&, const STObject&))
{
- value.sort (compare);
+ std::sort(v_.begin(), v_.end(), compare);
}
} // ripple
diff --git a/src/ripple/protocol/impl/STBase.cpp b/src/ripple/protocol/impl/STBase.cpp
index d07aa5d46e..2a1309c7c3 100644
--- a/src/ripple/protocol/impl/STBase.cpp
+++ b/src/ripple/protocol/impl/STBase.cpp
@@ -145,28 +145,8 @@ STBase::addFieldID (Serializer& s) const
s.addFieldID (fName->fieldType, fName->fieldValue);
}
-std::unique_ptr
-STBase::deserialize (SField::ref name)
-{
- return std::make_unique(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&
operator<< (std::ostream& out, const STBase& t)
{
diff --git a/src/ripple/protocol/impl/STInteger.cpp b/src/ripple/protocol/impl/STInteger.cpp
index 0c8cd24b6e..33def2a942 100644
--- a/src/ripple/protocol/impl/STInteger.cpp
+++ b/src/ripple/protocol/impl/STInteger.cpp
@@ -28,6 +28,12 @@
namespace ripple {
+template<>
+STInteger::STInteger(SerialIter& sit, SField::ref name)
+ : STInteger(name, sit.get8())
+{
+}
+
template <>
SerializedTypeID
STUInt8::getSType () const
@@ -35,13 +41,6 @@ STUInt8::getSType () const
return STI_UINT8;
}
-template <>
-std::unique_ptr
-STUInt8::deserialize (SerialIter& sit, SField::ref name)
-{
- return std::make_unique (name, sit.get8 ());
-}
-
template <>
std::string
STUInt8::getText () const
@@ -77,6 +76,12 @@ STUInt8::getJson (int) const
//------------------------------------------------------------------------------
+template<>
+STInteger::STInteger(SerialIter& sit, SField::ref name)
+ : STInteger(name, sit.get16())
+{
+}
+
template <>
SerializedTypeID
STUInt16::getSType () const
@@ -84,13 +89,6 @@ STUInt16::getSType () const
return STI_UINT16;
}
-template <>
-std::unique_ptr
-STUInt16::deserialize (SerialIter& sit, SField::ref name)
-{
- return std::make_unique (name, sit.get16 ());
-}
-
template <>
std::string
STUInt16::getText () const
@@ -143,6 +141,12 @@ STUInt16::getJson (int) const
//------------------------------------------------------------------------------
+template<>
+STInteger::STInteger(SerialIter& sit, SField::ref name)
+ : STInteger(name, sit.get32())
+{
+}
+
template <>
SerializedTypeID
STUInt32::getSType () const
@@ -150,13 +154,6 @@ STUInt32::getSType () const
return STI_UINT32;
}
-template <>
-std::unique_ptr
-STUInt32::deserialize (SerialIter& sit, SField::ref name)
-{
- return std::make_unique (name, sit.get32 ());
-}
-
template <>
std::string
STUInt32::getText () const
@@ -173,6 +170,12 @@ STUInt32::getJson (int) const
//------------------------------------------------------------------------------
+template<>
+STInteger::STInteger(SerialIter& sit, SField::ref name)
+ : STInteger(name, sit.get64())
+{
+}
+
template <>
SerializedTypeID
STUInt64::getSType () const
@@ -180,13 +183,6 @@ STUInt64::getSType () const
return STI_UINT64;
}
-template <>
-std::unique_ptr
-STUInt64::deserialize (SerialIter& sit, SField::ref name)
-{
- return std::make_unique (name, sit.get64 ());
-}
-
template <>
std::string
STUInt64::getText () const
diff --git a/src/ripple/protocol/impl/STObject.cpp b/src/ripple/protocol/impl/STObject.cpp
index 201a9af9bc..ec7baed184 100644
--- a/src/ripple/protocol/impl/STObject.cpp
+++ b/src/ripple/protocol/impl/STObject.cpp
@@ -31,222 +31,150 @@
namespace ripple {
-std::unique_ptr
-STObject::makeDefaultObject (SerializedTypeID id, SField::ref name)
+STObject::~STObject()
{
- assert ((id == STI_NOTPRESENT) || (id == name.fieldType));
-
- switch (id)
- {
- case STI_NOTPRESENT:
- return std::make_unique (name);
-
- case STI_UINT8:
- return std::make_unique (name);
-
- case STI_UINT16:
- return std::make_unique (name);
-
- case STI_UINT32:
- return std::make_unique (name);
-
- case STI_UINT64:
- return std::make_unique (name);
-
- case STI_AMOUNT:
- return std::make_unique (name);
-
- case STI_HASH128:
- return std::make_unique (name);
-
- case STI_HASH160:
- return std::make_unique (name);
-
- case STI_HASH256:
- return std::make_unique (name);
-
- case STI_VECTOR256:
- return std::make_unique (name);
-
- case STI_VL:
- return std::make_unique (name);
-
- case STI_ACCOUNT:
- return std::make_unique (name);
-
- case STI_PATHSET:
- return std::make_unique (name);
-
- case STI_OBJECT:
- return std::make_unique (name);
-
- case STI_ARRAY:
- return std::make_unique (name);
-
- default:
- WriteLog (lsFATAL, STObject) <<
- "Object type: " << beast::lexicalCast (id);
- assert (false);
- throw std::runtime_error ("Unknown object type");
- }
+#if 0
+ // Turn this on to get a histogram on exit
+ static beast::static_initializer log;
+ (*log)(v_.size());
+#endif
}
-// VFALCO TODO Remove the 'depth' parameter
-std::unique_ptr
-STObject::makeDeserializedObject (SerializedTypeID id, SField::ref name,
- SerialIter& sit, int depth)
+STObject::STObject(STObject&& other)
+ : STBase(other.getFName())
+ , v_(std::move(other.v_))
+ , mType(other.mType)
{
- switch (id)
- {
- case STI_NOTPRESENT:
- return STBase::deserialize (name);
+}
- case STI_UINT8:
- return STUInt8::deserialize (sit, name);
+STObject::STObject (SField::ref name)
+ : STBase (name)
+ , mType (nullptr)
+{
+ // VFALCO TODO See if this is the right thing to do
+ //v_.reserve(reserveSize);
+}
- case STI_UINT16:
- return STUInt16::deserialize (sit, name);
+STObject::STObject (SOTemplate const& type,
+ SField::ref name)
+ : STBase (name)
+{
+ set (type);
+}
- case STI_UINT32:
- return STUInt32::deserialize (sit, name);
+STObject::STObject (SOTemplate const& type,
+ SerialIter & sit, SField::ref name)
+ : STBase (name)
+{
+ v_.reserve(type.peek().size());
+ set (sit);
+ setType (type);
+}
- case STI_UINT64:
- return STUInt64::deserialize (sit, name);
+STObject::STObject (SField::ref name,
+ boost::ptr_vector& data)
+ : STBase (name)
+ , mType (nullptr)
+{
+ v_.reserve(data.size());
+ for (auto const& b : data)
+ v_.emplace_back(b);
+}
- case STI_AMOUNT:
- return STAmount::deserialize (sit, name);
+STObject::STObject (SerialIter& sit, SField::ref name)
+ : STBase(name)
+ , mType(nullptr)
+{
+ set(sit, 0);
+}
- case STI_HASH128:
- return STHash128::deserialize (sit, name);
-
- case STI_HASH160:
- return STHash160::deserialize (sit, name);
-
- case STI_HASH256:
- 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");
- }
+STObject&
+STObject::operator= (STObject&& other)
+{
+ setFName(other.getFName());
+ mType = other.mType;
+ v_ = std::move(other.v_);
+ return *this;
}
void STObject::set (const SOTemplate& type)
{
- mData.clear ();
+ v_.clear();
+ v_.reserve(type.peek().size());
mType = &type;
- for (SOTemplate::value_type const& elem : type.peek ())
+ for (auto const& elem : type.peek())
{
if (elem->flags != SOE_REQUIRED)
- giveObject (makeNonPresentObject (elem->e_field));
+ v_.emplace_back(detail::nonPresentObject, elem->e_field);
else
- giveObject (makeDefaultObject (elem->e_field));
+ v_.emplace_back(detail::defaultObject, elem->e_field);
}
}
bool STObject::setType (const SOTemplate& type)
{
- boost::ptr_vector newData (type.peek ().size ());
bool valid = true;
-
mType = &type;
-
- STBase** array = mData.c_array();
- std::size_t count = mData.size ();
-
- for (auto const& elem : type.peek ())
+ decltype(v_) v;
+ v.reserve(type.peek().size());
+ for (auto const& e : type.peek())
{
- // Loop through all the fields in the template
- bool match = false;
-
- for (std::size_t i = 0; i < count; ++i)
- 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)
+ auto const iter = std::find_if(
+ v_.begin(), v_.end(), [&](detail::STVar const& b)
+ { return b.get().getFName() == e->e_field; });
+ if (iter != v_.end())
{
- // no match found in the object for an entry in the template
- if (elem->flags == SOE_REQUIRED)
+ if ((e->flags == SOE_DEFAULT) && iter->get().isDefault())
{
WriteLog (lsWARNING, STObject) <<
"setType( " << getFName ().getName () <<
- ") invalid missing " << elem->e_field.fieldName;
+ ") invalid default " << e->e_field.fieldName;
valid = false;
}
-
- // Make a default object
- newData.push_back (makeNonPresentObject (elem->e_field).release ());
+ v.emplace_back(std::move(*iter));
+ v_.erase(iter);
+ }
+ 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 (std::size_t i = 0; i < count; ++i)
+ for (auto const& e : v_)
{
// Anything left over in the object must be discardable
- if ((array[i] != nullptr) && !array[i]->getFName ().isDiscardable ())
+ if (! e->getFName().isDiscardable())
{
WriteLog (lsWARNING, STObject) <<
"setType( " << getFName ().getName () <<
- ") invalid leftover " << array[i]->getFName ().getName ();
+ ") invalid leftover " << e->getFName ().getName ();
valid = false;
}
}
-
// Swap the template matching data in for the old data,
// freeing any leftover junk
- mData.swap (newData);
-
+ v_.swap(v);
return valid;
}
bool STObject::isValidForType ()
{
- boost::ptr_vector::iterator it = mData.begin ();
-
- for (SOTemplate::value_type const& elem : mType->peek ())
+ auto it = v_.begin();
+ for (SOTemplate::value_type const& elem : mType->peek())
{
- if (it == mData.end ())
+ if (it == v_.end())
return false;
-
- if (elem->e_field != it->getFName ())
+ if (elem->e_field != it->get().getFName())
return false;
-
++it;
}
-
return true;
}
@@ -263,9 +191,7 @@ bool STObject::set (SerialIter& sit, int depth)
{
bool reachedEndOfObject = false;
- // Empty the destination buffer
- //
- mData.clear ();
+ v_.clear();
// 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
- //
- giveObject (
- makeDeserializedObject (fn.fieldType, fn, sit, depth + 1));
+ v_.emplace_back(sit, fn);
}
}
return reachedEndOfObject;
}
-
-std::unique_ptr
-STObject::deserialize (SerialIter& sit, SField::ref name)
-{
- std::unique_ptr object (std::make_unique (name));
- object->set (sit, 1);
- return std::move (object);
-}
-
bool STObject::hasMatchingEntry (const STBase& t)
{
const STBase* o = peekAtPField (t.getFName ());
@@ -342,16 +257,16 @@ std::string STObject::getFullText () const
}
else ret = "{";
- for (STBase const& elem : mData)
+ for (auto const& elem : v_)
{
- if (elem.getSType () != STI_NOTPRESENT)
+ if (elem->getSType () != STI_NOTPRESENT)
{
if (!first)
ret += ", ";
else
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
{
- std::map fields;
-
- for (STBase const& elem : mData)
+ std::map fields;
+ for (auto const& e : v_)
{
// pick out the fields and sort them
- if ((elem.getSType () != STI_NOTPRESENT) &&
- elem.getFName ().shouldInclude (withSigningFields))
+ if ((e->getSType() != STI_NOTPRESENT) &&
+ 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
- const STBase* field = mapEntry.second;
+ auto const field = e.second;
// When we serialize an object inside another object,
// the type associated by rule with this field name
// must be OBJECT, or the object cannot be deserialized
assert ((field->getSType() != STI_OBJECT) ||
(field->getFName().fieldType == STI_OBJECT));
-
field->addFieldID (s);
field->add (s);
-
if (dynamic_cast (field) != nullptr)
s.addFieldID (STI_ARRAY, 1);
else if (dynamic_cast (field) != nullptr)
@@ -398,15 +311,15 @@ std::string STObject::getText () const
{
std::string ret = "{";
bool first = false;
- for (STBase const& elem : mData)
+ for (auto const& elem : v_)
{
- if (!first)
+ if (! first)
{
ret += ", ";
first = false;
}
- ret += elem.getText ();
+ ret += elem->getText ();
}
ret += "}";
return ret;
@@ -423,23 +336,23 @@ bool STObject::isEquivalent (const STBase& t) const
return false;
}
- typedef boost::ptr_vector::const_iterator const_iter;
- const_iter it1 = mData.begin (), end1 = mData.end ();
- const_iter it2 = v->mData.begin (), end2 = v->mData.end ();
+ auto it1 = v_.begin (), end1 = v_.end ();
+ auto it2 = v->v_.begin (), end2 = v->v_.end ();
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 " <<
- it1->getFullText() << " != " << it2->getFullText();
+ it1->get().getFullText() << " != " << it2->get().getFullText();
}
else
{
WriteLog (lsDEBUG, STObject) << "notEquiv " <<
- it1->getFullText() << " != " << it2->getFullText();
+ it1->get().getFullText() << " != " << it2->get().getFullText();
}
return false;
}
@@ -473,11 +386,10 @@ int STObject::getFieldIndex (SField::ref field) const
return mType->getIndex (field);
int i = 0;
- for (STBase const& elem : mData)
+ for (auto const& elem : v_)
{
- if (elem.getFName () == field)
+ if (elem->getFName () == field)
return i;
-
++i;
}
return -1;
@@ -505,7 +417,7 @@ STBase& STObject::getField (SField::ref field)
SField::ref STObject::getFieldSType (int index) const
{
- return mData[index].getFName ();
+ return v_[index]->getFName ();
}
const STBase* STObject::peekAtPField (SField::ref field) const
@@ -525,7 +437,7 @@ STBase* STObject::getPField (SField::ref field, bool createOkay)
if (index == -1)
{
if (createOkay && isFree ())
- return getPIndex (giveObject (makeDefaultObject (field)));
+ return getPIndex(emplace_back(detail::defaultObject, field));
return nullptr;
}
@@ -607,7 +519,7 @@ STBase* STObject::makeFieldPresent (SField::ref field)
if (!isFree ())
throw std::runtime_error ("Field not found");
- return getPIndex (giveObject (makeNonPresentObject (field)));
+ return getPIndex (emplace_back(detail::nonPresentObject, field));
}
STBase* f = getPIndex (index);
@@ -615,7 +527,8 @@ STBase* STObject::makeFieldPresent (SField::ref field)
if (f->getSType () != STI_NOTPRESENT)
return f;
- mData.replace (index, makeDefaultObject (f->getFName ()).release ());
+ v_[index] = detail::STVar(
+ detail::defaultObject, f->getFName());
return getPIndex (index);
}
@@ -630,8 +543,8 @@ void STObject::makeFieldAbsent (SField::ref field)
if (f.getSType () == STI_NOTPRESENT)
return;
-
- mData.replace (index, makeNonPresentObject (f.getFName ()).release ());
+ v_[index] = detail::STVar(
+ detail::nonPresentObject, f.getFName());
}
bool STObject::delField (SField::ref field)
@@ -647,7 +560,7 @@ bool STObject::delField (SField::ref field)
void STObject::delField (int index)
{
- mData.erase (mData.begin () + index);
+ v_.erase (v_.begin () + index);
}
std::string STObject::getFieldString (SField::ref field) const
@@ -771,14 +684,14 @@ STObject::set (std::unique_ptr v)
getFieldIndex(v->getFName());
if (i != -1)
{
- mData.replace(i, v.release());
+ v_[i] = std::move(*v);
}
else
{
if (! isFree())
throw std::runtime_error(
"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...?
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 ()) :
std::to_string (index);
- ret[key] = it.getJson (options);
+ ret[key] = elem->getJson (options);
}
}
return ret;
@@ -880,15 +793,15 @@ bool STObject::operator== (const STObject& obj) const
// This is not particularly efficient, and only compares data elements
// with binary representations
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
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)
return false;
@@ -903,16 +816,16 @@ bool STObject::operator== (const STObject& obj) const
{
WriteLog (lsTRACE, STObject) <<
"STObject::operator==: no match for " <<
- t1.getFName ().getName ();
+ t1->getFName ().getName ();
return false;
}
}
}
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;
}
diff --git a/src/ripple/protocol/impl/STPathSet.cpp b/src/ripple/protocol/impl/STPathSet.cpp
index 275e4fd821..9491246bcb 100644
--- a/src/ripple/protocol/impl/STPathSet.cpp
+++ b/src/ripple/protocol/impl/STPathSet.cpp
@@ -50,14 +50,11 @@ STPathElement::get_hash (STPathElement const& element)
return (hash_account ^ hash_currency ^ hash_issuer);
}
-std::unique_ptr
-STPathSet::deserialize (SerialIter& sit, SField::ref name)
+STPathSet::STPathSet (SerialIter& sit, SField::ref name)
+ : STBase(name)
{
std::vector path;
-
- auto pathset = std::make_unique (name);
-
- do
+ for(;;)
{
int iType = sit.get8 ();
@@ -71,13 +68,11 @@ STPathSet::deserialize (SerialIter& sit, SField::ref name)
throw std::runtime_error ("empty path");
}
- pathset->push_back (path);
+ push_back (path);
path.clear ();
if (iType == STPathElement::typeNone)
- {
- return std::move (pathset);
- }
+ return;
}
else if (iType & ~STPathElement::typeAll)
{
@@ -108,7 +103,6 @@ STPathSet::deserialize (SerialIter& sit, SField::ref name)
path.emplace_back (account, currency, issuer, hasCurrency);
}
}
- while (1);
}
bool
diff --git a/src/ripple/protocol/impl/STTx.cpp b/src/ripple/protocol/impl/STTx.cpp
index a6185918b5..70b0dbc923 100644
--- a/src/ripple/protocol/impl/STTx.cpp
+++ b/src/ripple/protocol/impl/STTx.cpp
@@ -127,7 +127,7 @@ STTx::getMentionedAccounts () const
{
std::vector accounts;
- for (auto const& it : peekData ())
+ for (auto const& it : *this)
{
if (auto sa = dynamic_cast (&it))
{
diff --git a/src/ripple/protocol/impl/STVar.cpp b/src/ripple/protocol/impl/STVar.cpp
new file mode 100644
index 0000000000..4d5940c46d
--- /dev/null
+++ b/src/ripple/protocol/impl/STVar.cpp
@@ -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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+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 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(name); return;
+ case STI_UINT8: construct(sit, name); return;
+ case STI_UINT16: construct(sit, name); return;
+ case STI_UINT32: construct(sit, name); return;
+ case STI_UINT64: construct(sit, name); return;
+ case STI_AMOUNT: construct(sit, name); return;
+ case STI_HASH128: construct(sit, name); return;
+ case STI_HASH160: construct(sit, name); return;
+ case STI_HASH256: construct(sit, name); return;
+ case STI_VECTOR256: construct(sit, name); return;
+ case STI_VL: construct(sit, name); return;
+ case STI_ACCOUNT: construct(sit, name); return;
+ case STI_PATHSET: construct(sit, name); return;
+ case STI_OBJECT: construct(sit, name); return;
+ case STI_ARRAY: construct(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(name); return;
+ case STI_UINT8: construct(name); return;
+ case STI_UINT16: construct(name); return;
+ case STI_UINT32: construct(name); return;
+ case STI_UINT64: construct(name); return;
+ case STI_AMOUNT: construct(name); return;
+ case STI_HASH128: construct(name); return;
+ case STI_HASH160: construct(name); return;
+ case STI_HASH256: construct(name); return;
+ case STI_VECTOR256: construct(name); return;
+ case STI_VL: construct(name); return;
+ case STI_ACCOUNT: construct(name); return;
+ case STI_PATHSET: construct(name); return;
+ case STI_OBJECT: construct(name); return;
+ case STI_ARRAY: construct(name); return;
+ default:
+ throw std::runtime_error ("Unknown object type");
+ }
+}
+
+void
+STVar::destroy()
+{
+ if (on_heap())
+ delete p_;
+ else
+ p_->~STBase();
+}
+
+} // detail
+} // ripple
diff --git a/src/ripple/protocol/impl/STVar.h b/src/ripple/protocol/impl/STVar.h
new file mode 100644
index 0000000000..ea31641e9f
--- /dev/null
+++ b/src/ripple/protocol/impl/STVar.h
@@ -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
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+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
+ void
+ construct(Args&&... args)
+ {
+ if(sizeof(T) > sizeof(d_))
+ p_ = new T(
+ std::forward(args)...);
+ else
+ p_ = new(&d_) T(
+ std::forward(args)...);
+ }
+
+ bool
+ on_heap() const
+ {
+ return static_cast(p_) !=
+ static_cast(&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
diff --git a/src/ripple/protocol/impl/STVector256.cpp b/src/ripple/protocol/impl/STVector256.cpp
index 6ffec60937..18bca897c2 100644
--- a/src/ripple/protocol/impl/STVector256.cpp
+++ b/src/ripple/protocol/impl/STVector256.cpp
@@ -25,31 +25,22 @@
namespace ripple {
-std::unique_ptr
-STVector256::deserialize (SerialIter& sit, SField::ref name)
+STVector256::STVector256(SerialIter& sit, SField::ref name)
+ : STBase(name)
{
- auto vec = std::make_unique (name);
-
Blob data = sit.getVL ();
-
auto const count = data.size () / (256 / 8);
-
- vec->mValue.reserve (count);
-
+ mValue.reserve (count);
Blob::iterator begin = data.begin ();
unsigned int uStart = 0;
-
for (unsigned int i = 0; i != count; i++)
{
- unsigned int uEnd = uStart + (256 / 8);
-
- // This next line could be optimized to construct a default uint256
- // in the vector and then copy into it
- vec->mValue.push_back (uint256 (Blob (begin + uStart, begin + uEnd)));
+ unsigned int uEnd = uStart + (256 / 8);
+ // This next line could be optimized to construct a default
+ // uint256 in the vector and then copy into it
+ mValue.push_back (uint256 (Blob (begin + uStart, begin + uEnd)));
uStart = uEnd;
}
-
- return std::move (vec);
}
void
diff --git a/src/ripple/protocol/tests/STAmount.test.cpp b/src/ripple/protocol/tests/STAmount.test.cpp
index 6c934d509b..125e39b9f1 100644
--- a/src/ripple/protocol/tests/STAmount.test.cpp
+++ b/src/ripple/protocol/tests/STAmount.test.cpp
@@ -34,7 +34,7 @@ public:
s.add (ser);
SerialIter sit (ser);
- return STAmount::deserialize (sit);
+ return STAmount(sit, sfGeneric);
}
//--------------------------------------------------------------------------
diff --git a/src/ripple/unity/protocol.cpp b/src/ripple/unity/protocol.cpp
index 0ba50c8d8c..86d6ecb175 100644
--- a/src/ripple/unity/protocol.cpp
+++ b/src/ripple/unity/protocol.cpp
@@ -47,6 +47,7 @@
#include
#include
#include
+#include
#include
#include