rippled
AmountSpec.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_PATH_IMPL_AMOUNTSPEC_H_INCLUDED
21 #define RIPPLE_PATH_IMPL_AMOUNTSPEC_H_INCLUDED
22 
23 #include <ripple/basics/IOUAmount.h>
24 #include <ripple/basics/XRPAmount.h>
25 #include <ripple/protocol/STAmount.h>
26 
27 namespace ripple {
28 
29 struct AmountSpec
30 {
31  explicit AmountSpec() = default;
32 
33  bool native;
34  union
35  {
38  };
39  boost::optional<AccountID> issuer;
40  boost::optional<Currency> currency;
41 
42  friend std::ostream&
43  operator<<(std::ostream& stream, AmountSpec const& amt)
44  {
45  if (amt.native)
46  stream << to_string(amt.xrp);
47  else
48  stream << to_string(amt.iou);
49  if (amt.currency)
50  stream << "/(" << *amt.currency << ")";
51  if (amt.issuer)
52  stream << "/" << *amt.issuer << "";
53  return stream;
54  }
55 };
56 
58 {
59 #ifndef NDEBUG
60  bool native = false;
61 #endif
62 
63  union
64  {
67  };
68 
69  EitherAmount() = default;
70 
71  explicit EitherAmount(IOUAmount const& a) : iou(a)
72  {
73  }
74 
75 #if defined(__GNUC__) && !defined(__clang__)
76 #pragma GCC diagnostic push
77  // ignore warning about half of iou amount being uninitialized
78 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
79 #endif
80  explicit EitherAmount(XRPAmount const& a) : xrp(a)
81  {
82 #ifndef NDEBUG
83  native = true;
84 #endif
85  }
86 #if defined(__GNUC__) && !defined(__clang__)
87 #pragma GCC diagnostic pop
88 #endif
89 
90  explicit EitherAmount(AmountSpec const& a)
91  {
92 #ifndef NDEBUG
93  native = a.native;
94 #endif
95  if (a.native)
96  xrp = a.xrp;
97  else
98  iou = a.iou;
99  }
100 
101 #ifndef NDEBUG
102  friend std::ostream&
103  operator<<(std::ostream& stream, EitherAmount const& amt)
104  {
105  if (amt.native)
106  stream << to_string(amt.xrp);
107  else
108  stream << to_string(amt.iou);
109  return stream;
110  }
111 #endif
112 };
113 
114 template <class T>
115 T&
117 {
118  static_assert(sizeof(T) == -1, "Must used specialized function");
119  return T(0);
120 }
121 
122 template <>
123 inline IOUAmount&
125 {
126  assert(!amt.native);
127  return amt.iou;
128 }
129 
130 template <>
131 inline XRPAmount&
133 {
134  assert(amt.native);
135  return amt.xrp;
136 }
137 
138 template <class T>
139 T const&
140 get(EitherAmount const& amt)
141 {
142  static_assert(sizeof(T) == -1, "Must used specialized function");
143  return T(0);
144 }
145 
146 template <>
147 inline IOUAmount const&
149 {
150  assert(!amt.native);
151  return amt.iou;
152 }
153 
154 template <>
155 inline XRPAmount const&
157 {
158  assert(amt.native);
159  return amt.xrp;
160 }
161 
162 inline AmountSpec
164 {
166  bool const isNeg = amt.negative();
167  std::int64_t const sMant =
168  isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa();
169  AmountSpec result;
170 
171  result.native = isXRP(amt);
172  if (result.native)
173  {
174  result.xrp = XRPAmount(sMant);
175  }
176  else
177  {
178  result.iou = IOUAmount(sMant, amt.exponent());
179  result.issuer = amt.issue().account;
180  result.currency = amt.issue().currency;
181  }
182 
183  return result;
184 }
185 
186 inline EitherAmount
188 {
189  if (isXRP(amt))
190  return EitherAmount{amt.xrp()};
191  return EitherAmount{amt.iou()};
192 }
193 
194 inline AmountSpec
195 toAmountSpec(EitherAmount const& ea, boost::optional<Currency> const& c)
196 {
197  AmountSpec r;
198  r.native = (!c || isXRP(*c));
199  r.currency = c;
200  assert(ea.native == r.native);
201  if (r.native)
202  {
203  r.xrp = ea.xrp;
204  }
205  else
206  {
207  r.iou = ea.iou;
208  }
209  return r;
210 }
211 
212 } // namespace ripple
213 
214 #endif
ripple::get< XRPAmount >
XRPAmount & get< XRPAmount >(EitherAmount &amt)
Definition: AmountSpec.h:132
ripple::EitherAmount::xrp
XRPAmount xrp
Definition: AmountSpec.h:66
ripple::toEitherAmount
EitherAmount toEitherAmount(STAmount const &amt)
Definition: AmountSpec.h:187
ripple::STAmount::mantissa
std::uint64_t mantissa() const noexcept
Definition: STAmount.h:192
ripple::AmountSpec::operator<<
friend std::ostream & operator<<(std::ostream &stream, AmountSpec const &amt)
Definition: AmountSpec.h:43
ripple::AmountSpec::currency
boost::optional< Currency > currency
Definition: AmountSpec.h:40
ripple::Issue::currency
Currency currency
Definition: Issue.h:37
ripple::AmountSpec::iou
IOUAmount iou
Definition: AmountSpec.h:37
ripple::IOUAmount
Floating point representation of amounts with high dynamic range.
Definition: IOUAmount.h:41
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:45
ripple::get< IOUAmount >
IOUAmount & get< IOUAmount >(EitherAmount &amt)
Definition: AmountSpec.h:124
ripple::STAmount::iou
IOUAmount iou() const
Definition: STAmount.cpp:314
ripple::STAmount::xrp
XRPAmount xrp() const
Definition: STAmount.cpp:299
ripple::EitherAmount::EitherAmount
EitherAmount(XRPAmount const &a)
Definition: AmountSpec.h:80
ripple::STAmount::exponent
int exponent() const noexcept
Definition: STAmount.h:177
ripple::toAmountSpec
AmountSpec toAmountSpec(STAmount const &amt)
Definition: AmountSpec.h:163
std::ostream
STL class.
ripple::EitherAmount::native
bool native
Definition: AmountSpec.h:60
ripple::AmountSpec::AmountSpec
AmountSpec()=default
ripple::EitherAmount::EitherAmount
EitherAmount(AmountSpec const &a)
Definition: AmountSpec.h:90
ripple::STAmount
Definition: STAmount.h:42
ripple::AmountSpec
Definition: AmountSpec.h:29
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:89
std::int64_t
ripple::AmountSpec::native
bool native
Definition: AmountSpec.h:33
ripple::AmountSpec::xrp
XRPAmount xrp
Definition: AmountSpec.h:36
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::AmountSpec::issuer
boost::optional< AccountID > issuer
Definition: AmountSpec.h:39
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:197
ripple::EitherAmount::EitherAmount
EitherAmount(IOUAmount const &a)
Definition: AmountSpec.h:71
ripple::EitherAmount::operator<<
friend std::ostream & operator<<(std::ostream &stream, EitherAmount const &amt)
Definition: AmountSpec.h:103
ripple::STAmount::negative
bool negative() const noexcept
Definition: STAmount.h:187
ripple::EitherAmount
Definition: AmountSpec.h:57
ripple::EitherAmount::iou
IOUAmount iou
Definition: AmountSpec.h:65
ripple::EitherAmount::EitherAmount
EitherAmount()=default
std::numeric_limits
ripple::Issue::account
AccountID account
Definition: Issue.h:38
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:116
ripple::XRPAmount
Definition: XRPAmount.h:46