diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index bd76f5c84..fbd861c44 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -294,34 +294,54 @@ STPathSet* STPathSet::construct(SerializerIterator& s, const char *name) { std::vector paths; std::vector path; + do { - switch(s.get8()) + int iType = s.get8(); + + if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary) { - case STPathElement::typeEnd: - if (path.empty()) - { - if (!paths.empty()) - throw std::runtime_error("empty last path"); - } - else paths.push_back(path); + if (path.empty()) + throw std::runtime_error("empty path"); + + paths.push_back(path); + path.clear(); + + if (iType == STPathElement::typeEnd) + { return new STPathSet(name, paths); + } + } + else if (iType & STPathElement::typeStrayBits) + { + throw std::runtime_error("bad path element"); + } + else + { + bool bAccount = !!(iType & STPathElement::typeAccount); + bool bOffer = !!(iType & STPathElement::typeOffer); + bool bCurrency = !!(iType & STPathElement::typeCurrency); + bool bIssuer = !!(iType & STPathElement::typeIssuer); - case STPathElement::typeBoundary: - if (path.empty()) - throw std::runtime_error("empty path"); - paths.push_back(path); - path.clear(); + if (!bAccount && !bOffer) + { + throw std::runtime_error("bad path element"); + } - case STPathElement::typeAccount: - path.push_back(STPathElement(STPathElement::typeAccount, s.get160())); - break; + uint160 uAccountID; + uint160 uCurrency; + uint160 uIssuerID; - case STPathElement::typeOffer: - path.push_back(STPathElement(STPathElement::typeOffer, s.get160())); - break; + if (bAccount) + uAccountID = s.get160(); - default: throw std::runtime_error("Unknown path element"); + if (bCurrency) + uCurrency = s.get160(); + + if (bIssuer) + uIssuerID = s.get160(); + + path.push_back(STPathElement(uAccountID, uCurrency, uIssuerID)); } } while(1); } @@ -329,8 +349,10 @@ STPathSet* STPathSet::construct(SerializerIterator& s, const char *name) int STPathSet::getLength() const { int ret = 0; + for (std::vector::const_iterator it = value.begin(), end = value.end(); it != end; ++it) ret += it->getSerializeSize(); + return (ret != 0) ? ret : (ret + 1); } @@ -340,30 +362,22 @@ Json::Value STPath::getJson(int) const BOOST_FOREACH(std::vector::const_iterator::value_type it, mPath) { - switch (it.getNodeType()) - { - case STPathElement::typeAccount: - { - Json::Value elem(Json::objectValue); + Json::Value elem(Json::objectValue); + int iType = it.getNodeType(); - elem["account"] = NewcoinAddress::createHumanAccountID(it.getNode()); + elem["type"] = it.getNodeType(); + elem["type_hex"] = strHex(it.getNodeType()); - ret.append(elem); - break; - } + if (iType & STPathElement::typeAccount) + elem["account"] = NewcoinAddress::createHumanAccountID(it.getAccountID()); - case STPathElement::typeOffer: - { - Json::Value elem(Json::objectValue); + if (iType & STPathElement::typeCurrency) + elem["currency"] = STAmount::createHumanCurrency(it.getCurrency()); - elem["offer"] = it.getNode().GetHex(); + if (iType & STPathElement::typeIssuer) + elem["issuer"] = NewcoinAddress::createHumanAccountID(it.getIssuerID()); - ret.append(elem); - break; - } - - default: throw std::runtime_error("Unknown path element"); - } + ret.append(elem); } return ret; @@ -379,12 +393,13 @@ Json::Value STPathSet::getJson(int options) const return ret; } +#if 0 std::string STPath::getText() const { std::string ret("["); bool first = true; - BOOST_FOREACH(std::vector::const_iterator::value_type it, mPath) + BOOST_FOREACH(const STPathElement& it, mPath) { if (!first) ret += ", "; switch (it.getNodeType()) @@ -410,7 +425,9 @@ std::string STPath::getText() const return ret + "]"; } +#endif +#if 0 std::string STPathSet::getText() const { std::string ret("{"); @@ -427,23 +444,34 @@ std::string STPathSet::getText() const } return ret + "}"; } +#endif void STPathSet::add(Serializer& s) const { - bool firstPath = true; + bool bFirst = true; - BOOST_FOREACH(std::vector::const_iterator::value_type pit, value) + BOOST_FOREACH(const STPath& spPath, value) { - if (!firstPath) + if (!bFirst) { s.add8(STPathElement::typeBoundary); - firstPath = false; + bFirst = false; } - for (std::vector::const_iterator eit = pit.begin(), eend = pit.end(); eit != eend; ++eit) + BOOST_FOREACH(const STPathElement& speElement, spPath) { - s.add8(eit->getNodeType()); - s.add160(eit->getNode()); + int iType = speElement.getNodeType(); + + s.add8(iType); + + if (iType && STPathElement::typeAccount) + s.add160(speElement.getAccountID()); + + if (iType && STPathElement::typeCurrency) + s.add160(speElement.getCurrency()); + + if (iType && STPathElement::typeIssuer) + s.add160(speElement.getIssuerID()); } } s.add8(STPathElement::typeEnd); diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index b1ce80eed..89c3a89dd 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -518,26 +518,40 @@ public: class STPathElement { public: - static const int typeEnd = 0x00; - static const int typeAccount = 0x01; // Rippling through an account - static const int typeOffer = 0x02; // Claiming an offer - static const int typeBoundary = 0xFF; // boundary between alternate paths + enum { + typeEnd = 0x00, + typeAccount = 0x01, // Rippling through an account + typeOffer = 0x02, // Claiming an offer + typeCurrency = 0x10, // Currency follows + typeIssuer = 0x20, // Issuer follows + typeBoundary = 0xFF, // boundary between alternate paths + typeStrayBits = 0xCC, // Bits that must be zero. + }; protected: - int mType; - uint160 mNode; + int mType; + uint160 mAccountID; + uint160 mCurrency; + uint160 mIssuerID; public: - STPathElement(int type, const uint160& node) : mType(type), mNode(node) { ; } - int getNodeType() const { return mType; } - bool isAccount() const { return mType == typeAccount; } - bool isOffer() const { return mType == typeOffer; } + STPathElement(const uint160& uAccountID, const uint160& uCurrency, const uint160& uIssuerID) + : mAccountID(uAccountID), mCurrency(uCurrency), mIssuerID(uIssuerID) + { + mType = + (uAccountID.isZero() ? STPathElement::typeOffer : STPathElement::typeAccount) + | (uCurrency.isZero() ? 0 : STPathElement::typeCurrency) + | (uIssuerID.isZero() ? 0 : STPathElement::typeIssuer); + } + + int getNodeType() const { return mType; } + bool isOffer() const { return mAccountID.isZero(); } + bool isAccount() const { return !isOffer(); } // Nodes are either an account ID or a offer prefix. Offer prefixs denote a class of offers. - const uint160& getNode() const { return mNode; } - - void setType(int type) { mType = type; } - void setNode(const uint160& n) { mNode = n; } + const uint160& getAccountID() const { return mAccountID; } + const uint160& getCurrency() const { return mCurrency; } + const uint160& getIssuerID() const { return mIssuerID; } }; class STPath @@ -556,12 +570,49 @@ public: void addElement(const STPathElement& e) { mPath.push_back(e); } void clear() { mPath.clear(); } int getSerializeSize() const { return 1 + mPath.size() * 21; } - std::string getText() const; +// std::string getText() const; Json::Value getJson(int) const; + + std::vector::iterator begin() { return mPath.begin(); } + std::vector::iterator end() { return mPath.end(); } std::vector::const_iterator begin() const { return mPath.begin(); } std::vector::const_iterator end() const { return mPath.end(); } }; +inline std::vector::iterator range_begin(STPath & x) +{ + return x.begin(); +} + +inline std::vector::iterator range_end(STPath & x) +{ + return x.end(); +} + +inline std::vector::const_iterator range_begin(const STPath& x) +{ + return x.begin(); +} + +inline std::vector::const_iterator range_end(const STPath& x) +{ + return x.end(); +} + +namespace boost +{ + template<> + struct range_mutable_iterator< STPath > + { + typedef std::vector::iterator type; + }; + + template<> + struct range_const_iterator< STPath > + { + typedef std::vector::const_iterator type; + }; +} class STPathSet : public SerializedType { // A set of zero or more payment paths protected: @@ -580,7 +631,7 @@ public: { return std::auto_ptr(construct(sit, name)); } int getLength() const; - std::string getText() const; +// std::string getText() const; void add(Serializer& s) const; virtual Json::Value getJson(int) const;