OGLplus  (0.59.0) a C++ wrapper for rendering APIs

from_string.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_FROM_STRING_HPP
10 #define EAGINE_FROM_STRING_HPP
11 
12 #include "is_within_limits.hpp"
13 #include "memory/span_algo.hpp"
14 #include "mp_string.hpp"
15 #include "selector.hpp"
16 #include "string_span.hpp"
17 #include "type_identity.hpp"
18 #include "valid_if/always.hpp"
19 #include "valid_if/decl.hpp"
20 #include <chrono>
21 #include <cstdlib>
22 
23 namespace eagine {
24 //------------------------------------------------------------------------------
25 auto _parse_from_string(string_view src, long long int&) noexcept -> bool;
26 //------------------------------------------------------------------------------
27 template <typename T>
28 static inline auto parse_from_string(string_view src, type_identity<T>) noexcept
29  -> std::enable_if_t<std::is_integral_v<T>, optionally_valid<T>> {
30  long long int parsed{};
31  if(_parse_from_string(src, parsed)) {
32  return convert_if_fits<T>(parsed);
33  }
34  return {};
35 }
36 //------------------------------------------------------------------------------
37 auto _parse_from_string(string_view src, long double&) noexcept -> bool;
38 //------------------------------------------------------------------------------
39 template <typename T>
40 static inline auto parse_from_string(string_view src, type_identity<T>) noexcept
41  -> std::enable_if_t<std::is_floating_point_v<T>, optionally_valid<T>> {
42  long double parsed{};
43  if(_parse_from_string(src, parsed)) {
44  return convert_if_fits<T>(parsed);
45  }
46  return {};
47 }
48 //------------------------------------------------------------------------------
49 template <identifier_t V>
50 static inline auto
51 from_string(string_view src, type_identity<bool>, selector<V>) noexcept
52  -> optionally_valid<bool> {
53 
54  const string_view true_strs[] = {{"true"}, {"True"}, {"1"}, {"t"}, {"T"}};
55  if(find_element(view(true_strs), src)) {
56  return {true, true};
57  }
58 
59  const string_view false_strs[] = {
60  {"false"}, {"False"}, {"0"}, {"f"}, {"F"}};
61  if(find_element(view(false_strs), src)) {
62  return {false, true};
63  }
64 
65  return {};
66 }
67 
68 template <identifier_t V>
69 static inline auto
70 from_string(string_view src, type_identity<char>, selector<V>) noexcept
71  -> optionally_valid<char> {
72  if(src.size() == 1) {
73  return {extract(src), true};
74  }
75  return {};
76 }
77 //------------------------------------------------------------------------------
78 template <typename T, typename N>
79 auto multiply_and_convert_if_fits(N n, const char* c) noexcept
80  -> optionally_valid<T> {
81  if(!c[0]) {
82  return convert_if_fits<T>(n);
83  } else if((c[0] == 'k') && (!c[1])) {
84  return convert_if_fits<T>(n * 1000);
85  } else if((c[0] == 'M') && (!c[1])) {
86  return convert_if_fits<T>(n * 1000000);
87  } else if((c[0] == 'G') && (!c[1])) {
88  return convert_if_fits<T>(n * 1000000000);
89  }
90 
91  return {};
92 }
93 //------------------------------------------------------------------------------
94 template <typename T, typename N>
95 auto convert_from_string_with(
96  N (*converter)(const char*, char**),
97  string_view src,
98  type_identity<T> tid) noexcept -> optionally_valid<T> {
99  char* end = nullptr;
100  auto cstr = c_str(src);
101  errno = 0;
102  const N result{converter(cstr, &end)};
103  if((errno != ERANGE) && (end != cstr) && (end != nullptr)) {
104  if(auto converted{multiply_and_convert_if_fits<T>(result, end)}) {
105  return converted;
106  }
107  }
108 
109  return parse_from_string(src, tid);
110 }
111 //------------------------------------------------------------------------------
112 template <typename T, typename N>
113 auto convert_from_string_with(
114  N (*converter)(const char*, char**, int),
115  int base,
116  string_view src,
117  type_identity<T> tid) noexcept -> optionally_valid<T> {
118  char* end = nullptr;
119  auto cstr = c_str(src);
120  errno = 0;
121  const N result = converter(cstr, &end, base);
122  if((errno != ERANGE) && (end != cstr) && (end != nullptr)) {
123  if(auto converted{multiply_and_convert_if_fits<T>(result, end)}) {
124  return converted;
125  }
126  }
127 
128  return parse_from_string(src, tid);
129 }
130 //------------------------------------------------------------------------------
131 template <identifier_t V>
132 static inline auto from_string(
133  string_view src,
134  type_identity<short> id,
135  selector<V>,
136  int base = 10) noexcept -> optionally_valid<short> {
137  return convert_from_string_with(&std::strtol, base, src, id);
138 }
139 
140 template <identifier_t V>
141 static inline auto from_string(
142  string_view src,
143  type_identity<int> id,
144  selector<V>,
145  int base = 10) noexcept -> optionally_valid<int> {
146  return convert_from_string_with(&std::strtol, base, src, id);
147 }
148 
149 template <identifier_t V>
150 static inline auto from_string(
151  string_view src,
152  type_identity<long> id,
153  selector<V>,
154  int base = 10) noexcept -> optionally_valid<long> {
155  return convert_from_string_with(&std::strtol, base, src, id);
156 }
157 
158 template <identifier_t V>
159 static inline auto from_string(
160  string_view src,
161  type_identity<long long> id,
162  selector<V>,
163  int base = 10) noexcept -> optionally_valid<long long> {
164  return convert_from_string_with(&std::strtoll, base, src, id);
165 }
166 
167 template <identifier_t V>
168 static inline auto from_string(
169  string_view src,
170  type_identity<unsigned short> id,
171  selector<V>,
172  int base = 10) noexcept -> optionally_valid<unsigned short> {
173  return convert_from_string_with(&std::strtoul, base, src, id);
174 }
175 
176 template <identifier_t V>
177 static inline auto from_string(
178  string_view src,
179  type_identity<unsigned int> id,
180  selector<V>,
181  int base = 10) noexcept -> optionally_valid<unsigned int> {
182  return convert_from_string_with(&std::strtoul, base, src, id);
183 }
184 
185 template <identifier_t V>
186 static inline auto from_string(
187  string_view src,
188  type_identity<unsigned long> id,
189  selector<V>,
190  int base = 10) noexcept -> optionally_valid<unsigned long> {
191  return convert_from_string_with(&std::strtoul, base, src, id);
192 }
193 
194 template <identifier_t V>
195 static inline auto from_string(
196  string_view src,
197  type_identity<unsigned long long> id,
198  selector<V>,
199  int base = 10) noexcept -> optionally_valid<unsigned long long> {
200  return convert_from_string_with(&std::strtoull, base, src, id);
201 }
202 //------------------------------------------------------------------------------
203 template <identifier_t V>
204 static inline auto
205 from_string(string_view src, type_identity<byte>, selector<V> sel) noexcept
206  -> optionally_valid<byte> {
207  if(starts_with(src, string_view("0x"))) {
208  if(const auto opt_val{
209  from_string(skip(src, 2), type_identity<unsigned>(), sel, 16)}) {
210  return {static_cast<byte>(extract(opt_val)), bool(opt_val <= 255U)};
211  }
212  }
213  if(starts_with(src, string_view("0"))) {
214  if(const auto opt_val{
215  from_string(skip(src, 1), type_identity<unsigned>(), sel, 8)}) {
216  return {static_cast<byte>(extract(opt_val)), bool(opt_val <= 255U)};
217  }
218  }
219  if(const auto opt_val{
220  from_string(src, type_identity<unsigned>(), sel, 10)}) {
221  return {static_cast<byte>(extract(opt_val)), bool(opt_val <= 255U)};
222  }
223  return {};
224 }
225 //------------------------------------------------------------------------------
226 template <identifier_t V>
227 static inline auto
228 from_string(string_view src, type_identity<float> id, selector<V>) noexcept
229  -> optionally_valid<float> {
230  return convert_from_string_with(&std::strtof, src, id);
231 }
232 
233 template <identifier_t V>
234 static inline auto
235 from_string(string_view src, type_identity<double> id, selector<V>) noexcept
236  -> optionally_valid<double> {
237  return convert_from_string_with(&std::strtod, src, id);
238 }
239 
240 template <identifier_t V>
241 static inline auto from_string(
242  string_view src,
243  type_identity<long double> id,
244  selector<V>) noexcept -> optionally_valid<long double> {
245  return convert_from_string_with(&std::strtold, src, id);
246 }
247 
248 template <identifier_t V>
249 static inline auto
250 from_string(string_view src, type_identity<std::string>, selector<V>) noexcept
251  -> always_valid<std::string> {
252  return to_string(src);
253 }
254 //------------------------------------------------------------------------------
255 template <typename Rep, typename Period, identifier_t V, typename Symbol>
256 static inline auto convert_from_string(
257  string_view src,
258  type_identity<std::chrono::duration<Rep, Period>>,
259  selector<V> sel,
260  Symbol sym_const) noexcept
261  -> optionally_valid<std::chrono::duration<Rep, Period>> {
262  const string_view symbol{sym_const};
263  if(memory::ends_with(src, symbol)) {
264  if(
265  auto opt_val =
266  from_string(snip(src, symbol.size()), type_identity<Rep>(), sel)) {
267  return {std::chrono::duration<Rep, Period>(extract(opt_val)), true};
268  }
269  }
270  return {};
271 }
272 //------------------------------------------------------------------------------
273 template <typename Rep, typename Period, identifier_t V>
274 static inline auto from_string(
275  string_view str,
276  type_identity<std::chrono::duration<Rep, Period>>,
277  selector<V> sel) noexcept
278  -> optionally_valid<std::chrono::duration<Rep, Period>> {
279  using dur_t = std::chrono::duration<Rep, Period>;
280 
281  if(
282  auto d = convert_from_string(
283  str,
284  type_identity<std::chrono::duration<Rep, std::ratio<1>>>(),
285  sel,
286  mp_string<'s'>())) {
287  return {std::chrono::duration_cast<dur_t>(extract(d)), true};
288  }
289  if(
290  auto d = convert_from_string(
291  str,
292  type_identity<std::chrono::duration<Rep, std::milli>>(),
293  sel,
294  mp_string<'m', 's'>())) {
295  return {std::chrono::duration_cast<dur_t>(extract(d)), true};
296  }
297  if(
298  auto d = convert_from_string(
299  str,
300  type_identity<std::chrono::duration<Rep, std::micro>>(),
301  sel,
302  mp_string<char(0xc2), char(0xb5), 's'>())) {
303  return {std::chrono::duration_cast<dur_t>(extract(d)), true};
304  }
305  if(
306  auto d = convert_from_string(
307  str,
308  type_identity<std::chrono::duration<Rep, std::nano>>(),
309  sel,
310  mp_string<'n', 's'>())) {
311  return {std::chrono::duration_cast<dur_t>(extract(d)), true};
312  }
313  if(
314  auto d = convert_from_string(
315  str,
316  type_identity<std::chrono::duration<Rep, std::ratio<60>>>(),
317  sel,
318  mp_string<'m', 'i', 'n'>())) {
319  return {std::chrono::duration_cast<dur_t>(extract(d)), true};
320  }
321  if(
322  auto d = convert_from_string(
323  str,
324  type_identity<std::chrono::duration<Rep, std::ratio<3600>>>(),
325  sel,
326  mp_string<'h', 'r'>())) {
327  return {std::chrono::duration_cast<dur_t>(extract(d)), true};
328  }
329  if(
330  auto d = convert_from_string(
331  str,
332  type_identity<std::chrono::duration<Rep, std::ratio<86400LL>>>(),
333  sel,
334  mp_string<'d', 'y'>())) {
335  return {std::chrono::duration_cast<dur_t>(extract(d)), true};
336  }
337  if(
338  auto d = convert_from_string(
339  str,
340  type_identity<std::chrono::duration<Rep, std::ratio<31556952LL>>>(),
341  sel,
342  mp_string<'y', 'r'>())) {
343  return {std::chrono::duration_cast<dur_t>(extract(d)), true};
344  }
345  if(
346  auto d = convert_from_string(
347  str,
348  type_identity<std::chrono::duration<Rep, std::ratio<31556952LL>>>(),
349  sel,
350  mp_string<'a'>())) {
351  return {std::chrono::duration_cast<dur_t>(extract(d)), true};
352  }
353  return {};
354 }
355 //------------------------------------------------------------------------------
359 template <typename T>
360 auto from_string(string_view src) noexcept {
361  return from_string(src, type_identity<T>(), default_selector);
362 }
363 //------------------------------------------------------------------------------
370 template <typename T, identifier_t V>
371 auto from_string(string_view src, selector<V> sel) noexcept {
372  return from_string(src, type_identity<T>(), sel);
373 }
374 //------------------------------------------------------------------------------
375 } // namespace eagine
376 
377 #if !EAGINE_LINK_LIBRARY || defined(EAGINE_IMPLEMENTING_LIBRARY)
378 #include <eagine/from_string.inl>
379 #endif
380 
381 #endif // EAGINE_FROM_STRING_HPP
static constexpr auto ends_with(basic_span< T1, P1, S1 > spn, basic_span< T2, P2, S2 > with) -> bool
Indicates if span spn ends with the content of with.
Definition: span_algo.hpp:187
basic_string_span< const char > string_view
Alias for const string views.
Definition: string_span.hpp:116
static constexpr auto c_str(memory::basic_span< C, P, S > s) -> std::enable_if_t< std::is_convertible_v< memory::basic_span< C, P, S >, basic_string_span< C, P, S >>, basic_c_str< C, P, S >>
Functions that construct a basic_c_str from a basic_string_span.
Definition: string_span.hpp:226
Common code is placed in this namespace.
Definition: eagine.hpp:21
static constexpr auto extract(api_result_value< Result, api_result_validity::never > &) noexcept -> Result &
Overload of extract for api_result_value.
Definition: c_api_wrap.hpp:270
static constexpr auto find_element(basic_span< T, P, S > spn, E what) noexcept -> optionally_valid< S >
Finds the position of the first occurrence of what in a span.
Definition: span_algo.hpp:279
static constexpr auto view(T *addr, S size) noexcept -> const_span< T >
Creates a view starting at the specified pointer and specified length.
Definition: span.hpp:458
Template used to construct tag-types used mostly in tag-dispatching.
Definition: selector.hpp:21
static constexpr auto snip(basic_span< T, P, S > s, L l) noexcept -> basic_span< T, P, S >
Snips a specified count of elements from the back of a span.
Definition: span_algo.hpp:73
static constexpr auto skip(basic_span< T, P, S > s, L l) noexcept -> basic_span< T, P, S >
Skips a specified count of elements from the front of a span.
Definition: span_algo.hpp:60
Template type used mostly for function type-tag dispatching.
Definition: type_identity.hpp:19
static constexpr auto starts_with(basic_span< T1, P1, S1 > spn, basic_span< T2, P2, S2 > with) -> bool
Indicates if span spn starts with the content of with.
Definition: span_algo.hpp:170
valid_if< T, valid_flag_policy > optionally_valid
Specialization of valid_if with flag indicating validity.
Definition: decl.hpp:300
constexpr const default_selector_t default_selector
The default overload selector constant.
Definition: selector.hpp:34

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).