9 #ifndef EAGINE_FROM_STRING_HPP
10 #define EAGINE_FROM_STRING_HPP
25 auto _parse_from_string(
string_view src,
long long int&) noexcept -> bool;
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);
37 auto _parse_from_string(
string_view src,
long double&) noexcept -> bool;
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>> {
43 if(_parse_from_string(src, parsed)) {
44 return convert_if_fits<T>(parsed);
49 template <
identifier_t V>
51 from_string(
string_view src, type_identity<bool>, selector<V>) noexcept
52 -> optionally_valid<bool> {
54 const string_view true_strs[] = {{
"true"}, {
"True"}, {
"1"}, {
"t"}, {
"T"}};
60 {
"false"}, {
"False"}, {
"0"}, {
"f"}, {
"F"}};
68 template <
identifier_t V>
70 from_string(
string_view src, type_identity<char>, selector<V>) noexcept
71 -> optionally_valid<char> {
78 template <
typename T,
typename N>
79 auto multiply_and_convert_if_fits(N n,
const char* c) noexcept
80 -> optionally_valid<T> {
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);
94 template <
typename T,
typename N>
95 auto convert_from_string_with(
96 N (*converter)(
const char*,
char**),
98 type_identity<T> tid) noexcept -> optionally_valid<T> {
100 auto cstr =
c_str(src);
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)}) {
109 return parse_from_string(src, tid);
112 template <
typename T,
typename N>
113 auto convert_from_string_with(
114 N (*converter)(
const char*,
char**,
int),
117 type_identity<T> tid) noexcept -> optionally_valid<T> {
119 auto cstr =
c_str(src);
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)}) {
128 return parse_from_string(src, tid);
131 template <
identifier_t V>
132 static inline auto from_string(
134 type_identity<short>
id,
137 return convert_from_string_with(&std::strtol, base, src,
id);
140 template <
identifier_t V>
141 static inline auto from_string(
143 type_identity<int>
id,
146 return convert_from_string_with(&std::strtol, base, src,
id);
149 template <
identifier_t V>
150 static inline auto from_string(
152 type_identity<long>
id,
155 return convert_from_string_with(&std::strtol, base, src,
id);
158 template <
identifier_t V>
159 static inline auto from_string(
161 type_identity<long long>
id,
164 return convert_from_string_with(&std::strtoll, base, src,
id);
167 template <
identifier_t V>
168 static inline auto from_string(
170 type_identity<unsigned short>
id,
173 return convert_from_string_with(&std::strtoul, base, src,
id);
176 template <
identifier_t V>
177 static inline auto from_string(
179 type_identity<unsigned int>
id,
182 return convert_from_string_with(&std::strtoul, base, src,
id);
185 template <
identifier_t V>
186 static inline auto from_string(
188 type_identity<unsigned long>
id,
191 return convert_from_string_with(&std::strtoul, base, src,
id);
194 template <
identifier_t V>
195 static inline auto from_string(
197 type_identity<unsigned long long>
id,
200 return convert_from_string_with(&std::strtoull, base, src,
id);
203 template <
identifier_t V>
205 from_string(
string_view src, type_identity<byte>, selector<V> sel) noexcept
206 -> optionally_valid<byte> {
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)};
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)};
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)};
226 template <
identifier_t V>
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);
233 template <
identifier_t V>
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);
240 template <
identifier_t V>
241 static inline auto from_string(
243 type_identity<long double>
id,
244 selector<V>) noexcept -> optionally_valid<long double> {
245 return convert_from_string_with(&std::strtold, src,
id);
248 template <
identifier_t V>
250 from_string(
string_view src, type_identity<std::string>, selector<V>) noexcept
251 -> always_valid<std::string> {
252 return to_string(src);
255 template <
typename Rep,
typename Period,
identifier_t V,
typename Symbol>
256 static inline auto convert_from_string(
258 type_identity<std::chrono::duration<Rep, Period>>,
260 Symbol sym_const) noexcept
261 -> optionally_valid<std::chrono::duration<Rep, Period>> {
266 from_string(
snip(src, symbol.size()), type_identity<Rep>(), sel)) {
267 return {std::chrono::duration<Rep, Period>(
extract(opt_val)),
true};
273 template <
typename Rep,
typename Period,
identifier_t V>
274 static inline auto from_string(
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>;
282 auto d = convert_from_string(
284 type_identity<std::chrono::duration<Rep, std::ratio<1>>>(),
287 return {std::chrono::duration_cast<dur_t>(
extract(d)),
true};
290 auto d = convert_from_string(
292 type_identity<std::chrono::duration<Rep, std::milli>>(),
294 mp_string<'m', 's'>())) {
295 return {std::chrono::duration_cast<dur_t>(
extract(d)),
true};
298 auto d = convert_from_string(
300 type_identity<std::chrono::duration<Rep, std::micro>>(),
302 mp_string<
char(0xc2),
char(0xb5),
's'>())) {
303 return {std::chrono::duration_cast<dur_t>(
extract(d)),
true};
306 auto d = convert_from_string(
308 type_identity<std::chrono::duration<Rep, std::nano>>(),
310 mp_string<'n', 's'>())) {
311 return {std::chrono::duration_cast<dur_t>(
extract(d)),
true};
314 auto d = convert_from_string(
316 type_identity<std::chrono::duration<Rep, std::ratio<60>>>(),
318 mp_string<'m', 'i', 'n'>())) {
319 return {std::chrono::duration_cast<dur_t>(
extract(d)),
true};
322 auto d = convert_from_string(
324 type_identity<std::chrono::duration<Rep, std::ratio<3600>>>(),
326 mp_string<'h', 'r'>())) {
327 return {std::chrono::duration_cast<dur_t>(
extract(d)),
true};
330 auto d = convert_from_string(
332 type_identity<std::chrono::duration<Rep, std::ratio<86400LL>>>(),
334 mp_string<'d', 'y'>())) {
335 return {std::chrono::duration_cast<dur_t>(
extract(d)),
true};
338 auto d = convert_from_string(
340 type_identity<std::chrono::duration<Rep, std::ratio<31556952LL>>>(),
342 mp_string<'y', 'r'>())) {
343 return {std::chrono::duration_cast<dur_t>(
extract(d)),
true};
346 auto d = convert_from_string(
348 type_identity<std::chrono::duration<Rep, std::ratio<31556952LL>>>(),
351 return {std::chrono::duration_cast<dur_t>(
extract(d)),
true};
359 template <
typename T>
370 template <
typename T,
identifier_t V>
377 #if !EAGINE_LINK_LIBRARY || defined(EAGINE_IMPLEMENTING_LIBRARY)
378 #include <eagine/from_string.inl>
381 #endif // EAGINE_FROM_STRING_HPP