|
@@ -45,12 +45,23 @@ bool cast_number(std::string_view str, T & to, F func) noexcept {
|
|
|
return counter == str.end();
|
|
return counter == str.end();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-std::vector<std::string_view> keyval(std::string_view input) {
|
|
|
|
|
|
|
+inline std::vector<std::string_view> keyval(std::string_view input) noexcept {
|
|
|
if (size_t const pos = input.find('='); pos < input.size()) {
|
|
if (size_t const pos = input.find('='); pos < input.size()) {
|
|
|
return {input.substr(0, pos), input.substr(pos + 1)};
|
|
return {input.substr(0, pos), input.substr(pos + 1)};
|
|
|
}
|
|
}
|
|
|
return {input};
|
|
return {input};
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+inline bool cast_bool(bool & out, std::string_view str) noexcept {
|
|
|
|
|
+ if (any_of(str, "true", "TRUE", "YES", "1")) {
|
|
|
|
|
+ out = true;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } else if (any_of(str, "false", "FALSE", "NO", "0")) {
|
|
|
|
|
+ out = false;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// This should be placed last in the file
|
|
// This should be placed last in the file
|
|
@@ -59,32 +70,31 @@ namespace string_utils {
|
|
|
template <typename Out> bool cast(Out & out, std::string_view str) noexcept {
|
|
template <typename Out> bool cast(Out & out, std::string_view str) noexcept {
|
|
|
if constexpr (std::is_same_v<Out, long>) {
|
|
if constexpr (std::is_same_v<Out, long>) {
|
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtol, 10));
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtol, 10));
|
|
|
- } else if constexpr (std::is_same_v<Out, long>) {
|
|
|
|
|
- return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtol, 10));
|
|
|
|
|
|
|
+ } else if constexpr (std::is_same_v<Out, unsigned long>) {
|
|
|
|
|
+ return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtoul, 10));
|
|
|
} else if constexpr (std::is_same_v<Out, long long>) {
|
|
} else if constexpr (std::is_same_v<Out, long long>) {
|
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtoll, 10));
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtoll, 10));
|
|
|
|
|
+ } else if constexpr (std::is_same_v<Out, unsigned long long>) {
|
|
|
|
|
+ return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtoull, 10));
|
|
|
} else if constexpr (std::is_same_v<Out, float>) {
|
|
} else if constexpr (std::is_same_v<Out, float>) {
|
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtof));
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtof));
|
|
|
} else if constexpr (std::is_same_v<Out, double>) {
|
|
} else if constexpr (std::is_same_v<Out, double>) {
|
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtod));
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtod));
|
|
|
} else if constexpr (std::is_same_v<Out, long double>) {
|
|
} else if constexpr (std::is_same_v<Out, long double>) {
|
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtold));
|
|
return detail::cast_number(str, out, SAFE_NUMBER_PARSE(std::strtold));
|
|
|
- } else if constexpr (std::is_same_v<Out, int>) {
|
|
|
|
|
- auto [tmp, success] = cast<long>(str);
|
|
|
|
|
- out = static_cast<int>(tmp);
|
|
|
|
|
- return success && tmp == static_cast<long>(out);
|
|
|
|
|
} else if constexpr (std::is_same_v<Out, bool>) {
|
|
} else if constexpr (std::is_same_v<Out, bool>) {
|
|
|
- if (any_of(str, "true", "TRUE", "YES", "1")) {
|
|
|
|
|
- out = true;
|
|
|
|
|
- return true;
|
|
|
|
|
- } else if (any_of(str, "false", "FALSE", "NO", "0")) {
|
|
|
|
|
- out = false;
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ return detail::cast_bool(out, str);
|
|
|
|
|
+ } else if constexpr (std::is_same_v<Out, char>) {
|
|
|
|
|
+ out = str[0];
|
|
|
|
|
+ return str.size() == 1;
|
|
|
} else if constexpr (std::is_constructible_v<Out, std::string_view>) {
|
|
} else if constexpr (std::is_constructible_v<Out, std::string_view>) {
|
|
|
out = Out(str);
|
|
out = Out(str);
|
|
|
return true;
|
|
return true;
|
|
|
|
|
+ } else if constexpr (std::is_integral_v<Out>) {
|
|
|
|
|
+ using V = std::conditional_t<std::is_unsigned_v<Out>, unsigned long, long>;
|
|
|
|
|
+ auto [tmp, success] = cast<V>(str);
|
|
|
|
|
+ out = static_cast<Out>(tmp);
|
|
|
|
|
+ return success && tmp == static_cast<V>(out);
|
|
|
} else {
|
|
} else {
|
|
|
static_assert(detail::always_false<Out>{}, "No match for cast(string)");
|
|
static_assert(detail::always_false<Out>{}, "No match for cast(string)");
|
|
|
}
|
|
}
|