mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Rename RippleAsset to Issue and RippleBook to Book:
* Split STAmount out of SerializedTypes.h * New concept of "Issue consistency": when either both or neither of its currency and account are XRP. * Stop checking for consistency of Issue in its constructor. * Clarification of mIsNative logic in STAmount. * Usual cleanups.
This commit is contained in:
committed by
Nik Bougalis
parent
a96dee85d2
commit
206efbf30d
@@ -28,7 +28,7 @@ std::uint64_t STAmount::uRateOne =
|
||||
|
||||
std::string STAmount::getHumanCurrency () const
|
||||
{
|
||||
return to_string (mCurrency);
|
||||
return to_string (mIssue.currency);
|
||||
}
|
||||
|
||||
bool STAmount::bSetJson (const Json::Value& jvSource)
|
||||
@@ -101,14 +101,14 @@ STAmount::STAmount (SField::ref n, const Json::Value& v)
|
||||
else
|
||||
{
|
||||
// non-XRP
|
||||
if (!to_currency (mCurrency, currency.asString ()))
|
||||
if (!to_currency (mIssue.currency, currency.asString ()))
|
||||
throw std::runtime_error ("invalid currency");
|
||||
|
||||
if (!issuer.isString ()
|
||||
|| !to_issuer (mIssuer, issuer.asString ()))
|
||||
|| !to_issuer (mIssue.account, issuer.asString ()))
|
||||
throw std::runtime_error ("invalid issuer");
|
||||
|
||||
if (mIssuer.isZero ())
|
||||
if (isXRP (*this))
|
||||
throw std::runtime_error ("invalid issuer");
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ STAmount::STAmount (SField::ref n, const Json::Value& v)
|
||||
|
||||
bool STAmount::setValue (const std::string& sAmount)
|
||||
{
|
||||
// Note: mIsNative and mCurrency must be set already!
|
||||
// Note: mIsNative and mIssue.currency must be set already!
|
||||
|
||||
static boost::regex reNumber (
|
||||
"\\`([+-]?)(\\d*)(\\.(\\d*))?([eE]([+-]?)(\\d+))?\\'");
|
||||
@@ -253,14 +253,14 @@ bool STAmount::setFullValue (const std::string& sAmount, const std::string& sCur
|
||||
//
|
||||
// Figure out the currency.
|
||||
//
|
||||
if (!to_currency (mCurrency, sCurrency))
|
||||
if (!to_currency (mIssue.currency, sCurrency))
|
||||
{
|
||||
WriteLog (lsINFO, STAmount) << "Currency malformed: " << sCurrency;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
mIsNative = !mCurrency;
|
||||
mIsNative = !mIssue.currency;
|
||||
|
||||
//
|
||||
// Figure out the issuer.
|
||||
@@ -275,10 +275,10 @@ bool STAmount::setFullValue (const std::string& sAmount, const std::string& sCur
|
||||
return false;
|
||||
}
|
||||
|
||||
mIssuer = naIssuerID.getAccountID ();
|
||||
mIssue.account = naIssuerID.getAccountID ();
|
||||
|
||||
// Stamps not must have an issuer.
|
||||
if (mIsNative && !mIssuer.isZero ())
|
||||
if (mIsNative && !isXRP (*this))
|
||||
{
|
||||
WriteLog (lsINFO, STAmount) << "Issuer specified for XRP: " << sIssuer;
|
||||
|
||||
@@ -289,13 +289,15 @@ bool STAmount::setFullValue (const std::string& sAmount, const std::string& sCur
|
||||
}
|
||||
|
||||
// amount = value * [10 ^ offset]
|
||||
// representation range is 10^80 - 10^(-80)
|
||||
// on the wire, high 8 bits are (offset+142), low 56 bits are value
|
||||
// value is zero if amount is zero, otherwise value is 10^15 to (10^16 - 1) inclusive
|
||||
// Representation range is 10^80 - 10^(-80).
|
||||
// On the wire, high 8 bits are (offset+142), low 56 bits are value.
|
||||
//
|
||||
// Value is zero if amount is zero, otherwise value is 10^15 to (10^16 - 1)
|
||||
// inclusive.
|
||||
|
||||
void STAmount::canonicalize ()
|
||||
{
|
||||
if (mCurrency.isZero ())
|
||||
if (isXRP (*this))
|
||||
{
|
||||
// native currency amounts should always have an offset of zero
|
||||
mIsNative = true;
|
||||
@@ -384,8 +386,8 @@ void STAmount::add (Serializer& s) const
|
||||
else // 256 = positive
|
||||
s.add64 (mValue | (static_cast<std::uint64_t> (mOffset + 512 + 256 + 97) << (64 - 10)));
|
||||
|
||||
s.add160 (mCurrency);
|
||||
s.add160 (mIssuer);
|
||||
s.add160 (mIssue.currency);
|
||||
s.add160 (mIssue.account);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,18 +400,23 @@ STAmount STAmount::createFromInt64 (SField::ref name, std::int64_t value)
|
||||
|
||||
void STAmount::setValue (const STAmount& a)
|
||||
{
|
||||
mCurrency = a.mCurrency;
|
||||
mIssuer = a.mIssuer;
|
||||
mIssue = a.mIssue;
|
||||
mValue = a.mValue;
|
||||
mOffset = a.mOffset;
|
||||
mIsNative = a.mIsNative;
|
||||
mIsNegative = a.mIsNegative;
|
||||
}
|
||||
|
||||
void STAmount::setIssue (Issue const& issue) {
|
||||
mIssue = std::move(issue);
|
||||
mIsNative = isXRP (*this);
|
||||
}
|
||||
|
||||
int STAmount::compare (const STAmount& a) const
|
||||
{
|
||||
// Compares the value of a to the value of this STAmount, amounts must be comparable
|
||||
if (mIsNegative != a.mIsNegative) return mIsNegative ? -1 : 1;
|
||||
if (mIsNegative != a.mIsNegative)
|
||||
return mIsNegative ? -1 : 1;
|
||||
|
||||
if (!mValue)
|
||||
{
|
||||
@@ -446,14 +453,16 @@ STAmount* STAmount::construct (SerializerIterator& sit, SField::ref name)
|
||||
return new STAmount (name, value, true); // negative
|
||||
}
|
||||
|
||||
Currency currency;
|
||||
currency.copyFrom (sit.get160 ());
|
||||
Issue issue;
|
||||
issue.currency.copyFrom (sit.get160 ());
|
||||
|
||||
if (!currency)
|
||||
throw std::runtime_error ("invalid non-native currency");
|
||||
if (isXRP (issue.currency))
|
||||
throw std::runtime_error ("invalid native currency");
|
||||
|
||||
Account issuer;
|
||||
issuer.copyFrom (sit.get160 ());
|
||||
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<int> (value >> (64 - 10));
|
||||
@@ -473,21 +482,23 @@ STAmount* STAmount::construct (SerializerIterator& sit, SField::ref name)
|
||||
throw std::runtime_error ("invalid currency value");
|
||||
}
|
||||
|
||||
return new STAmount (name, currency, issuer, value, offset, isNegative);
|
||||
return new STAmount (name, issue, value, offset, isNegative);
|
||||
}
|
||||
|
||||
if (offset != 512)
|
||||
throw std::runtime_error ("invalid currency value");
|
||||
|
||||
return new STAmount (name, currency, issuer);
|
||||
return new STAmount (name, issue);
|
||||
}
|
||||
|
||||
std::int64_t STAmount::getSNValue () const
|
||||
{
|
||||
// signed native value
|
||||
if (!mIsNative) throw std::runtime_error ("not native");
|
||||
if (!mIsNative)
|
||||
throw std::runtime_error ("not native");
|
||||
|
||||
if (mIsNegative) return - static_cast<std::int64_t> (mValue);
|
||||
if (mIsNegative)
|
||||
return - static_cast<std::int64_t> (mValue);
|
||||
|
||||
return static_cast<std::int64_t> (mValue);
|
||||
}
|
||||
@@ -526,7 +537,7 @@ std::string STAmount::getText () const
|
||||
{
|
||||
ret.append (raw_value);
|
||||
|
||||
if(scientific)
|
||||
if (scientific)
|
||||
{
|
||||
ret.append (1, 'e');
|
||||
ret.append (std::to_string (mOffset));
|
||||
@@ -604,16 +615,13 @@ bool STAmount::isComparable (const STAmount& t) const
|
||||
|
||||
if (t.mIsNative) return false;
|
||||
|
||||
return mCurrency == t.mCurrency;
|
||||
return mIssue.currency == t.mIssue.currency;
|
||||
}
|
||||
|
||||
bool STAmount::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STAmount* v = dynamic_cast<const STAmount*> (&t);
|
||||
|
||||
if (!v) return false;
|
||||
|
||||
return isComparable (*v) && (mIsNegative == v->mIsNegative) && (mValue == v->mValue) && (mOffset == v->mOffset);
|
||||
return v && (*v == *this);
|
||||
}
|
||||
|
||||
void STAmount::throwComparable (const STAmount& t) const
|
||||
@@ -625,12 +633,18 @@ void STAmount::throwComparable (const STAmount& t) const
|
||||
|
||||
bool STAmount::operator== (const STAmount& a) const
|
||||
{
|
||||
return isComparable (a) && (mIsNegative == a.mIsNegative) && (mOffset == a.mOffset) && (mValue == a.mValue);
|
||||
return isComparable (a) &&
|
||||
mIsNegative == a.mIsNegative &&
|
||||
mOffset == a.mOffset &&
|
||||
mValue == a.mValue;
|
||||
}
|
||||
|
||||
bool STAmount::operator!= (const STAmount& a) const
|
||||
{
|
||||
return (mOffset != a.mOffset) || (mValue != a.mValue) || (mIsNegative != a.mIsNegative) || !isComparable (a);
|
||||
return mOffset != a.mOffset ||
|
||||
mValue != a.mValue ||
|
||||
mIsNegative != a.mIsNegative ||
|
||||
!isComparable (a);
|
||||
}
|
||||
|
||||
bool STAmount::operator< (const STAmount& a) const
|
||||
@@ -673,17 +687,19 @@ STAmount STAmount::operator- (void) const
|
||||
{
|
||||
if (mValue == 0) return *this;
|
||||
|
||||
return STAmount (getFName (), mCurrency, mIssuer, mValue, mOffset, mIsNative, !mIsNegative);
|
||||
return STAmount (
|
||||
getFName (), mIssue, mValue, mOffset, mIsNative, !mIsNegative);
|
||||
}
|
||||
|
||||
STAmount& STAmount::operator= (std::uint64_t v)
|
||||
{
|
||||
// does not copy name, does not change currency type
|
||||
// Does not copy name, does not change currency type.
|
||||
mOffset = 0;
|
||||
mValue = v;
|
||||
mIsNegative = false;
|
||||
|
||||
if (!mIsNative) canonicalize ();
|
||||
if (!mIsNative)
|
||||
canonicalize ();
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -732,12 +748,14 @@ bool STAmount::operator>= (std::uint64_t v) const
|
||||
|
||||
STAmount STAmount::operator+ (std::uint64_t v) const
|
||||
{
|
||||
return STAmount (getFName (), getSNValue () + static_cast<std::int64_t> (v));
|
||||
return STAmount (
|
||||
getFName (), getSNValue () + static_cast<std::int64_t> (v));
|
||||
}
|
||||
|
||||
STAmount STAmount::operator- (std::uint64_t v) const
|
||||
{
|
||||
return STAmount (getFName (), getSNValue () - static_cast<std::int64_t> (v));
|
||||
return STAmount (
|
||||
getFName (), getSNValue () - static_cast<std::int64_t> (v));
|
||||
}
|
||||
|
||||
STAmount::operator double () const
|
||||
@@ -746,7 +764,8 @@ STAmount::operator double () const
|
||||
if (!mValue)
|
||||
return 0.0;
|
||||
|
||||
if (mIsNegative) return -1.0 * static_cast<double> (mValue) * pow (10.0, mOffset);
|
||||
if (mIsNegative)
|
||||
return -1.0 * static_cast<double> (mValue) * pow (10.0, mOffset);
|
||||
|
||||
return static_cast<double> (mValue) * pow (10.0, mOffset);
|
||||
}
|
||||
@@ -761,18 +780,22 @@ STAmount operator+ (const STAmount& v1, const STAmount& v2)
|
||||
if (v1 == zero)
|
||||
{
|
||||
// Result must be in terms of v1 currency and issuer.
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative);
|
||||
return STAmount (v1.getFName (), v1.mIssue,
|
||||
v2.mValue, v2.mOffset, v2.mIsNegative);
|
||||
}
|
||||
|
||||
if (v1.mIsNative)
|
||||
return STAmount (v1.getFName (), v1.getSNValue () + v2.getSNValue ());
|
||||
|
||||
int ov1 = v1.mOffset, ov2 = v2.mOffset;
|
||||
std::int64_t vv1 = static_cast<std::int64_t> (v1.mValue), vv2 = static_cast<std::int64_t> (v2.mValue);
|
||||
std::int64_t vv1 = static_cast<std::int64_t> (v1.mValue);
|
||||
std::int64_t vv2 = static_cast<std::int64_t> (v2.mValue);
|
||||
|
||||
if (v1.mIsNegative) vv1 = -vv1;
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
|
||||
if (v2.mIsNegative) vv2 = -vv2;
|
||||
if (v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
|
||||
while (ov1 < ov2)
|
||||
{
|
||||
@@ -786,16 +809,17 @@ STAmount operator+ (const STAmount& v1, const STAmount& v2)
|
||||
++ov2;
|
||||
}
|
||||
|
||||
// this addition cannot overflow an std::int64_t, it can overflow an STAmount and the constructor will throw
|
||||
// This addition cannot overflow an std::int64_t. It can overflow an
|
||||
// STAmount and the constructor will throw.
|
||||
|
||||
std::int64_t fv = vv1 + vv2;
|
||||
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
|
||||
else if (fv >= 0)
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, fv, ov1, false);
|
||||
return STAmount (v1.getFName (), v1.mIssue);
|
||||
if (fv >= 0)
|
||||
return STAmount (v1.getFName (), v1.mIssue, fv, ov1, false);
|
||||
else
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, -fv, ov1, true);
|
||||
return STAmount (v1.getFName (), v1.mIssue, -fv, ov1, true);
|
||||
}
|
||||
|
||||
STAmount operator- (const STAmount& v1, const STAmount& v2)
|
||||
@@ -807,16 +831,21 @@ STAmount operator- (const STAmount& v1, const STAmount& v2)
|
||||
|
||||
if (v2.mIsNative)
|
||||
{
|
||||
// XXX This could be better, check for overflow and that maximum range is covered.
|
||||
return STAmount::createFromInt64 (v1.getFName (), v1.getSNValue () - v2.getSNValue ());
|
||||
// XXX This could be better, check for overflow and that maximum range
|
||||
// is covered.
|
||||
return STAmount::createFromInt64 (
|
||||
v1.getFName (), v1.getSNValue () - v2.getSNValue ());
|
||||
}
|
||||
|
||||
int ov1 = v1.mOffset, ov2 = v2.mOffset;
|
||||
std::int64_t vv1 = static_cast<std::int64_t> (v1.mValue), vv2 = static_cast<std::int64_t> (v2.mValue);
|
||||
auto vv1 = static_cast<std::int64_t> (v1.mValue);
|
||||
auto vv2 = static_cast<std::int64_t> (v2.mValue);
|
||||
|
||||
if (v1.mIsNegative) vv1 = -vv1;
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
|
||||
if (v2.mIsNegative) vv2 = -vv2;
|
||||
if (v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
|
||||
while (ov1 < ov2)
|
||||
{
|
||||
@@ -835,23 +864,22 @@ STAmount operator- (const STAmount& v1, const STAmount& v2)
|
||||
std::int64_t fv = vv1 - vv2;
|
||||
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
|
||||
else if (fv >= 0)
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, fv, ov1, false);
|
||||
return STAmount (v1.getFName (), v1.mIssue);
|
||||
if (fv >= 0)
|
||||
return STAmount (v1.getFName (), v1.mIssue, fv, ov1, false);
|
||||
else
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, -fv, ov1, true);
|
||||
return STAmount (v1.getFName (), v1.mIssue, -fv, ov1, true);
|
||||
}
|
||||
|
||||
// NIKB TODO Make Amount::divide skip math if den == QUALITY_ONE
|
||||
STAmount STAmount::divide (
|
||||
const STAmount& num, const STAmount& den, Currency const& currency,
|
||||
Account const& issuer)
|
||||
const STAmount& num, const STAmount& den, Issue const& issue)
|
||||
{
|
||||
if (den == zero)
|
||||
throw std::runtime_error ("division by zero");
|
||||
|
||||
if (num == zero)
|
||||
return STAmount (currency, issuer);
|
||||
return {issue};
|
||||
|
||||
std::uint64_t numVal = num.mValue, denVal = den.mValue;
|
||||
int numOffset = num.mOffset, denOffset = den.mOffset;
|
||||
@@ -884,21 +912,24 @@ STAmount STAmount::divide (
|
||||
// 10^16 <= quotient <= 10^18
|
||||
assert (BN_num_bytes (&v) <= 64);
|
||||
|
||||
return STAmount (currency, issuer, v.getuint64 () + 5,
|
||||
numOffset - denOffset - 17, num.mIsNegative != den.mIsNegative);
|
||||
// TODO(tom): where do 5 and 17 come from?
|
||||
return STAmount (issue, v.getuint64 () + 5,
|
||||
numOffset - denOffset - 17,
|
||||
num.mIsNegative != den.mIsNegative);
|
||||
}
|
||||
|
||||
STAmount STAmount::multiply (
|
||||
const STAmount& v1, const STAmount& v2, Currency const& currency,
|
||||
Account const& issuer)
|
||||
const STAmount& v1, const STAmount& v2, Issue const& issue)
|
||||
{
|
||||
if (v1 == zero || v2 == zero)
|
||||
return STAmount (currency, issuer);
|
||||
return STAmount (issue);
|
||||
|
||||
if (v1.mIsNative && v2.mIsNative && currency.isZero ())
|
||||
if (v1.mIsNative && v2.mIsNative && isXRP (issue) )
|
||||
{
|
||||
std::uint64_t minV = (v1.getSNValue () < v2.getSNValue ()) ? v1.getSNValue () : v2.getSNValue ();
|
||||
std::uint64_t maxV = (v1.getSNValue () < v2.getSNValue ()) ? v2.getSNValue () : v1.getSNValue ();
|
||||
std::uint64_t minV = v1.getSNValue () < v2.getSNValue ()
|
||||
? v1.getSNValue () : v2.getSNValue ();
|
||||
std::uint64_t maxV = v1.getSNValue () < v2.getSNValue ()
|
||||
? v2.getSNValue () : v1.getSNValue ();
|
||||
|
||||
if (minV > 3000000000ull) // sqrt(cMaxNative)
|
||||
throw std::runtime_error ("Native value overflow");
|
||||
@@ -944,8 +975,9 @@ STAmount STAmount::multiply (
|
||||
// 10^16 <= product <= 10^18
|
||||
assert (BN_num_bytes (&v) <= 64);
|
||||
|
||||
return STAmount (currency, issuer, v.getuint64 () + 7, offset1 + offset2 + 14,
|
||||
v1.mIsNegative != v2.mIsNegative);
|
||||
// TODO(tom): where do 7 and 14 come from?
|
||||
return STAmount (issue, v.getuint64 () + 7,
|
||||
offset1 + offset2 + 14, v1.mIsNegative != v2.mIsNegative);
|
||||
}
|
||||
|
||||
// Convert an offer into an index amount so they sort by rate.
|
||||
@@ -964,7 +996,7 @@ std::uint64_t STAmount::getRate (const STAmount& offerOut, const STAmount& offer
|
||||
|
||||
try
|
||||
{
|
||||
STAmount r = divide (offerIn, offerOut, noCurrency(), noAccount());
|
||||
STAmount r = divide (offerIn, offerOut, noIssue());
|
||||
|
||||
if (r == zero) // offer is too good
|
||||
return 0;
|
||||
@@ -985,34 +1017,39 @@ std::uint64_t STAmount::getRate (const STAmount& offerOut, const STAmount& offer
|
||||
STAmount STAmount::setRate (std::uint64_t rate)
|
||||
{
|
||||
if (rate == 0)
|
||||
return STAmount (noCurrency(), noAccount());
|
||||
return STAmount (noIssue());
|
||||
|
||||
std::uint64_t mantissa = rate & ~ (255ull << (64 - 8));
|
||||
int exponent = static_cast<int> (rate >> (64 - 8)) - 100;
|
||||
|
||||
return STAmount (noCurrency(), noAccount(), mantissa, exponent);
|
||||
return STAmount (noIssue(), mantissa, exponent);
|
||||
}
|
||||
|
||||
STAmount STAmount::getPay (const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed)
|
||||
STAmount STAmount::getPay (
|
||||
const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed)
|
||||
{
|
||||
// Someone wants to get (needed) out of the offer, how much should they pay in?
|
||||
// Someone wants to get (needed) out of the offer, how much should they pay
|
||||
// in?
|
||||
if (offerOut == zero)
|
||||
return STAmount (offerIn.getCurrency (), offerIn.getIssuer ());
|
||||
return STAmount (offerIn.issue ());
|
||||
|
||||
if (needed >= offerOut)
|
||||
{
|
||||
// They need more than offered, pay full amount.
|
||||
return needed;
|
||||
}
|
||||
|
||||
STAmount ret = divide (multiply (needed, offerIn, noCurrency(), noAccount()), offerOut, offerIn.getCurrency (), offerIn.getIssuer ());
|
||||
|
||||
STAmount ret = divide (multiply (needed, offerIn, noIssue()),
|
||||
offerOut, offerIn.issue());
|
||||
|
||||
return (ret > offerIn) ? offerIn : ret;
|
||||
}
|
||||
|
||||
STAmount STAmount::deserialize (SerializerIterator& it)
|
||||
{
|
||||
std::unique_ptr<STAmount> s (dynamic_cast<STAmount*> (construct (it, sfGeneric)));
|
||||
auto s = dynamic_cast<STAmount*> (construct (it, sfGeneric));
|
||||
if (!s)
|
||||
throw std::runtime_error("Deserialization error");
|
||||
|
||||
STAmount ret (*s);
|
||||
return ret;
|
||||
}
|
||||
@@ -1028,12 +1065,12 @@ std::string STAmount::getFullText () const
|
||||
{
|
||||
ret += "/";
|
||||
|
||||
if (!mIssuer)
|
||||
if (isXRP (*this))
|
||||
ret += "0";
|
||||
else if (mIssuer == noAccount())
|
||||
else if (mIssue.account == noAccount())
|
||||
ret += "1";
|
||||
else
|
||||
ret += to_string (mIssuer);
|
||||
ret += to_string (mIssue.account);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1047,9 +1084,9 @@ STAmount STAmount::getRound () const
|
||||
std::uint64_t valueDigits = mValue % 1000000000ull;
|
||||
|
||||
if (valueDigits == 1)
|
||||
return STAmount (mCurrency, mIssuer, mValue - 1, mOffset, mIsNegative);
|
||||
return STAmount (mIssue, mValue - 1, mOffset, mIsNegative);
|
||||
else if (valueDigits == 999999999ull)
|
||||
return STAmount (mCurrency, mIssuer, mValue + 1, mOffset, mIsNegative);
|
||||
return STAmount (mIssue, mValue + 1, mOffset, mIsNegative);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -1083,11 +1120,11 @@ void STAmount::setJson (Json::Value& elem) const
|
||||
|
||||
if (!mIsNative)
|
||||
{
|
||||
// It is an error for currency or issuer not to be specified for valid json.
|
||||
|
||||
// It is an error for currency or issuer not to be specified for valid
|
||||
// json.
|
||||
elem[jss::value] = getText ();
|
||||
elem[jss::currency] = getHumanCurrency ();
|
||||
elem[jss::issuer] = to_string (mIssuer);
|
||||
elem[jss::issuer] = to_string (mIssue.account);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1110,11 +1147,9 @@ public:
|
||||
static STAmount serializeAndDeserialize (const STAmount& s)
|
||||
{
|
||||
Serializer ser;
|
||||
|
||||
s.add (ser);
|
||||
|
||||
SerializerIterator sit (ser);
|
||||
|
||||
return STAmount::deserialize (sit);
|
||||
}
|
||||
|
||||
@@ -1123,17 +1158,17 @@ public:
|
||||
bool roundTest (int n, int d, int m)
|
||||
{
|
||||
// check STAmount rounding
|
||||
STAmount num (noCurrency(), noAccount(), n);
|
||||
STAmount den (noCurrency(), noAccount(), d);
|
||||
STAmount mul (noCurrency(), noAccount(), m);
|
||||
STAmount quot = STAmount::divide (n, d, noCurrency(), noAccount());
|
||||
STAmount res = STAmount::multiply (quot, mul, noCurrency(), noAccount());
|
||||
STAmount num (noIssue(), n);
|
||||
STAmount den (noIssue(), d);
|
||||
STAmount mul (noIssue(), m);
|
||||
STAmount quot = STAmount::divide (n, d, noIssue());
|
||||
STAmount res = STAmount::multiply (quot, mul, noIssue());
|
||||
|
||||
expect (! res.isNative (), "Product should not be native");
|
||||
|
||||
res.roundSelf ();
|
||||
|
||||
STAmount cmp (noCurrency(), noAccount(), (n * m) / d);
|
||||
STAmount cmp (noIssue(), (n * m) / d);
|
||||
|
||||
expect (! cmp.isNative (), "Comparison amount should not be native");
|
||||
|
||||
@@ -1158,13 +1193,13 @@ public:
|
||||
|
||||
void mulTest (int a, int b)
|
||||
{
|
||||
STAmount aa (noCurrency(), noAccount(), a);
|
||||
STAmount bb (noCurrency(), noAccount(), b);
|
||||
STAmount prod1 (STAmount::multiply (aa, bb, noCurrency(), noAccount()));
|
||||
STAmount aa (noIssue(), a);
|
||||
STAmount bb (noIssue(), b);
|
||||
STAmount prod1 (STAmount::multiply (aa, bb, noIssue()));
|
||||
|
||||
expect (! prod1.isNative ());
|
||||
|
||||
STAmount prod2 (noCurrency(), noAccount(), static_cast<std::uint64_t> (a) * static_cast<std::uint64_t> (b));
|
||||
STAmount prod2 (noIssue(), static_cast<std::uint64_t> (a) * static_cast<std::uint64_t> (b));
|
||||
|
||||
if (prod1 != prod2)
|
||||
{
|
||||
@@ -1179,7 +1214,7 @@ public:
|
||||
}
|
||||
|
||||
aa = a;
|
||||
prod1 = STAmount::multiply (aa, bb, noCurrency(), noAccount());
|
||||
prod1 = STAmount::multiply (aa, bb, noIssue());
|
||||
|
||||
if (prod1 != prod2)
|
||||
{
|
||||
@@ -1374,7 +1409,7 @@ public:
|
||||
{
|
||||
testcase ("custom currency");
|
||||
|
||||
STAmount zeroSt (noCurrency(), noAccount()), one (noCurrency(), noAccount(), 1), hundred (noCurrency(), noAccount(), 100);
|
||||
STAmount zeroSt (noIssue()), one (noIssue(), 1), hundred (noIssue(), 100);
|
||||
|
||||
unexpected (serializeAndDeserialize (zeroSt) != zeroSt, "STAmount fail");
|
||||
|
||||
@@ -1500,33 +1535,33 @@ public:
|
||||
|
||||
unexpected ((hundred != hundred), "STAmount fail");
|
||||
|
||||
unexpected (STAmount (noCurrency(), noAccount()).getText () != "0", "STAmount fail");
|
||||
unexpected (STAmount (noIssue()).getText () != "0", "STAmount fail");
|
||||
|
||||
unexpected (STAmount (noCurrency(), noAccount(), 31).getText () != "31", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31).getText () != "31", "STAmount fail");
|
||||
|
||||
unexpected (STAmount (noCurrency(), noAccount(), 31, 1).getText () != "310", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31, 1).getText () != "310", "STAmount fail");
|
||||
|
||||
unexpected (STAmount (noCurrency(), noAccount(), 31, -1).getText () != "3.1", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31, -1).getText () != "3.1", "STAmount fail");
|
||||
|
||||
unexpected (STAmount (noCurrency(), noAccount(), 31, -2).getText () != "0.31", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31, -2).getText () != "0.31", "STAmount fail");
|
||||
|
||||
unexpected (STAmount::multiply (STAmount (noCurrency(), noAccount(), 20), STAmount (3), noCurrency(), noAccount()).getText () != "60",
|
||||
unexpected (STAmount::multiply (STAmount (noIssue(), 20), STAmount (3), noIssue()).getText () != "60",
|
||||
"STAmount multiply fail 1");
|
||||
|
||||
unexpected (STAmount::multiply (STAmount (noCurrency(), noAccount(), 20), STAmount (3), xrpCurrency (), xrpIssuer()).getText () != "60",
|
||||
unexpected (STAmount::multiply (STAmount (noIssue(), 20), STAmount (3), xrpIssue ()).getText () != "60",
|
||||
"STAmount multiply fail 2");
|
||||
|
||||
unexpected (STAmount::multiply (STAmount (20), STAmount (3), noCurrency(), noAccount()).getText () != "60",
|
||||
unexpected (STAmount::multiply (STAmount (20), STAmount (3), noIssue()).getText () != "60",
|
||||
"STAmount multiply fail 3");
|
||||
|
||||
unexpected (STAmount::multiply (STAmount (20), STAmount (3), xrpCurrency (), xrpIssuer()).getText () != "60",
|
||||
unexpected (STAmount::multiply (STAmount (20), STAmount (3), xrpIssue ()).getText () != "60",
|
||||
"STAmount multiply fail 4");
|
||||
|
||||
if (STAmount::divide (STAmount (noCurrency(), noAccount(), 60), STAmount (3), noCurrency(), noAccount()).getText () != "20")
|
||||
if (STAmount::divide (STAmount (noIssue(), 60), STAmount (3), noIssue()).getText () != "20")
|
||||
{
|
||||
WriteLog (lsFATAL, STAmount) << "60/3 = " <<
|
||||
STAmount::divide (STAmount (noCurrency(), noAccount(), 60),
|
||||
STAmount (3), noCurrency(), noAccount()).getText ();
|
||||
STAmount::divide (STAmount (noIssue(), 60),
|
||||
STAmount (3), noIssue()).getText ();
|
||||
fail ("STAmount divide fail");
|
||||
}
|
||||
else
|
||||
@@ -1534,21 +1569,21 @@ public:
|
||||
pass ();
|
||||
}
|
||||
|
||||
unexpected (STAmount::divide (STAmount (noCurrency(), noAccount(), 60), STAmount (3), xrpCurrency (), xrpIssuer()).getText () != "20",
|
||||
unexpected (STAmount::divide (STAmount (noIssue(), 60), STAmount (3), xrpIssue ()).getText () != "20",
|
||||
"STAmount divide fail");
|
||||
|
||||
unexpected (STAmount::divide (STAmount (noCurrency(), noAccount(), 60), STAmount (noCurrency(), noAccount(), 3), noCurrency(), noAccount()).getText () != "20",
|
||||
unexpected (STAmount::divide (STAmount (noIssue(), 60), STAmount (noIssue(), 3), noIssue()).getText () != "20",
|
||||
"STAmount divide fail");
|
||||
|
||||
unexpected (STAmount::divide (STAmount (noCurrency(), noAccount(), 60), STAmount (noCurrency(), noAccount(), 3), xrpCurrency (), xrpIssuer()).getText () != "20",
|
||||
unexpected (STAmount::divide (STAmount (noIssue(), 60), STAmount (noIssue(), 3), xrpIssue ()).getText () != "20",
|
||||
"STAmount divide fail");
|
||||
|
||||
STAmount a1 (noCurrency(), noAccount(), 60), a2 (noCurrency(), noAccount(), 10, -1);
|
||||
STAmount a1 (noIssue(), 60), a2 (noIssue(), 10, -1);
|
||||
|
||||
unexpected (STAmount::divide (a2, a1, noCurrency(), noAccount()) != STAmount::setRate (STAmount::getRate (a1, a2)),
|
||||
unexpected (STAmount::divide (a2, a1, noIssue()) != STAmount::setRate (STAmount::getRate (a1, a2)),
|
||||
"STAmount setRate(getRate) fail");
|
||||
|
||||
unexpected (STAmount::divide (a1, a2, noCurrency(), noAccount()) != STAmount::setRate (STAmount::getRate (a2, a1)),
|
||||
unexpected (STAmount::divide (a1, a2, noIssue()) != STAmount::setRate (STAmount::getRate (a2, a1)),
|
||||
"STAmount setRate(getRate) fail");
|
||||
}
|
||||
|
||||
@@ -1587,22 +1622,22 @@ public:
|
||||
unexpected (STAmount::getRate (STAmount (10), STAmount (1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 2");
|
||||
|
||||
unexpected (STAmount::getRate (STAmount (noCurrency(), noAccount(), 1), STAmount (noCurrency(), noAccount(), 10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
unexpected (STAmount::getRate (STAmount (noIssue(), 1), STAmount (noIssue(), 10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 3");
|
||||
|
||||
unexpected (STAmount::getRate (STAmount (noCurrency(), noAccount(), 10), STAmount (noCurrency(), noAccount(), 1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
unexpected (STAmount::getRate (STAmount (noIssue(), 10), STAmount (noIssue(), 1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 4");
|
||||
|
||||
unexpected (STAmount::getRate (STAmount (noCurrency(), noAccount(), 1), STAmount (10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
unexpected (STAmount::getRate (STAmount (noIssue(), 1), STAmount (10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 5");
|
||||
|
||||
unexpected (STAmount::getRate (STAmount (noCurrency(), noAccount(), 10), STAmount (1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
unexpected (STAmount::getRate (STAmount (noIssue(), 10), STAmount (1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 6");
|
||||
|
||||
unexpected (STAmount::getRate (STAmount (1), STAmount (noCurrency(), noAccount(), 10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
unexpected (STAmount::getRate (STAmount (1), STAmount (noIssue(), 10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 7");
|
||||
|
||||
unexpected (STAmount::getRate (STAmount (10), STAmount (noCurrency(), noAccount(), 1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
unexpected (STAmount::getRate (STAmount (10), STAmount (noIssue(), 1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 8");
|
||||
|
||||
roundTest (1, 3, 3);
|
||||
@@ -1637,29 +1672,33 @@ public:
|
||||
testcase ("underflow");
|
||||
|
||||
STAmount bigNative (STAmount::cMaxNative / 2);
|
||||
STAmount bigValue (noCurrency(), noAccount(),
|
||||
STAmount bigValue (noIssue(),
|
||||
(STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMaxOffset - 1);
|
||||
STAmount smallValue (noCurrency(), noAccount(),
|
||||
STAmount smallValue (noIssue(),
|
||||
(STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMinOffset + 1);
|
||||
STAmount zeroSt (noCurrency(), noAccount(), 0);
|
||||
STAmount zeroSt (noIssue(), 0);
|
||||
|
||||
STAmount smallXsmall = STAmount::multiply (smallValue, smallValue, noCurrency(), noAccount());
|
||||
STAmount smallXsmall = STAmount::multiply (smallValue, smallValue, noIssue());
|
||||
|
||||
expect (smallXsmall == zero, "smallXsmall != 0");
|
||||
|
||||
STAmount bigDsmall = STAmount::divide (smallValue, bigValue, noCurrency(), noAccount());
|
||||
STAmount bigDsmall = STAmount::divide (smallValue, bigValue, noIssue());
|
||||
|
||||
expect (bigDsmall == zero, beast::String ("small/big != 0: ") + bigDsmall.getText ());
|
||||
|
||||
bigDsmall = STAmount::divide (smallValue, bigNative, noCurrency(), xrpIssuer ());
|
||||
#if 0
|
||||
// TODO(tom): this test makes no sense - we should have no way to have
|
||||
// the currency not be XRP while the account is XRP.
|
||||
bigDsmall = STAmount::divide (smallValue, bigNative, noCurrency(), xrpAccount ());
|
||||
#endif
|
||||
|
||||
expect (bigDsmall == zero, beast::String ("small/bigNative != 0: ") + bigDsmall.getText ());
|
||||
|
||||
bigDsmall = STAmount::divide (smallValue, bigValue, xrpCurrency (), xrpIssuer ());
|
||||
bigDsmall = STAmount::divide (smallValue, bigValue, xrpIssue ());
|
||||
|
||||
expect (bigDsmall == zero, beast::String ("(small/big)->N != 0: ") + bigDsmall.getText ());
|
||||
|
||||
bigDsmall = STAmount::divide (smallValue, bigNative, xrpCurrency (), xrpIssuer ());
|
||||
bigDsmall = STAmount::divide (smallValue, bigNative, xrpIssue ());
|
||||
|
||||
expect (bigDsmall == zero, beast::String ("(small/bigNative)->N != 0: ") + bigDsmall.getText ());
|
||||
|
||||
@@ -1688,27 +1727,27 @@ public:
|
||||
int offset = -14;
|
||||
STAmount::canonicalizeRound (false, value, offset, true);
|
||||
|
||||
STAmount one (noCurrency(), noAccount(), 1);
|
||||
STAmount two (noCurrency(), noAccount(), 2);
|
||||
STAmount three (noCurrency(), noAccount(), 3);
|
||||
STAmount one (noIssue(), 1);
|
||||
STAmount two (noIssue(), 2);
|
||||
STAmount three (noIssue(), 3);
|
||||
|
||||
STAmount oneThird1 = STAmount::divRound (one, three, noCurrency(), noAccount(), false);
|
||||
STAmount oneThird2 = STAmount::divide (one, three, noCurrency(), noAccount());
|
||||
STAmount oneThird3 = STAmount::divRound (one, three, noCurrency(), noAccount(), true);
|
||||
STAmount oneThird1 = STAmount::divRound (one, three, noIssue(), false);
|
||||
STAmount oneThird2 = STAmount::divide (one, three, noIssue());
|
||||
STAmount oneThird3 = STAmount::divRound (one, three, noIssue(), true);
|
||||
WriteLog (lsINFO, STAmount) << oneThird1;
|
||||
WriteLog (lsINFO, STAmount) << oneThird2;
|
||||
WriteLog (lsINFO, STAmount) << oneThird3;
|
||||
|
||||
STAmount twoThird1 = STAmount::divRound (two, three, noCurrency(), noAccount(), false);
|
||||
STAmount twoThird2 = STAmount::divide (two, three, noCurrency(), noAccount());
|
||||
STAmount twoThird3 = STAmount::divRound (two, three, noCurrency(), noAccount(), true);
|
||||
STAmount twoThird1 = STAmount::divRound (two, three, noIssue(), false);
|
||||
STAmount twoThird2 = STAmount::divide (two, three, noIssue());
|
||||
STAmount twoThird3 = STAmount::divRound (two, three, noIssue(), true);
|
||||
WriteLog (lsINFO, STAmount) << twoThird1;
|
||||
WriteLog (lsINFO, STAmount) << twoThird2;
|
||||
WriteLog (lsINFO, STAmount) << twoThird3;
|
||||
|
||||
STAmount oneA = STAmount::mulRound (oneThird1, three, noCurrency(), noAccount(), false);
|
||||
STAmount oneB = STAmount::multiply (oneThird2, three, noCurrency(), noAccount());
|
||||
STAmount oneC = STAmount::mulRound (oneThird3, three, noCurrency(), noAccount(), true);
|
||||
STAmount oneA = STAmount::mulRound (oneThird1, three, noIssue(), false);
|
||||
STAmount oneB = STAmount::multiply (oneThird2, three, noIssue());
|
||||
STAmount oneC = STAmount::mulRound (oneThird3, three, noIssue(), true);
|
||||
WriteLog (lsINFO, STAmount) << oneA;
|
||||
WriteLog (lsINFO, STAmount) << oneB;
|
||||
WriteLog (lsINFO, STAmount) << oneC;
|
||||
@@ -1720,9 +1759,9 @@ public:
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsB;
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsC;
|
||||
|
||||
STAmount dripTest1 = STAmount::mulRound (twoThird2, two, xrpCurrency (), xrpIssuer (), false);
|
||||
STAmount dripTest2 = STAmount::multiply (twoThird2, two, xrpCurrency (), xrpIssuer ());
|
||||
STAmount dripTest3 = STAmount::mulRound (twoThird2, two, xrpCurrency (), xrpIssuer (), true);
|
||||
STAmount dripTest1 = STAmount::mulRound (twoThird2, two, xrpIssue (), false);
|
||||
STAmount dripTest2 = STAmount::multiply (twoThird2, two, xrpIssue ());
|
||||
STAmount dripTest3 = STAmount::mulRound (twoThird2, two, xrpIssue (), true);
|
||||
WriteLog (lsINFO, STAmount) << dripTest1;
|
||||
WriteLog (lsINFO, STAmount) << dripTest2;
|
||||
WriteLog (lsINFO, STAmount) << dripTest3;
|
||||
|
||||
458
src/ripple/module/data/protocol/STAmount.h
Normal file
458
src/ripple/module/data/protocol/STAmount.h
Normal file
@@ -0,0 +1,458 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_STAMOUNT_H
|
||||
#define RIPPLE_STAMOUNT_H
|
||||
|
||||
#include <ripple/module/data/protocol/FieldNames.h>
|
||||
#include <ripple/module/data/protocol/Serializer.h>
|
||||
#include <ripple/module/data/protocol/SerializedType.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// Internal form:
|
||||
// 1: If amount is zero, then value is zero and offset is -100
|
||||
// 2: Otherwise:
|
||||
// legal offset range is -96 to +80 inclusive
|
||||
// value range is 10^15 to (10^16 - 1) inclusive
|
||||
// amount = value * [10 ^ offset]
|
||||
|
||||
// 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 : public SerializedType
|
||||
{
|
||||
public:
|
||||
static const int cMinOffset = -96;
|
||||
static const int cMaxOffset = 80;
|
||||
|
||||
static const std::uint64_t cMinValue = 1000000000000000ull;
|
||||
static const std::uint64_t cMaxValue = 9999999999999999ull;
|
||||
static const std::uint64_t cMaxNative = 9000000000000000000ull;
|
||||
|
||||
// Max native value on network.
|
||||
static const std::uint64_t cMaxNativeN = 100000000000000000ull;
|
||||
static const std::uint64_t cNotNative = 0x8000000000000000ull;
|
||||
static const std::uint64_t cPosNative = 0x4000000000000000ull;
|
||||
|
||||
static std::uint64_t uRateOne;
|
||||
|
||||
STAmount (std::uint64_t v = 0, bool negative = false)
|
||||
: mValue (v), mOffset (0), mIsNative (true), mIsNegative (negative)
|
||||
{
|
||||
if (v == 0) mIsNegative = false;
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, std::uint64_t v = 0, bool negative = false)
|
||||
: SerializedType (n), mValue (v), mOffset (0), mIsNative (true),
|
||||
mIsNegative (negative)
|
||||
{
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, std::int64_t v)
|
||||
: SerializedType (n), mOffset (0), mIsNative (true)
|
||||
{
|
||||
set (v);
|
||||
}
|
||||
|
||||
STAmount (Issue const& issue,
|
||||
std::uint64_t uV = 0, int iOff = 0, bool negative = false)
|
||||
: mIssue(issue), mValue (uV), mOffset (iOff), mIsNegative (negative)
|
||||
{
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (Issue const& issue,
|
||||
std::uint32_t uV, int iOff = 0, bool negative = false)
|
||||
: mIssue(issue), mValue (uV), mOffset (iOff), mIsNegative (negative)
|
||||
{
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, Issue const& issue,
|
||||
std::uint64_t v = 0, int off = 0, bool negative = false) :
|
||||
SerializedType (n), mIssue(issue), mValue (v), mOffset (off),
|
||||
mIsNegative (negative)
|
||||
{
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (Issue const& issue, std::int64_t v, int iOff = 0)
|
||||
: mIssue(issue), mOffset (iOff)
|
||||
{
|
||||
set (v);
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, Issue const& issue, std::int64_t v, int off = 0)
|
||||
: SerializedType (n), mIssue(issue), mOffset (off)
|
||||
{
|
||||
set (v);
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (Issue const& issue, int v, int iOff = 0)
|
||||
: mIssue(issue), mOffset (iOff)
|
||||
{
|
||||
set (v);
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, Issue const& issue, int v, int off = 0)
|
||||
: SerializedType (n), mIssue(issue), mOffset (off)
|
||||
{
|
||||
set (v);
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (SField::ref, const Json::Value&);
|
||||
|
||||
static STAmount createFromInt64 (SField::ref n, std::int64_t v);
|
||||
|
||||
static std::unique_ptr<SerializedType> deserialize (
|
||||
SerializerIterator& sit, SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
bool bSetJson (const Json::Value& jvSource);
|
||||
|
||||
static STAmount saFromRate (std::uint64_t uRate = 0)
|
||||
{
|
||||
return STAmount (noIssue(), uRate, -9, false);
|
||||
}
|
||||
|
||||
SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_AMOUNT;
|
||||
}
|
||||
std::string getText () const;
|
||||
std::string getFullText () const;
|
||||
void add (Serializer& s) const;
|
||||
|
||||
int getExponent () const
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
std::uint64_t getMantissa () const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
int signum () const
|
||||
{
|
||||
return mValue ? (mIsNegative ? -1 : 1) : 0;
|
||||
}
|
||||
|
||||
// When the currency is XRP, the value in raw units. S=signed
|
||||
std::uint64_t getNValue () const
|
||||
{
|
||||
if (!mIsNative)
|
||||
throw std::runtime_error ("not native");
|
||||
|
||||
return mValue;
|
||||
}
|
||||
void setNValue (std::uint64_t v)
|
||||
{
|
||||
if (!mIsNative)
|
||||
throw std::runtime_error ("not native");
|
||||
|
||||
mValue = v;
|
||||
}
|
||||
std::int64_t getSNValue () const;
|
||||
void setSNValue (std::int64_t);
|
||||
|
||||
std::string getHumanCurrency () const;
|
||||
|
||||
bool isNative () const
|
||||
{
|
||||
return mIsNative;
|
||||
}
|
||||
bool isLegalNet () const
|
||||
{
|
||||
return !mIsNative || (mValue <= cMaxNativeN);
|
||||
}
|
||||
|
||||
explicit
|
||||
operator bool () const noexcept
|
||||
{
|
||||
return *this != zero;
|
||||
}
|
||||
|
||||
void negate ()
|
||||
{
|
||||
if (*this != zero)
|
||||
mIsNegative = !mIsNegative;
|
||||
}
|
||||
|
||||
/** @return a copy of amount with the same Issuer and Currency but zero
|
||||
value. */
|
||||
STAmount zeroed() const
|
||||
{
|
||||
// TODO(tom): what does this next comment mean here?
|
||||
// See https://ripplelabs.atlassian.net/browse/WC-1847?jql=
|
||||
return STAmount (mIssue);
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
// VFALCO: Why -100?
|
||||
mOffset = mIsNative ? 0 : -100;
|
||||
mValue = 0;
|
||||
mIsNegative = false;
|
||||
}
|
||||
|
||||
// Zero while copying currency and issuer.
|
||||
void clear (const STAmount& saTmpl)
|
||||
{
|
||||
clear(saTmpl.mIssue);
|
||||
}
|
||||
|
||||
void clear (Issue const& issue)
|
||||
{
|
||||
setIssue(issue);
|
||||
clear ();
|
||||
}
|
||||
|
||||
STAmount& operator=(beast::Zero)
|
||||
{
|
||||
clear ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
int compare (const STAmount&) const;
|
||||
|
||||
Account const& getIssuer () const
|
||||
{
|
||||
return mIssue.account;
|
||||
}
|
||||
|
||||
void setIssuer (Account const& uIssuer)
|
||||
{
|
||||
mIssue.account = uIssuer;
|
||||
setIssue(mIssue);
|
||||
}
|
||||
|
||||
/** Set the Issue for this amount and update mIsNative. */
|
||||
void setIssue (Issue const& issue);
|
||||
|
||||
Currency const& getCurrency () const
|
||||
{
|
||||
return mIssue.currency;
|
||||
}
|
||||
|
||||
Issue const& issue () const
|
||||
{
|
||||
return mIssue;
|
||||
}
|
||||
|
||||
bool setValue (const std::string& sAmount);
|
||||
bool setFullValue (
|
||||
const std::string& sAmount, const std::string& sCurrency = "",
|
||||
const std::string& sIssuer = "");
|
||||
void setValue (const STAmount&);
|
||||
|
||||
virtual bool isEquivalent (const SerializedType& t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return (mValue == 0) && mIsNative;
|
||||
}
|
||||
|
||||
bool operator== (const STAmount&) const;
|
||||
bool operator!= (const STAmount&) const;
|
||||
bool operator< (const STAmount&) const;
|
||||
bool operator> (const STAmount&) const;
|
||||
bool operator<= (const STAmount&) const;
|
||||
bool operator>= (const STAmount&) const;
|
||||
bool isComparable (const STAmount&) const;
|
||||
void throwComparable (const STAmount&) const;
|
||||
|
||||
// native currency only
|
||||
bool operator< (std::uint64_t) const;
|
||||
bool operator> (std::uint64_t) const;
|
||||
bool operator<= (std::uint64_t) const;
|
||||
bool operator>= (std::uint64_t) const;
|
||||
STAmount operator+ (std::uint64_t) const;
|
||||
STAmount operator- (std::uint64_t) const;
|
||||
STAmount operator- (void) const;
|
||||
|
||||
STAmount& operator+= (const STAmount&);
|
||||
STAmount& operator-= (const STAmount&);
|
||||
STAmount& operator+= (std::uint64_t);
|
||||
STAmount& operator-= (std::uint64_t);
|
||||
STAmount& operator= (std::uint64_t);
|
||||
|
||||
operator double () const;
|
||||
|
||||
friend STAmount operator+ (const STAmount& v1, const STAmount& v2);
|
||||
friend STAmount operator- (const STAmount& v1, const STAmount& v2);
|
||||
|
||||
static STAmount divide (
|
||||
const STAmount& v1, const STAmount& v2, Issue const& issue);
|
||||
|
||||
static STAmount divide (
|
||||
const STAmount& v1, const STAmount& v2, const STAmount& saUnit)
|
||||
{
|
||||
return divide (v1, v2, saUnit.issue ());
|
||||
}
|
||||
static STAmount divide (const STAmount& v1, const STAmount& v2)
|
||||
{
|
||||
return divide (v1, v2, v1);
|
||||
}
|
||||
|
||||
static STAmount multiply (
|
||||
const STAmount& v1, const STAmount& v2, Issue const& issue);
|
||||
|
||||
static STAmount multiply (
|
||||
const STAmount& v1, const STAmount& v2, const STAmount& saUnit)
|
||||
{
|
||||
return multiply (v1, v2, saUnit.issue());
|
||||
}
|
||||
static STAmount multiply (const STAmount& v1, const STAmount& v2)
|
||||
{
|
||||
return multiply (v1, v2, v1);
|
||||
}
|
||||
|
||||
/* addRound, subRound can end up rounding if the amount subtracted is too small
|
||||
to make a change. Consder (X-d) where d is very small relative to X.
|
||||
If you ask to round down, then (X-d) should not be X unless d is zero.
|
||||
If you ask to round up, (X+d) should never be X unless d is zero. (Assuming X and d are positive).
|
||||
*/
|
||||
// Add, subtract, multiply, or divide rounding result in specified direction
|
||||
static STAmount addRound (
|
||||
const STAmount& v1, const STAmount& v2, bool roundUp);
|
||||
static STAmount subRound (
|
||||
const STAmount& v1, const STAmount& v2, bool roundUp);
|
||||
static STAmount mulRound (
|
||||
const STAmount& v1, const STAmount& v2, Issue const& issue,
|
||||
bool roundUp);
|
||||
static STAmount divRound (
|
||||
const STAmount& v1, const STAmount& v2, Issue const& issue,
|
||||
bool roundUp);
|
||||
|
||||
static STAmount mulRound (
|
||||
const STAmount& v1, const STAmount& v2, const STAmount& saUnit,
|
||||
bool roundUp)
|
||||
{
|
||||
return mulRound (v1, v2, saUnit.issue (), roundUp);
|
||||
}
|
||||
static STAmount mulRound (
|
||||
const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
{
|
||||
return mulRound (v1, v2, v1.issue (), roundUp);
|
||||
}
|
||||
static STAmount divRound (
|
||||
const STAmount& v1, const STAmount& v2, const STAmount& saUnit,
|
||||
bool roundUp)
|
||||
{
|
||||
return divRound (v1, v2, saUnit.issue (), roundUp);
|
||||
}
|
||||
static STAmount divRound (
|
||||
const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
{
|
||||
return divRound (v1, v2, v1.issue (), roundUp);
|
||||
}
|
||||
|
||||
// Someone is offering X for Y, what is the rate?
|
||||
// Rate: smaller is better, the taker wants the most out: in/out
|
||||
static std::uint64_t getRate (
|
||||
const STAmount& offerOut, const STAmount& offerIn);
|
||||
static STAmount setRate (std::uint64_t rate);
|
||||
|
||||
// Someone is offering X for Y, I need Z, how much do I pay
|
||||
|
||||
// WARNING: most methods in rippled have parameters ordered "in, out" - this
|
||||
// one is ordered "out, in".
|
||||
static STAmount getPay (
|
||||
const STAmount& out, const STAmount& in, const STAmount& needed);
|
||||
|
||||
static STAmount deserialize (SerializerIterator&);
|
||||
|
||||
Json::Value getJson (int) const;
|
||||
void setJson (Json::Value&) const;
|
||||
|
||||
STAmount getRound () const;
|
||||
void roundSelf ();
|
||||
|
||||
static void canonicalizeRound (
|
||||
bool isNative, std::uint64_t& value, int& offset, bool roundUp);
|
||||
|
||||
private:
|
||||
Issue mIssue;
|
||||
|
||||
std::uint64_t mValue;
|
||||
int mOffset;
|
||||
bool mIsNative; // A shorthand for isXRP(mIssue).
|
||||
bool mIsNegative;
|
||||
|
||||
void canonicalize ();
|
||||
STAmount* duplicate () const
|
||||
{
|
||||
return new STAmount (*this);
|
||||
}
|
||||
static STAmount* construct (SerializerIterator&, SField::ref name);
|
||||
|
||||
STAmount (SField::ref name, Issue const& issue,
|
||||
std::uint64_t val, int off, bool isNat, bool negative)
|
||||
: SerializedType (name), mIssue(issue), mValue (val),
|
||||
mOffset (off), mIsNative (isNat), mIsNegative (negative)
|
||||
{
|
||||
}
|
||||
|
||||
void set (std::int64_t v)
|
||||
{
|
||||
if (v < 0)
|
||||
{
|
||||
mIsNegative = true;
|
||||
mValue = static_cast<std::uint64_t> (-v);
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsNegative = false;
|
||||
mValue = static_cast<std::uint64_t> (v);
|
||||
}
|
||||
}
|
||||
|
||||
void set (int v)
|
||||
{
|
||||
if (v < 0)
|
||||
{
|
||||
mIsNegative = true;
|
||||
mValue = static_cast<std::uint64_t> (-v);
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsNegative = false;
|
||||
mValue = static_cast<std::uint64_t> (v);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline bool isXRP(STAmount const& amount)
|
||||
{
|
||||
return isXRP (amount.issue().currency);
|
||||
}
|
||||
|
||||
// VFALCO TODO Make static member accessors for these in STAmount
|
||||
extern const STAmount saZero;
|
||||
extern const STAmount saOne;
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -73,7 +73,7 @@ STAmount STAmount::addRound (const STAmount& v1, const STAmount& v2, bool roundU
|
||||
return v1;
|
||||
|
||||
if (v1.mValue == 0)
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue,
|
||||
return STAmount (v1.getFName (), v1.mIssue, v2.mValue,
|
||||
v2.mOffset, v2.mIsNegative);
|
||||
|
||||
if (v1.mIsNative)
|
||||
@@ -122,18 +122,18 @@ STAmount STAmount::addRound (const STAmount& v1, const STAmount& v2, bool roundU
|
||||
std::int64_t fv = vv1 + vv2;
|
||||
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
|
||||
return STAmount (v1.getFName (), v1.mIssue);
|
||||
else if (fv >= 0)
|
||||
{
|
||||
std::uint64_t v = static_cast<std::uint64_t> (fv);
|
||||
canonicalizeRound (false, v, ov1, roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
return STAmount (v1.getFName (), v1.mIssue, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::uint64_t v = static_cast<std::uint64_t> (-fv);
|
||||
canonicalizeRound (false, v, ov1, !roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
|
||||
return STAmount (v1.getFName (), v1.mIssue, v, ov1, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ STAmount STAmount::subRound (const STAmount& v1, const STAmount& v2, bool roundU
|
||||
return v1;
|
||||
|
||||
if (v1.mValue == 0)
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue,
|
||||
return STAmount (v1.getFName (), v1.mIssue, v2.mValue,
|
||||
v2.mOffset, !v2.mIsNegative);
|
||||
|
||||
if (v1.mIsNative)
|
||||
@@ -194,30 +194,29 @@ STAmount STAmount::subRound (const STAmount& v1, const STAmount& v2, bool roundU
|
||||
std::int64_t fv = vv1 + vv2;
|
||||
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
|
||||
return STAmount (v1.getFName (), v1.mIssue);
|
||||
|
||||
if (fv >= 0)
|
||||
{
|
||||
std::uint64_t v = static_cast<std::uint64_t> (fv);
|
||||
canonicalizeRound (false, v, ov1, roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
return STAmount (v1.getFName (), v1.mIssue, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::uint64_t v = static_cast<std::uint64_t> (-fv);
|
||||
canonicalizeRound (false, v, ov1, !roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
|
||||
return STAmount (v1.getFName (), v1.mIssue, v, ov1, true);
|
||||
}
|
||||
}
|
||||
|
||||
STAmount STAmount::mulRound (
|
||||
const STAmount& v1, const STAmount& v2, Currency const& currency,
|
||||
Account const& issuer, bool roundUp)
|
||||
const STAmount& v1, const STAmount& v2, Issue const& issue, bool roundUp)
|
||||
{
|
||||
if (v1 == zero || v2 == zero)
|
||||
return STAmount (currency, issuer);
|
||||
return {issue};
|
||||
|
||||
if (v1.mIsNative && v2.mIsNative && currency.isZero ())
|
||||
if (v1.mIsNative && v2.mIsNative && isXRP (issue))
|
||||
{
|
||||
std::uint64_t minV = (v1.getSNValue () < v2.getSNValue ()) ?
|
||||
v1.getSNValue () : v2.getSNValue ();
|
||||
@@ -274,19 +273,19 @@ STAmount STAmount::mulRound (
|
||||
std::uint64_t amount = v.getuint64 ();
|
||||
int offset = offset1 + offset2 + 14;
|
||||
canonicalizeRound (
|
||||
currency.isZero (), amount, offset, resultNegative != roundUp);
|
||||
return STAmount (currency, issuer, amount, offset, resultNegative);
|
||||
isXRP (issue), amount, offset, resultNegative != roundUp);
|
||||
return STAmount (issue, amount, offset, resultNegative);
|
||||
}
|
||||
|
||||
STAmount STAmount::divRound (
|
||||
const STAmount& num, const STAmount& den,
|
||||
Currency const& currency, Account const& issuer, bool roundUp)
|
||||
Issue const& issue, bool roundUp)
|
||||
{
|
||||
if (den == zero)
|
||||
throw std::runtime_error ("division by zero");
|
||||
|
||||
if (num == zero)
|
||||
return STAmount (currency, issuer);
|
||||
return {issue};
|
||||
|
||||
std::uint64_t numVal = num.mValue, denVal = den.mValue;
|
||||
int numOffset = num.mOffset, denOffset = den.mOffset;
|
||||
@@ -325,8 +324,8 @@ STAmount STAmount::divRound (
|
||||
std::uint64_t amount = v.getuint64 ();
|
||||
int offset = numOffset - denOffset - 17;
|
||||
canonicalizeRound (
|
||||
currency.isZero (), amount, offset, resultNegative != roundUp);
|
||||
return STAmount (currency, issuer, amount, offset, resultNegative);
|
||||
isXRP (issue), amount, offset, resultNegative != roundUp);
|
||||
return STAmount (issue, amount, offset, resultNegative);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
203
src/ripple/module/data/protocol/SerializedType.h
Normal file
203
src/ripple/module/data/protocol/SerializedType.h
Normal file
@@ -0,0 +1,203 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_SERIALIZEDTYPE_H
|
||||
#define RIPPLE_SERIALIZEDTYPE_H
|
||||
|
||||
#include <ripple/module/data/protocol/FieldNames.h>
|
||||
#include <ripple/module/data/protocol/Serializer.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO TODO fix this restriction on copy assignment.
|
||||
//
|
||||
// CAUTION: Do not create a vector (or similar container) of any object derived
|
||||
// from SerializedType. Use Boost ptr_* containers. The copy assignment operator
|
||||
// of SerializedType has semantics that will cause contained types to change
|
||||
// their names when an object is deleted because copy assignment is used to
|
||||
// "slide down" the remaining types and this will not copy the field
|
||||
// name. Changing the copy assignment operator to copy the field name breaks the
|
||||
// use of copy assignment just to copy values, which is used in the transaction
|
||||
// engine code.
|
||||
|
||||
// VFALCO TODO Remove this unused enum
|
||||
/*
|
||||
enum PathFlags
|
||||
{
|
||||
PF_END = 0x00, // End of current path & path list.
|
||||
PF_BOUNDARY = 0xFF, // End of current path & new path follows.
|
||||
|
||||
PF_ACCOUNT = 0x01,
|
||||
PF_OFFER = 0x02,
|
||||
|
||||
PF_WANTED_CURRENCY = 0x10,
|
||||
PF_WANTED_ISSUER = 0x20,
|
||||
PF_REDEEM = 0x40,
|
||||
PF_ISSUE = 0x80,
|
||||
};
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A type which can be exported to a well known binary format.
|
||||
|
||||
A SerializedType:
|
||||
- Always a field
|
||||
- Can always go inside an eligible enclosing SerializedType
|
||||
(such as STArray)
|
||||
- Has a field name
|
||||
|
||||
|
||||
Like JSON, a SerializedObject is a basket which has rules
|
||||
on what it can hold.
|
||||
*/
|
||||
// VFALCO TODO Document this as it looks like a central class.
|
||||
// STObject is derived from it
|
||||
//
|
||||
class SerializedType
|
||||
{
|
||||
public:
|
||||
SerializedType () : fName (&sfGeneric)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
explicit SerializedType (SField::ref n) : fName (&n)
|
||||
{
|
||||
assert (fName);
|
||||
}
|
||||
|
||||
virtual ~SerializedType () { }
|
||||
|
||||
static std::unique_ptr<SerializedType> deserialize (SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (new SerializedType (name));
|
||||
}
|
||||
|
||||
/** A SerializeType is a field.
|
||||
This sets the name.
|
||||
*/
|
||||
void setFName (SField::ref n)
|
||||
{
|
||||
fName = &n;
|
||||
assert (fName);
|
||||
}
|
||||
SField::ref getFName () const
|
||||
{
|
||||
return *fName;
|
||||
}
|
||||
virtual SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_NOTPRESENT;
|
||||
}
|
||||
std::unique_ptr<SerializedType> clone () const
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (duplicate ());
|
||||
}
|
||||
|
||||
virtual std::string getFullText () const;
|
||||
virtual std::string getText () const // just the value
|
||||
{
|
||||
return std::string ();
|
||||
}
|
||||
virtual Json::Value getJson (int /*options*/) const
|
||||
{
|
||||
return getText ();
|
||||
}
|
||||
|
||||
virtual void add (Serializer& s) const
|
||||
{
|
||||
assert (false);
|
||||
}
|
||||
|
||||
virtual bool isEquivalent (const SerializedType& t) const;
|
||||
|
||||
void addFieldID (Serializer& s) const
|
||||
{
|
||||
assert (fName->isBinary ());
|
||||
s.addFieldID (fName->fieldType, fName->fieldValue);
|
||||
}
|
||||
|
||||
SerializedType& operator= (const SerializedType& t);
|
||||
|
||||
bool operator== (const SerializedType& t) const
|
||||
{
|
||||
return (getSType () == t.getSType ()) && isEquivalent (t);
|
||||
}
|
||||
bool operator!= (const SerializedType& t) const
|
||||
{
|
||||
return (getSType () != t.getSType ()) || !isEquivalent (t);
|
||||
}
|
||||
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class D>
|
||||
D& downcast()
|
||||
{
|
||||
D* ptr = dynamic_cast<D*> (this);
|
||||
if (ptr == nullptr)
|
||||
throw std::runtime_error ("type mismatch");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
template <class D>
|
||||
D const& downcast() const
|
||||
{
|
||||
D const * ptr = dynamic_cast<D const*> (this);
|
||||
if (ptr == nullptr)
|
||||
throw std::runtime_error ("type mismatch");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
// VFALCO TODO make accessors for this
|
||||
SField::ptr fName;
|
||||
|
||||
private:
|
||||
virtual SerializedType* duplicate () const
|
||||
{
|
||||
return new SerializedType (*fName);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline SerializedType* new_clone (const SerializedType& s)
|
||||
{
|
||||
SerializedType* const copy (s.clone ().release ());
|
||||
assert (typeid (*copy) == typeid (s));
|
||||
return copy;
|
||||
}
|
||||
|
||||
inline void delete_clone (const SerializedType* s)
|
||||
{
|
||||
boost::checked_delete (s);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& out, const SerializedType& t)
|
||||
{
|
||||
return out << t.getFullText ();
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
const STAmount saZero (noCurrency(), noAccount(), 0);
|
||||
const STAmount saOne (noCurrency(), noAccount(), 1);
|
||||
const STAmount saZero (noIssue(), 0);
|
||||
const STAmount saOne (noIssue(), 1);
|
||||
|
||||
SerializedType& SerializedType::operator= (const SerializedType& t)
|
||||
{
|
||||
@@ -522,26 +522,6 @@ std::string STPath::getText () const
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
std::string STPathSet::getText () const
|
||||
{
|
||||
std::string ret ("{");
|
||||
bool firstPath = true;
|
||||
|
||||
BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
|
||||
{
|
||||
if (!firstPath)
|
||||
{
|
||||
ret += ", ";
|
||||
firstPath = false;
|
||||
}
|
||||
|
||||
ret += it.getText ();
|
||||
}
|
||||
return ret + "}";
|
||||
}
|
||||
#endif
|
||||
|
||||
void STPathSet::add (Serializer& s) const
|
||||
{
|
||||
assert (fName->isBinary ());
|
||||
|
||||
@@ -22,183 +22,14 @@
|
||||
|
||||
#include <ripple/module/data/protocol/FieldNames.h>
|
||||
#include <ripple/module/data/protocol/Serializer.h>
|
||||
#include <ripple/module/data/protocol/SerializedType.h>
|
||||
#include <ripple/module/data/protocol/STAmount.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO TODO fix this restriction on copy assignment.
|
||||
//
|
||||
// CAUTION: Do not create a vector (or similar container) of any object derived
|
||||
// from SerializedType. Use Boost ptr_* containers. The copy assignment operator
|
||||
// of SerializedType has semantics that will cause contained types to change
|
||||
// their names when an object is deleted because copy assignment is used to
|
||||
// "slide down" the remaining types and this will not copy the field
|
||||
// name. Changing the copy assignment operator to copy the field name breaks the
|
||||
// use of copy assignment just to copy values, which is used in the transaction
|
||||
// engine code.
|
||||
|
||||
// VFALCO TODO Remove this unused enum
|
||||
/*
|
||||
enum PathFlags
|
||||
{
|
||||
PF_END = 0x00, // End of current path & path list.
|
||||
PF_BOUNDARY = 0xFF, // End of current path & new path follows.
|
||||
|
||||
PF_ACCOUNT = 0x01,
|
||||
PF_OFFER = 0x02,
|
||||
|
||||
PF_WANTED_CURRENCY = 0x10,
|
||||
PF_WANTED_ISSUER = 0x20,
|
||||
PF_REDEEM = 0x40,
|
||||
PF_ISSUE = 0x80,
|
||||
};
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A type which can be exported to a well known binary format.
|
||||
|
||||
A SerializedType:
|
||||
- Always a field
|
||||
- Can always go inside an eligible enclosing SerializedType
|
||||
(such as STArray)
|
||||
- Has a field name
|
||||
|
||||
|
||||
Like JSON, a SerializedObject is a basket which has rules
|
||||
on what it can hold.
|
||||
*/
|
||||
// VFALCO TODO Document this as it looks like a central class.
|
||||
// STObject is derived from it
|
||||
//
|
||||
class SerializedType
|
||||
{
|
||||
public:
|
||||
SerializedType () : fName (&sfGeneric)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
explicit SerializedType (SField::ref n) : fName (&n)
|
||||
{
|
||||
assert (fName);
|
||||
}
|
||||
|
||||
virtual ~SerializedType () { }
|
||||
|
||||
static std::unique_ptr<SerializedType> deserialize (SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (new SerializedType (name));
|
||||
}
|
||||
|
||||
/** A SerializeType is a field.
|
||||
This sets the name.
|
||||
*/
|
||||
void setFName (SField::ref n)
|
||||
{
|
||||
fName = &n;
|
||||
assert (fName);
|
||||
}
|
||||
SField::ref getFName () const
|
||||
{
|
||||
return *fName;
|
||||
}
|
||||
virtual SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_NOTPRESENT;
|
||||
}
|
||||
std::unique_ptr<SerializedType> clone () const
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (duplicate ());
|
||||
}
|
||||
|
||||
virtual std::string getFullText () const;
|
||||
virtual std::string getText () const // just the value
|
||||
{
|
||||
return std::string ();
|
||||
}
|
||||
virtual Json::Value getJson (int /*options*/) const
|
||||
{
|
||||
return getText ();
|
||||
}
|
||||
|
||||
virtual void add (Serializer& s) const
|
||||
{
|
||||
assert (false);
|
||||
}
|
||||
|
||||
virtual bool isEquivalent (const SerializedType& t) const;
|
||||
|
||||
void addFieldID (Serializer& s) const
|
||||
{
|
||||
assert (fName->isBinary ());
|
||||
s.addFieldID (fName->fieldType, fName->fieldValue);
|
||||
}
|
||||
|
||||
SerializedType& operator= (const SerializedType& t);
|
||||
|
||||
bool operator== (const SerializedType& t) const
|
||||
{
|
||||
return (getSType () == t.getSType ()) && isEquivalent (t);
|
||||
}
|
||||
bool operator!= (const SerializedType& t) const
|
||||
{
|
||||
return (getSType () != t.getSType ()) || !isEquivalent (t);
|
||||
}
|
||||
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class D>
|
||||
D& downcast()
|
||||
{
|
||||
D* ptr = dynamic_cast<D*> (this);
|
||||
if (ptr == nullptr)
|
||||
throw std::runtime_error ("type mismatch");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
template <class D>
|
||||
D const& downcast() const
|
||||
{
|
||||
D const * ptr = dynamic_cast<D const*> (this);
|
||||
if (ptr == nullptr)
|
||||
throw std::runtime_error ("type mismatch");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
// VFALCO TODO make accessors for this
|
||||
SField::ptr fName;
|
||||
|
||||
private:
|
||||
virtual SerializedType* duplicate () const
|
||||
{
|
||||
return new SerializedType (*fName);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline SerializedType* new_clone (const SerializedType& s)
|
||||
{
|
||||
SerializedType* const copy (s.clone ().release ());
|
||||
assert (typeid (*copy) == typeid (s));
|
||||
return copy;
|
||||
}
|
||||
|
||||
inline void delete_clone (const SerializedType* s)
|
||||
{
|
||||
boost::checked_delete (s);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& out, const SerializedType& t)
|
||||
{
|
||||
return out << t.getFullText ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// TODO(tom): make STUInt8, STUInt16, STUInt32, STUInt64 a single templated
|
||||
// class to reduce the quadruple redundancy we have all over the rippled code
|
||||
// regarding uint-like types.
|
||||
|
||||
class STUInt8 : public SerializedType
|
||||
{
|
||||
@@ -443,406 +274,10 @@ private:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Internal form:
|
||||
// 1: If amount is zero, then value is zero and offset is -100
|
||||
// 2: Otherwise:
|
||||
// legal offset range is -96 to +80 inclusive
|
||||
// value range is 10^15 to (10^16 - 1) inclusive
|
||||
// amount = value * [10 ^ offset]
|
||||
|
||||
// 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 : public SerializedType
|
||||
{
|
||||
public:
|
||||
static const int cMinOffset = -96, cMaxOffset = 80;
|
||||
static const std::uint64_t cMinValue = 1000000000000000ull, cMaxValue = 9999999999999999ull;
|
||||
static const std::uint64_t cMaxNative = 9000000000000000000ull;
|
||||
static const std::uint64_t cMaxNativeN = 100000000000000000ull; // max native value on network
|
||||
static const std::uint64_t cNotNative = 0x8000000000000000ull;
|
||||
static const std::uint64_t cPosNative = 0x4000000000000000ull;
|
||||
|
||||
static std::uint64_t uRateOne;
|
||||
|
||||
STAmount (std::uint64_t v = 0, bool isNeg = false)
|
||||
: mValue (v), mOffset (0), mIsNative (true), mIsNegative (isNeg)
|
||||
{
|
||||
if (v == 0) mIsNegative = false;
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, std::uint64_t v = 0, bool isNeg = false)
|
||||
: SerializedType (n), mValue (v), mOffset (0), mIsNative (true), mIsNegative (isNeg)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, std::int64_t v) : SerializedType (n), mOffset (0), mIsNative (true)
|
||||
{
|
||||
set (v);
|
||||
}
|
||||
|
||||
STAmount (Currency const& currency, Account const& issuer,
|
||||
std::uint64_t uV = 0, int iOff = 0, bool bNegative = false)
|
||||
: mCurrency (currency), mIssuer (issuer), mValue (uV), mOffset (iOff), mIsNegative (bNegative)
|
||||
{
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (Currency const& currency, Account const& issuer,
|
||||
std::uint32_t uV, int iOff = 0, bool bNegative = false)
|
||||
: mCurrency (currency), mIssuer (issuer), mValue (uV), mOffset (iOff), mIsNegative (bNegative)
|
||||
{
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, Currency const& currency, Account const& issuer,
|
||||
std::uint64_t v = 0, int off = 0, bool isNeg = false) :
|
||||
SerializedType (n), mCurrency (currency), mIssuer (issuer), mValue (v), mOffset (off), mIsNegative (isNeg)
|
||||
{
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (Currency const& currency, Account const& issuer, std::int64_t v, int iOff = 0)
|
||||
: mCurrency (currency), mIssuer (issuer), mOffset (iOff)
|
||||
{
|
||||
set (v);
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, Currency const& currency, Account const& issuer, std::int64_t v, int off = 0)
|
||||
: SerializedType (n), mCurrency (currency), mIssuer (issuer), mOffset (off)
|
||||
{
|
||||
set (v);
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (Currency const& currency, Account const& issuer, int v, int iOff = 0)
|
||||
: mCurrency (currency), mIssuer (issuer), mOffset (iOff)
|
||||
{
|
||||
set (v);
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (SField::ref n, Currency const& currency, Account const& issuer, int v, int off = 0)
|
||||
: SerializedType (n), mCurrency (currency), mIssuer (issuer), mOffset (off)
|
||||
{
|
||||
set (v);
|
||||
canonicalize ();
|
||||
}
|
||||
|
||||
STAmount (SField::ref, const Json::Value&);
|
||||
|
||||
static STAmount createFromInt64 (SField::ref n, std::int64_t v);
|
||||
|
||||
static std::unique_ptr<SerializedType> deserialize (SerializerIterator& sit, SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
bool bSetJson (const Json::Value& jvSource);
|
||||
|
||||
static STAmount saFromRate (std::uint64_t uRate = 0)
|
||||
{
|
||||
return STAmount (noCurrency(), noAccount(), uRate, -9, false);
|
||||
}
|
||||
|
||||
SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_AMOUNT;
|
||||
}
|
||||
std::string getText () const;
|
||||
std::string getFullText () const;
|
||||
void add (Serializer& s) const;
|
||||
|
||||
int getExponent () const
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
std::uint64_t getMantissa () const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
int signum () const
|
||||
{
|
||||
return mValue ? (mIsNegative ? -1 : 1) : 0;
|
||||
}
|
||||
|
||||
// When the currency is XRP, the value in raw units. S=signed
|
||||
std::uint64_t getNValue () const
|
||||
{
|
||||
if (!mIsNative) throw std::runtime_error ("not native");
|
||||
|
||||
return mValue;
|
||||
}
|
||||
void setNValue (std::uint64_t v)
|
||||
{
|
||||
if (!mIsNative) throw std::runtime_error ("not native");
|
||||
|
||||
mValue = v;
|
||||
}
|
||||
std::int64_t getSNValue () const;
|
||||
void setSNValue (std::int64_t);
|
||||
|
||||
std::string getHumanCurrency () const;
|
||||
|
||||
bool isNative () const
|
||||
{
|
||||
return mIsNative;
|
||||
}
|
||||
bool isLegalNet () const
|
||||
{
|
||||
return !mIsNative || (mValue <= cMaxNativeN);
|
||||
}
|
||||
|
||||
explicit
|
||||
operator bool () const noexcept
|
||||
{
|
||||
return *this != zero;
|
||||
}
|
||||
|
||||
void negate ()
|
||||
{
|
||||
if (*this != zero)
|
||||
mIsNegative = !mIsNegative;
|
||||
}
|
||||
|
||||
// Return a copy of amount with the same Issuer and Currency but zero value.
|
||||
STAmount zeroed() const
|
||||
{
|
||||
STAmount c(mCurrency, mIssuer);
|
||||
c = zero;
|
||||
// See https://ripplelabs.atlassian.net/browse/WC-1847?jql=
|
||||
return c;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
// VFALCO: Why -100?
|
||||
mOffset = mIsNative ? 0 : -100;
|
||||
mValue = 0;
|
||||
mIsNegative = false;
|
||||
}
|
||||
|
||||
// Zero while copying currency and issuer.
|
||||
void clear (const STAmount& saTmpl)
|
||||
{
|
||||
mCurrency = saTmpl.mCurrency;
|
||||
mIssuer = saTmpl.mIssuer;
|
||||
mIsNative = saTmpl.mIsNative;
|
||||
clear ();
|
||||
}
|
||||
void clear (Currency const& currency, Account const& issuer)
|
||||
{
|
||||
mCurrency = currency;
|
||||
mIssuer = issuer;
|
||||
mIsNative = !currency;
|
||||
clear ();
|
||||
}
|
||||
|
||||
STAmount& operator=(beast::Zero)
|
||||
{
|
||||
clear ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
int compare (const STAmount&) const;
|
||||
|
||||
Account const& getIssuer () const
|
||||
{
|
||||
return mIssuer;
|
||||
}
|
||||
STAmount* setIssuer (Account const& uIssuer)
|
||||
{
|
||||
mIssuer = uIssuer;
|
||||
return this;
|
||||
}
|
||||
|
||||
Currency const& getCurrency () const
|
||||
{
|
||||
return mCurrency;
|
||||
}
|
||||
bool setValue (const std::string& sAmount);
|
||||
bool setFullValue (
|
||||
const std::string& sAmount, const std::string& sCurrency = "",
|
||||
const std::string& sIssuer = "");
|
||||
void setValue (const STAmount&);
|
||||
|
||||
virtual bool isEquivalent (const SerializedType& t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return (mValue == 0) && mIssuer.isZero () && mCurrency.isZero ();
|
||||
}
|
||||
|
||||
bool operator== (const STAmount&) const;
|
||||
bool operator!= (const STAmount&) const;
|
||||
bool operator< (const STAmount&) const;
|
||||
bool operator> (const STAmount&) const;
|
||||
bool operator<= (const STAmount&) const;
|
||||
bool operator>= (const STAmount&) const;
|
||||
bool isComparable (const STAmount&) const;
|
||||
void throwComparable (const STAmount&) const;
|
||||
|
||||
// native currency only
|
||||
bool operator< (std::uint64_t) const;
|
||||
bool operator> (std::uint64_t) const;
|
||||
bool operator<= (std::uint64_t) const;
|
||||
bool operator>= (std::uint64_t) const;
|
||||
STAmount operator+ (std::uint64_t) const;
|
||||
STAmount operator- (std::uint64_t) const;
|
||||
STAmount operator- (void) const;
|
||||
|
||||
STAmount& operator+= (const STAmount&);
|
||||
STAmount& operator-= (const STAmount&);
|
||||
STAmount& operator+= (std::uint64_t);
|
||||
STAmount& operator-= (std::uint64_t);
|
||||
STAmount& operator= (std::uint64_t);
|
||||
|
||||
operator double () const;
|
||||
|
||||
friend STAmount operator+ (const STAmount& v1, const STAmount& v2);
|
||||
friend STAmount operator- (const STAmount& v1, const STAmount& v2);
|
||||
|
||||
static STAmount divide (
|
||||
const STAmount& v1, const STAmount& v2,
|
||||
Currency const& currency, Account const& issuer);
|
||||
|
||||
static STAmount divide (
|
||||
const STAmount& v1, const STAmount& v2, const STAmount& saUnit)
|
||||
{
|
||||
return divide (v1, v2, saUnit.getCurrency (), saUnit.getIssuer ());
|
||||
}
|
||||
static STAmount divide (const STAmount& v1, const STAmount& v2)
|
||||
{
|
||||
return divide (v1, v2, v1);
|
||||
}
|
||||
|
||||
static STAmount multiply (
|
||||
const STAmount& v1, const STAmount& v2,
|
||||
Currency const& currency, Account const& issuer);
|
||||
|
||||
static STAmount multiply (
|
||||
const STAmount& v1, const STAmount& v2, const STAmount& saUnit)
|
||||
{
|
||||
return multiply (v1, v2, saUnit.getCurrency (), saUnit.getIssuer ());
|
||||
}
|
||||
static STAmount multiply (const STAmount& v1, const STAmount& v2)
|
||||
{
|
||||
return multiply (v1, v2, v1);
|
||||
}
|
||||
|
||||
/* addRound, subRound can end up rounding if the amount subtracted is too small
|
||||
to make a change. Consder (X-d) where d is very small relative to X.
|
||||
If you ask to round down, then (X-d) should not be X unless d is zero.
|
||||
If you ask to round up, (X+d) should never be X unless d is zero. (Assuming X and d are positive).
|
||||
*/
|
||||
// Add, subtract, multiply, or divide rounding result in specified direction
|
||||
static STAmount addRound (const STAmount& v1, const STAmount& v2, bool roundUp);
|
||||
static STAmount subRound (const STAmount& v1, const STAmount& v2, bool roundUp);
|
||||
static STAmount mulRound (const STAmount& v1, const STAmount& v2,
|
||||
Currency const& currency, Account const& issuer, bool roundUp);
|
||||
static STAmount divRound (const STAmount& v1, const STAmount& v2,
|
||||
Currency const& currency, Account const& issuer, bool roundUp);
|
||||
|
||||
static STAmount mulRound (const STAmount& v1, const STAmount& v2, const STAmount& saUnit, bool roundUp)
|
||||
{
|
||||
return mulRound (v1, v2, saUnit.getCurrency (), saUnit.getIssuer (), roundUp);
|
||||
}
|
||||
static STAmount mulRound (const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
{
|
||||
return mulRound (v1, v2, v1.getCurrency (), v1.getIssuer (), roundUp);
|
||||
}
|
||||
static STAmount divRound (const STAmount& v1, const STAmount& v2, const STAmount& saUnit, bool roundUp)
|
||||
{
|
||||
return divRound (v1, v2, saUnit.getCurrency (), saUnit.getIssuer (), roundUp);
|
||||
}
|
||||
static STAmount divRound (const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
{
|
||||
return divRound (v1, v2, v1.getCurrency (), v1.getIssuer (), roundUp);
|
||||
}
|
||||
|
||||
// Someone is offering X for Y, what is the rate?
|
||||
// Rate: smaller is better, the taker wants the most out: in/out
|
||||
static std::uint64_t getRate (const STAmount& offerOut, const STAmount& offerIn);
|
||||
static STAmount setRate (std::uint64_t rate);
|
||||
|
||||
// Someone is offering X for Y, I need Z, how much do I pay
|
||||
static STAmount getPay (
|
||||
const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed);
|
||||
|
||||
static STAmount deserialize (SerializerIterator&);
|
||||
|
||||
Json::Value getJson (int) const;
|
||||
void setJson (Json::Value&) const;
|
||||
|
||||
STAmount getRound () const;
|
||||
void roundSelf ();
|
||||
|
||||
static void canonicalizeRound (
|
||||
bool isNative, std::uint64_t& value, int& offset, bool roundUp);
|
||||
|
||||
private:
|
||||
Currency mCurrency; // Compared by ==. Always update mIsNative.
|
||||
Account mIssuer; // Not compared by ==. 0 for XRP.
|
||||
|
||||
std::uint64_t mValue;
|
||||
int mOffset;
|
||||
bool mIsNative; // Always !mCurrency. Native is XRP.
|
||||
bool mIsNegative;
|
||||
|
||||
void canonicalize ();
|
||||
STAmount* duplicate () const
|
||||
{
|
||||
return new STAmount (*this);
|
||||
}
|
||||
static STAmount* construct (SerializerIterator&, SField::ref name);
|
||||
|
||||
STAmount (SField::ref name, Currency const& cur, Account const& iss,
|
||||
std::uint64_t val, int off, bool isNat, bool isNeg)
|
||||
: SerializedType (name), mCurrency (cur), mIssuer (iss), mValue (val),
|
||||
mOffset (off), mIsNative (isNat), mIsNegative (isNeg)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void set (std::int64_t v)
|
||||
{
|
||||
if (v < 0)
|
||||
{
|
||||
mIsNegative = true;
|
||||
mValue = static_cast<std::uint64_t> (-v);
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsNegative = false;
|
||||
mValue = static_cast<std::uint64_t> (v);
|
||||
}
|
||||
}
|
||||
|
||||
void set (int v)
|
||||
{
|
||||
if (v < 0)
|
||||
{
|
||||
mIsNegative = true;
|
||||
mValue = static_cast<std::uint64_t> (-v);
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsNegative = false;
|
||||
mValue = static_cast<std::uint64_t> (v);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// VFALCO TODO Make static member accessors for these in STAmount
|
||||
extern const STAmount saZero;
|
||||
extern const STAmount saOne;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// TODO(tom): make STHash128, STHash160 and STHash256 a single templated class
|
||||
// to reduce the triple redundancy we have all over the rippled code.
|
||||
// to reduce the triple redundancy we have all over the rippled code regarding
|
||||
// hash-like classes.
|
||||
|
||||
class STHash128 : public SerializedType
|
||||
{
|
||||
public:
|
||||
@@ -1497,7 +932,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual bool isEquivalent (const SerializedType& t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user