Revise STPathSet.

This commit is contained in:
Arthur Britto
2012-07-28 17:35:51 -07:00
parent 74d0fe000c
commit fde853d388
2 changed files with 142 additions and 63 deletions

View File

@@ -294,34 +294,54 @@ STPathSet* STPathSet::construct(SerializerIterator& s, const char *name)
{
std::vector<STPath> paths;
std::vector<STPathElement> 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<STPath>::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<STPathElement>::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<STPathElement>::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<STPath>::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<STPathElement>::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);

View File

@@ -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<STPathElement>::iterator begin() { return mPath.begin(); }
std::vector<STPathElement>::iterator end() { return mPath.end(); }
std::vector<STPathElement>::const_iterator begin() const { return mPath.begin(); }
std::vector<STPathElement>::const_iterator end() const { return mPath.end(); }
};
inline std::vector<STPathElement>::iterator range_begin(STPath & x)
{
return x.begin();
}
inline std::vector<STPathElement>::iterator range_end(STPath & x)
{
return x.end();
}
inline std::vector<STPathElement>::const_iterator range_begin(const STPath& x)
{
return x.begin();
}
inline std::vector<STPathElement>::const_iterator range_end(const STPath& x)
{
return x.end();
}
namespace boost
{
template<>
struct range_mutable_iterator< STPath >
{
typedef std::vector<STPathElement>::iterator type;
};
template<>
struct range_const_iterator< STPath >
{
typedef std::vector<STPathElement>::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<SerializedType>(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;