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