rippled
Loading...
Searching...
No Matches
LexicalCast.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of Beast: https://github.com/vinniefalco/Beast
4 Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef BEAST_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED
21#define BEAST_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED
22
23#include <xrpl/beast/utility/instrumentation.h>
24
25#include <boost/core/detail/string_view.hpp>
26#include <algorithm>
27#include <cerrno>
28#include <charconv>
29#include <cstdlib>
30#include <iterator>
31#include <limits>
32#include <string>
33#include <type_traits>
34#include <typeinfo>
35#include <utility>
36
37namespace beast {
38
39namespace detail {
40
41// These specializatons get called by the non-member functions to do the work
42template <class Out, class In>
44
45// conversion to std::string
46template <class In>
47struct LexicalCast<std::string, In>
48{
49 explicit LexicalCast() = default;
50
51 template <class Arithmetic = In>
53 operator()(std::string& out, Arithmetic in)
54 {
55 out = std::to_string(in);
56 return true;
57 }
58
59 template <class Enumeration = In>
61 operator()(std::string& out, Enumeration in)
62 {
63 out = std::to_string(
65 return true;
66 }
67};
68
69// Parse a std::string_view into a number
70template <typename Out>
71struct LexicalCast<Out, std::string_view>
72{
73 explicit LexicalCast() = default;
74
75 static_assert(
76 std::is_integral_v<Out>,
77 "beast::LexicalCast can only be used with integral types");
78
79 template <class Integral = Out>
81 std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>,
82 bool>
83 operator()(Integral& out, std::string_view in) const
84 {
85 auto first = in.data();
86 auto last = in.data() + in.size();
87
88 if (first != last && *first == '+')
89 ++first;
90
91 auto ret = std::from_chars(first, last, out);
92
93 return ret.ec == std::errc() && ret.ptr == last;
94 }
95
96 bool
97 operator()(bool& out, std::string_view in) const
98 {
99 std::string result;
100
101 // Convert the input to lowercase
103 in.begin(), in.end(), std::back_inserter(result), [](auto c) {
104 return std::tolower(static_cast<unsigned char>(c));
105 });
106
107 if (result == "1" || result == "true")
108 {
109 out = true;
110 return true;
111 }
112
113 if (result == "0" || result == "false")
114 {
115 out = false;
116 return true;
117 }
118
119 return false;
120 }
121};
122//------------------------------------------------------------------------------
123
124// Parse boost library's string_view to number or boolean value
125// Note: As of Jan 2024, Boost contains three different types of string_view
126// (boost::core::basic_string_view<char>, boost::string_ref and
127// boost::string_view). The below template specialization is included because
128// it is used in the handshake.cpp file
129template <class Out>
130struct LexicalCast<Out, boost::core::basic_string_view<char>>
131{
132 explicit LexicalCast() = default;
133
134 bool
135 operator()(Out& out, boost::core::basic_string_view<char> in) const
136 {
137 return LexicalCast<Out, std::string_view>()(out, in);
138 }
139};
140
141// Parse std::string to number or boolean value
142template <class Out>
143struct LexicalCast<Out, std::string>
144{
145 explicit LexicalCast() = default;
146
147 bool
148 operator()(Out& out, std::string in) const
149 {
150 return LexicalCast<Out, std::string_view>()(out, in);
151 }
152};
153
154// Conversion from null terminated char const*
155template <class Out>
156struct LexicalCast<Out, char const*>
157{
158 explicit LexicalCast() = default;
159
160 bool
161 operator()(Out& out, char const* in) const
162 {
163 XRPL_ASSERT(
164 in, "beast::detail::LexicalCast(char const*) : non-null input");
165 return LexicalCast<Out, std::string_view>()(out, in);
166 }
167};
168
169// Conversion from null terminated char*
170// The string is not modified.
171template <class Out>
172struct LexicalCast<Out, char*>
173{
174 explicit LexicalCast() = default;
175
176 bool
177 operator()(Out& out, char* in) const
178 {
179 XRPL_ASSERT(in, "beast::detail::LexicalCast(char*) : non-null input");
180 return LexicalCast<Out, std::string_view>()(out, in);
181 }
182};
183
184} // namespace detail
185
186//------------------------------------------------------------------------------
187
192{
193 explicit BadLexicalCast() = default;
194};
195
199template <class Out, class In>
200bool
201lexicalCastChecked(Out& out, In in)
202{
203 return detail::LexicalCast<Out, In>()(out, in);
204}
205
212template <class Out, class In>
213Out
215{
216 if (Out out; lexicalCastChecked(out, in))
217 return out;
218
219 throw BadLexicalCast();
220}
221
227template <class Out, class In>
228Out
229lexicalCast(In in, Out defaultValue = Out())
230{
231 if (Out out; lexicalCastChecked(out, in))
232 return out;
233
234 return defaultValue;
235}
236
237} // namespace beast
238
239#endif
T back_inserter(T... args)
T from_chars(T... args)
Out lexicalCastThrow(In in)
Convert from one type to another, throw on error.
Definition: LexicalCast.h:214
Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
Definition: LexicalCast.h:229
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Definition: LexicalCast.h:201
STL namespace.
Thrown when a conversion is not possible with LexicalCast.
Definition: LexicalCast.h:192
bool operator()(Out &out, boost::core::basic_string_view< char > in) const
Definition: LexicalCast.h:135
bool operator()(Out &out, char *in) const
Definition: LexicalCast.h:177
bool operator()(Out &out, char const *in) const
Definition: LexicalCast.h:161
bool operator()(Out &out, std::string in) const
Definition: LexicalCast.h:148
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:83
bool operator()(bool &out, std::string_view in) const
Definition: LexicalCast.h:97
std::enable_if_t< std::is_arithmetic_v< Arithmetic >, bool > operator()(std::string &out, Arithmetic in)
Definition: LexicalCast.h:53
std::enable_if_t< std::is_enum_v< Enumeration >, bool > operator()(std::string &out, Enumeration in)
Definition: LexicalCast.h:61
T to_string(T... args)
T transform(T... args)