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