19#include <userver/utils/meta_light.hpp> 
   21USERVER_NAMESPACE_BEGIN
 
   27[[noreturn]] 
void ThrowFromStringException(std::string_view message,
 
   28                                           std::string_view input,
 
   29                                           std::type_index resultType);
 
   32std::enable_if_t<std::is_floating_point_v<T>, T> FromString(
const char* str) {
 
   33  static_assert(!std::is_const_v<T> && !std::is_volatile_v<T>);
 
   34  static_assert(!std::is_reference_v<T>);
 
   37    impl::ThrowFromStringException(
"nullptr string", 
"<null>", 
typeid(T));
 
   40    impl::ThrowFromStringException(
"empty string", str, 
typeid(T));
 
   42  if (std::isspace(str[0])) {
 
   43    impl::ThrowFromStringException(
"leading spaces are not allowed", str,
 
   50  const auto result = [&] {
 
   51    if constexpr (std::is_same_v<T, 
float>) {
 
   52      return std::strtof(str, &end);
 
   53    } 
else if constexpr (std::is_same_v<T, 
double>) {
 
   54      return std::strtod(str, &end);
 
   55    } 
else if constexpr (std::is_same_v<T, 
long double>) {
 
   56      return std::strtold(str, &end);
 
   60  if (errno == ERANGE && !(result < 1 && result > 0.0)) {
 
   61    impl::ThrowFromStringException(
"overflow", str, 
typeid(T));
 
   65    impl::ThrowFromStringException(
"no number found", str, 
typeid(T));
 
   69    if (std::isspace(*end)) {
 
   70      impl::ThrowFromStringException(
"trailing spaces are not allowed", str,
 
   73      impl::ThrowFromStringException(
 
   74          "extra junk at the end of the string is not allowed", str, 
typeid(T));
 
   82std::enable_if_t<std::is_floating_point_v<T>, T> FromString(
 
   83    const std::string& str) {
 
   84  return FromString<T>(str.data());
 
   88std::enable_if_t<std::is_floating_point_v<T>, T> FromString(
 
   89    std::string_view str) {
 
   90  static constexpr std::size_t kSmallBufferSize = 32;
 
   92  if (str.size() >= kSmallBufferSize) {
 
   93    return FromString<T>(std::string{str});
 
   96  char buffer[kSmallBufferSize];
 
   97  std::copy(str.data(), str.data() + str.size(), buffer);
 
   98  buffer[str.size()] = 
'\0';
 
  100  return FromString<T>(buffer);
 
  104std::enable_if_t<meta::kIsInteger<T>, T> FromString(std::string_view str) {
 
  105  static_assert(!std::is_const_v<T> && !std::is_volatile_v<T>);
 
  106  static_assert(!std::is_reference_v<T>);
 
  109    impl::ThrowFromStringException(
"empty string", str, 
typeid(T));
 
  111  if (std::isspace(str[0])) {
 
  112    impl::ThrowFromStringException(
"leading spaces are not allowed", str,
 
  116  std::size_t offset = 0;
 
  119  if (str.size() > 1 && str[0] == 
'+' && str[1] == 
'-') {
 
  120    impl::ThrowFromStringException(
"no number found", str, 
typeid(T));
 
  122  if (str[0] == 
'+') offset = 1;
 
  125  if (std::is_unsigned_v<T> && str[0] == 
'-') offset = 1;
 
  128  const auto [end, error_code] =
 
  129      std::from_chars(str.data() + offset, str.data() + str.size(), result);
 
  131  if (error_code == std::errc::result_out_of_range) {
 
  132    impl::ThrowFromStringException(
"overflow", str, 
typeid(T));
 
  134  if (error_code == std::errc::invalid_argument) {
 
  135    impl::ThrowFromStringException(
"no number found", str, 
typeid(T));
 
  138  if (std::is_unsigned_v<T> && str[0] == 
'-' && result != 0) {
 
  139    impl::ThrowFromStringException(
"overflow", str, 
typeid(T));
 
  142  if (end != str.data() + str.size()) {
 
  143    if (std::isspace(*end)) {
 
  144      impl::ThrowFromStringException(
"trailing spaces are not allowed", str,
 
  147      impl::ThrowFromStringException(
 
  148          "extra junk at the end of the string is not allowed", str, 
typeid(T));
 
  171template <
typename T, 
typename StringType,
 
  175  return impl::FromString<T>(str);
 
  178std::int64_t FromHexString(
const std::string& str);