mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-23 12:35:50 +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/STBase.h>
|
||||
#include <ripple/protocol/Issue.h>
|
||||
#include <ripple/protocol/IOUAmount.h>
|
||||
#include <ripple/protocol/XRPAmount.h>
|
||||
#include <beast/cxx14/memory.h> // <memory>
|
||||
|
||||
namespace ripple {
|
||||
@@ -114,6 +116,10 @@ public:
|
||||
|
||||
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*
|
||||
copy (std::size_t n, void* buf) const override
|
||||
{
|
||||
@@ -271,6 +277,9 @@ public:
|
||||
{
|
||||
return (mValue == 0) && mIsNative;
|
||||
}
|
||||
|
||||
XRPAmount xrp () const;
|
||||
IOUAmount iou () const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <beast/utility/Zero.h>
|
||||
#include <boost/operators.hpp>
|
||||
#include <cstdint>
|
||||
#include <beast/cxx14/type_traits.h>
|
||||
|
||||
using beast::zero;
|
||||
|
||||
@@ -35,82 +36,94 @@ class XRPAmount
|
||||
, private boost::additive <XRPAmount>
|
||||
{
|
||||
private:
|
||||
std::int64_t value_;
|
||||
std::int64_t drops_;
|
||||
|
||||
public:
|
||||
/** @{ */
|
||||
XRPAmount () = default;
|
||||
XRPAmount (XRPAmount const& other) = default;
|
||||
XRPAmount& operator= (XRPAmount const& other) = default;
|
||||
|
||||
XRPAmount (beast::Zero)
|
||||
: value_ (0)
|
||||
: drops_ (0)
|
||||
{
|
||||
}
|
||||
|
||||
XRPAmount&
|
||||
operator= (beast::Zero)
|
||||
{
|
||||
value_ = 0;
|
||||
drops_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
XRPAmount (std::int64_t value)
|
||||
: value_ (value)
|
||||
template <class Integer,
|
||||
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&
|
||||
operator= (std::int64_t v)
|
||||
operator= (Integer drops)
|
||||
{
|
||||
value_ = v;
|
||||
drops_ = static_cast<std::int64_t> (drops);
|
||||
return *this;
|
||||
}
|
||||
|
||||
XRPAmount&
|
||||
operator+= (XRPAmount const& other)
|
||||
{
|
||||
value_ += other.value_;
|
||||
drops_ += other.drops_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
XRPAmount&
|
||||
operator-= (XRPAmount const& other)
|
||||
{
|
||||
value_ -= other.value_;
|
||||
drops_ -= other.drops_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
operator- () const
|
||||
{
|
||||
return { -value_ };
|
||||
return { -drops_ };
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(XRPAmount const& other) const
|
||||
{
|
||||
return value_ == other.value_;
|
||||
return drops_ == other.drops_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(XRPAmount const& other) const
|
||||
{
|
||||
return value_ < other.value_;
|
||||
return drops_ < other.drops_;
|
||||
}
|
||||
|
||||
/** Returns true if the amount is not zero */
|
||||
explicit
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return value_ != 0;
|
||||
return drops_ != 0;
|
||||
}
|
||||
|
||||
/** Return the sign of the amount */
|
||||
int
|
||||
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
|
||||
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>
|
||||
STAmount::construct (SerialIter& sit, SField const& 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
|
||||
|
||||
@@ -567,6 +567,70 @@ public:
|
||||
#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 ()
|
||||
@@ -577,6 +641,8 @@ public:
|
||||
testArithmetic ();
|
||||
testUnderflow ();
|
||||
testRounding ();
|
||||
testConvertXRP ();
|
||||
testConvertIOU ();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user