From 6ef555e6fb79363fae057a9a46b52cd208d9e305 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 8 Jan 2024 14:52:00 -0500 Subject: [PATCH] This PR updates the backup string_view implementation. It also adds a few comments to our README.md file. (#2105) * This PR updates the backup string_view implementation. It also adds a few comments to our README.md file. * removing trailing space --- README.md | 5 +- doc/basics.md | 2 +- include/simdjson/nonstd/string_view.hpp | 39 +++-- singleheader/simdjson.cpp | 167 +++++++++++----------- singleheader/simdjson.h | 181 ++++++++++++------------ 5 files changed, 208 insertions(+), 186 deletions(-) diff --git a/README.md b/README.md index 2dba43502..96073ada0 100644 --- a/README.md +++ b/README.md @@ -68,9 +68,9 @@ The simdjson library is easily consumable with a single .h and .cpp file. 0. Prerequisites: `g++` (version 7 or better) or `clang++` (version 6 or better), and a 64-bit system with a command-line shell (e.g., Linux, macOS, freeBSD). We also support programming - environments like Visual Studio and Xcode, but different steps are needed. + environments like Visual Studio and Xcode, but different steps are needed. Users of clang++ may need to specify the C++ version (e.g., `c++ -std=c++17`) since clang++ tends to default on C++98. 1. Pull [simdjson.h](singleheader/simdjson.h) and [simdjson.cpp](singleheader/simdjson.cpp) into a - directory, along with the sample file [twitter.json](jsonexamples/twitter.json). + directory, along with the sample file [twitter.json](jsonexamples/twitter.json). You can download them with the `wget` utility: ``` wget https://raw.githubusercontent.com/simdjson/simdjson/master/singleheader/simdjson.h https://raw.githubusercontent.com/simdjson/simdjson/master/singleheader/simdjson.cpp https://raw.githubusercontent.com/simdjson/simdjson/master/jsonexamples/twitter.json @@ -95,6 +95,7 @@ int main(void) { 100 results. ``` + Documentation ------------- diff --git a/doc/basics.md b/doc/basics.md index 404febfae..c3a52fa94 100644 --- a/doc/basics.md +++ b/doc/basics.md @@ -2133,4 +2133,4 @@ Further reading -------- -- John Keiser, Daniel Lemire, [On-Demand JSON: A Better Way to Parse Documents?](http://arxiv.org/abs/2312.17149), Software: Practice and Experience (to appear) +- John Keiser, Daniel Lemire, [On-Demand JSON: A Better Way to Parse Documents?](http://arxiv.org/abs/2312.17149), Software: Practice and Experience (to appear) diff --git a/include/simdjson/nonstd/string_view.hpp b/include/simdjson/nonstd/string_view.hpp index 3b4526fe2..e6cea1769 100644 --- a/include/simdjson/nonstd/string_view.hpp +++ b/include/simdjson/nonstd/string_view.hpp @@ -6,7 +6,7 @@ // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#pragma once +// #pragma once // We remove #pragma once here as it generates a warning in some cases. We rely on the include guard. #ifndef NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED @@ -69,6 +69,10 @@ # define nssv_CONFIG_NO_STREAM_INSERTION 0 #endif +#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH +# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1 +#endif + // Control presence of exception handling (try and auto discover): #ifndef nssv_CONFIG_NO_EXCEPTIONS @@ -267,7 +271,7 @@ using std::operator<<; # define nssv_HAS_CPP0X 0 #endif -// Unless defined otherwise below, consider VC14 as C++11 for variant-lite: +// Unless defined otherwise below, consider VC14 as C++11 for string-view-lite: #if nssv_COMPILER_MSVC_VER >= 1900 # undef nssv_CPP11_OR_GREATER @@ -434,9 +438,9 @@ using std::operator<<; # pragma clang diagnostic ignored "-Wreserved-user-defined-literal" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wuser-defined-literals" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wliteral-suffix" +#elif nssv_COMPILER_GNUC_VERSION >= 480 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wliteral-suffix" #endif // __clang__ #if nssv_COMPILER_MSVC_VERSION >= 140 @@ -451,8 +455,8 @@ using std::operator<<; #if defined(__clang__) # define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") -#elif defined(__GNUC__) -# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") +#elif nssv_COMPILER_GNUC_VERSION >= 480 +# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") #elif nssv_COMPILER_MSVC_VERSION >= 140 # define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) #else @@ -567,12 +571,31 @@ constexpr const CharT* search( basic_string_view haystack, basic_ // non-recursive: +#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH + template< class CharT, class Traits = std::char_traits > constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) { return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); } +#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH + +template< class CharT, class Traits = std::char_traits > +nssv_constexpr14 const CharT* search( basic_string_view haystack, basic_string_view needle ) +{ + while ( needle.size() <= haystack.size() ) + { + if ( haystack.starts_with(needle) ) + { + return haystack.cbegin(); + } + haystack = basic_string_view{ haystack.begin() + 1, haystack.size() - 1U }; + } + return haystack.cend(); +} +#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH + #endif // OPTIMIZE #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER @@ -845,7 +868,7 @@ public: // find(), 4x: - nssv_constexpr size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) + nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) { return assert( v.size() == 0 || v.data() != nssv_nullptr ) , pos >= size() diff --git a/singleheader/simdjson.cpp b/singleheader/simdjson.cpp index 4dd913b70..bafa74af8 100644 --- a/singleheader/simdjson.cpp +++ b/singleheader/simdjson.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2023-12-07 12:42:28 -0500. Do not edit! */ +/* auto-generated on . Do not edit! */ /* including simdjson.cpp: */ /* begin file simdjson.cpp */ #define SIMDJSON_SRC_SIMDJSON_CPP @@ -525,7 +525,7 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#pragma once +// #pragma once // We remove #pragma once here as it generates a warning in some cases. We rely on the include guard. #ifndef NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED @@ -588,6 +588,10 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS # define nssv_CONFIG_NO_STREAM_INSERTION 0 #endif +#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH +# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1 +#endif + // Control presence of exception handling (try and auto discover): #ifndef nssv_CONFIG_NO_EXCEPTIONS @@ -786,7 +790,7 @@ using std::operator<<; # define nssv_HAS_CPP0X 0 #endif -// Unless defined otherwise below, consider VC14 as C++11 for variant-lite: +// Unless defined otherwise below, consider VC14 as C++11 for string-view-lite: #if nssv_COMPILER_MSVC_VER >= 1900 # undef nssv_CPP11_OR_GREATER @@ -953,9 +957,9 @@ using std::operator<<; # pragma clang diagnostic ignored "-Wreserved-user-defined-literal" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wuser-defined-literals" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wliteral-suffix" +#elif nssv_COMPILER_GNUC_VERSION >= 480 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wliteral-suffix" #endif // __clang__ #if nssv_COMPILER_MSVC_VERSION >= 140 @@ -970,8 +974,8 @@ using std::operator<<; #if defined(__clang__) # define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") -#elif defined(__GNUC__) -# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") +#elif nssv_COMPILER_GNUC_VERSION >= 480 +# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") #elif nssv_COMPILER_MSVC_VERSION >= 140 # define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) #else @@ -1086,12 +1090,31 @@ constexpr const CharT* search( basic_string_view haystack, basic_ // non-recursive: +#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH + template< class CharT, class Traits = std::char_traits > constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) { return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); } +#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH + +template< class CharT, class Traits = std::char_traits > +nssv_constexpr14 const CharT* search( basic_string_view haystack, basic_string_view needle ) +{ + while ( needle.size() <= haystack.size() ) + { + if ( haystack.starts_with(needle) ) + { + return haystack.cbegin(); + } + haystack = basic_string_view{ haystack.begin() + 1, haystack.size() - 1U }; + } + return haystack.cend(); +} +#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH + #endif // OPTIMIZE #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER @@ -1364,7 +1387,7 @@ public: // find(), 4x: - nssv_constexpr size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) + nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) { return assert( v.size() == 0 || v.data() != nssv_nullptr ) , pos >= size() @@ -9025,11 +9048,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -9053,13 +9073,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -14823,11 +14843,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -14851,13 +14868,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -19226,11 +19243,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -19254,13 +19268,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -25390,11 +25404,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -25418,13 +25429,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -31710,11 +31721,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -31738,13 +31746,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -38396,11 +38404,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -38424,13 +38429,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other diff --git a/singleheader/simdjson.h b/singleheader/simdjson.h index bfe8640f2..8f8141275 100644 --- a/singleheader/simdjson.h +++ b/singleheader/simdjson.h @@ -1,4 +1,4 @@ -/* auto-generated on 2023-12-07 12:42:28 -0500. Do not edit! */ +/* auto-generated on . Do not edit! */ /* including simdjson.h: */ /* begin file simdjson.h */ #ifndef SIMDJSON_H @@ -545,7 +545,7 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#pragma once +// #pragma once // We remove #pragma once here as it generates a warning in some cases. We rely on the include guard. #ifndef NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED @@ -608,6 +608,10 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS # define nssv_CONFIG_NO_STREAM_INSERTION 0 #endif +#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH +# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1 +#endif + // Control presence of exception handling (try and auto discover): #ifndef nssv_CONFIG_NO_EXCEPTIONS @@ -806,7 +810,7 @@ using std::operator<<; # define nssv_HAS_CPP0X 0 #endif -// Unless defined otherwise below, consider VC14 as C++11 for variant-lite: +// Unless defined otherwise below, consider VC14 as C++11 for string-view-lite: #if nssv_COMPILER_MSVC_VER >= 1900 # undef nssv_CPP11_OR_GREATER @@ -973,9 +977,9 @@ using std::operator<<; # pragma clang diagnostic ignored "-Wreserved-user-defined-literal" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wuser-defined-literals" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wliteral-suffix" +#elif nssv_COMPILER_GNUC_VERSION >= 480 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wliteral-suffix" #endif // __clang__ #if nssv_COMPILER_MSVC_VERSION >= 140 @@ -990,8 +994,8 @@ using std::operator<<; #if defined(__clang__) # define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") -#elif defined(__GNUC__) -# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") +#elif nssv_COMPILER_GNUC_VERSION >= 480 +# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") #elif nssv_COMPILER_MSVC_VERSION >= 140 # define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) #else @@ -1106,12 +1110,31 @@ constexpr const CharT* search( basic_string_view haystack, basic_ // non-recursive: +#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH + template< class CharT, class Traits = std::char_traits > constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) { return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); } +#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH + +template< class CharT, class Traits = std::char_traits > +nssv_constexpr14 const CharT* search( basic_string_view haystack, basic_string_view needle ) +{ + while ( needle.size() <= haystack.size() ) + { + if ( haystack.starts_with(needle) ) + { + return haystack.cbegin(); + } + haystack = basic_string_view{ haystack.begin() + 1, haystack.size() - 1U }; + } + return haystack.cend(); +} +#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH + #endif // OPTIMIZE #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER @@ -1384,7 +1407,7 @@ public: // find(), 4x: - nssv_constexpr size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) + nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) { return assert( v.size() == 0 || v.data() != nssv_nullptr ) , pos >= size() @@ -5484,7 +5507,7 @@ public: static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " "The supported types are Boolean (bool), numbers (double, uint64_t, int64_t), " "strings (std::string_view, const char *), arrays (dom::array) and objects (dom::object). " - "We recommand you use get_double(), get_bool(), get_uint64(), get_int64(), " + "We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " "get_object(), get_array() or get_string() instead of the get template."); } @@ -12109,11 +12132,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -12137,13 +12157,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -14161,11 +14181,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -14189,13 +14206,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -16705,11 +16722,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -16733,13 +16747,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -19248,11 +19262,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -19276,13 +19287,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -21906,11 +21917,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -21934,13 +21942,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -24887,11 +24895,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d } // unnamed namespace /** @private */ -template -error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { - double d; - if (parse_float_fallback(src, &d)) { - writer.append_double(d); +static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) { + if (parse_float_fallback(src, answer)) { return SUCCESS; } return INVALID_NUMBER(src); @@ -24915,13 +24920,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative, // 10000000000000000000000000000000000000000000e+308 // 3.1415926535897932384626433832795028841971693993751 // - // NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens - // because slow_float_parsing is a non-inlined function. If we passed our writer reference to - // it, it would force it to be stored in memory, preventing the compiler from picking it apart - // and putting into registers. i.e. if we pass it as reference, it gets slow. - // This is what forces the skip_double, as well. - error_code error = slow_float_parsing(src, writer); - writer.skip_double(); + // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer + // reference to it, it would force it to be stored in memory, preventing the compiler from + // picking it apart and putting into registers. i.e. if we pass it as reference, + // it gets slow. + double d; + error_code error = slow_float_parsing(src, &d); + writer.append_double(d); return error; } // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other @@ -28613,8 +28618,6 @@ protected: */ friend class value_iterator; template - friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer); - template friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); template friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); @@ -38534,8 +38537,6 @@ protected: */ friend class value_iterator; template - friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer); - template friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); template friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); @@ -48947,8 +48948,6 @@ protected: */ friend class value_iterator; template - friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer); - template friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); template friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); @@ -59359,8 +59358,6 @@ protected: */ friend class value_iterator; template - friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer); - template friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); template friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); @@ -69886,8 +69883,6 @@ protected: */ friend class value_iterator; template - friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer); - template friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); template friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); @@ -80736,8 +80731,6 @@ protected: */ friend class value_iterator; template - friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer); - template friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); template friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);