| 448 | |
| 449 | template<class T> |
| 450 | T get_integer_impl(const std::string &str, double mi, double ma_plus_1) { |
| 451 | try { |
| 452 | return common::integer_cast<T>(str); |
| 453 | } catch (const std::exception &) { |
| 454 | } |
| 455 | double value_real = 0; |
| 456 | size_t pos = 0; |
| 457 | try { |
| 458 | value_real = std::stod(str, &pos); |
| 459 | } catch (const std::exception &ex) { |
| 460 | throw std::out_of_range("Json number (" + str + ") can not be converted because " + common::what(ex)); |
| 461 | } |
| 462 | if (has_tail(str, pos)) |
| 463 | throw std::out_of_range("Json number (" + str + ") can not be converted"); |
| 464 | if (std::isinf(value_real) || std::isnan(value_real)) |
| 465 | throw std::runtime_error("Json number (" + str + ") must not be inf or nan"); |
| 466 | double intpart = 0; |
| 467 | double fractpart = modf(value_real, &intpart); |
| 468 | if (fractpart != 0) |
| 469 | throw std::runtime_error("Json number (" + str + ") must be integer"); |
| 470 | if (std::isless(value_real, mi) || std::isgreaterequal(value_real, ma_plus_1)) |
| 471 | throw std::runtime_error("Json number (" + str + ") must be in range [" + |
| 472 | common::to_string(std::numeric_limits<T>::min()) + ".." + |
| 473 | common::to_string(std::numeric_limits<T>::max()) + "]"); |
| 474 | return static_cast<T>(value_real); // Hopefully no undefined behaviour here |
| 475 | } |
| 476 | |
| 477 | template<class T> |
| 478 | T get_integer_impl2(const std::string &str) { |