#ifndef XRPL_PROTOCOL_AMOUNTCONVERSION_H_INCLUDED #define XRPL_PROTOCOL_AMOUNTCONVERSION_H_INCLUDED #include #include #include #include namespace ripple { inline STAmount toSTAmount(IOUAmount const& iou, Issue const& iss) { bool const isNeg = iou.signum() < 0; std::uint64_t const umant = isNeg ? -iou.mantissa() : iou.mantissa(); return STAmount(iss, umant, iou.exponent(), isNeg, STAmount::unchecked()); } inline STAmount toSTAmount(IOUAmount const& iou) { return toSTAmount(iou, noIssue()); } inline STAmount toSTAmount(XRPAmount const& xrp) { bool const isNeg = xrp.signum() < 0; std::uint64_t const umant = isNeg ? -xrp.drops() : xrp.drops(); return STAmount(umant, isNeg); } inline STAmount toSTAmount(XRPAmount const& xrp, Issue const& iss) { XRPL_ASSERT( isXRP(iss.account) && isXRP(iss.currency), "ripple::toSTAmount : is XRP"); return toSTAmount(xrp); } template T toAmount(STAmount const& amt) = delete; template <> inline STAmount toAmount(STAmount const& amt) { return amt; } template <> inline IOUAmount toAmount(STAmount const& amt) { XRPL_ASSERT( amt.mantissa() < std::numeric_limits::max(), "ripple::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); XRPL_ASSERT(!isXRP(amt), "ripple::toAmount : is not XRP"); return IOUAmount(sMant, amt.exponent()); } template <> inline XRPAmount toAmount(STAmount const& amt) { XRPL_ASSERT( amt.mantissa() < std::numeric_limits::max(), "ripple::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); XRPL_ASSERT(isXRP(amt), "ripple::toAmount : is XRP"); return XRPAmount(sMant); } template T toAmount(IOUAmount const& amt) = delete; template <> inline IOUAmount toAmount(IOUAmount const& amt) { return amt; } template T toAmount(XRPAmount const& amt) = delete; template <> inline XRPAmount toAmount(XRPAmount const& amt) { return amt; } template T toAmount( Issue const& issue, Number const& n, Number::rounding_mode mode = Number::getround()) { saveNumberRoundMode rm(Number::getround()); if (isXRP(issue)) Number::setround(mode); if constexpr (std::is_same_v) return IOUAmount(n); else if constexpr (std::is_same_v) return XRPAmount(static_cast(n)); else if constexpr (std::is_same_v) { if (isXRP(issue)) return STAmount(issue, static_cast(n)); return STAmount(issue, n.mantissa(), n.exponent()); } else { constexpr bool alwaysFalse = !std::is_same_v; static_assert(alwaysFalse, "Unsupported type for toAmount"); } } template T toMaxAmount(Issue const& issue) { if constexpr (std::is_same_v) return IOUAmount(STAmount::cMaxValue, STAmount::cMaxOffset); else if constexpr (std::is_same_v) return XRPAmount(static_cast(STAmount::cMaxNativeN)); else if constexpr (std::is_same_v) { if (isXRP(issue)) return STAmount( issue, static_cast(STAmount::cMaxNativeN)); return STAmount(issue, STAmount::cMaxValue, STAmount::cMaxOffset); } else { constexpr bool alwaysFalse = !std::is_same_v; static_assert(alwaysFalse, "Unsupported type for toMaxAmount"); } } inline STAmount toSTAmount( Issue const& issue, Number const& n, Number::rounding_mode mode = Number::getround()) { return toAmount(issue, n, mode); } template Issue getIssue(T const& amt) { if constexpr (std::is_same_v) return noIssue(); else if constexpr (std::is_same_v) return xrpIssue(); else if constexpr (std::is_same_v) return amt.issue(); else { constexpr bool alwaysFalse = !std::is_same_v; static_assert(alwaysFalse, "Unsupported type for getIssue"); } } template constexpr T get(STAmount const& a) { if constexpr (std::is_same_v) return a.iou(); else if constexpr (std::is_same_v) return a.xrp(); else if constexpr (std::is_same_v) return a; else { constexpr bool alwaysFalse = !std::is_same_v; static_assert(alwaysFalse, "Unsupported type for get"); } } } // namespace ripple #endif