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 #include <optional>
28 
29 namespace ripple {
30 
31 struct AmountSpec
32 {
33  explicit AmountSpec() = default;
34 
35  bool native;
36  union
37  {
39  IOUAmount iou = {};
40  };
43 
44  friend std::ostream&
45  operator<<(std::ostream& stream, AmountSpec const& amt)
46  {
47  if (amt.native)
48  stream << to_string(amt.xrp);
49  else
50  stream << to_string(amt.iou);
51  if (amt.currency)
52  stream << "/(" << *amt.currency << ")";
53  if (amt.issuer)
54  stream << "/" << *amt.issuer << "";
55  return stream;
56  }
57 };
58 
60 {
61 #ifndef NDEBUG
62  bool native = false;
63 #endif
64 
65  union
66  {
67  IOUAmount iou = {};
69  };
70 
71  EitherAmount() = default;
72 
73  explicit EitherAmount(IOUAmount const& a) : iou(a)
74  {
75  }
76 
77 #if defined(__GNUC__) && !defined(__clang__)
78 #pragma GCC diagnostic push
79  // ignore warning about half of iou amount being uninitialized
80 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
81 #endif
82  explicit EitherAmount(XRPAmount const& a) : xrp(a)
83  {
84 #ifndef NDEBUG
85  native = true;
86 #endif
87  }
88 #if defined(__GNUC__) && !defined(__clang__)
89 #pragma GCC diagnostic pop
90 #endif
91 
92  explicit EitherAmount(AmountSpec const& a)
93  {
94 #ifndef NDEBUG
95  native = a.native;
96 #endif
97  if (a.native)
98  xrp = a.xrp;
99  else
100  iou = a.iou;
101  }
102 
103 #ifndef NDEBUG
104  friend std::ostream&
105  operator<<(std::ostream& stream, EitherAmount const& amt)
106  {
107  if (amt.native)
108  stream << to_string(amt.xrp);
109  else
110  stream << to_string(amt.iou);
111  return stream;
112  }
113 #endif
114 };
115 
116 template <class T>
117 T&
119 {
120  static_assert(sizeof(T) == -1, "Must used specialized function");
121  return T(0);
122 }
123 
124 template <>
125 inline IOUAmount&
127 {
128  assert(!amt.native);
129  return amt.iou;
130 }
131 
132 template <>
133 inline XRPAmount&
135 {
136  assert(amt.native);
137  return amt.xrp;
138 }
139 
140 template <class T>
141 T const&
142 get(EitherAmount const& amt)
143 {
144  static_assert(sizeof(T) == -1, "Must used specialized function");
145  return T(0);
146 }
147 
148 template <>
149 inline IOUAmount const&
151 {
152  assert(!amt.native);
153  return amt.iou;
154 }
155 
156 template <>
157 inline XRPAmount const&
159 {
160  assert(amt.native);
161  return amt.xrp;
162 }
163 
164 inline AmountSpec
166 {
168  bool const isNeg = amt.negative();
169  std::int64_t const sMant =
170  isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa();
171  AmountSpec result;
172 
173  result.native = isXRP(amt);
174  if (result.native)
175  {
176  result.xrp = XRPAmount(sMant);
177  }
178  else
179  {
180  result.iou = IOUAmount(sMant, amt.exponent());
181  result.issuer = amt.issue().account;
182  result.currency = amt.issue().currency;
183  }
184 
185  return result;
186 }
187 
188 inline EitherAmount
190 {
191  if (isXRP(amt))
192  return EitherAmount{amt.xrp()};
193  return EitherAmount{amt.iou()};
194 }
195 
196 inline AmountSpec
198 {
199  AmountSpec r;
200  r.native = (!c || isXRP(*c));
201  r.currency = c;
202  assert(ea.native == r.native);
203  if (r.native)
204  {
205  r.xrp = ea.xrp;
206  }
207  else
208  {
209  r.iou = ea.iou;
210  }
211  return r;
212 }
213 
214 } // namespace ripple
215 
216 #endif
ripple::get< XRPAmount >
XRPAmount & get< XRPAmount >(EitherAmount &amt)
Definition: AmountSpec.h:134
ripple::EitherAmount::xrp
XRPAmount xrp
Definition: AmountSpec.h:68
ripple::toEitherAmount
EitherAmount toEitherAmount(STAmount const &amt)
Definition: AmountSpec.h:189
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:347
ripple::STAmount::mantissa
std::uint64_t mantissa() const noexcept
Definition: STAmount.h:341
ripple::AmountSpec::operator<<
friend std::ostream & operator<<(std::ostream &stream, AmountSpec const &amt)
Definition: AmountSpec.h:45
ripple::AmountSpec::issuer
std::optional< AccountID > issuer
Definition: AmountSpec.h:41
ripple::Issue::currency
Currency currency
Definition: Issue.h:37
ripple::AmountSpec::iou
IOUAmount iou
Definition: AmountSpec.h:39
ripple::IOUAmount
Floating point representation of amounts with high dynamic range.
Definition: IOUAmount.h:43
ripple::get< IOUAmount >
IOUAmount & get< IOUAmount >(EitherAmount &amt)
Definition: AmountSpec.h:126
ripple::STAmount::iou
IOUAmount iou() const
Definition: STAmount.cpp:349
ripple::STAmount::xrp
XRPAmount xrp() const
Definition: STAmount.cpp:334
ripple::EitherAmount::EitherAmount
EitherAmount(XRPAmount const &a)
Definition: AmountSpec.h:82
ripple::STAmount::exponent
int exponent() const noexcept
Definition: STAmount.h:323
ripple::toAmountSpec
AmountSpec toAmountSpec(STAmount const &amt)
Definition: AmountSpec.h:165
std::ostream
STL class.
ripple::EitherAmount::native
bool native
Definition: AmountSpec.h:62
ripple::AmountSpec::AmountSpec
AmountSpec()=default
ripple::EitherAmount::EitherAmount
EitherAmount(AmountSpec const &a)
Definition: AmountSpec.h:92
ripple::STAmount
Definition: STAmount.h:45
ripple::AmountSpec
Definition: AmountSpec.h:31
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:89
std::int64_t
ripple::AmountSpec::native
bool native
Definition: AmountSpec.h:35
ripple::AmountSpec::xrp
XRPAmount xrp
Definition: AmountSpec.h:38
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::EitherAmount::EitherAmount
EitherAmount(IOUAmount const &a)
Definition: AmountSpec.h:73
ripple::EitherAmount::operator<<
friend std::ostream & operator<<(std::ostream &stream, EitherAmount const &amt)
Definition: AmountSpec.h:105
ripple::STAmount::negative
bool negative() const noexcept
Definition: STAmount.h:335
ripple::EitherAmount
Definition: AmountSpec.h:59
ripple::EitherAmount::iou
IOUAmount iou
Definition: AmountSpec.h:67
ripple::EitherAmount::EitherAmount
EitherAmount()=default
optional
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::AmountSpec::currency
std::optional< Currency > currency
Definition: AmountSpec.h:42
std::numeric_limits
ripple::Issue::account
AccountID account
Definition: Issue.h:38
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:118
ripple::XRPAmount
Definition: XRPAmount.h:46