mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-24 21:15:58 +00:00
Support STAmount conversions to XRPAmount and IOUAmount
This commit is contained in:
@@ -24,6 +24,8 @@
|
|||||||
#include <ripple/protocol/Serializer.h>
|
#include <ripple/protocol/Serializer.h>
|
||||||
#include <ripple/protocol/STBase.h>
|
#include <ripple/protocol/STBase.h>
|
||||||
#include <ripple/protocol/Issue.h>
|
#include <ripple/protocol/Issue.h>
|
||||||
|
#include <ripple/protocol/IOUAmount.h>
|
||||||
|
#include <ripple/protocol/XRPAmount.h>
|
||||||
#include <beast/cxx14/memory.h> // <memory>
|
#include <beast/cxx14/memory.h> // <memory>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -114,6 +116,10 @@ public:
|
|||||||
|
|
||||||
STAmount (Issue const& issue, int mantissa, int exponent = 0);
|
STAmount (Issue const& issue, int mantissa, int exponent = 0);
|
||||||
|
|
||||||
|
// Legacy support for new-style amounts
|
||||||
|
STAmount (IOUAmount const& amount, Issue const& issue);
|
||||||
|
STAmount (XRPAmount const& amount);
|
||||||
|
|
||||||
STBase*
|
STBase*
|
||||||
copy (std::size_t n, void* buf) const override
|
copy (std::size_t n, void* buf) const override
|
||||||
{
|
{
|
||||||
@@ -271,6 +277,9 @@ public:
|
|||||||
{
|
{
|
||||||
return (mValue == 0) && mIsNative;
|
return (mValue == 0) && mIsNative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XRPAmount xrp () const;
|
||||||
|
IOUAmount iou () const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <beast/utility/Zero.h>
|
#include <beast/utility/Zero.h>
|
||||||
#include <boost/operators.hpp>
|
#include <boost/operators.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <beast/cxx14/type_traits.h>
|
||||||
|
|
||||||
using beast::zero;
|
using beast::zero;
|
||||||
|
|
||||||
@@ -35,82 +36,94 @@ class XRPAmount
|
|||||||
, private boost::additive <XRPAmount>
|
, private boost::additive <XRPAmount>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::int64_t value_;
|
std::int64_t drops_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** @{ */
|
|
||||||
XRPAmount () = default;
|
XRPAmount () = default;
|
||||||
XRPAmount (XRPAmount const& other) = default;
|
XRPAmount (XRPAmount const& other) = default;
|
||||||
XRPAmount& operator= (XRPAmount const& other) = default;
|
XRPAmount& operator= (XRPAmount const& other) = default;
|
||||||
|
|
||||||
XRPAmount (beast::Zero)
|
XRPAmount (beast::Zero)
|
||||||
: value_ (0)
|
: drops_ (0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
XRPAmount&
|
XRPAmount&
|
||||||
operator= (beast::Zero)
|
operator= (beast::Zero)
|
||||||
{
|
{
|
||||||
value_ = 0;
|
drops_ = 0;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRPAmount (std::int64_t value)
|
template <class Integer,
|
||||||
: value_ (value)
|
class = typename std::enable_if_t <
|
||||||
|
std::is_integral<Integer>::value>>
|
||||||
|
XRPAmount (Integer drops)
|
||||||
|
: drops_ (static_cast<std::int64_t> (drops))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Integer,
|
||||||
|
class = typename std::enable_if_t <
|
||||||
|
std::is_integral<Integer>::value>>
|
||||||
XRPAmount&
|
XRPAmount&
|
||||||
operator= (std::int64_t v)
|
operator= (Integer drops)
|
||||||
{
|
{
|
||||||
value_ = v;
|
drops_ = static_cast<std::int64_t> (drops);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRPAmount&
|
XRPAmount&
|
||||||
operator+= (XRPAmount const& other)
|
operator+= (XRPAmount const& other)
|
||||||
{
|
{
|
||||||
value_ += other.value_;
|
drops_ += other.drops_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRPAmount&
|
XRPAmount&
|
||||||
operator-= (XRPAmount const& other)
|
operator-= (XRPAmount const& other)
|
||||||
{
|
{
|
||||||
value_ -= other.value_;
|
drops_ -= other.drops_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRPAmount
|
XRPAmount
|
||||||
operator- () const
|
operator- () const
|
||||||
{
|
{
|
||||||
return { -value_ };
|
return { -drops_ };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
operator==(XRPAmount const& other) const
|
operator==(XRPAmount const& other) const
|
||||||
{
|
{
|
||||||
return value_ == other.value_;
|
return drops_ == other.drops_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
operator<(XRPAmount const& other) const
|
operator<(XRPAmount const& other) const
|
||||||
{
|
{
|
||||||
return value_ < other.value_;
|
return drops_ < other.drops_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if the amount is not zero */
|
/** Returns true if the amount is not zero */
|
||||||
explicit
|
explicit
|
||||||
operator bool() const noexcept
|
operator bool() const noexcept
|
||||||
{
|
{
|
||||||
return value_ != 0;
|
return drops_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the sign of the amount */
|
/** Return the sign of the amount */
|
||||||
int
|
int
|
||||||
signum() const noexcept
|
signum() const noexcept
|
||||||
{
|
{
|
||||||
return (value_ < 0) ? -1 : (value_ ? 1 : 0);
|
return (drops_ < 0) ? -1 : (drops_ ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the number of drops */
|
||||||
|
std::int64_t
|
||||||
|
drops () const
|
||||||
|
{
|
||||||
|
return drops_;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,7 +131,7 @@ public:
|
|||||||
inline
|
inline
|
||||||
bool isLegalAmount (XRPAmount const& amount)
|
bool isLegalAmount (XRPAmount const& amount)
|
||||||
{
|
{
|
||||||
return amount <= SYSTEM_CURRENCY_START;
|
return amount.drops () <= SYSTEM_CURRENCY_START;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,12 +248,72 @@ STAmount::STAmount (Issue const& issue,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Legacy support for new-style amounts
|
||||||
|
STAmount::STAmount (IOUAmount const& amount, Issue const& issue)
|
||||||
|
: mIssue (issue)
|
||||||
|
, mOffset (amount.exponent ())
|
||||||
|
, mIsNative (false)
|
||||||
|
, mIsNegative (amount < zero)
|
||||||
|
{
|
||||||
|
if (mIsNegative)
|
||||||
|
mValue = static_cast<std::uint64_t> (-amount.mantissa ());
|
||||||
|
else
|
||||||
|
mValue = static_cast<std::uint64_t> (amount.mantissa ());
|
||||||
|
|
||||||
|
canonicalize ();
|
||||||
|
}
|
||||||
|
|
||||||
|
STAmount::STAmount (XRPAmount const& amount)
|
||||||
|
: mOffset (0)
|
||||||
|
, mIsNative (true)
|
||||||
|
, mIsNegative (amount < zero)
|
||||||
|
{
|
||||||
|
if (mIsNegative)
|
||||||
|
mValue = static_cast<std::uint64_t> (-amount.drops ());
|
||||||
|
else
|
||||||
|
mValue = static_cast<std::uint64_t> (amount.drops ());
|
||||||
|
|
||||||
|
canonicalize ();
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<STAmount>
|
std::unique_ptr<STAmount>
|
||||||
STAmount::construct (SerialIter& sit, SField const& name)
|
STAmount::construct (SerialIter& sit, SField const& name)
|
||||||
{
|
{
|
||||||
return std::make_unique<STAmount>(sit, name);
|
return std::make_unique<STAmount>(sit, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Conversion
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
XRPAmount STAmount::xrp () const
|
||||||
|
{
|
||||||
|
if (!mIsNative)
|
||||||
|
throw std::logic_error ("Cannot return non-native STAmount as XRPAmount");
|
||||||
|
|
||||||
|
auto drops = static_cast<std::int64_t> (mValue);
|
||||||
|
|
||||||
|
if (mIsNegative)
|
||||||
|
drops = -drops;
|
||||||
|
|
||||||
|
return { drops };
|
||||||
|
}
|
||||||
|
|
||||||
|
IOUAmount STAmount::iou () const
|
||||||
|
{
|
||||||
|
if (mIsNative)
|
||||||
|
throw std::logic_error ("Cannot return native STAmount as IOUAmount");
|
||||||
|
|
||||||
|
auto mantissa = static_cast<std::int64_t> (mValue);
|
||||||
|
auto exponent = mOffset;
|
||||||
|
|
||||||
|
if (mIsNegative)
|
||||||
|
mantissa = -mantissa;
|
||||||
|
|
||||||
|
return { mantissa, exponent };
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Operators
|
// Operators
|
||||||
|
|||||||
@@ -567,6 +567,70 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testConvertXRP ()
|
||||||
|
{
|
||||||
|
testcase ("STAmount to XRPAmount conversions");
|
||||||
|
|
||||||
|
Issue const usd { Currency (0x5553440000000000), AccountID (0x4985601) };
|
||||||
|
Issue const xrp { xrpIssue () };
|
||||||
|
|
||||||
|
for (std::uint64_t drops = 100000000000000000; drops != 1; drops = drops / 10)
|
||||||
|
{
|
||||||
|
auto const t = amountFromString (xrp, std::to_string (drops));
|
||||||
|
auto const s = t.xrp ();
|
||||||
|
expect (s.drops() == drops);
|
||||||
|
expect (t == STAmount (XRPAmount (drops)));
|
||||||
|
expect (s == XRPAmount (drops));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto const t = amountFromString (usd, "136500");
|
||||||
|
fail (to_string (t.xrp ()));
|
||||||
|
}
|
||||||
|
catch (std::logic_error const&)
|
||||||
|
{
|
||||||
|
pass ();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
fail ("wrong exception");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testConvertIOU ()
|
||||||
|
{
|
||||||
|
testcase ("STAmount to IOUAmount conversions");
|
||||||
|
|
||||||
|
Issue const usd { Currency (0x5553440000000000), AccountID (0x4985601) };
|
||||||
|
Issue const xrp { xrpIssue () };
|
||||||
|
|
||||||
|
for (std::uint64_t dollars = 10000000000; dollars != 1; dollars = dollars / 10)
|
||||||
|
{
|
||||||
|
auto const t = amountFromString (usd, std::to_string (dollars));
|
||||||
|
auto const s = t.iou ();
|
||||||
|
expect (t == STAmount (s, usd));
|
||||||
|
expect (s.mantissa () == t.mantissa ());
|
||||||
|
expect (s.exponent () == t.exponent ());
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto const t = amountFromString (xrp, "136500");
|
||||||
|
fail (to_string (t.iou ()));
|
||||||
|
}
|
||||||
|
catch (std::logic_error const&)
|
||||||
|
{
|
||||||
|
pass ();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
fail ("wrong exception");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
void run ()
|
void run ()
|
||||||
@@ -577,6 +641,8 @@ public:
|
|||||||
testArithmetic ();
|
testArithmetic ();
|
||||||
testUnderflow ();
|
testUnderflow ();
|
||||||
testRounding ();
|
testRounding ();
|
||||||
|
testConvertXRP ();
|
||||||
|
testConvertIOU ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user