7
7
#include < cstring>
8
8
#include < iterator>
9
9
10
+ #if defined __has_include
11
+ #if __has_include(<version>)
12
+ #include < version>
13
+ #if defined(__cpp_lib_bit_cast)
14
+ #include < bit>
15
+ #endif
16
+ #endif
17
+ #endif
18
+
10
19
#include " float_common.h"
11
20
12
21
namespace fast_float {
13
22
14
23
// Next function can be micro-optimized, but compilers are entirely
15
24
// able to optimize it well.
16
- fastfloat_really_inline bool is_integer (char c) noexcept { return c >= ' 0' && c <= ' 9' ; }
25
+ CXX20_CONSTEXPR fastfloat_really_inline bool is_integer (char c) noexcept { return c >= ' 0' && c <= ' 9' ; }
17
26
18
- fastfloat_really_inline uint64_t byteswap (uint64_t val) {
27
+ CXX20_CONSTEXPR fastfloat_really_inline uint64_t byteswap (uint64_t val) {
19
28
return (val & 0xFF00000000000000 ) >> 56
20
29
| (val & 0x00FF000000000000 ) >> 40
21
30
| (val & 0x0000FF0000000000 ) >> 24
@@ -26,26 +35,40 @@ fastfloat_really_inline uint64_t byteswap(uint64_t val) {
26
35
| (val & 0x00000000000000FF ) << 56 ;
27
36
}
28
37
29
- fastfloat_really_inline uint64_t read_u64 (const char *chars) {
38
+ CXX20_CONSTEXPR fastfloat_really_inline uint64_t read_u64 (const char *chars) {
30
39
uint64_t val;
40
+ #if defined(__cpp_lib_bit_cast)
41
+ val = std::bit_cast<uint64_t >(reinterpret_cast <const char (&)[8 ]>(chars));
42
+ #else
31
43
::memcpy (&val, chars, sizeof (uint64_t ));
44
+ #endif
32
45
#if FASTFLOAT_IS_BIG_ENDIAN == 1
33
46
// Need to read as-if the number was in little-endian order.
34
47
val = byteswap (val);
35
48
#endif
36
49
return val;
37
50
}
38
51
39
- fastfloat_really_inline void write_u64 (uint8_t *chars, uint64_t val) {
52
+ CXX20_CONSTEXPR fastfloat_really_inline void write_u64 (uint8_t *chars, uint64_t val) {
40
53
#if FASTFLOAT_IS_BIG_ENDIAN == 1
41
54
// Need to read as-if the number was in little-endian order.
42
55
val = byteswap (val);
43
56
#endif
57
+ #if defined(__cpp_lib_bit_cast)
58
+ if (std::is_constant_evaluated ()) {
59
+ char (&dst)[8 ] = reinterpret_cast <char (&)[8 ]>(chars);
60
+ const char (&src)[8 ] = reinterpret_cast <const char (&)[8 ]>(val);
61
+ std::copy (std::begin (src), std::end (src), std::begin (dst));
62
+ } else {
63
+ ::memcpy (chars, &val, sizeof (uint64_t ));
64
+ }
65
+ #else
44
66
::memcpy (chars, &val, sizeof (uint64_t ));
67
+ #endif
45
68
}
46
69
47
70
// credit @aqrit
48
- fastfloat_really_inline uint32_t parse_eight_digits_unrolled (uint64_t val) {
71
+ CXX20_CONSTEXPR fastfloat_really_inline uint32_t parse_eight_digits_unrolled (uint64_t val) {
49
72
const uint64_t mask = 0x000000FF000000FF ;
50
73
const uint64_t mul1 = 0x000F424000000064 ; // 100 + (1000000ULL << 32)
51
74
const uint64_t mul2 = 0x0000271000000001 ; // 1 + (10000ULL << 32)
@@ -55,17 +78,17 @@ fastfloat_really_inline uint32_t parse_eight_digits_unrolled(uint64_t val) {
55
78
return uint32_t (val);
56
79
}
57
80
58
- fastfloat_really_inline uint32_t parse_eight_digits_unrolled (const char *chars) noexcept {
81
+ CXX20_CONSTEXPR fastfloat_really_inline uint32_t parse_eight_digits_unrolled (const char *chars) noexcept {
59
82
return parse_eight_digits_unrolled (read_u64 (chars));
60
83
}
61
84
62
85
// credit @aqrit
63
- fastfloat_really_inline bool is_made_of_eight_digits_fast (uint64_t val) noexcept {
86
+ CXX20_CONSTEXPR fastfloat_really_inline bool is_made_of_eight_digits_fast (uint64_t val) noexcept {
64
87
return !((((val + 0x4646464646464646 ) | (val - 0x3030303030303030 )) &
65
88
0x8080808080808080 ));
66
89
}
67
90
68
- fastfloat_really_inline bool is_made_of_eight_digits_fast (const char *chars) noexcept {
91
+ CXX20_CONSTEXPR fastfloat_really_inline bool is_made_of_eight_digits_fast (const char *chars) noexcept {
69
92
return is_made_of_eight_digits_fast (read_u64 (chars));
70
93
}
71
94
@@ -81,7 +104,7 @@ struct parsed_number_string {
81
104
82
105
// Assuming that you use no more than 19 digits, this will
83
106
// parse an ASCII string.
84
- fastfloat_really_inline
107
+ CXX20_CONSTEXPR fastfloat_really_inline
85
108
parsed_number_string parse_number_string (const char *p, const char *pend, parse_options options) noexcept {
86
109
const chars_format fmt = options.format ;
87
110
const char decimal_point = options.decimal_point ;
@@ -221,7 +244,7 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
221
244
// This function could be optimized. In particular, we could stop after 19 digits
222
245
// and try to bail out. Furthermore, we should be able to recover the computed
223
246
// exponent from the pass in parse_number_string.
224
- fastfloat_really_inline decimal parse_decimal (const char *p, const char *pend, parse_options options) noexcept {
247
+ CXX20_CONSTEXPR fastfloat_really_inline decimal parse_decimal (const char *p, const char *pend, parse_options options) noexcept {
225
248
const char decimal_point = options.decimal_point ;
226
249
227
250
decimal answer;
0 commit comments