21 #include <ripple/protocol/STAmount.h>
22 #include <ripple/basics/contract.h>
23 #include <ripple/basics/Log.h>
24 #include <ripple/basics/safe_cast.h>
25 #include <ripple/protocol/jss.h>
26 #include <ripple/protocol/SystemParameters.h>
27 #include <ripple/protocol/UintTypes.h>
28 #include <ripple/beast/core/LexicalCast.h>
29 #include <boost/regex.hpp>
30 #include <boost/algorithm/string.hpp>
31 #include <boost/multiprecision/cpp_int.hpp>
48 Throw<std::runtime_error> (
"amount is not native!");
88 Throw<std::runtime_error> (
"negative zero is not canonical");
101 Throw<std::runtime_error> (
"invalid native currency");
106 Throw<std::runtime_error> (
"invalid native account");
109 int offset =
static_cast<int>(
value >> (64 - 10));
111 value &= ~ (1023ull << (64 - 10));
115 bool isNegative = (offset & 256) == 0;
116 offset = (offset & 255) - 97;
123 Throw<std::runtime_error> (
"invalid currency value");
135 Throw<std::runtime_error> (
"invalid currency value");
152 , mIsNegative (negative)
163 , mIsNegative (negative)
170 bool native,
bool negative)
176 , mIsNegative (negative)
195 , mIsNegative (negative)
206 , mIsNegative (negative)
218 , mIsNegative (mantissa != 0 && negative)
228 , mIsNegative (negative)
249 int mantissa,
int exponent)
257 , mOffset (amount.exponent ())
259 , mIsNegative (amount <
beast::zero)
272 , mIsNegative (amount <
beast::zero)
275 mValue = unsafe_cast<std::uint64_t> (-amount.
drops ());
277 mValue = unsafe_cast<std::uint64_t> (amount.
drops ());
285 return std::make_unique<STAmount>(sit, name);
297 Throw<std::logic_error> (
298 "Cannot return non-native STAmount as XRPAmount");
312 Throw<std::logic_error> (
"Cannot return native STAmount as IOUAmount");
344 Throw<std::runtime_error> (
"Can't add amounts that are't comparable!");
346 if (v2 == beast::zero)
349 if (v1 == beast::zero)
386 if ((fv >= -10) && (fv <= 10))
425 if (offerOut == beast::zero)
430 if (r == beast::zero)
434 return (ret << (64 - 8)) | r.
mantissa();
495 if (*
this == beast::zero)
521 size_t const pad_prefix = 27;
522 size_t const pad_suffix = 23;
526 val.
append (pad_prefix,
'0');
528 val.
append (pad_suffix,
'0');
530 size_t const offset (
mOffset + 43);
532 auto pre_from (val.
begin ());
533 auto const pre_to (val.
begin () + offset);
535 auto const post_from (val.
begin () + offset);
536 auto post_to (val.
end ());
541 pre_from += pad_prefix;
543 assert (post_to >= post_from);
554 post_to -= pad_suffix;
556 assert (post_to >= post_from);
567 if (pre_from == pre_to)
570 ret.
append(pre_from, pre_to);
572 if (post_to != post_from)
575 ret.
append (post_from, post_to);
603 if (*
this == beast::zero)
619 return v && (*v == *
this);
667 Throw<std::runtime_error> (
"Native currency amount out of range");
690 Throw<std::runtime_error> (
"value overflow");
705 Throw<std::runtime_error> (
"value overflow");
735 int exponent =
static_cast<int>(rate >> (64 - 8)) - 100;
743 static boost::regex
const reNumber (
748 "([eE]([+-]?)([0-9]+))?"
750 boost::regex_constants::optimize);
754 if (!boost::regex_match (amount, match, reNumber))
755 Throw<std::runtime_error> (
"Number '" + amount +
"' is not valid");
768 if ((match[2].length () + match[4].length ()) > 32)
769 Throw<std::runtime_error> (
"Number '" + amount +
"' is overlong");
771 bool negative = (match[1].matched && (match[1] ==
"-"));
774 if (
isXRP(issue) && match[3].matched)
775 Throw<std::runtime_error> (
"XRP must be specified in integral drops.");
780 if (!match[4].matched)
782 mantissa = beast::lexicalCastThrow <std::uint64_t> (
std::string (match[2]));
788 mantissa = beast::lexicalCastThrow <std::uint64_t> (match[2] + match[4]);
789 exponent = -(match[4].length ());
792 if (match[5].matched)
795 if (match[6].matched && (match[6] ==
"-"))
796 exponent -= beast::lexicalCastThrow <int> (
std::string (match[7]));
798 exponent += beast::lexicalCastThrow <int> (
std::string (match[7]));
801 return { issue, mantissa, exponent, negative };
809 bool negative =
false;
818 Throw<std::runtime_error> (
"XRP may not be specified with a null Json value");
822 value = v[jss::value];
823 currency = v[jss::currency];
824 issuer = v[jss::issuer];
836 boost::split (elements, val, boost::is_any_of (
"\t\n\r ,/"));
838 if (elements.
size () > 3)
839 Throw<std::runtime_error> (
"invalid amount string");
843 if (elements.
size () > 1)
844 currency = elements[1];
846 if (elements.
size () > 2)
847 issuer = elements[2];
854 bool const native = ! currency.
isString () ||
861 Throw<std::runtime_error> (
"XRP may not be specified as an object");
868 Throw<std::runtime_error> (
"invalid currency");
872 Throw<std::runtime_error> (
"invalid issuer");
875 Throw<std::runtime_error> (
"invalid issuer");
880 if (value.
asInt () >= 0)
882 mantissa = value.
asInt ();
886 mantissa = -value.
asInt ();
898 mantissa = ret.mantissa ();
899 exponent = ret.exponent ();
900 negative = ret.negative ();
904 Throw<std::runtime_error> (
"invalid amount type");
907 return { name, issue, mantissa, exponent, native, negative };
921 "amountFromJsonNoThrow: caught: " << e.
what ();
945 Throw<std::runtime_error> (
"Can't compare amounts that are't comparable!");
960 if (rhs.
mantissa() == 0)
return false;
995 boost::multiprecision::uint128_t ret;
997 boost::multiprecision::multiply(ret, multiplier, multiplicand);
1002 Throw<std::overflow_error> (
"overflow: (" +
1008 return static_cast<uint64_t
>(ret);
1019 boost::multiprecision::uint128_t ret;
1021 boost::multiprecision::multiply(ret, multiplier, multiplicand);
1027 Throw<std::overflow_error> (
"overflow: ((" +
1034 return static_cast<uint64_t
>(ret);
1040 if (den == beast::zero)
1041 Throw<std::runtime_error> (
"division by zero");
1043 if (num == beast::zero)
1077 numOffset - denOffset - 17,
1084 if (v1 == beast::zero || v2 == beast::zero)
1094 if (minV > 3000000000ull)
1095 Throw<std::runtime_error> (
"Native value overflow");
1097 if (((maxV >> 32) * minV) > 2095475792ull)
1098 Throw<std::runtime_error> (
"Native value overflow");
1132 offset1 + offset2 + 14,
1153 value += (loops >= 2) ? 9 : 10;
1176 if (v1 == beast::zero || v2 == beast::zero)
1179 bool const xrp =
isXRP (issue);
1188 if (minV > 3000000000ull)
1189 Throw<std::runtime_error> (
"Native value overflow");
1191 if (((maxV >> 32) * minV) > 2095475792ull)
1192 Throw<std::runtime_error> (
"Native value overflow");
1230 (resultNegative != roundUp) ?
tenTo14m1 : 0);
1232 int offset = offset1 + offset2 + 14;
1233 if (resultNegative != roundUp)
1235 STAmount result (issue, amount, offset, resultNegative);
1237 if (roundUp && !resultNegative && !result)
1251 return STAmount(issue, amount, offset, resultNegative);
1258 Issue const& issue,
bool roundUp)
1260 if (den == beast::zero)
1261 Throw<std::runtime_error> (
"division by zero");
1263 if (num == beast::zero)
1287 bool const resultNegative =
1300 (resultNegative != roundUp) ? denVal - 1 : 0);
1302 int offset = numOffset - denOffset - 17;
1304 if (resultNegative != roundUp)
1307 STAmount result (issue, amount, offset, resultNegative);
1308 if (roundUp && !resultNegative && !result)
1322 return STAmount(issue, amount, offset, resultNegative);