rippled
Loading...
Searching...
No Matches
STNumber.cpp
1#include <xrpl/basics/Number.h>
2#include <xrpl/beast/core/LexicalCast.h>
3#include <xrpl/beast/utility/instrumentation.h>
4#include <xrpl/protocol/SField.h>
5#include <xrpl/protocol/STBase.h>
6#include <xrpl/protocol/STNumber.h>
7#include <xrpl/protocol/Serializer.h>
8
9#include <boost/lexical_cast.hpp>
10#include <boost/regex.hpp>
11
12#include <cstddef>
13#include <ostream>
14#include <string>
15#include <utility>
16
17namespace xrpl {
18
19STNumber::STNumber(SField const& field, Number const& value)
20 : STBase(field), value_(value)
21{
22}
23
24STNumber::STNumber(SerialIter& sit, SField const& field) : STBase(field)
25{
26 // We must call these methods in separate statements
27 // to guarantee their order of execution.
28 auto mantissa = sit.geti64();
29 auto exponent = sit.geti32();
30 value_ = Number{mantissa, exponent};
31}
32
35{
36 return STI_NUMBER;
37}
38
41{
42 return to_string(value_);
43}
44
45void
47{
48 XRPL_ASSERT(getFName().isBinary(), "xrpl::STNumber::add : field is binary");
49 XRPL_ASSERT(
50 getFName().fieldType == getSType(),
51 "xrpl::STNumber::add : field type match");
54}
55
56Number const&
58{
59 return value_;
60}
61
62void
64{
65 value_ = v;
66}
67
68STBase*
69STNumber::copy(std::size_t n, void* buf) const
70{
71 return emplace(n, buf, *this);
72}
73
74STBase*
76{
77 return emplace(n, buf, std::move(*this));
78}
79
80bool
82{
83 XRPL_ASSERT(
84 t.getSType() == this->getSType(),
85 "xrpl::STNumber::isEquivalent : field type match");
86 STNumber const& v = dynamic_cast<STNumber const&>(t);
87 return value_ == v;
88}
89
90bool
92{
93 return value_ == Number();
94}
95
98{
99 return out << rhs.getText();
100}
101
102NumberParts
104{
105 static boost::regex const reNumber(
106 "^" // the beginning of the string
107 "([-+]?)" // (optional) + or - character
108 "(0|[1-9][0-9]*)" // a number (no leading zeroes, unless 0)
109 "(\\.([0-9]+))?" // (optional) period followed by any number
110 "([eE]([+-]?)([0-9]+))?" // (optional) E, optional + or -, any number
111 "$",
112 boost::regex_constants::optimize);
113
114 boost::smatch match;
115
116 if (!boost::regex_match(number, match, reNumber))
117 Throw<std::runtime_error>("'" + number + "' is not a number");
118
119 // Match fields:
120 // 0 = whole input
121 // 1 = sign
122 // 2 = integer portion
123 // 3 = whole fraction (with '.')
124 // 4 = fraction (without '.')
125 // 5 = whole exponent (with 'e')
126 // 6 = exponent sign
127 // 7 = exponent number
128
129 bool negative = (match[1].matched && (match[1] == "-"));
130
131 std::uint64_t mantissa;
132 int exponent;
133
134 if (!match[4].matched) // integer only
135 {
136 mantissa = boost::lexical_cast<std::uint64_t>(std::string(match[2]));
137 exponent = 0;
138 }
139 else
140 {
141 // integer and fraction
142 mantissa = boost::lexical_cast<std::uint64_t>(match[2] + match[4]);
143 exponent = -(match[4].length());
144 }
145
146 if (match[5].matched)
147 {
148 // we have an exponent
149 if (match[6].matched && (match[6] == "-"))
150 exponent -= boost::lexical_cast<int>(std::string(match[7]));
151 else
152 exponent += boost::lexical_cast<int>(std::string(match[7]));
153 }
154
155 return {mantissa, exponent, negative};
156}
157
158STNumber
159numberFromJson(SField const& field, Json::Value const& value)
160{
161 NumberParts parts;
162
163 if (value.isInt())
164 {
165 if (value.asInt() >= 0)
166 {
167 parts.mantissa = value.asInt();
168 }
169 else
170 {
171 parts.mantissa = value.asAbsUInt();
172 parts.negative = true;
173 }
174 }
175 else if (value.isUInt())
176 {
177 parts.mantissa = value.asUInt();
178 }
179 else if (value.isString())
180 {
181 parts = partsFromString(value.asString());
182 // Only strings can represent out-of-range values.
184 Throw<std::range_error>("too high");
185 }
186 else
187 {
188 Throw<std::runtime_error>("not a number");
189 }
190
191 std::int64_t mantissa = parts.mantissa;
192 if (parts.negative)
193 mantissa = -mantissa;
194
195 return STNumber{field, Number{mantissa, parts.exponent}};
196}
197
198} // namespace xrpl
Represents a JSON value.
Definition json_value.h:131
Int asInt() const
UInt asAbsUInt() const
Correct absolute value from int or unsigned int.
bool isString() const
UInt asUInt() const
std::string asString() const
Returns the unquoted string value.
bool isUInt() const
bool isInt() const
constexpr rep mantissa() const noexcept
Definition Number.h:209
constexpr int exponent() const noexcept
Definition Number.h:215
Identifies fields.
Definition SField.h:127
A type which can be exported to a well known binary format.
Definition STBase.h:116
SField const & getFName() const
Definition STBase.cpp:124
static STBase * emplace(std::size_t n, void *buf, T &&val)
Definition STBase.h:214
virtual SerializedTypeID getSType() const
Definition STBase.cpp:56
A serializable number.
Definition STNumber.h:24
void add(Serializer &s) const override
Definition STNumber.cpp:46
bool isDefault() const override
Definition STNumber.cpp:91
void setValue(Number const &v)
Definition STNumber.cpp:63
STNumber()=default
std::string getText() const override
Definition STNumber.cpp:40
bool isEquivalent(STBase const &t) const override
Definition STNumber.cpp:81
STBase * move(std::size_t n, void *buf) override
Definition STNumber.cpp:75
SerializedTypeID getSType() const override
Definition STNumber.cpp:34
STBase * copy(std::size_t n, void *buf) const override
Definition STNumber.cpp:69
Number value_
Definition STNumber.h:26
Number const & value() const
Definition STNumber.cpp:57
std::int32_t geti32()
std::int64_t geti64()
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
NumberParts partsFromString(std::string const &number)
Definition STNumber.cpp:103
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
std::ostream & operator<<(std::ostream &out, base_uint< Bits, Tag > const &u)
Definition base_uint.h:628
SerializedTypeID
Definition SField.h:91
STNumber numberFromJson(SField const &field, Json::Value const &value)
Definition STNumber.cpp:159
std::uint64_t mantissa
Definition STNumber.h:76