mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
enum class chars_format
This commit is contained in:
parent
42fded19ae
commit
b8b5da75a5
@ -291,7 +291,8 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
answer.too_many_digits = false;
|
answer.too_many_digits = false;
|
||||||
answer.negative = (*p == UC('-'));
|
answer.negative = (*p == UC('-'));
|
||||||
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
||||||
if ((*p == UC('-')) || (!(fmt & FASTFLOAT_JSONFMT) && *p == UC('+'))) {
|
if ((*p == UC('-')) ||
|
||||||
|
(!int(fmt & detail::basic_json_fmt) && *p == UC('+'))) {
|
||||||
#else
|
#else
|
||||||
if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
||||||
#endif
|
#endif
|
||||||
@ -300,7 +301,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
return report_parse_error<UC>(
|
return report_parse_error<UC>(
|
||||||
p, parse_error::missing_integer_or_dot_after_sign);
|
p, parse_error::missing_integer_or_dot_after_sign);
|
||||||
}
|
}
|
||||||
if (fmt & FASTFLOAT_JSONFMT) {
|
if (int(fmt & detail::basic_json_fmt)) {
|
||||||
if (!is_integer(*p)) { // a sign must be followed by an integer
|
if (!is_integer(*p)) { // a sign must be followed by an integer
|
||||||
return report_parse_error<UC>(p,
|
return report_parse_error<UC>(p,
|
||||||
parse_error::missing_integer_after_sign);
|
parse_error::missing_integer_after_sign);
|
||||||
@ -329,7 +330,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
UC const *const end_of_integer_part = p;
|
UC const *const end_of_integer_part = p;
|
||||||
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
|
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
|
||||||
answer.integer = span<const UC>(start_digits, size_t(digit_count));
|
answer.integer = span<const UC>(start_digits, size_t(digit_count));
|
||||||
if (fmt & FASTFLOAT_JSONFMT) {
|
if (int(fmt & detail::basic_json_fmt)) {
|
||||||
// at least 1 digit in integer part, without leading zeros
|
// at least 1 digit in integer part, without leading zeros
|
||||||
if (digit_count == 0) {
|
if (digit_count == 0) {
|
||||||
return report_parse_error<UC>(p, parse_error::no_digits_in_integer_part);
|
return report_parse_error<UC>(p, parse_error::no_digits_in_integer_part);
|
||||||
@ -358,7 +359,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
answer.fraction = span<const UC>(before, size_t(p - before));
|
answer.fraction = span<const UC>(before, size_t(p - before));
|
||||||
digit_count -= exponent;
|
digit_count -= exponent;
|
||||||
}
|
}
|
||||||
if (fmt & FASTFLOAT_JSONFMT) {
|
if (int(fmt & detail::basic_json_fmt)) {
|
||||||
// at least 1 digit in fractional part
|
// at least 1 digit in fractional part
|
||||||
if (has_decimal_point && exponent == 0) {
|
if (has_decimal_point && exponent == 0) {
|
||||||
return report_parse_error<UC>(p,
|
return report_parse_error<UC>(p,
|
||||||
@ -369,9 +370,9 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
return report_parse_error<UC>(p, parse_error::no_digits_in_mantissa);
|
return report_parse_error<UC>(p, parse_error::no_digits_in_mantissa);
|
||||||
}
|
}
|
||||||
int64_t exp_number = 0; // explicit exponential part
|
int64_t exp_number = 0; // explicit exponential part
|
||||||
if (((fmt & chars_format::scientific) && (p != pend) &&
|
if ((int(fmt & chars_format::scientific) && (p != pend) &&
|
||||||
((UC('e') == *p) || (UC('E') == *p))) ||
|
((UC('e') == *p) || (UC('E') == *p))) ||
|
||||||
((fmt & FASTFLOAT_FORTRANFMT) && (p != pend) &&
|
(int(fmt & detail::basic_fortran_fmt) && (p != pend) &&
|
||||||
((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) ||
|
((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) ||
|
||||||
(UC('D') == *p)))) {
|
(UC('D') == *p)))) {
|
||||||
UC const *location_of_e = p;
|
UC const *location_of_e = p;
|
||||||
@ -389,7 +390,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if ((p == pend) || !is_integer(*p)) {
|
if ((p == pend) || !is_integer(*p)) {
|
||||||
if (!(fmt & chars_format::fixed)) {
|
if (!int(fmt & chars_format::fixed)) {
|
||||||
// The exponential part is invalid for scientific notation, so it must
|
// The exponential part is invalid for scientific notation, so it must
|
||||||
// be a trailing token for fixed notation. However, fixed notation is
|
// be a trailing token for fixed notation. However, fixed notation is
|
||||||
// disabled, so report a scientific notation error.
|
// disabled, so report a scientific notation error.
|
||||||
@ -412,7 +413,8 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If it scientific and not fixed, we have to bail out.
|
// If it scientific and not fixed, we have to bail out.
|
||||||
if ((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) {
|
if (int(fmt & chars_format::scientific) &&
|
||||||
|
!int(fmt & chars_format::fixed)) {
|
||||||
return report_parse_error<UC>(p, parse_error::missing_exponential_part);
|
return report_parse_error<UC>(p, parse_error::missing_exponential_part);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,20 +16,24 @@
|
|||||||
|
|
||||||
namespace fast_float {
|
namespace fast_float {
|
||||||
|
|
||||||
#define FASTFLOAT_JSONFMT (1 << 5)
|
enum class chars_format;
|
||||||
#define FASTFLOAT_FORTRANFMT (1 << 6)
|
|
||||||
|
|
||||||
enum chars_format {
|
namespace detail {
|
||||||
|
constexpr chars_format basic_json_fmt = chars_format(1 << 5);
|
||||||
|
constexpr chars_format basic_fortran_fmt = chars_format(1 << 6);
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
enum class chars_format {
|
||||||
scientific = 1 << 0,
|
scientific = 1 << 0,
|
||||||
fixed = 1 << 2,
|
fixed = 1 << 2,
|
||||||
hex = 1 << 3,
|
hex = 1 << 3,
|
||||||
no_infnan = 1 << 4,
|
no_infnan = 1 << 4,
|
||||||
// RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6
|
// RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6
|
||||||
json = FASTFLOAT_JSONFMT | fixed | scientific | no_infnan,
|
json = int(detail::basic_json_fmt) | fixed | scientific | no_infnan,
|
||||||
// Extension of RFC 8259 where, e.g., "inf" and "nan" are allowed.
|
// Extension of RFC 8259 where, e.g., "inf" and "nan" are allowed.
|
||||||
json_or_infnan = FASTFLOAT_JSONFMT | fixed | scientific,
|
json_or_infnan = int(detail::basic_json_fmt) | fixed | scientific,
|
||||||
fortran = FASTFLOAT_FORTRANFMT | fixed | scientific,
|
fortran = int(detail::basic_fortran_fmt) | fixed | scientific,
|
||||||
general = fixed | scientific
|
general = fixed | scientific,
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename UC> struct from_chars_result_t {
|
template <typename UC> struct from_chars_result_t {
|
||||||
@ -797,6 +801,44 @@ fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) {
|
|||||||
return int_luts<>::min_safe_u64[base - 2];
|
return int_luts<>::min_safe_u64[base - 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr chars_format operator~(chars_format rhs) noexcept {
|
||||||
|
using int_type = std::underlying_type<chars_format>::type;
|
||||||
|
return static_cast<chars_format>(~static_cast<int_type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr chars_format operator&(chars_format lhs, chars_format rhs) noexcept {
|
||||||
|
using int_type = std::underlying_type<chars_format>::type;
|
||||||
|
return static_cast<chars_format>(static_cast<int_type>(lhs) &
|
||||||
|
static_cast<int_type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr chars_format operator|(chars_format lhs, chars_format rhs) noexcept {
|
||||||
|
using int_type = std::underlying_type<chars_format>::type;
|
||||||
|
return static_cast<chars_format>(static_cast<int_type>(lhs) |
|
||||||
|
static_cast<int_type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr chars_format operator^(chars_format lhs, chars_format rhs) noexcept {
|
||||||
|
using int_type = std::underlying_type<chars_format>::type;
|
||||||
|
return static_cast<chars_format>(static_cast<int_type>(lhs) ^
|
||||||
|
static_cast<int_type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format &
|
||||||
|
operator&=(chars_format &lhs, chars_format rhs) noexcept {
|
||||||
|
return lhs = (lhs & rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format &
|
||||||
|
operator|=(chars_format &lhs, chars_format rhs) noexcept {
|
||||||
|
return lhs = (lhs | rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format &
|
||||||
|
operator^=(chars_format &lhs, chars_format rhs) noexcept {
|
||||||
|
return lhs = (lhs ^ rhs);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace fast_float
|
} // namespace fast_float
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -292,6 +292,8 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
|
|||||||
static_assert(is_supported_char_type<UC>(),
|
static_assert(is_supported_char_type<UC>(),
|
||||||
"only char, wchar_t, char16_t and char32_t are supported");
|
"only char, wchar_t, char16_t and char32_t are supported");
|
||||||
|
|
||||||
|
chars_format const fmt = options.format;
|
||||||
|
|
||||||
from_chars_result_t<UC> answer;
|
from_chars_result_t<UC> answer;
|
||||||
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||||
while ((first != last) && fast_float::is_space(uint8_t(*first))) {
|
while ((first != last) && fast_float::is_space(uint8_t(*first))) {
|
||||||
@ -306,7 +308,7 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
|
|||||||
parsed_number_string_t<UC> pns =
|
parsed_number_string_t<UC> pns =
|
||||||
parse_number_string<UC>(first, last, options);
|
parse_number_string<UC>(first, last, options);
|
||||||
if (!pns.valid) {
|
if (!pns.valid) {
|
||||||
if (options.format & chars_format::no_infnan) {
|
if (int(fmt & chars_format::no_infnan)) {
|
||||||
answer.ec = std::errc::invalid_argument;
|
answer.ec = std::errc::invalid_argument;
|
||||||
answer.ptr = first;
|
answer.ptr = first;
|
||||||
return answer;
|
return answer;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user