rippled
Loading...
Searching...
No Matches
LexicalCast.h
1#ifndef BEAST_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED
2#define BEAST_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED
3
4#include <xrpl/beast/utility/instrumentation.h>
5
6#include <boost/core/detail/string_view.hpp>
7
8#include <algorithm>
9#include <cerrno>
10#include <charconv>
11#include <cstdlib>
12#include <iterator>
13#include <string>
14#include <type_traits>
15#include <typeinfo>
16
17namespace beast {
18
19namespace detail {
20
21// These specializatons get called by the non-member functions to do the work
22template <class Out, class In>
24
25// conversion to std::string
26template <class In>
27struct LexicalCast<std::string, In>
28{
29 explicit LexicalCast() = default;
30
31 template <class Arithmetic = In>
33 operator()(std::string& out, Arithmetic in)
34 {
35 out = std::to_string(in);
36 return true;
37 }
38
39 template <class Enumeration = In>
41 operator()(std::string& out, Enumeration in)
42 {
43 out = std::to_string(
45 return true;
46 }
47};
48
49// Parse a std::string_view into a number
50template <typename Out>
51struct LexicalCast<Out, std::string_view>
52{
53 explicit LexicalCast() = default;
54
55 static_assert(
57 "beast::LexicalCast can only be used with integral types");
58
59 template <class Integral = Out>
62 bool>
63 operator()(Integral& out, std::string_view in) const
64 {
65 auto first = in.data();
66 auto last = in.data() + in.size();
67
68 if (first != last && *first == '+')
69 ++first;
70
71 auto ret = std::from_chars(first, last, out);
72
73 return ret.ec == std::errc() && ret.ptr == last;
74 }
75
76 bool
77 operator()(bool& out, std::string_view in) const
78 {
79 std::string result;
80
81 // Convert the input to lowercase
83 in.begin(), in.end(), std::back_inserter(result), [](auto c) {
84 return std::tolower(static_cast<unsigned char>(c));
85 });
86
87 if (result == "1" || result == "true")
88 {
89 out = true;
90 return true;
91 }
92
93 if (result == "0" || result == "false")
94 {
95 out = false;
96 return true;
97 }
98
99 return false;
100 }
101};
102//------------------------------------------------------------------------------
103
104// Parse boost library's string_view to number or boolean value
105// Note: As of Jan 2024, Boost contains three different types of string_view
106// (boost::core::basic_string_view<char>, boost::string_ref and
107// boost::string_view). The below template specialization is included because
108// it is used in the handshake.cpp file
109template <class Out>
110struct LexicalCast<Out, boost::core::basic_string_view<char>>
111{
112 explicit LexicalCast() = default;
113
114 bool
115 operator()(Out& out, boost::core::basic_string_view<char> in) const
116 {
117 return LexicalCast<Out, std::string_view>()(out, in);
118 }
119};
120
121// Parse std::string to number or boolean value
122template <class Out>
123struct LexicalCast<Out, std::string>
124{
125 explicit LexicalCast() = default;
126
127 bool
128 operator()(Out& out, std::string in) const
129 {
130 return LexicalCast<Out, std::string_view>()(out, in);
131 }
132};
133
134// Conversion from null terminated char const*
135template <class Out>
136struct LexicalCast<Out, char const*>
137{
138 explicit LexicalCast() = default;
139
140 bool
141 operator()(Out& out, char const* in) const
142 {
143 XRPL_ASSERT(
144 in, "beast::detail::LexicalCast(char const*) : non-null input");
145 return LexicalCast<Out, std::string_view>()(out, in);
146 }
147};
148
149// Conversion from null terminated char*
150// The string is not modified.
151template <class Out>
152struct LexicalCast<Out, char*>
153{
154 explicit LexicalCast() = default;
155
156 bool
157 operator()(Out& out, char* in) const
158 {
159 XRPL_ASSERT(in, "beast::detail::LexicalCast(char*) : non-null input");
160 return LexicalCast<Out, std::string_view>()(out, in);
161 }
162};
163
164} // namespace detail
165
166//------------------------------------------------------------------------------
167
172{
173 explicit BadLexicalCast() = default;
174};
175
179template <class Out, class In>
180bool
181lexicalCastChecked(Out& out, In in)
182{
183 return detail::LexicalCast<Out, In>()(out, in);
184}
185
192template <class Out, class In>
193Out
195{
196 if (Out out; lexicalCastChecked(out, in))
197 return out;
198
199 throw BadLexicalCast();
200}
201
207template <class Out, class In>
208Out
209lexicalCast(In in, Out defaultValue = Out())
210{
211 if (Out out; lexicalCastChecked(out, in))
212 return out;
213
214 return defaultValue;
215}
216
217} // namespace beast
218
219#endif
T back_inserter(T... args)
T from_chars(T... args)
T is_same_v
Out lexicalCastThrow(In in)
Convert from one type to another, throw on error.
Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
STL namespace.
Thrown when a conversion is not possible with LexicalCast.
bool operator()(Out &out, boost::core::basic_string_view< char > in) const
bool operator()(Out &out, char *in) const
bool operator()(Out &out, char const *in) const
bool operator()(Out &out, std::string in) const
std::enable_if_t< std::is_integral_v< Integral > &&!std::is_same_v< Integral, bool >, bool > operator()(Integral &out, std::string_view in) const
Definition LexicalCast.h:63
bool operator()(bool &out, std::string_view in) const
Definition LexicalCast.h:77
std::enable_if_t< std::is_arithmetic_v< Arithmetic >, bool > operator()(std::string &out, Arithmetic in)
Definition LexicalCast.h:33
std::enable_if_t< std::is_enum_v< Enumeration >, bool > operator()(std::string &out, Enumeration in)
Definition LexicalCast.h:41
T to_string(T... args)
T transform(T... args)