diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2023-11-29 12:25:23 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2023-11-29 13:15:56 +0300 |
commit | 44fcb486ca4cace93b2718807c54405216a24c4b (patch) | |
tree | 701673a79d901fd1701c6f3e1585aaf96de99ad1 /contrib | |
parent | 828320171bedc3cc8521e9045bf85e9ee083e00a (diff) | |
download | ydb-44fcb486ca4cace93b2718807c54405216a24c4b.tar.gz |
Update contrib/restricted/fast_float to 5.3.0
Diffstat (limited to 'contrib')
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() |