rippled
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 <algorithm>
24 #include <cassert>
25 #include <cerrno>
26 #include <charconv>
27 #include <cstdlib>
28 #include <iterator>
29 #include <limits>
30 #include <string>
31 #include <type_traits>
32 #include <typeinfo>
33 #include <utility>
34 
35 namespace beast {
36 
37 namespace detail {
38 
39 // These specializatons get called by the non-member functions to do the work
40 template <class Out, class In>
41 struct LexicalCast;
42 
43 // conversion to std::string
44 template <class In>
45 struct LexicalCast<std::string, In>
46 {
47  explicit LexicalCast() = default;
48 
49  template <class Arithmetic = In>
51  operator()(std::string& out, Arithmetic in)
52  {
53  out = std::to_string(in);
54  return true;
55  }
56 
57  template <class Enumeration = In>
59  operator()(std::string& out, Enumeration in)
60  {
61  out = std::to_string(
62  static_cast<std::underlying_type_t<Enumeration>>(in));
63  return true;
64  }
65 };
66 
67 // Parse std::string to number
68 template <class Out>
69 struct LexicalCast<Out, std::string>
70 {
71  explicit LexicalCast() = default;
72 
73  static_assert(
74  std::is_integral_v<Out>,
75  "beast::LexicalCast can only be used with integral types");
76 
77  template <class Integral = Out>
79  std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>,
80  bool>
81  operator()(Integral& out, std::string const& in) const
82  {
83  auto first = in.data();
84  auto last = in.data() + in.size();
85 
86  if (first != last && *first == '+')
87  ++first;
88 
89  auto ret = std::from_chars(first, last, out);
90 
91  return ret.ec == std::errc() && ret.ptr == last;
92  }
93 
94  bool
95  operator()(bool& out, std::string in) const
96  {
97  // Convert the input to lowercase
98  std::transform(in.begin(), in.end(), in.begin(), [](auto c) {
99  return std::tolower(static_cast<unsigned char>(c));
100  });
101 
102  if (in == "1" || in == "true")
103  {
104  out = true;
105  return true;
106  }
107 
108  if (in == "0" || in == "false")
109  {
110  out = false;
111  return true;
112  }
113 
114  return false;
115  }
116 };
117 
118 //------------------------------------------------------------------------------
119 
120 // Conversion from null terminated char const*
121 template <class Out>
122 struct LexicalCast<Out, char const*>
123 {
124  explicit LexicalCast() = default;
125 
126  bool
127  operator()(Out& out, char const* in) const
128  {
129  return LexicalCast<Out, std::string>()(out, in);
130  }
131 };
132 
133 // Conversion from null terminated char*
134 // The string is not modified.
135 template <class Out>
136 struct LexicalCast<Out, char*>
137 {
138  explicit LexicalCast() = default;
139 
140  bool
141  operator()(Out& out, char* in) const
142  {
143  return LexicalCast<Out, std::string>()(out, in);
144  }
145 };
146 
147 } // namespace detail
148 
149 //------------------------------------------------------------------------------
150 
155 {
156  explicit BadLexicalCast() = default;
157 };
158 
162 template <class Out, class In>
163 bool
164 lexicalCastChecked(Out& out, In in)
165 {
166  return detail::LexicalCast<Out, In>()(out, in);
167 }
168 
175 template <class Out, class In>
176 Out
178 {
179  if (Out out; lexicalCastChecked(out, in))
180  return out;
181 
182  throw BadLexicalCast();
183 }
184 
190 template <class Out, class In>
191 Out
192 lexicalCast(In in, Out defaultValue = Out())
193 {
194  if (Out out; lexicalCastChecked(out, in))
195  return out;
196 
197  return defaultValue;
198 }
199 
200 } // namespace beast
201 
202 #endif
std::string
STL class.
utility
beast::detail::LexicalCast< Out, std::string >::operator()
std::enable_if_t< std::is_integral_v< Integral > &&!std::is_same_v< Integral, bool >, bool > operator()(Integral &out, std::string const &in) const
Definition: LexicalCast.h:81
charconv
beast::lexicalCast
Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
Definition: LexicalCast.h:192
iterator
beast::detail::LexicalCast< std::string, In >::operator()
std::enable_if_t< std::is_arithmetic_v< Arithmetic >, bool > operator()(std::string &out, Arithmetic in)
Definition: LexicalCast.h:51
beast::BadLexicalCast
Thrown when a conversion is not possible with LexicalCast.
Definition: LexicalCast.h:154
beast::detail::LexicalCast< Out, char * >::operator()
bool operator()(Out &out, char *in) const
Definition: LexicalCast.h:141
algorithm
std::underlying_type_t
std::bad_cast
STL class.
beast::detail::LexicalCast< Out, std::string >
Definition: LexicalCast.h:69
std::enable_if_t
std::to_string
T to_string(T... args)
std::errc
std::from_chars
T from_chars(T... args)
std::transform
T transform(T... args)
beast::lexicalCastThrow
Out lexicalCastThrow(In in)
Convert from one type to another, throw on error.
Definition: LexicalCast.h:177
beast::detail::LexicalCast< Out, char const * >::operator()
bool operator()(Out &out, char const *in) const
Definition: LexicalCast.h:127
beast::detail::LexicalCast< Out, std::string >::operator()
bool operator()(bool &out, std::string in) const
Definition: LexicalCast.h:95
cstdlib
cerrno
limits
beast::lexicalCastChecked
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Definition: LexicalCast.h:164
std
STL namespace.
beast::BadLexicalCast::BadLexicalCast
BadLexicalCast()=default
cassert
typeinfo
beast::detail::LexicalCast< std::string, In >::operator()
std::enable_if_t< std::is_enum_v< Enumeration >, bool > operator()(std::string &out, Enumeration in)
Definition: LexicalCast.h:59
type_traits
beast::detail::LexicalCast
Definition: LexicalCast.h:41
beast
Definition: base_uint.h:641
string