19#include <userver/utils/meta_light.hpp>
21USERVER_NAMESPACE_BEGIN
28ThrowFromStringException(std::string_view message, std::string_view input, std::type_index resultType);
31std::enable_if_t<std::is_floating_point_v<T>, T> FromString(
const char* str) {
32 static_assert(!std::is_const_v<T> && !std::is_volatile_v<T>);
33 static_assert(!std::is_reference_v<T>);
36 impl::ThrowFromStringException(
"nullptr string",
"<null>",
typeid(T));
39 impl::ThrowFromStringException(
"empty string", str,
typeid(T));
41 if (std::isspace(str[0])) {
42 impl::ThrowFromStringException(
"leading spaces are not allowed", str,
typeid(T));
48 const auto result = [&] {
49 if constexpr (std::is_same_v<T,
float>) {
50 return std::strtof(str, &end);
51 }
else if constexpr (std::is_same_v<T,
double>) {
52 return std::strtod(str, &end);
53 }
else if constexpr (std::is_same_v<T,
long double>) {
54 return std::strtold(str, &end);
58 if (errno == ERANGE && !(result < 1 && result > 0.0)) {
59 impl::ThrowFromStringException(
"overflow", str,
typeid(T));
63 impl::ThrowFromStringException(
"no number found", str,
typeid(T));
67 if (std::isspace(*end)) {
68 impl::ThrowFromStringException(
"trailing spaces are not allowed", str,
typeid(T));
70 impl::ThrowFromStringException(
"extra junk at the end of the string is not allowed", str,
typeid(T));
78std::enable_if_t<std::is_floating_point_v<T>, T> FromString(
const std::string& str) {
79 return FromString<T>(str.data());
83std::enable_if_t<std::is_floating_point_v<T>, T> FromString(std::string_view str) {
84 static constexpr std::size_t kSmallBufferSize = 32;
86 if (str.size() >= kSmallBufferSize) {
87 return FromString<T>(std::string{str});
90 char buffer[kSmallBufferSize];
91 std::copy(str.data(), str.data() + str.size(), buffer);
92 buffer[str.size()] =
'\0';
94 return FromString<T>(buffer);
98std::enable_if_t<meta::kIsInteger<T>, T> FromString(std::string_view str) {
99 static_assert(!std::is_const_v<T> && !std::is_volatile_v<T>);
100 static_assert(!std::is_reference_v<T>);
103 impl::ThrowFromStringException(
"empty string", str,
typeid(T));
105 if (std::isspace(str[0])) {
106 impl::ThrowFromStringException(
"leading spaces are not allowed", str,
typeid(T));
109 std::size_t offset = 0;
112 if (str.size() > 1 && str[0] ==
'+' && str[1] ==
'-') {
113 impl::ThrowFromStringException(
"no number found", str,
typeid(T));
115 if (str[0] ==
'+') offset = 1;
118 if (std::is_unsigned_v<T> && str[0] ==
'-') offset = 1;
121 const auto [end, error_code] = std::from_chars(str.data() + offset, str.data() + str.size(), result);
123 if (error_code == std::errc::result_out_of_range) {
124 impl::ThrowFromStringException(
"overflow", str,
typeid(T));
126 if (error_code == std::errc::invalid_argument) {
127 impl::ThrowFromStringException(
"no number found", str,
typeid(T));
130 if (std::is_unsigned_v<T> && str[0] ==
'-' && result != 0) {
131 impl::ThrowFromStringException(
"overflow", str,
typeid(T));
134 if (end != str.data() + str.size()) {
135 if (std::isspace(*end)) {
136 impl::ThrowFromStringException(
"trailing spaces are not allowed", str,
typeid(T));
138 impl::ThrowFromStringException(
"extra junk at the end of the string is not allowed", str,
typeid(T));
166 return impl::FromString<T>(str);
169std::int64_t FromHexString(
const std::string& str);