#pragma once #include #include #include #include #include #include #include #include #include #include namespace xrpl { class STPathElement final : public CountedObject { unsigned int type_; AccountID accountID_; PathAsset assetID_; AccountID issuerID_; bool isOffer_; std::size_t hashValue_; public: // Bitwise values (typeCurrency | typeMPT) // NOLINTNEXTLINE(cppcoreguidelines-use-enum-class) enum Type { TypeNone = 0x00, TypeAccount = 0x01, // Rippling through an account (vs taking an offer). TypeCurrency = 0x10, // Currency follows. TypeIssuer = 0x20, // Issuer follows. TypeMpt = 0x40, // MPT follows. TypeBoundary = 0xFF, // Boundary between alternate paths. TypeAsset = TypeCurrency | TypeMpt, TypeAll = TypeAccount | TypeCurrency | TypeIssuer | TypeMpt, // Combination of all types. }; STPathElement(); STPathElement(STPathElement const&) = default; STPathElement& operator=(STPathElement const&) = default; STPathElement( std::optional const& account, std::optional const& asset, std::optional const& issuer); STPathElement( AccountID const& account, PathAsset const& asset, AccountID const& issuer, bool forceAsset = false); STPathElement( unsigned int uType, AccountID const& account, PathAsset const& asset, AccountID const& issuer); [[nodiscard]] auto getNodeType() const; [[nodiscard]] bool isOffer() const; [[nodiscard]] bool isAccount() const; [[nodiscard]] bool hasIssuer() const; [[nodiscard]] bool hasCurrency() const; [[nodiscard]] bool hasMPT() const; [[nodiscard]] bool hasAsset() const; [[nodiscard]] bool isNone() const; // Nodes are either an account ID or a offer prefix. Offer prefixs denote a // class of offers. [[nodiscard]] AccountID const& getAccountID() const; [[nodiscard]] PathAsset const& getPathAsset() const; [[nodiscard]] Currency const& getCurrency() const; [[nodiscard]] MPTID const& getMPTID() const; [[nodiscard]] AccountID const& getIssuerID() const; [[nodiscard]] bool isType(Type const& pe) const; bool operator==(STPathElement const& t) const; bool operator!=(STPathElement const& t) const; private: static std::size_t getHash(STPathElement const& element); }; class STPath final : public CountedObject { std::vector path_; public: STPath() = default; STPath(std::vector p); [[nodiscard]] std::vector::size_type size() const; [[nodiscard]] bool empty() const; void pushBack(STPathElement const& e); template void emplaceBack(Args&&... args); [[nodiscard]] bool hasSeen(AccountID const& account, PathAsset const& asset, AccountID const& issuer) const; [[nodiscard]] json::Value getJson(JsonOptions) const; [[nodiscard]] std::vector::const_iterator begin() const; [[nodiscard]] std::vector::const_iterator end() const; bool operator==(STPath const& t) const; [[nodiscard]] std::vector::const_reference back() const; [[nodiscard]] 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; [[nodiscard]] json::Value getJson(JsonOptions) const override; [[nodiscard]] SerializedTypeID getSType() const override; bool assembleAdd(STPath const& base, STPathElement const& tail); [[nodiscard]] bool isEquivalent(STBase const& t) const override; [[nodiscard]] 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); [[nodiscard]] std::vector::const_iterator begin() const; [[nodiscard]] std::vector::const_iterator end() const; [[nodiscard]] std::vector::size_type size() const; [[nodiscard]] bool empty() const; void pushBack(STPath const& e); template void emplaceBack(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() : type_(TypeNone), isOffer_(true) { hashValue_ = getHash(*this); } inline STPathElement::STPathElement( std::optional const& account, std::optional const& asset, std::optional const& issuer) : type_(TypeNone) { if (!account) { isOffer_ = true; } else { isOffer_ = false; accountID_ = *account; type_ |= TypeAccount; XRPL_ASSERT( accountID_ != noAccount(), "xrpl::STPathElement::STPathElement : account is set"); } if (asset) { assetID_ = *asset; type_ |= assetID_.holds() ? TypeCurrency : TypeMpt; } if (issuer) { issuerID_ = *issuer; type_ |= TypeIssuer; XRPL_ASSERT(issuerID_ != noAccount(), "xrpl::STPathElement::STPathElement : issuer is set"); } hashValue_ = getHash(*this); } inline STPathElement::STPathElement( AccountID const& account, PathAsset const& asset, AccountID const& issuer, bool forceAsset) : type_(TypeNone) , accountID_(account) , assetID_(asset) , issuerID_(issuer) , isOffer_(isXRP(accountID_)) { if (!isOffer_) type_ |= TypeAccount; if (forceAsset || !isXRP(assetID_)) type_ |= asset.holds() ? TypeCurrency : TypeMpt; if (!isXRP(issuer)) type_ |= TypeIssuer; hashValue_ = getHash(*this); } inline STPathElement::STPathElement( unsigned int uType, AccountID const& account, PathAsset const& asset, AccountID const& issuer) : type_(uType) , accountID_(account) , assetID_(asset) , issuerID_(issuer) , isOffer_(isXRP(accountID_)) { assetID_.visit( [&](Currency const&) { type_ = type_ & (~Type::TypeMpt); }, [&](MPTID const&) { type_ = type_ & (~Type::TypeCurrency); }); hashValue_ = getHash(*this); } inline auto STPathElement::getNodeType() const { return type_; } inline bool STPathElement::isOffer() const { return isOffer_; } inline bool STPathElement::isAccount() const { return !isOffer(); } inline bool STPathElement::isType(Type const& pe) const { return (type_ & pe) != 0u; } inline bool STPathElement::hasIssuer() const { return isType(STPathElement::TypeIssuer); } inline bool STPathElement::hasCurrency() const { return isType(STPathElement::TypeCurrency); } inline bool STPathElement::hasMPT() const { return isType(STPathElement::TypeMpt); } inline bool STPathElement::hasAsset() const { return isType(STPathElement::TypeAsset); } 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 accountID_; } inline PathAsset const& STPathElement::getPathAsset() const { return assetID_; } inline Currency const& STPathElement::getCurrency() const { return assetID_.get(); } inline MPTID const& STPathElement::getMPTID() const { return assetID_.get(); } inline AccountID const& STPathElement::getIssuerID() const { return issuerID_; } inline bool STPathElement::operator==(STPathElement const& t) const { return (type_ & TypeAccount) == (t.type_ & TypeAccount) && hashValue_ == t.hashValue_ && accountID_ == t.accountID_ && assetID_ == t.assetID_ && issuerID_ == t.issuerID_; } inline bool STPathElement::operator!=(STPathElement const& t) const { return !operator==(t); } // ------------ STPath ------------ inline STPath::STPath(std::vector p) : path_(std::move(p)) { } inline std::vector::size_type STPath::size() const { return path_.size(); } inline bool STPath::empty() const { return path_.empty(); } inline void STPath::pushBack(STPathElement const& e) { path_.push_back(e); } template inline void STPath::emplaceBack(Args&&... args) { path_.emplace_back(std::forward(args)...); } inline std::vector::const_iterator STPath::begin() const { return path_.begin(); } inline std::vector::const_iterator STPath::end() const { return path_.end(); } inline bool STPath::operator==(STPath const& t) const { return path_ == t.path_; } inline std::vector::const_reference STPath::back() const { return path_.back(); } inline std::vector::const_reference STPath::front() const { return path_.front(); } inline STPathElement& STPath::operator[](int i) { return path_[i]; } inline STPathElement const& STPath::operator[](int i) const { return path_[i]; } inline void STPath::reserve(size_t s) { path_.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::pushBack(STPath const& e) { value_.push_back(e); } template inline void STPathSet::emplaceBack(Args&&... args) { value_.emplace_back(std::forward(args)...); } } // namespace xrpl