mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-08 09:47:48 +08:00
move from feature macros to format flags
This commit is contained in:
parent
724834fe8e
commit
0bbba960f4
@ -289,12 +289,16 @@ parse_number_string(UC const *p, UC const *pend,
|
||||
parsed_number_string_t<UC> answer;
|
||||
answer.valid = false;
|
||||
answer.too_many_digits = false;
|
||||
// assume p < pend, so dereference without checks;
|
||||
answer.negative = (*p == UC('-'));
|
||||
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
||||
if ((*p == UC('-')) ||
|
||||
(!uint64_t(fmt & detail::basic_json_fmt) && *p == UC('+'))) {
|
||||
#else
|
||||
if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
||||
// C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
||||
if ((*p == UC('-')) ||
|
||||
(uint64_t(fmt & chars_format::allow_leading_plus) &&
|
||||
!uint64_t(fmt & detail::basic_json_fmt) && *p == UC('+'))) {
|
||||
#endif
|
||||
++p;
|
||||
if (p == pend) {
|
||||
@ -473,7 +477,11 @@ parse_number_string(UC const *p, UC const *pend,
|
||||
|
||||
template <typename T, typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
parse_int_string(UC const *p, UC const *pend, T &value, int base) {
|
||||
parse_int_string(UC const *p, UC const *pend, T &value,
|
||||
parse_options_t<UC> options) {
|
||||
chars_format const fmt = options.format;
|
||||
int const base = options.base;
|
||||
|
||||
from_chars_result_t<UC> answer;
|
||||
|
||||
UC const *const first = p;
|
||||
@ -487,7 +495,8 @@ parse_int_string(UC const *p, UC const *pend, T &value, int base) {
|
||||
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
||||
if ((*p == UC('-')) || (*p == UC('+'))) {
|
||||
#else
|
||||
if (*p == UC('-')) {
|
||||
if ((*p == UC('-')) ||
|
||||
(uint64_t(fmt & chars_format::allow_leading_plus) && (*p == UC('+')))) {
|
||||
#endif
|
||||
++p;
|
||||
}
|
||||
|
||||
@ -38,11 +38,13 @@ from_chars(UC const *first, UC const *last, T &value,
|
||||
|
||||
/**
|
||||
* Like from_chars, but accepts an `options` argument to govern number parsing.
|
||||
* Both for floating-point types and integer types.
|
||||
*/
|
||||
template <typename T, typename UC = char>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept;
|
||||
|
||||
/**
|
||||
* from_chars for integer types.
|
||||
*/
|
||||
|
||||
@ -34,6 +34,8 @@ enum class chars_format : uint64_t {
|
||||
json_or_infnan = uint64_t(detail::basic_json_fmt) | fixed | scientific,
|
||||
fortran = uint64_t(detail::basic_fortran_fmt) | fixed | scientific,
|
||||
general = fixed | scientific,
|
||||
allow_leading_plus = 1 << 7,
|
||||
skip_white_space = 1 << 8,
|
||||
};
|
||||
|
||||
template <typename UC> struct from_chars_result_t {
|
||||
@ -44,13 +46,15 @@ using from_chars_result = from_chars_result_t<char>;
|
||||
|
||||
template <typename UC> struct parse_options_t {
|
||||
constexpr explicit parse_options_t(chars_format fmt = chars_format::general,
|
||||
UC dot = UC('.'))
|
||||
: format(fmt), decimal_point(dot) {}
|
||||
UC dot = UC('.'), int b = 10)
|
||||
: format(fmt), decimal_point(dot), base(b) {}
|
||||
|
||||
/** Which number formats are accepted */
|
||||
chars_format format;
|
||||
/** The character used as decimal point */
|
||||
UC decimal_point;
|
||||
/** The base used for integers */
|
||||
int base;
|
||||
};
|
||||
using parse_options = parse_options_t<char>;
|
||||
|
||||
@ -674,7 +678,6 @@ to_float(bool negative, adjusted_mantissa am, T &value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||
template <typename = void> struct space_lut {
|
||||
static constexpr bool value[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@ -697,7 +700,6 @@ template <typename T> constexpr bool space_lut<T>::value[];
|
||||
#endif
|
||||
|
||||
inline constexpr bool is_space(uint8_t c) { return space_lut<>::value[c]; }
|
||||
#endif
|
||||
|
||||
template <typename UC> static constexpr uint64_t int_cmp_zeros() {
|
||||
static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4),
|
||||
|
||||
@ -19,9 +19,9 @@ namespace detail {
|
||||
* strings a null-free and fixed.
|
||||
**/
|
||||
template <typename T, typename UC>
|
||||
from_chars_result_t<UC> FASTFLOAT_CONSTEXPR14 parse_infnan(UC const *first,
|
||||
UC const *last,
|
||||
T &value) noexcept {
|
||||
from_chars_result_t<UC>
|
||||
FASTFLOAT_CONSTEXPR14 parse_infnan(UC const *first, UC const *last,
|
||||
T &value, chars_format fmt) noexcept {
|
||||
from_chars_result_t<UC> answer{};
|
||||
answer.ptr = first;
|
||||
answer.ec = std::errc(); // be optimistic
|
||||
@ -31,7 +31,9 @@ from_chars_result_t<UC> FASTFLOAT_CONSTEXPR14 parse_infnan(UC const *first,
|
||||
if ((*first == UC('-')) || (*first == UC('+'))) {
|
||||
#else
|
||||
// C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
||||
if (*first == UC('-')) {
|
||||
if ((*first == UC('-')) ||
|
||||
(uint64_t(fmt & chars_format::allow_leading_plus) &&
|
||||
(*first == UC('+')))) {
|
||||
#endif
|
||||
++first;
|
||||
}
|
||||
@ -284,8 +286,8 @@ from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept {
|
||||
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
from_chars_float_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
|
||||
static_assert(is_supported_float_type<T>(),
|
||||
"only some floating-point types are supported");
|
||||
@ -295,9 +297,13 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
chars_format const fmt = options.format;
|
||||
|
||||
from_chars_result_t<UC> answer;
|
||||
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||
while ((first != last) && fast_float::is_space(uint8_t(*first))) {
|
||||
first++;
|
||||
#ifndef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||
if (uint64_t(fmt & chars_format::skip_white_space)) {
|
||||
#endif
|
||||
while ((first != last) && fast_float::is_space(uint8_t(*first))) {
|
||||
first++;
|
||||
}
|
||||
#ifndef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||
}
|
||||
#endif
|
||||
if (first == last) {
|
||||
@ -313,7 +319,7 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
} else {
|
||||
return detail::parse_infnan(first, last, value);
|
||||
return detail::parse_infnan(first, last, value, fmt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,13 +330,36 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
template <typename T, typename UC, typename>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars(UC const *first, UC const *last, T &value, int base) noexcept {
|
||||
|
||||
static_assert(std::is_integral<T>::value, "only integer types are supported");
|
||||
static_assert(is_supported_char_type<UC>(),
|
||||
"only char, wchar_t, char16_t and char32_t are supported");
|
||||
|
||||
parse_options_t<UC> options;
|
||||
options.base = base;
|
||||
return from_chars_advanced(first, last, value, options);
|
||||
}
|
||||
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_int_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
|
||||
static_assert(std::is_integral<T>::value, "only integer types are supported");
|
||||
static_assert(is_supported_char_type<UC>(),
|
||||
"only char, wchar_t, char16_t and char32_t are supported");
|
||||
|
||||
chars_format const fmt = options.format;
|
||||
int const base = options.base;
|
||||
|
||||
from_chars_result_t<UC> answer;
|
||||
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||
while ((first != last) && fast_float::is_space(uint8_t(*first))) {
|
||||
first++;
|
||||
#ifndef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||
if (uint64_t(fmt & chars_format::skip_white_space)) {
|
||||
#endif
|
||||
while ((first != last) && fast_float::is_space(uint8_t(*first))) {
|
||||
first++;
|
||||
}
|
||||
#ifndef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||
}
|
||||
#endif
|
||||
if (first == last || base < 2 || base > 36) {
|
||||
@ -338,7 +367,34 @@ from_chars(UC const *first, UC const *last, T &value, int base) noexcept {
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
}
|
||||
return parse_int_string(first, last, value, base);
|
||||
|
||||
return parse_int_string(first, last, value, options);
|
||||
}
|
||||
|
||||
template <bool> struct from_chars_advanced_caller {
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
call(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_float_advanced(first, last, value, options);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct from_chars_advanced_caller<false> {
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
call(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_int_advanced(first, last, value, options);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_advanced_caller<is_supported_float_type<T>()>::call(
|
||||
first, last, value, options);
|
||||
}
|
||||
|
||||
} // namespace fast_float
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user