xrpld
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 <cctype>
9#include <charconv>
10#include <iterator>
11#include <string>
12#include <string_view>
13#include <system_error>
14#include <type_traits>
15#include <typeinfo>
16
17namespace beast {
18
19namespace detail {
20
21// These specializations 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>
32 bool
33 operator()(std::string& out, Arithmetic in)
35 {
36 out = std::to_string(in);
37 return true;
38 }
39
40 template <class Enumeration = In>
41 bool
42 operator()(std::string& out, Enumeration in)
44 {
46 return true;
47 }
48};
49
50// Parse a std::string_view into a number
51template <typename Out>
52struct LexicalCast<Out, std::string_view>
53{
54 explicit LexicalCast() = default;
55
56 static_assert(
58 "beast::LexicalCast can only be used with integral types");
59
60 template <class Integral = Out>
61 constexpr bool
62 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
82 std::transform(in.begin(), in.end(), std::back_inserter(result), [](auto c) {
83 return std::tolower(static_cast<unsigned char>(c));
84 });
85
86 if (result == "1" || result == "true")
87 {
88 out = true;
89 return true;
90 }
91
92 if (result == "0" || result == "false")
93 {
94 out = false;
95 return true;
96 }
97
98 return false;
99 }
100};
101//------------------------------------------------------------------------------
102
103// Parse boost library's string_view to number or boolean value
104// Note: As of Jan 2024, Boost contains three different types of string_view
105// (boost::core::basic_string_view<char>, boost::string_ref and
106// boost::string_view). The below template specialization is included because
107// it is used in the handshake.cpp file
108template <class Out>
109struct LexicalCast<Out, boost::core::basic_string_view<char>>
110{
111 explicit LexicalCast() = default;
112
113 constexpr bool
114 operator()(Out& out, boost::core::basic_string_view<char> in) const
115 {
116 return LexicalCast<Out, std::string_view>()(out, in);
117 }
118};
119
120// Parse std::string to number or boolean value
121template <class Out>
122struct LexicalCast<Out, std::string>
123{
124 explicit LexicalCast() = default;
125
126 constexpr bool
127 operator()(Out& out, std::string in) const
128 {
129 return LexicalCast<Out, std::string_view>()(out, in);
130 }
131};
132
133// Conversion from null terminated char const*
134template <class Out>
135struct LexicalCast<Out, char const*>
136{
137 explicit LexicalCast() = default;
138
139 constexpr bool
140 operator()(Out& out, char const* in) const
141 {
142 XRPL_ASSERT(in, "beast::detail::LexicalCast(char const*) : non-null input");
143 return LexicalCast<Out, std::string_view>()(out, in);
144 }
145};
146
147// Conversion from null terminated char*
148// The string is not modified.
149template <class Out>
150struct LexicalCast<Out, char*>
151{
152 explicit LexicalCast() = default;
153
154 constexpr bool
155 operator()(Out& out, char* in) const
156 {
157 XRPL_ASSERT(in, "beast::detail::LexicalCast(char*) : non-null input");
158 return LexicalCast<Out, std::string_view>()(out, in);
159 }
160};
161
162} // namespace detail
163
164//------------------------------------------------------------------------------
165
171{
172 explicit BadLexicalCast() = default;
173};
174
179template <class Out, class In>
180constexpr bool
181lexicalCastChecked(Out& out, In in)
182{
183 return detail::LexicalCast<Out, In>()(out, in);
184}
185
193template <class Out, class In>
194constexpr Out
196{
197 if (Out out; lexicalCastChecked(out, in))
198 return out;
199
200 throw BadLexicalCast();
201}
202
209template <class Out, class In>
210constexpr Out
211lexicalCast(In in, Out defaultValue = Out())
212{
213 if (Out out; lexicalCastChecked(out, in))
214 return out;
215
216 return defaultValue;
217}
218
219} // namespace beast
T back_inserter(T... args)
T begin(T... args)
T end(T... args)
T from_chars(T... args)
T is_arithmetic_v
T is_enum_v
T is_integral_v
T is_same_v
constexpr Out lexicalCastThrow(In in)
Convert from one type to another, throw on error.
constexpr bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
constexpr Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
STL namespace.
Thrown when a conversion is not possible with LexicalCast.
constexpr bool operator()(Out &out, boost::core::basic_string_view< char > in) const
constexpr bool operator()(Out &out, char *in) const
constexpr bool operator()(Out &out, char const *in) const
constexpr bool operator()(Out &out, std::string in) const
constexpr bool operator()(Integral &out, std::string_view in) const
Definition LexicalCast.h:62
bool operator()(bool &out, std::string_view in) const
Definition LexicalCast.h:77
bool operator()(std::string &out, Enumeration in)
Definition LexicalCast.h:42
bool operator()(std::string &out, Arithmetic in)
Definition LexicalCast.h:33
T to_string(T... args)
T transform(T... args)