Skip to content

Commit 724834f

Browse files
authored
Merge pull request #279 from dalle/issue278-scoped-enum
enum class chars_format
2 parents 42fded1 + b3526da commit 724834f

File tree

3 files changed

+62
-16
lines changed

3 files changed

+62
-16
lines changed

include/fast_float/ascii_number.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,8 @@ parse_number_string(UC const *p, UC const *pend,
291291
answer.too_many_digits = false;
292292
answer.negative = (*p == UC('-'));
293293
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
294-
if ((*p == UC('-')) || (!(fmt & FASTFLOAT_JSONFMT) && *p == UC('+'))) {
294+
if ((*p == UC('-')) ||
295+
(!uint64_t(fmt & detail::basic_json_fmt) && *p == UC('+'))) {
295296
#else
296297
if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
297298
#endif
@@ -300,7 +301,7 @@ parse_number_string(UC const *p, UC const *pend,
300301
return report_parse_error<UC>(
301302
p, parse_error::missing_integer_or_dot_after_sign);
302303
}
303-
if (fmt & FASTFLOAT_JSONFMT) {
304+
if (uint64_t(fmt & detail::basic_json_fmt)) {
304305
if (!is_integer(*p)) { // a sign must be followed by an integer
305306
return report_parse_error<UC>(p,
306307
parse_error::missing_integer_after_sign);
@@ -329,7 +330,7 @@ parse_number_string(UC const *p, UC const *pend,
329330
UC const *const end_of_integer_part = p;
330331
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
331332
answer.integer = span<const UC>(start_digits, size_t(digit_count));
332-
if (fmt & FASTFLOAT_JSONFMT) {
333+
if (uint64_t(fmt & detail::basic_json_fmt)) {
333334
// at least 1 digit in integer part, without leading zeros
334335
if (digit_count == 0) {
335336
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,
358359
answer.fraction = span<const UC>(before, size_t(p - before));
359360
digit_count -= exponent;
360361
}
361-
if (fmt & FASTFLOAT_JSONFMT) {
362+
if (uint64_t(fmt & detail::basic_json_fmt)) {
362363
// at least 1 digit in fractional part
363364
if (has_decimal_point && exponent == 0) {
364365
return report_parse_error<UC>(p,
@@ -369,9 +370,9 @@ parse_number_string(UC const *p, UC const *pend,
369370
return report_parse_error<UC>(p, parse_error::no_digits_in_mantissa);
370371
}
371372
int64_t exp_number = 0; // explicit exponential part
372-
if (((fmt & chars_format::scientific) && (p != pend) &&
373+
if ((uint64_t(fmt & chars_format::scientific) && (p != pend) &&
373374
((UC('e') == *p) || (UC('E') == *p))) ||
374-
((fmt & FASTFLOAT_FORTRANFMT) && (p != pend) &&
375+
(uint64_t(fmt & detail::basic_fortran_fmt) && (p != pend) &&
375376
((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) ||
376377
(UC('D') == *p)))) {
377378
UC const *location_of_e = p;
@@ -389,7 +390,7 @@ parse_number_string(UC const *p, UC const *pend,
389390
++p;
390391
}
391392
if ((p == pend) || !is_integer(*p)) {
392-
if (!(fmt & chars_format::fixed)) {
393+
if (!uint64_t(fmt & chars_format::fixed)) {
393394
// The exponential part is invalid for scientific notation, so it must
394395
// be a trailing token for fixed notation. However, fixed notation is
395396
// disabled, so report a scientific notation error.
@@ -412,7 +413,8 @@ parse_number_string(UC const *p, UC const *pend,
412413
}
413414
} else {
414415
// If it scientific and not fixed, we have to bail out.
415-
if ((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) {
416+
if (uint64_t(fmt & chars_format::scientific) &&
417+
!uint64_t(fmt & chars_format::fixed)) {
416418
return report_parse_error<UC>(p, parse_error::missing_exponential_part);
417419
}
418420
}

include/fast_float/float_common.h

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,24 @@
1616

1717
namespace fast_float {
1818

19-
#define FASTFLOAT_JSONFMT (1 << 5)
20-
#define FASTFLOAT_FORTRANFMT (1 << 6)
19+
enum class chars_format : uint64_t;
2120

22-
enum chars_format {
21+
namespace detail {
22+
constexpr chars_format basic_json_fmt = chars_format(1 << 5);
23+
constexpr chars_format basic_fortran_fmt = chars_format(1 << 6);
24+
} // namespace detail
25+
26+
enum class chars_format : uint64_t {
2327
scientific = 1 << 0,
2428
fixed = 1 << 2,
2529
hex = 1 << 3,
2630
no_infnan = 1 << 4,
2731
// RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6
28-
json = FASTFLOAT_JSONFMT | fixed | scientific | no_infnan,
32+
json = uint64_t(detail::basic_json_fmt) | fixed | scientific | no_infnan,
2933
// Extension of RFC 8259 where, e.g., "inf" and "nan" are allowed.
30-
json_or_infnan = FASTFLOAT_JSONFMT | fixed | scientific,
31-
fortran = FASTFLOAT_FORTRANFMT | fixed | scientific,
32-
general = fixed | scientific
34+
json_or_infnan = uint64_t(detail::basic_json_fmt) | fixed | scientific,
35+
fortran = uint64_t(detail::basic_fortran_fmt) | fixed | scientific,
36+
general = fixed | scientific,
3337
};
3438

3539
template <typename UC> struct from_chars_result_t {
@@ -797,6 +801,44 @@ fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) {
797801
return int_luts<>::min_safe_u64[base - 2];
798802
}
799803

804+
constexpr chars_format operator~(chars_format rhs) noexcept {
805+
using int_type = std::underlying_type<chars_format>::type;
806+
return static_cast<chars_format>(~static_cast<int_type>(rhs));
807+
}
808+
809+
constexpr chars_format operator&(chars_format lhs, chars_format rhs) noexcept {
810+
using int_type = std::underlying_type<chars_format>::type;
811+
return static_cast<chars_format>(static_cast<int_type>(lhs) &
812+
static_cast<int_type>(rhs));
813+
}
814+
815+
constexpr chars_format operator|(chars_format lhs, chars_format rhs) noexcept {
816+
using int_type = std::underlying_type<chars_format>::type;
817+
return static_cast<chars_format>(static_cast<int_type>(lhs) |
818+
static_cast<int_type>(rhs));
819+
}
820+
821+
constexpr chars_format operator^(chars_format lhs, chars_format rhs) noexcept {
822+
using int_type = std::underlying_type<chars_format>::type;
823+
return static_cast<chars_format>(static_cast<int_type>(lhs) ^
824+
static_cast<int_type>(rhs));
825+
}
826+
827+
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format &
828+
operator&=(chars_format &lhs, chars_format rhs) noexcept {
829+
return lhs = (lhs & rhs);
830+
}
831+
832+
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format &
833+
operator|=(chars_format &lhs, chars_format rhs) noexcept {
834+
return lhs = (lhs | rhs);
835+
}
836+
837+
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format &
838+
operator^=(chars_format &lhs, chars_format rhs) noexcept {
839+
return lhs = (lhs ^ rhs);
840+
}
841+
800842
} // namespace fast_float
801843

802844
#endif

include/fast_float/parse_number.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
292292
static_assert(is_supported_char_type<UC>(),
293293
"only char, wchar_t, char16_t and char32_t are supported");
294294

295+
chars_format const fmt = options.format;
296+
295297
from_chars_result_t<UC> answer;
296298
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
297299
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,
306308
parsed_number_string_t<UC> pns =
307309
parse_number_string<UC>(first, last, options);
308310
if (!pns.valid) {
309-
if (options.format & chars_format::no_infnan) {
311+
if (uint64_t(fmt & chars_format::no_infnan)) {
310312
answer.ec = std::errc::invalid_argument;
311313
answer.ptr = first;
312314
return answer;

0 commit comments

Comments
 (0)