aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2023-11-29 12:25:23 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2023-11-29 13:15:56 +0300
commit44fcb486ca4cace93b2718807c54405216a24c4b (patch)
tree701673a79d901fd1701c6f3e1585aaf96de99ad1
parent828320171bedc3cc8521e9045bf85e9ee083e00a (diff)
downloadydb-44fcb486ca4cace93b2718807c54405216a24c4b.tar.gz
Update contrib/restricted/fast_float to 5.3.0
-rw-r--r--contrib/restricted/fast_float/README.md119
-rw-r--r--contrib/restricted/fast_float/include/fast_float/ascii_number.h58
-rw-r--r--contrib/restricted/fast_float/include/fast_float/float_common.h29
-rw-r--r--contrib/restricted/fast_float/include/fast_float/parse_number.h8
-rw-r--r--contrib/restricted/fast_float/ya.make4
5 files changed, 167 insertions, 51 deletions
diff --git a/contrib/restricted/fast_float/README.md b/contrib/restricted/fast_float/README.md
index f12dea551e..d2ad1d874b 100644
--- a/contrib/restricted/fast_float/README.md
+++ b/contrib/restricted/fast_float/README.md
@@ -55,6 +55,34 @@ int main() {
}
```
+You can parse delimited numbers:
+```C++
+ const std::string input = "234532.3426362,7869234.9823,324562.645";
+ double result;
+ auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
+ if(answer.ec != std::errc()) {
+ // check error
+ }
+ // we have result == 234532.3426362.
+ if(answer.ptr[0] != ',') {
+ // unexpected delimiter
+ }
+ answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
+ if(answer.ec != std::errc()) {
+ // check error
+ }
+ // we have result == 7869234.9823.
+ if(answer.ptr[0] != ',') {
+ // unexpected delimiter
+ }
+ answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
+ if(answer.ec != std::errc()) {
+ // check error
+ }
+ // we have result == 324562.645.
+```
+
+
Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of
the type `fast_float::chars_format`. It is a bitset value: we check whether
@@ -115,7 +143,7 @@ int main() {
}
```
-## Using commas as decimal separator
+## Advanced options: using commas as decimal separator, JSON and Fortran
The C++ standard stipulate that `from_chars` has to be locale-independent. In
@@ -140,33 +168,72 @@ int main() {
}
```
-You can parse delimited numbers:
+You can also parse Fortran-like inputs:
+
```C++
- const std::string input = "234532.3426362,7869234.9823,324562.645";
- double result;
- auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
- if(answer.ec != std::errc()) {
- // check error
- }
- // we have result == 234532.3426362.
- if(answer.ptr[0] != ',') {
- // unexpected delimiter
- }
- answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
- if(answer.ec != std::errc()) {
- // check error
- }
- // we have result == 7869234.9823.
- if(answer.ptr[0] != ',') {
- // unexpected delimiter
- }
- answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
- if(answer.ec != std::errc()) {
- // check error
- }
- // we have result == 324562.645.
+#include "fast_float/fast_float.h"
+#include <iostream>
+
+int main() {
+ const std::string input = "1d+4";
+ double result;
+ fast_float::parse_options options{ fast_float::chars_format::fortran };
+ auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
+ if((answer.ec != std::errc()) || ((result != 10000))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
+ std::cout << "parsed the number " << result << std::endl;
+ return EXIT_SUCCESS;
+}
```
+You may also enforce the JSON format ([RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259#section-6)):
+
+
+```C++
+#include "fast_float/fast_float.h"
+#include <iostream>
+
+int main() {
+ const std::string input = "+.1"; // not valid
+ double result;
+ fast_float::parse_options options{ fast_float::chars_format::json };
+ auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
+ if(answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; }
+ return EXIT_SUCCESS;
+}
+```
+
+By default the JSON format does not allow `inf`:
+
+```C++
+
+#include "fast_float/fast_float.h"
+#include <iostream>
+
+int main() {
+ const std::string input = "inf"; // not valid in JSON
+ double result;
+ fast_float::parse_options options{ fast_float::chars_format::json };
+ auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
+ if(answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; }
+}
+```
+
+
+You can allow it with a non-standard `json_or_infnan` variant:
+
+```C++
+#include "fast_float/fast_float.h"
+#include <iostream>
+
+int main() {
+ const std::string input = "inf"; // not valid in JSON but we allow it with json_or_infnan
+ double result;
+ fast_float::parse_options options{ fast_float::chars_format::json_or_infnan };
+ auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
+ if(answer.ec != std::errc() || (!std::isinf(result))) { std::cerr << "should have parsed infinity\n"; return EXIT_FAILURE; }
+ return EXIT_SUCCESS;
+}
+``````
## Relation With Other Work
@@ -264,7 +331,7 @@ the command line help.
You may directly download automatically generated single-header files:
-https://github.com/fastfloat/fast_float/releases/download/v5.2.0/fast_float.h
+https://github.com/fastfloat/fast_float/releases/download/v5.3.0/fast_float.h
## Credit
diff --git a/contrib/restricted/fast_float/include/fast_float/ascii_number.h b/contrib/restricted/fast_float/include/fast_float/ascii_number.h
index eea2f672a6..d18e3d5360 100644
--- a/contrib/restricted/fast_float/include/fast_float/ascii_number.h
+++ b/contrib/restricted/fast_float/include/fast_float/ascii_number.h
@@ -111,9 +111,13 @@ FASTFLOAT_SIMD_RESTORE_WARNINGS
#endif // FASTFLOAT_SSE2
-// dummy for compile
-//template <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>())>
+// MSVC SFINAE is broken pre-VS2017
+#if defined(_MSC_VER) && _MSC_VER <= 1900
template <typename UC>
+#else
+template <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>())>
+#endif
+// dummy for compile
uint64_t simd_read8_to_u64(UC const*) {
return 0;
}
@@ -215,8 +219,13 @@ FASTFLOAT_SIMD_RESTORE_WARNINGS
#endif // FASTFLOAT_HAS_SIMD
-// dummy for compile
+// MSVC SFINAE is broken pre-VS2017
+#if defined(_MSC_VER) && _MSC_VER <= 1900
+template <typename UC>
+#else
template <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>())>
+#endif
+// dummy for compile
bool simd_parse_if_eight_digits_unrolled(UC const*, uint64_t&) {
return 0;
}
@@ -271,7 +280,7 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
answer.too_many_digits = false;
answer.negative = (*p == UC('-'));
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
- if ((*p == UC('-')) || (*p == UC('+'))) {
+ if ((*p == UC('-')) || (!(fmt & FASTFLOAT_JSONFMT) && *p == UC('+'))) {
#else
if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
#endif
@@ -279,8 +288,14 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
if (p == pend) {
return answer;
}
- if (!is_integer(*p) && (*p != decimal_point)) { // a sign must be followed by an integer or the dot
- return answer;
+ if (fmt & FASTFLOAT_JSONFMT) {
+ if (!is_integer(*p)) { // a sign must be followed by an integer
+ return answer;
+ }
+ } else {
+ if (!is_integer(*p) && (*p != decimal_point)) { // a sign must be followed by an integer or the dot
+ return answer;
+ }
}
}
UC const * const start_digits = p;
@@ -297,8 +312,16 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
UC const * const end_of_integer_part = p;
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
answer.integer = span<const UC>(start_digits, size_t(digit_count));
+ if (fmt & FASTFLOAT_JSONFMT) {
+ // at least 1 digit in integer part, without leading zeros
+ if (digit_count == 0 || (start_digits[0] == UC('0') && digit_count > 1)) {
+ return answer;
+ }
+ }
+
int64_t exponent = 0;
- if ((p != pend) && (*p == decimal_point)) {
+ const bool has_decimal_point = (p != pend) && (*p == decimal_point);
+ if (has_decimal_point) {
++p;
UC const * before = p;
// can occur at most twice without overflowing, but let it occur more, since
@@ -314,14 +337,27 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
answer.fraction = span<const UC>(before, size_t(p - before));
digit_count -= exponent;
}
- // we must have encountered at least one integer!
- if (digit_count == 0) {
+ if (fmt & FASTFLOAT_JSONFMT) {
+ // at least 1 digit in fractional part
+ if (has_decimal_point && exponent == 0) {
+ return answer;
+ }
+ }
+ else if (digit_count == 0) { // we must have encountered at least one integer!
return answer;
}
int64_t exp_number = 0; // explicit exponential part
- if ((fmt & chars_format::scientific) && (p != pend) && ((UC('e') == *p) || (UC('E') == *p))) {
+ if ( ((fmt & chars_format::scientific) &&
+ (p != pend) &&
+ ((UC('e') == *p) || (UC('E') == *p)))
+ ||
+ ((fmt & FASTFLOAT_FORTRANFMT) &&
+ (p != pend) &&
+ ((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) || (UC('D') == *p)))) {
UC const * location_of_e = p;
- ++p;
+ if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) || (UC('D') == *p)) {
+ ++p;
+ }
bool neg_exp = false;
if ((p != pend) && (UC('-') == *p)) {
neg_exp = true;
diff --git a/contrib/restricted/fast_float/include/fast_float/float_common.h b/contrib/restricted/fast_float/include/fast_float/float_common.h
index 1998b1094c..bee8821520 100644
--- a/contrib/restricted/fast_float/include/fast_float/float_common.h
+++ b/contrib/restricted/fast_float/include/fast_float/float_common.h
@@ -12,10 +12,19 @@
namespace fast_float {
+#define FASTFLOAT_JSONFMT (1 << 5)
+#define FASTFLOAT_FORTRANFMT (1 << 6)
+
enum chars_format {
scientific = 1 << 0,
fixed = 1 << 2,
hex = 1 << 3,
+ no_infnan = 1 << 4,
+ // RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6
+ json = FASTFLOAT_JSONFMT | fixed | scientific | no_infnan,
+ // Extension of RFC 8259 where, e.g., "inf" and "nan" are allowed.
+ json_or_infnan = FASTFLOAT_JSONFMT | fixed | scientific,
+ fortran = FASTFLOAT_FORTRANFMT | fixed | scientific,
general = fixed | scientific
};
@@ -217,18 +226,16 @@ struct value128 {
constexpr value128() : low(0), high(0) {}
};
-/* Helper C++11 constexpr generic implementation of leading_zeroes */
-fastfloat_really_inline constexpr
+/* Helper C++14 constexpr generic implementation of leading_zeroes */
+fastfloat_really_inline FASTFLOAT_CONSTEXPR14
int leading_zeroes_generic(uint64_t input_num, int last_bit = 0) {
- return (
- ((input_num & uint64_t(0xffffffff00000000)) && (input_num >>= 32, last_bit |= 32)),
- ((input_num & uint64_t( 0xffff0000)) && (input_num >>= 16, last_bit |= 16)),
- ((input_num & uint64_t( 0xff00)) && (input_num >>= 8, last_bit |= 8)),
- ((input_num & uint64_t( 0xf0)) && (input_num >>= 4, last_bit |= 4)),
- ((input_num & uint64_t( 0xc)) && (input_num >>= 2, last_bit |= 2)),
- ((input_num & uint64_t( 0x2)) && (input_num >>= 1, last_bit |= 1)),
- 63 - last_bit
- );
+ if(input_num & uint64_t(0xffffffff00000000)) { input_num >>= 32; last_bit |= 32; }
+ if(input_num & uint64_t( 0xffff0000)) { input_num >>= 16; last_bit |= 16; }
+ if(input_num & uint64_t( 0xff00)) { input_num >>= 8; last_bit |= 8; }
+ if(input_num & uint64_t( 0xf0)) { input_num >>= 4; last_bit |= 4; }
+ if(input_num & uint64_t( 0xc)) { input_num >>= 2; last_bit |= 2; }
+ if(input_num & uint64_t( 0x2)) { input_num >>= 1; last_bit |= 1; }
+ return 63 - last_bit;
}
/* result might be undefined when input_num is zero */
diff --git a/contrib/restricted/fast_float/include/fast_float/parse_number.h b/contrib/restricted/fast_float/include/fast_float/parse_number.h
index e077b9d03d..a011a8cbf4 100644
--- a/contrib/restricted/fast_float/include/fast_float/parse_number.h
+++ b/contrib/restricted/fast_float/include/fast_float/parse_number.h
@@ -164,7 +164,13 @@ from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
}
parsed_number_string_t<UC> pns = parse_number_string<UC>(first, last, options);
if (!pns.valid) {
- return detail::parse_infnan(first, last, value);
+ if (options.format & chars_format::no_infnan) {
+ answer.ec = std::errc::invalid_argument;
+ answer.ptr = first;
+ return answer;
+ } else {
+ return detail::parse_infnan(first, last, value);
+ }
}
answer.ec = std::errc(); // be optimistic
diff --git a/contrib/restricted/fast_float/ya.make b/contrib/restricted/fast_float/ya.make
index 154485e259..dba751fb8a 100644
--- a/contrib/restricted/fast_float/ya.make
+++ b/contrib/restricted/fast_float/ya.make
@@ -10,9 +10,9 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(5.2.0)
+VERSION(5.3.0)
-ORIGINAL_SOURCE(https://github.com/fastfloat/fast_float/archive/v5.2.0.tar.gz)
+ORIGINAL_SOURCE(https://github.com/fastfloat/fast_float/archive/v5.3.0.tar.gz)
NO_COMPILER_WARNINGS()