20 #include <ripple/basics/Log.h>
21 #include <ripple/basics/contract.h>
22 #include <ripple/basics/safe_cast.h>
23 #include <ripple/beast/core/LexicalCast.h>
24 #include <ripple/protocol/STAmount.h>
25 #include <ripple/protocol/SystemParameters.h>
26 #include <ripple/protocol/UintTypes.h>
27 #include <ripple/protocol/jss.h>
28 #include <boost/algorithm/string.hpp>
29 #include <boost/multiprecision/cpp_int.hpp>
30 #include <boost/regex.hpp>
48 Throw<std::runtime_error>(
"amount is not native!");
86 Throw<std::runtime_error>(
"negative zero is not canonical");
99 Throw<std::runtime_error>(
"invalid native currency");
104 Throw<std::runtime_error>(
"invalid native account");
107 int offset =
static_cast<int>(
value >> (64 - 10));
109 value &= ~(1023ull << (64 - 10));
113 bool isNegative = (offset & 256) == 0;
114 offset = (offset & 255) - 97;
119 Throw<std::runtime_error>(
"invalid currency value");
131 Throw<std::runtime_error>(
"invalid currency value");
153 , mIsNegative(negative)
168 , mIsNegative(negative)
184 , mIsNegative(negative)
190 :
STBase(name), mOffset(0), mIsNative(true)
200 , mIsNegative(negative)
215 , mIsNegative(negative)
227 , mIsNegative(mantissa != 0 && negative)
237 : mIssue(issue), mValue(mantissa), mOffset(exponent), mIsNegative(negative)
243 : mIssue(issue), mOffset(exponent)
266 , mOffset(amount.exponent())
268 , mIsNegative(amount <
beast::zero)
279 : mOffset(0), mIsNative(true), mIsNegative(amount <
beast::zero)
282 mValue = unsafe_cast<std::uint64_t>(-amount.
drops());
284 mValue = unsafe_cast<std::uint64_t>(amount.
drops());
292 return std::make_unique<STAmount>(sit, name);
304 return emplace(n, buf, std::move(*
this));
316 Throw<std::logic_error>(
317 "Cannot return non-native STAmount as XRPAmount");
331 Throw<std::logic_error>(
"Cannot return native STAmount as IOUAmount");
379 Throw<std::runtime_error>(
"Can't add amounts that are't comparable!");
381 if (v2 == beast::zero)
384 if (v1 == beast::zero)
432 if ((fv >= -10) && (fv <= 10))
476 if (offerOut == beast::zero)
481 if (r == beast::zero)
485 return (ret << (64 - 8)) | r.
mantissa();
553 if (*
this == beast::zero)
562 bool const scientific(
580 size_t const pad_prefix = 27;
581 size_t const pad_suffix = 23;
585 val.
append(pad_prefix,
'0');
587 val.
append(pad_suffix,
'0');
589 size_t const offset(
mOffset + 43);
591 auto pre_from(val.
begin());
592 auto const pre_to(val.
begin() + offset);
594 auto const post_from(val.
begin() + offset);
595 auto post_to(val.
end());
600 pre_from += pad_prefix;
602 assert(post_to >= post_from);
604 pre_from =
std::find_if(pre_from, pre_to, [](
char c) {
return c !=
'0'; });
609 post_to -= pad_suffix;
611 assert(post_to >= post_from);
616 [](
char c) {
return c !=
'0'; })
620 if (pre_from == pre_to)
623 ret.
append(pre_from, pre_to);
625 if (post_to != post_from)
628 ret.
append(post_from, post_to);
655 if (*
this == beast::zero)
676 return v && (*v == *
this);
724 Throw<std::runtime_error>(
725 "Native currency amount out of range");
752 Throw<std::runtime_error>(
753 "Native currency amount out of range");
761 Throw<std::runtime_error>(
"Native currency amount out of range");
790 Throw<std::runtime_error>(
"value overflow");
805 Throw<std::runtime_error>(
"value overflow");
837 int exponent =
static_cast<int>(rate >> (64 - 8)) - 100;
845 static boost::regex
const reNumber(
850 "([eE]([+-]?)([0-9]+))?"
852 boost::regex_constants::optimize);
856 if (!boost::regex_match(amount, match, reNumber))
857 Throw<std::runtime_error>(
"Number '" + amount +
"' is not valid");
870 if ((match[2].length() + match[4].length()) > 32)
871 Throw<std::runtime_error>(
"Number '" + amount +
"' is overlong");
873 bool negative = (match[1].matched && (match[1] ==
"-"));
876 if (
isXRP(issue) && match[3].matched)
877 Throw<std::runtime_error>(
"XRP must be specified in integral drops.");
882 if (!match[4].matched)
885 beast::lexicalCastThrow<std::uint64_t>(
std::string(match[2]));
891 mantissa = beast::lexicalCastThrow<std::uint64_t>(match[2] + match[4]);
892 exponent = -(match[4].length());
895 if (match[5].matched)
898 if (match[6].matched && (match[6] ==
"-"))
899 exponent -= beast::lexicalCastThrow<int>(
std::string(match[7]));
901 exponent += beast::lexicalCastThrow<int>(
std::string(match[7]));
904 return {issue, mantissa, exponent, negative};
912 bool negative =
false;
921 Throw<std::runtime_error>(
922 "XRP may not be specified with a null Json value");
926 value = v[jss::value];
927 currency = v[jss::currency];
928 issuer = v[jss::issuer];
940 boost::split(elements, val, boost::is_any_of(
"\t\n\r ,/"));
942 if (elements.
size() > 3)
943 Throw<std::runtime_error>(
"invalid amount string");
947 if (elements.
size() > 1)
948 currency = elements[1];
950 if (elements.
size() > 2)
951 issuer = elements[2];
964 Throw<std::runtime_error>(
"XRP may not be specified as an object");
971 Throw<std::runtime_error>(
"invalid currency");
974 Throw<std::runtime_error>(
"invalid issuer");
977 Throw<std::runtime_error>(
"invalid issuer");
982 if (value.
asInt() >= 0)
984 mantissa = value.
asInt();
988 mantissa = -value.
asInt();
1000 mantissa = ret.mantissa();
1001 exponent = ret.exponent();
1002 negative = ret.negative();
1006 Throw<std::runtime_error>(
"invalid amount type");
1009 return {name, issue, mantissa, exponent, native, negative};
1023 <<
"amountFromJsonNoThrow: caught: " << e.
what();
1045 Throw<std::runtime_error>(
1046 "Can't compare amounts that are't comparable!");
1105 boost::multiprecision::uint128_t ret;
1107 boost::multiprecision::multiply(ret, multiplier, multiplicand);
1112 Throw<std::overflow_error>(
1117 return static_cast<uint64_t
>(ret);
1127 boost::multiprecision::uint128_t ret;
1129 boost::multiprecision::multiply(ret, multiplier, multiplicand);
1135 Throw<std::overflow_error>(
1141 return static_cast<uint64_t
>(ret);
1147 if (den == beast::zero)
1148 Throw<std::runtime_error>(
"division by zero");
1150 if (num == beast::zero)
1185 numOffset - denOffset - 17,
1192 if (v1 == beast::zero || v2 == beast::zero)
1202 if (minV > 3000000000ull)
1203 Throw<std::runtime_error>(
"Native value overflow");
1205 if (((maxV >> 32) * minV) > 2095475792ull)
1206 Throw<std::runtime_error>(
"Native value overflow");
1244 offset1 + offset2 + 14,
1264 value += (loops >= 2) ? 9 : 10;
1290 if (v1 == beast::zero || v2 == beast::zero)
1293 bool const xrp =
isXRP(issue);
1302 if (minV > 3000000000ull)
1303 Throw<std::runtime_error>(
"Native value overflow");
1305 if (((maxV >> 32) * minV) > 2095475792ull)
1306 Throw<std::runtime_error>(
"Native value overflow");
1345 int offset = offset1 + offset2 + 14;
1346 if (resultNegative != roundUp)
1348 STAmount result(issue, amount, offset, resultNegative);
1350 if (roundUp && !resultNegative && !result)
1364 return STAmount(issue, amount, offset, resultNegative);
1376 if (den == beast::zero)
1377 Throw<std::runtime_error>(
"division by zero");
1379 if (num == beast::zero)
1414 numVal,
tenTo17, denVal, (resultNegative != roundUp) ? denVal - 1 : 0);
1416 int offset = numOffset - denOffset - 17;
1418 if (resultNegative != roundUp)
1421 STAmount result(issue, amount, offset, resultNegative);
1422 if (roundUp && !resultNegative && !result)
1436 return STAmount(issue, amount, offset, resultNegative);