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(
55 "beast::LexicalCast can only be used with integral types");
56
57 template <class Integral = Out>
59 operator()(Integral& out, std::string_view in) const
60 {
61 auto first = in.data();
62 auto last = in.data() + in.size();
63
64 if (first != last && *first == '+')
65 ++first;
66
67 auto ret = std::from_chars(first, last, out);
68
69 return ret.ec == std::errc() && ret.ptr == last;
70 }
71
72 bool
73 operator()(bool& out, std::string_view in) const
74 {
75 std::string result;
76
77 // Convert the input to lowercase
78 std::transform(in.begin(), in.end(), std::back_inserter(result), [](auto c) {
79 return std::tolower(static_cast<unsigned char>(c));
80 });
81
82 if (result == "1" || result == "true")
83 {
84 out = true;
85 return true;
86 }
87
88 if (result == "0" || result == "false")
89 {
90 out = false;
91 return true;
92 }
93
94 return false;
95 }
96};
97//------------------------------------------------------------------------------
98
99// Parse boost library's string_view to number or boolean value
100// Note: As of Jan 2024, Boost contains three different types of string_view
101// (boost::core::basic_string_view<char>, boost::string_ref and
102// boost::string_view). The below template specialization is included because
103// it is used in the handshake.cpp file
104template <class Out>
105struct LexicalCast<Out, boost::core::basic_string_view<char>>
106{
107 explicit LexicalCast() = default;
108
109 bool
110 operator()(Out& out, boost::core::basic_string_view<char> in) const
111 {
112 return LexicalCast<Out, std::string_view>()(out, in);
113 }
114};
115
116// Parse std::string to number or boolean value
117template <class Out>
118struct LexicalCast<Out, std::string>
119{
120 explicit LexicalCast() = default;
121
122 bool
123 operator()(Out& out, std::string in) const
124 {
125 return LexicalCast<Out, std::string_view>()(out, in);
126 }
127};
128
129// Conversion from null terminated char const*
130template <class Out>
131struct LexicalCast<Out, char const*>
132{
133 explicit LexicalCast() = default;
134
135 bool
136 operator()(Out& out, char const* in) const
137 {
138 XRPL_ASSERT(in, "beast::detail::LexicalCast(char const*) : non-null input");
139 return LexicalCast<Out, std::string_view>()(out, in);
140 }
141};
142
143// Conversion from null terminated char*
144// The string is not modified.
145template <class Out>
146struct LexicalCast<Out, char*>
147{
148 explicit LexicalCast() = default;
149
150 bool
151 operator()(Out& out, char* in) const
152 {
153 XRPL_ASSERT(in, "beast::detail::LexicalCast(char*) : non-null input");
154 return LexicalCast<Out, std::string_view>()(out, in);
155 }
156};
157
158} // namespace detail
159
160//------------------------------------------------------------------------------
161
166{
167 explicit BadLexicalCast() = default;
168};
169
173template <class Out, class In>
174bool
175lexicalCastChecked(Out& out, In in)
176{
177 return detail::LexicalCast<Out, In>()(out, in);
178}
179
186template <class Out, class In>
187Out
189{
190 if (Out out; lexicalCastChecked(out, in))
191 return out;
192
193 throw BadLexicalCast();
194}
195
201template <class Out, class In>
202Out
203lexicalCast(In in, Out defaultValue = Out())
204{
205 if (Out out; lexicalCastChecked(out, in))
206 return out;
207
208 return defaultValue;
209}
210
211} // 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:59
bool operator()(bool &out, std::string_view in) const
Definition LexicalCast.h:73
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)