|
|
@@ -11,6 +11,7 @@
|
|
|
#include <cstdlib>
|
|
|
#include <stdexcept>
|
|
|
#include <string>
|
|
|
+#include <errno.h>
|
|
|
|
|
|
namespace json {
|
|
|
using string_jt = std::string;
|
|
|
@@ -97,47 +98,34 @@ namespace json { namespace helper {
|
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
|
- void parse_double_impl(T & json, char const * begin, char const * end) {
|
|
|
- json = std::stod(std::string(begin, end));
|
|
|
+ T parse_double_impl(char const * begin, char const * & end) {
|
|
|
+ return std::strtod(begin, const_cast<char**>(&end));
|
|
|
}
|
|
|
template <>
|
|
|
- inline void parse_double_impl<float>(float & json, char const * begin, char const * end) {
|
|
|
- json = std::stof(std::string(begin, end));
|
|
|
+ inline float parse_double_impl<float>(char const * begin, char const * & end) {
|
|
|
+ return std::strtof(begin, const_cast<char**>(&end));
|
|
|
}
|
|
|
template <>
|
|
|
- inline void parse_double_impl<long double>(long double & json, char const * begin, char const * end) {
|
|
|
- json = std::stold(std::string(begin, end));
|
|
|
+ inline long double parse_double_impl<long double>(char const * begin, char const * & end) {
|
|
|
+ return std::strtold(begin, const_cast<char**>(&end));
|
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
|
void parse_double(T& json, char const * & data) {
|
|
|
char const * begin = data;
|
|
|
- if (*data == '-') { ++data; }
|
|
|
- while (isdigit(*data) || *data == '-') { ++data; }
|
|
|
- if (*data == '.') { ++data; }
|
|
|
- else if (begin != data && (*data == 'e' || *data == 'E')) {
|
|
|
- ++data;
|
|
|
- if (*data == '-') { ++data; }
|
|
|
- }
|
|
|
- while (isdigit(*data)) { ++data; }
|
|
|
- if ( begin == data ) {
|
|
|
- throw json::json_numeric_exception{"Expected numeric data"};
|
|
|
- }
|
|
|
- try {
|
|
|
- parse_double_impl(json, begin, data);
|
|
|
- } catch (std::domain_error const &) {
|
|
|
- throw json::json_numeric_exception{"Expected a numeric type"};
|
|
|
- } catch (std::out_of_range const &) {
|
|
|
+ errno = 0;
|
|
|
+ T tmp = parse_double_impl<T>(begin, data);
|
|
|
+ if (errno != 0) {
|
|
|
throw json::json_numeric_width_exception{"Number is out-of-range for floating-point type"};
|
|
|
+ } else if ( begin == data ) {
|
|
|
+ throw json::json_numeric_exception{"Expected numeric data"};
|
|
|
}
|
|
|
+ errno = 0;
|
|
|
+ json = std::move(tmp);
|
|
|
}
|
|
|
|
|
|
template <typename J>
|
|
|
void parse_numeric(J & json, char const * & data) {
|
|
|
- if (std::is_floating_point<J>::value) {
|
|
|
- helper::parse_double(json, data);
|
|
|
- return;
|
|
|
- }
|
|
|
numeric_token_info info = data;
|
|
|
|
|
|
if ( info.is_double || info.parse_numeric() == DOUBLE ) {
|