#ifndef XRPL_PROTOCOL_STPATHSET_H_INCLUDED #define XRPL_PROTOCOL_STPATHSET_H_INCLUDED #include #include #include #include #include #include #include #include namespace ripple { class STPathElement final : public CountedObject { unsigned int mType; AccountID mAccountID; Currency mCurrencyID; AccountID mIssuerID; bool is_offer_; std::size_t hash_value_; public: enum Type { typeNone = 0x00, typeAccount = 0x01, // Rippling through an account (vs taking an offer). typeCurrency = 0x10, // Currency follows. typeIssuer = 0x20, // Issuer follows. typeBoundary = 0xFF, // Boundary between alternate paths. typeAll = typeAccount | typeCurrency | typeIssuer, // Combination of all types. }; STPathElement(); STPathElement(STPathElement const&) = default; STPathElement& operator=(STPathElement const&) = default; STPathElement( std::optional const& account, std::optional const& currency, std::optional const& issuer); STPathElement( AccountID const& account, Currency const& currency, AccountID const& issuer, bool forceCurrency = false); STPathElement( unsigned int uType, AccountID const& account, Currency const& currency, AccountID const& issuer); auto getNodeType() const; bool isOffer() const; bool isAccount() const; bool hasIssuer() const; bool hasCurrency() const; bool isNone() const; // Nodes are either an account ID or a offer prefix. Offer prefixs denote a // class of offers. AccountID const& getAccountID() const; Currency const& getCurrency() const; AccountID const& getIssuerID() const; bool operator==(STPathElement const& t) const; bool operator!=(STPathElement const& t) const; private: static std::size_t get_hash(STPathElement const& element); }; class STPath final : public CountedObject { std::vector mPath; public: STPath() = default; STPath(std::vector p); std::vector::size_type size() const; bool empty() const; void push_back(STPathElement const& e); template void emplace_back(Args&&... args); bool hasSeen( AccountID const& account, Currency const& currency, AccountID const& issuer) const; Json::Value getJson(JsonOptions) const; std::vector::const_iterator begin() const; std::vector::const_iterator end() const; bool operator==(STPath const& t) const; std::vector::const_reference back() const; std::vector::const_reference front() const; STPathElement& operator[](int i); STPathElement const& operator[](int i) const; void reserve(size_t s); }; //------------------------------------------------------------------------------ // A set of zero or more payment paths class STPathSet final : public STBase, public CountedObject { std::vector value; public: STPathSet() = default; STPathSet(SField const& n); STPathSet(SerialIter& sit, SField const& name); void add(Serializer& s) const override; Json::Value getJson(JsonOptions) const override; SerializedTypeID getSType() const override; bool assembleAdd(STPath const& base, STPathElement const& tail); bool isEquivalent(STBase const& t) const override; bool isDefault() const override; // std::vector like interface: std::vector::const_reference operator[](std::vector::size_type n) const; std::vector::reference operator[](std::vector::size_type n); std::vector::const_iterator begin() const; std::vector::const_iterator end() const; std::vector::size_type size() const; bool empty() const; void push_back(STPath const& e); template void emplace_back(Args&&... args); private: STBase* copy(std::size_t n, void* buf) const override; STBase* move(std::size_t n, void* buf) override; friend class detail::STVar; }; // ------------ STPathElement ------------ inline STPathElement::STPathElement() : mType(typeNone), is_offer_(true) { hash_value_ = get_hash(*this); } inline STPathElement::STPathElement( std::optional const& account, std::optional const& currency, std::optional const& issuer) : mType(typeNone) { if (!account) { is_offer_ = true; } else { is_offer_ = false; mAccountID = *account; mType |= typeAccount; XRPL_ASSERT( mAccountID != noAccount(), "ripple::STPathElement::STPathElement : account is set"); } if (currency) { mCurrencyID = *currency; mType |= typeCurrency; } if (issuer) { mIssuerID = *issuer; mType |= typeIssuer; XRPL_ASSERT( mIssuerID != noAccount(), "ripple::STPathElement::STPathElement : issuer is set"); } hash_value_ = get_hash(*this); } inline STPathElement::STPathElement( AccountID const& account, Currency const& currency, AccountID const& issuer, bool forceCurrency) : mType(typeNone) , mAccountID(account) , mCurrencyID(currency) , mIssuerID(issuer) , is_offer_(isXRP(mAccountID)) { if (!is_offer_) mType |= typeAccount; if (forceCurrency || !isXRP(currency)) mType |= typeCurrency; if (!isXRP(issuer)) mType |= typeIssuer; hash_value_ = get_hash(*this); } inline STPathElement::STPathElement( unsigned int uType, AccountID const& account, Currency const& currency, AccountID const& issuer) : mType(uType) , mAccountID(account) , mCurrencyID(currency) , mIssuerID(issuer) , is_offer_(isXRP(mAccountID)) { hash_value_ = get_hash(*this); } inline auto STPathElement::getNodeType() const { return mType; } inline bool STPathElement::isOffer() const { return is_offer_; } inline bool STPathElement::isAccount() const { return !isOffer(); } inline bool STPathElement::hasIssuer() const { return getNodeType() & STPathElement::typeIssuer; } inline bool STPathElement::hasCurrency() const { return getNodeType() & STPathElement::typeCurrency; } inline bool STPathElement::isNone() const { return getNodeType() == STPathElement::typeNone; } // Nodes are either an account ID or a offer prefix. Offer prefixs denote a // class of offers. inline AccountID const& STPathElement::getAccountID() const { return mAccountID; } inline Currency const& STPathElement::getCurrency() const { return mCurrencyID; } inline AccountID const& STPathElement::getIssuerID() const { return mIssuerID; } inline bool STPathElement::operator==(STPathElement const& t) const { return (mType & typeAccount) == (t.mType & typeAccount) && hash_value_ == t.hash_value_ && mAccountID == t.mAccountID && mCurrencyID == t.mCurrencyID && mIssuerID == t.mIssuerID; } inline bool STPathElement::operator!=(STPathElement const& t) const { return !operator==(t); } // ------------ STPath ------------ inline STPath::STPath(std::vector p) : mPath(std::move(p)) { } inline std::vector::size_type STPath::size() const { return mPath.size(); } inline bool STPath::empty() const { return mPath.empty(); } inline void STPath::push_back(STPathElement const& e) { mPath.push_back(e); } template inline void STPath::emplace_back(Args&&... args) { mPath.emplace_back(std::forward(args)...); } inline std::vector::const_iterator STPath::begin() const { return mPath.begin(); } inline std::vector::const_iterator STPath::end() const { return mPath.end(); } inline bool STPath::operator==(STPath const& t) const { return mPath == t.mPath; } inline std::vector::const_reference STPath::back() const { return mPath.back(); } inline std::vector::const_reference STPath::front() const { return mPath.front(); } inline STPathElement& STPath::operator[](int i) { return mPath[i]; } inline STPathElement const& STPath::operator[](int i) const { return mPath[i]; } inline void STPath::reserve(size_t s) { mPath.reserve(s); } // ------------ STPathSet ------------ inline STPathSet::STPathSet(SField const& n) : STBase(n) { } // std::vector like interface: inline std::vector::const_reference STPathSet::operator[](std::vector::size_type n) const { return value[n]; } inline std::vector::reference STPathSet::operator[](std::vector::size_type n) { return value[n]; } inline std::vector::const_iterator STPathSet::begin() const { return value.begin(); } inline std::vector::const_iterator STPathSet::end() const { return value.end(); } inline std::vector::size_type STPathSet::size() const { return value.size(); } inline bool STPathSet::empty() const { return value.empty(); } inline void STPathSet::push_back(STPath const& e) { value.push_back(e); } template inline void STPathSet::emplace_back(Args&&... args) { value.emplace_back(std::forward(args)...); } } // namespace ripple #endif