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 ripple {
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(
49 getFName().isBinary(), "ripple::STNumber::add : field is binary");
50 XRPL_ASSERT(
51 getFName().fieldType == getSType(),
52 "ripple::STNumber::add : field type match");
55}
56
57Number const&
59{
60 return value_;
61}
62
63void
65{
66 value_ = v;
67}
68
69STBase*
70STNumber::copy(std::size_t n, void* buf) const
71{
72 return emplace(n, buf, *this);
73}
74
75STBase*
77{
78 return emplace(n, buf, std::move(*this));
79}
80
81bool
83{
84 XRPL_ASSERT(
85 t.getSType() == this->getSType(),
86 "ripple::STNumber::isEquivalent : field type match");
87 STNumber const& v = dynamic_cast<STNumber const&>(t);
88 return value_ == v;
89}
90
91bool
93{
94 return value_ == Number();
95}
96
99{
100 return out << rhs.getText();
101}
102
103NumberParts
105{
106 static boost::regex const reNumber(
107 "^" // the beginning of the string
108 "([-+]?)" // (optional) + or - character
109 "(0|[1-9][0-9]*)" // a number (no leading zeroes, unless 0)
110 "(\\.([0-9]+))?" // (optional) period followed by any number
111 "([eE]([+-]?)([0-9]+))?" // (optional) E, optional + or -, any number
112 "$",
113 boost::regex_constants::optimize);
114
115 boost::smatch match;
116
117 if (!boost::regex_match(number, match, reNumber))
118 Throw<std::runtime_error>("'" + number + "' is not a number");
119
120 // Match fields:
121 // 0 = whole input
122 // 1 = sign
123 // 2 = integer portion
124 // 3 = whole fraction (with '.')
125 // 4 = fraction (without '.')
126 // 5 = whole exponent (with 'e')
127 // 6 = exponent sign
128 // 7 = exponent number
129
130 bool negative = (match[1].matched && (match[1] == "-"));
131
132 std::uint64_t mantissa;
133 int exponent;
134
135 if (!match[4].matched) // integer only
136 {
137 mantissa = boost::lexical_cast<std::uint64_t>(std::string(match[2]));
138 exponent = 0;
139 }
140 else
141 {
142 // integer and fraction
143 mantissa = boost::lexical_cast<std::uint64_t>(match[2] + match[4]);
144 exponent = -(match[4].length());
145 }
146
147 if (match[5].matched)
148 {
149 // we have an exponent
150 if (match[6].matched && (match[6] == "-"))
151 exponent -= boost::lexical_cast<int>(std::string(match[7]));
152 else
153 exponent += boost::lexical_cast<int>(std::string(match[7]));
154 }
155
156 return {mantissa, exponent, negative};
157}
158
159STNumber
160numberFromJson(SField const& field, Json::Value const& value)
161{
162 NumberParts parts;
163
164 if (value.isInt())
165 {
166 if (value.asInt() >= 0)
167 {
168 parts.mantissa = value.asInt();
169 }
170 else
171 {
172 parts.mantissa = value.asAbsUInt();
173 parts.negative = true;
174 }
175 }
176 else if (value.isUInt())
177 {
178 parts.mantissa = value.asUInt();
179 }
180 else if (value.isString())
181 {
182 parts = partsFromString(value.asString());
183 // Only strings can represent out-of-range values.
185 Throw<std::range_error>("too high");
186 }
187 else
188 {
189 Throw<std::runtime_error>("not a number");
190 }
191
192 std::int64_t mantissa = parts.mantissa;
193 if (parts.negative)
194 mantissa = -mantissa;
195
196 return STNumber{field, Number{mantissa, parts.exponent}};
197}
198
199} // namespace ripple
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 int exponent() const noexcept
Definition Number.h:217
constexpr rep mantissa() const noexcept
Definition Number.h:211
Identifies fields.
Definition SField.h:127
A type which can be exported to a well known binary format.
Definition STBase.h:116
virtual SerializedTypeID getSType() const
Definition STBase.cpp:56
SField const & getFName() const
Definition STBase.cpp:124
static STBase * emplace(std::size_t n, void *buf, T &&val)
Definition STBase.h:214
A serializable number.
Definition STNumber.h:24
SerializedTypeID getSType() const override
Definition STNumber.cpp:34
bool isDefault() const override
Definition STNumber.cpp:92
void add(Serializer &s) const override
Definition STNumber.cpp:46
STNumber()=default
std::string getText() const override
Definition STNumber.cpp:40
void setValue(Number const &v)
Definition STNumber.cpp:64
STBase * move(std::size_t n, void *buf) override
Definition STNumber.cpp:76
Number const & value() const
Definition STNumber.cpp:58
STBase * copy(std::size_t n, void *buf) const override
Definition STNumber.cpp:70
bool isEquivalent(STBase const &t) const override
Definition STNumber.cpp:82
std::int64_t geti64()
std::int32_t geti32()
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:104
SerializedTypeID
Definition SField.h:91
std::ostream & operator<<(std::ostream &out, base_uint< Bits, Tag > const &u)
Definition base_uint.h:628
STNumber numberFromJson(SField const &field, Json::Value const &value)
Definition STNumber.cpp:160
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
std::uint64_t mantissa
Definition STNumber.h:76