|
@@ -11,6 +11,7 @@
|
|
|
#include <cstdlib>
|
|
#include <cstdlib>
|
|
|
#include <optional>
|
|
#include <optional>
|
|
|
#include <string>
|
|
#include <string>
|
|
|
|
|
+#include <string_view>
|
|
|
#include <type_traits>
|
|
#include <type_traits>
|
|
|
#include <utility>
|
|
#include <utility>
|
|
|
#include <variant>
|
|
#include <variant>
|
|
@@ -26,8 +27,8 @@ namespace string_utils {
|
|
|
template <typename, typename = void> struct cast_helper {};
|
|
template <typename, typename = void> struct cast_helper {};
|
|
|
|
|
|
|
|
// The main parser
|
|
// The main parser
|
|
|
-template <typename T> std::pair<T, bool> cast(std::string const & str) noexcept;
|
|
|
|
|
-template <typename T> bool cast(std::string const & str, T & to) noexcept;
|
|
|
|
|
|
|
+template <typename T> std::pair<T, bool> cast(std::string_view str) noexcept;
|
|
|
|
|
+template <typename T> bool cast(std::string_view str, T & to) noexcept;
|
|
|
|
|
|
|
|
// A section of multi-argument parsers
|
|
// A section of multi-argument parsers
|
|
|
template <typename... Ts>
|
|
template <typename... Ts>
|
|
@@ -49,13 +50,13 @@ namespace string_utils::detail {
|
|
|
template <typename Tuple>
|
|
template <typename Tuple>
|
|
|
bool cast_tuple(std::vector<std::string> const & str, Tuple & to) noexcept;
|
|
bool cast_tuple(std::vector<std::string> const & str, Tuple & to) noexcept;
|
|
|
template <typename T, typename F>
|
|
template <typename T, typename F>
|
|
|
-bool cast_number(std::string const &str, T & to, F func) noexcept;
|
|
|
|
|
|
|
+bool cast_number(std::string_view str, T & to, F func) noexcept;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
namespace string_utils {
|
|
namespace string_utils {
|
|
|
|
|
|
|
|
template <typename T>
|
|
template <typename T>
|
|
|
-bool cast(std::string const & str, T & to) noexcept {
|
|
|
|
|
|
|
+bool cast(std::string_view str, T & to) noexcept {
|
|
|
if constexpr (detail::has_cast_helper_v<T>) {
|
|
if constexpr (detail::has_cast_helper_v<T>) {
|
|
|
return cast_helper<T>{}(str, to);
|
|
return cast_helper<T>{}(str, to);
|
|
|
} else if constexpr (std::is_same_v<T, std::string>) {
|
|
} else if constexpr (std::is_same_v<T, std::string>) {
|
|
@@ -90,34 +91,34 @@ struct cast_helper<std::optional<T>> {
|
|
|
|
|
|
|
|
namespace string_utils {
|
|
namespace string_utils {
|
|
|
|
|
|
|
|
-inline bool cast(std::string const &str, long & to) noexcept {
|
|
|
|
|
|
|
+inline bool cast(std::string_view str, long & to) noexcept {
|
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtol, 10));
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtol, 10));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-inline bool cast(std::string const &str, long long & to) noexcept {
|
|
|
|
|
|
|
+inline bool cast(std::string_view str, long long & to) noexcept {
|
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtoll, 10));
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtoll, 10));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-inline bool cast(std::string const &str, float & to) noexcept {
|
|
|
|
|
|
|
+inline bool cast(std::string_view str, float & to) noexcept {
|
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtof));
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtof));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-inline bool cast(std::string const &str, double & to) noexcept {
|
|
|
|
|
|
|
+inline bool cast(std::string_view str, double & to) noexcept {
|
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtod));
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtod));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-inline bool cast(std::string const &str, long double & to) noexcept {
|
|
|
|
|
|
|
+inline bool cast(std::string_view str, long double & to) noexcept {
|
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtold));
|
|
return detail::cast_number(str, to, SAFE_NUMBER_PARSE(std::strtold));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-inline bool cast(std::string const & str, int & to) noexcept {
|
|
|
|
|
|
|
+inline bool cast(std::string_view str, int & to) noexcept {
|
|
|
long tmp;
|
|
long tmp;
|
|
|
bool rval = cast(str, tmp);
|
|
bool rval = cast(str, tmp);
|
|
|
to = static_cast<int>(tmp);
|
|
to = static_cast<int>(tmp);
|
|
|
return rval && tmp == static_cast<long>(to);
|
|
return rval && tmp == static_cast<long>(to);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-inline bool cast(std::string const & str, bool & to) noexcept {
|
|
|
|
|
|
|
+inline bool cast(std::string_view str, bool & to) noexcept {
|
|
|
if (any_of(str, "true", "TRUE", "YES", "1")) {
|
|
if (any_of(str, "true", "TRUE", "YES", "1")) {
|
|
|
to = true;
|
|
to = true;
|
|
|
return true;
|
|
return true;
|
|
@@ -158,16 +159,16 @@ bool cast_tuple(std::vector<std::string> const & str, Tuple & to) noexcept {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
template <typename T, typename F>
|
|
template <typename T, typename F>
|
|
|
-bool cast_number(std::string const &str, T & to, F func) noexcept {
|
|
|
|
|
|
|
+bool cast_number(std::string_view str, T & to, F func) noexcept {
|
|
|
char *counter = nullptr;
|
|
char *counter = nullptr;
|
|
|
- to = func(str.c_str(), &counter);
|
|
|
|
|
- return counter == str.c_str() + str.length();
|
|
|
|
|
|
|
+ to = func(str.data(), &counter);
|
|
|
|
|
+ return counter == str.end();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// This should be placed last in the file
|
|
// This should be placed last in the file
|
|
|
namespace string_utils {
|
|
namespace string_utils {
|
|
|
-template <typename T> std::pair<T, bool> cast(std::string const & str) noexcept {
|
|
|
|
|
|
|
+template <typename T> std::pair<T, bool> cast(std::string_view str) noexcept {
|
|
|
using string_utils::cast;
|
|
using string_utils::cast;
|
|
|
std::pair<T, bool> rval;
|
|
std::pair<T, bool> rval;
|
|
|
rval.second = cast(str, rval.first);
|
|
rval.second = cast(str, rval.first);
|