JSON-SIMD
view release on metacpan or search on metacpan
simdjson.cpp view on Meta::CPAN
// v = buf * 10^(n-k)
// k is the length of the buffer (number of decimal digits)
// n is the position of the decimal point relative to the start of the buffer.
if (k <= n && n <= max_exp) {
// digits[000]
// len <= max_exp + 2
std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
// Make it look like a floating-point number (#362, #378)
buf[n + 0] = '.';
buf[n + 1] = '0';
return buf + (static_cast<size_t>(n)) + 2;
}
if (0 < n && n <= max_exp) {
// dig.its
// len <= max_digits10 + 1
std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n,
static_cast<size_t>(k) - static_cast<size_t>(n));
buf[n] = '.';
return buf + (static_cast<size_t>(k) + 1U);
}
if (min_exp < n && n <= 0) {
// 0.[000]digits
// len <= 2 + (-min_exp - 1) + max_digits10
std::memmove(buf + (2 + static_cast<size_t>(-n)), buf,
static_cast<size_t>(k));
buf[0] = '0';
buf[1] = '.';
std::memset(buf + 2, '0', static_cast<size_t>(-n));
return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
}
if (k == 1) {
// dE+123
// len <= 1 + 5
buf += 1;
} else {
// d.igitsE+123
// len <= max_digits10 + 1 + 5
std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
buf[1] = '.';
buf += 1 + static_cast<size_t>(k);
}
*buf++ = 'e';
return append_exponent(buf, n - 1);
}
} // namespace dtoa_impl
/*!
The format of the resulting decimal representation is similar to printf's %g
format. Returns an iterator pointing past-the-end of the decimal representation.
@note The input number must be finite, i.e. NaN's and Inf's are not supported.
@note The buffer must be large enough.
@note The result is NOT null-terminated.
*/
char *to_chars(char *first, const char *last, double value) {
static_cast<void>(last); // maybe unused - fix warning
bool negative = std::signbit(value);
if (negative) {
value = -value;
*first++ = '-';
}
if (value == 0) // +-0
{
*first++ = '0';
// Make it look like a floating-point number (#362, #378)
*first++ = '.';
*first++ = '0';
return first;
}
// Compute v = buffer * 10^decimal_exponent.
// The decimal digits are stored in the buffer, which needs to be interpreted
// as an unsigned decimal integer.
// len is the length of the buffer, i.e. the number of decimal digits.
int len = 0;
int decimal_exponent = 0;
dtoa_impl::grisu2(first, len, decimal_exponent, value);
// Format the buffer like printf("%.*g", prec, value)
constexpr int kMinExp = -4;
constexpr int kMaxExp = std::numeric_limits<double>::digits10;
return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp,
kMaxExp);
}
} // namespace internal
} // namespace simdjson
#endif // SIMDJSON_SRC_TO_CHARS_CPP
/* end file to_chars.cpp */
/* including from_chars.cpp: #include <from_chars.cpp> */
/* begin file from_chars.cpp */
#ifndef SIMDJSON_SRC_FROM_CHARS_CPP
#define SIMDJSON_SRC_FROM_CHARS_CPP
/* skipped duplicate #include <base.h> */
#include <cstdint>
#include <cstring>
#include <limits>
namespace simdjson {
namespace internal {
/**
* The code in the internal::from_chars function is meant to handle the floating-point number parsing
* when we have more than 19 digits in the decimal mantissa. This should only be seen
* in adversarial scenarios: we do not expect production systems to even produce
* such floating-point numbers.
*
* The parser is based on work by Nigel Tao (at https://github.com/google/wuffs/)
* who credits Ken Thompson for the design (via a reference to the Go source
( run in 0.616 second using v1.01-cache-2.11-cpan-39bf76dae61 )