typename std::enable_if<std::is_same<CharT,wchar_t>::value,double>::type operator()(const CharT* s, size_t /*length*/) const { CharT *end = nullptr; double val = wcstod(s, &end); if (s == end) { JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed")); } return val; }
typename std::enable_if<std::is_same<CharT,char>::value,double>::type operator()(const CharT* s, size_t length) const { char *end = nullptr; double val = strtold_l(s, &end, locale_); if (s == end) { JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed")); } return val; }
size_t operator()(double val, Result& result) { size_t count = 0; chars_format format = override_.format() != chars_format() ? override_.format() : chars_format::general; int decimal_places; if (override_.decimal_places() != 0) { decimal_places = override_.decimal_places(); } else { format = chars_format::general; decimal_places = 0; } char number_buffer[200]; int length = 0; switch (format) { case chars_format::fixed: { length = snprintf(number_buffer, sizeof(number_buffer), "%1.*f", decimal_places, val); if (length < 0) { JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed.")); } dump_buffer(number_buffer, length, decimal_point_, result); } break; case chars_format::scientific: { length = snprintf(number_buffer, sizeof(number_buffer), "%1.*e", decimal_places, val); if (length < 0) { JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed.")); } dump_buffer(number_buffer, length, decimal_point_, result); } break; case chars_format::general: { if (override_.precision() != 0) { int precision = override_.precision(); length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision, val); if (length < 0) { JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed.")); } dump_buffer(number_buffer, length, decimal_point_, result); } else { if (!dtoa(val, decimal_point_, result)) { JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed.")); } } break; } default: JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed.")); break; } return count; }
void operator()(double val, const floating_point_options& fmt, Writer& writer) { typedef typename Writer::char_type char_type; chars_format format; if (override_.format() != chars_format::hex) { format = override_.format(); } else { format = fmt.format(); } int precision; int precision2 = 0; if (override_.precision() != 0) { precision = override_.precision(); } else if (fmt.precision() != 0) { precision = fmt.precision(); } else { precision = std::numeric_limits<double>::digits10; precision2 = std::numeric_limits<double>::max_digits10; } int decimal_places; if (override_.decimal_places() != 0) { decimal_places = override_.decimal_places(); } else if (fmt.decimal_places() != 0) { decimal_places = fmt.decimal_places(); } else { format = chars_format::general; } char number_buffer[200]; int length = 0; switch (format) { case chars_format::fixed: { length = snprintf(number_buffer, sizeof(number_buffer), "%1.*f", decimal_places, val); if (length < 0) { JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed.")); } } break; case chars_format::scientific: { length = snprintf(number_buffer, sizeof(number_buffer), "%1.*e", decimal_places, val); if (length < 0) { JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed.")); } } break; default: { length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision, val); if (length < 0) { JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed.")); } if (precision2 > 0) { if (to_double_(number_buffer,sizeof(number_buffer)) != val) { length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision2, val); if (length < 0) { JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed.")); } } } } break; } const char* sbeg = number_buffer; const char* send = sbeg + length; const char* pexp = send; if (sbeg != send) { bool dot = false; for (pexp = sbeg; *pexp != 'e' && *pexp != 'E' && pexp < send; ++pexp) { } for (const char* q = sbeg; q < pexp; ++q) { switch (*q) { case '-':case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': writer.put(*q); break; default: if (*q == decimal_point_) { dot = true; writer.put('.'); } break; } } if (!dot) { writer.put('.'); writer.put('0'); dot = true; } for (const char* q = pexp; q < send; ++q) { writer.put(*q); } } }