diff --git a/.gitignore b/.gitignore index 46b58114d..250dd4d66 100644 --- a/.gitignore +++ b/.gitignore @@ -106,7 +106,9 @@ objs /perfdiff /pointercheck /readme_examples +/readme_examples11 /readme_examples_noexceptions +/readme_examples_noexceptions11 /staticchecks /statisticalmodel /stringparsingcheck @@ -124,7 +126,9 @@ objs /tests/integer_tests /tests/parse_many_test /tests/readme_examples +/tests/readme_examples11 /tests/readme_examples_noexceptions +/tests/readme_examples_noexceptions11 /tests/staticchecks /tools/json2json /tools/jsonstats diff --git a/Makefile b/Makefile index 96fcc17b4..06d80a75c 100644 --- a/Makefile +++ b/Makefile @@ -91,7 +91,7 @@ JSON_INCLUDE:=dependencies/json/single_include/nlohmann/json.hpp EXTRAOBJECTS=ujdecode.o MAINEXECUTABLES=parse minify json2json jsonstats statisticalmodel jsonpointer get_corpus_benchmark -TESTEXECUTABLES=jsoncheck jsoncheck_westmere jsoncheck_fallback integer_tests numberparsingcheck stringparsingcheck pointercheck parse_many_test basictests errortests readme_examples readme_examples_noexceptions +TESTEXECUTABLES=jsoncheck jsoncheck_westmere jsoncheck_fallback integer_tests numberparsingcheck stringparsingcheck pointercheck parse_many_test basictests errortests readme_examples readme_examples11 readme_examples_noexceptions readme_examples_noexceptions11 COMPARISONEXECUTABLES=minifiercompetition parsingcompetition parseandstatcompetition distinctuseridcompetition allparserscheckfile allparsingcompetition SUPPLEMENTARYEXECUTABLES=parse_noutf8validation parse_nonumberparsing parse_nostringparsing @@ -141,22 +141,22 @@ run_pointercheck: pointercheck run_issue150_sh: allparserscheckfile ./scripts/issue150.sh -quickstart: singleheader/simdjson.h singleheader/simdjson.cpp +quickstart: amalgamate cd examples/quickstart && make quickstart -run_quickstart: +run_quickstart: amalgamate cd examples/quickstart && make test -quickstart11: +quickstart11: amalgamate cd examples/quickstart && make quickstart11 -run_quickstart11: +run_quickstart11: amalgamate cd examples/quickstart && make test11 -quickstart14: +quickstart14: amalgamate cd examples/quickstart && make quickstart14 -run_quickstart14: +run_quickstart14: amalgamate cd examples/quickstart && make test14 run_testjson2json_sh: minify json2json @@ -173,7 +173,7 @@ test: quicktests slowtests quiettest: quicktests slowtests -quicktests: run_basictests run_quickstart readme_examples readme_examples_noexceptions run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsoncheck run_parse_many_test run_pointercheck run_jsoncheck_westmere run_jsoncheck_fallback run_quickstart14 +quicktests: run_basictests run_quickstart readme_examples readme_examples_noexceptions run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsoncheck run_parse_many_test run_pointercheck run_jsoncheck_westmere run_jsoncheck_fallback run_quickstart14 run_quickstart11 slowtests: run_testjson2json_sh run_issue150_sh @@ -246,9 +246,15 @@ errortests: tests/errortests.cpp $(HEADERS) $(LIBFILES) readme_examples: tests/readme_examples.cpp $(HEADERS) $(LIBFILES) $(CXX) $(CXXFLAGS) -o readme_examples tests/readme_examples.cpp -I. $(LIBFILES) $(LIBFLAGS) +readme_examples11: tests/readme_examples.cpp $(HEADERS) $(LIBFILES) + $(CXX) $(CXXFLAGS) -o readme_examples11 tests/readme_examples.cpp -I. $(LIBFILES) $(LIBFLAGS) -std=c++11 + readme_examples_noexceptions: tests/readme_examples_noexceptions.cpp $(HEADERS) $(LIBFILES) $(CXX) $(CXXFLAGS) -o readme_examples_noexceptions tests/readme_examples_noexceptions.cpp -I. $(LIBFILES) $(LIBFLAGS) -fno-exceptions +readme_examples_noexceptions11: tests/readme_examples_noexceptions.cpp $(HEADERS) $(LIBFILES) + $(CXX) $(CXXFLAGS) -o readme_examples_noexceptions11 tests/readme_examples_noexceptions.cpp -I. $(LIBFILES) $(LIBFLAGS) -fno-exceptions -std=c++11 + staticchecks: tests/staticchecks.cpp $(HEADERS) src/simdjson.cpp $(CXX) $(CXXFLAGS) -o staticchecks tests/staticchecks.cpp -I. $(LIBFLAGS) @@ -258,8 +264,6 @@ numberparsingcheck: tests/numberparsingcheck.cpp $(HEADERS) src/simdjson.cpp integer_tests:tests/integer_tests.cpp $(HEADERS) $(LIBFILES) $(CXX) $(CXXFLAGS) -o integer_tests tests/integer_tests.cpp -I. $(LIBFILES) $(LIBFLAGS) - - stringparsingcheck: tests/stringparsingcheck.cpp $(HEADERS) src/simdjson.cpp $(CXX) $(CXXFLAGS) -o stringparsingcheck tests/stringparsingcheck.cpp -I. $(LIBFLAGS) -DJSON_TEST_STRINGS diff --git a/README.md b/README.md index e7a3de14d..985235487 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ The simdjson library is easily consumable with a single .h and .cpp file. std::cout << tweets["search_metadata"]["count"] << " results." << std::endl; } ``` -3. `c++ -o quickstart quickstart.cpp simdjson.cpp -std=c++17` +3. `c++ -o quickstart quickstart.cpp simdjson.cpp` 4. `./quickstart` ``` 100 results. @@ -184,3 +184,5 @@ License This code is made available under the Apache License 2.0. Under Windows, we build some tools using the windows/dirent_portable.h file (which is outside our library code): it under the liberal (business-friendly) MIT license. + +For compilers that do not support C++17, we bundle the string-view library which is published under the Boost license (http://www.boost.org/LICENSE_1_0.txt). Like the Apache license, the Boost license is a permissive license allowing commercial redistribution. \ No newline at end of file diff --git a/doc/basics.md b/doc/basics.md index dcfc712b3..4e72fc80e 100644 --- a/doc/basics.md +++ b/doc/basics.md @@ -28,7 +28,7 @@ using namespace simdjson; // optional You can compile with: ``` -c++ myproject.cpp simdjson.cpp --std=c++17 +c++ myproject.cpp simdjson.cpp ``` The Basics: Loading and Parsing JSON Documents @@ -98,12 +98,42 @@ for (dom::object car : parser.parse(cars_json)) { cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl; // Writing out all the information about the car - for (auto [key, value] : car) { - cout << "- " << key << ": " << value << endl; + for (auto field : car) { + cout << "- " << field.key << ": " << field.value << endl; } } ``` +C++17 Support +------------- + +While the simdjson library can be used in any project using C++ 11 and above, it has special support +for C++ 17. The APIs for field iteration and error handling in particular are designed to work +nicely with C++17's destructuring syntax. For example: + +```c++ +dom::parser parser; +padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded; +auto [object, error] = parser.parse(json).get(); +for (auto [key, value] : object) { + cout << key << " = " << value << endl; +} +``` + +For comparison, here is the C++ 11 version of the same code: + +```c++ +// C++ 11 version for comparison +dom::parser parser; +padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded; +dom::object object; +simdjson::error_code error; +parser.parse(json).get().tie(object, error); +for (dom::key_value_pair field : object) { + cout << field.key << " = " << field.value << endl; +} +``` + JSON Pointer ------------ @@ -159,7 +189,9 @@ auto cars_json = R"( [ { "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] } ] )"_padded; dom::parser parser; -auto [cars, error] = parser.parse(cars_json).get(); +dom::array cars; +simdjson::error_code error; +parser.parse(cars_json).get().tie(cars, error); if (error) { cerr << error << endl; exit(1); } // Iterating through an array of objects @@ -196,8 +228,8 @@ for (dom::element tire_pressure_element : tire_pressure_array) { cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl; // Writing out all the information about the car -for (auto [key, value] : car) { - cout << "- " << key << ": " << value << endl; +for (auto field : car) { + cout << "- " << field.key << ": " << field.value << endl; } ``` diff --git a/examples/quickstart/Makefile b/examples/quickstart/Makefile index cb1a61d7a..4d3f227e8 100644 --- a/examples/quickstart/Makefile +++ b/examples/quickstart/Makefile @@ -5,9 +5,9 @@ JSONEXAMPLES=$(ROOT)/jsonexamples test: quickstart twitter.json ./quickstart quickstart: quickstart.cpp simdjson.cpp simdjson.h - c++ -o ./quickstart quickstart.cpp simdjson.cpp -std=c++17 + c++ -o ./quickstart quickstart.cpp simdjson.cpp clean: - rm -f simdjson.cpp simdjson.h twitter.json quickstart + rm -f simdjson.cpp simdjson.h twitter.json quickstart quickstart11 quickstart14 simdjson.cpp: $(SINGLEHEADER)/simdjson.cpp cp $(SINGLEHEADER)/simdjson.cpp . simdjson.h: $(SINGLEHEADER)/simdjson.h diff --git a/include/simdjson/common_defs.h b/include/simdjson/common_defs.h index 02b0f0abc..1df0822c0 100644 --- a/include/simdjson/common_defs.h +++ b/include/simdjson/common_defs.h @@ -37,20 +37,20 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024; } // namespace simdjson #if defined(__GNUC__) -// Marks a block with a name so that MCA analysis can see it. -#define BEGIN_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-BEGIN " #name); -#define END_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-END " #name); -#define DEBUG_BLOCK(name, block) BEGIN_DEBUG_BLOCK(name); block; END_DEBUG_BLOCK(name); + // Marks a block with a name so that MCA analysis can see it. + #define BEGIN_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-BEGIN " #name); + #define END_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-END " #name); + #define DEBUG_BLOCK(name, block) BEGIN_DEBUG_BLOCK(name); block; END_DEBUG_BLOCK(name); #else -#define BEGIN_DEBUG_BLOCK(name) -#define END_DEBUG_BLOCK(name) -#define DEBUG_BLOCK(name, block) + #define BEGIN_DEBUG_BLOCK(name) + #define END_DEBUG_BLOCK(name) + #define DEBUG_BLOCK(name, block) #endif #if !defined(_MSC_VER) && !defined(SIMDJSON_NO_COMPUTED_GOTO) -// Implemented using Labels as Values which works in GCC and CLANG (and maybe -// also in Intel's compiler), but won't work in MSVC. -#define SIMDJSON_USE_COMPUTED_GOTO + // Implemented using Labels as Values which works in GCC and CLANG (and maybe + // also in Intel's compiler), but won't work in MSVC. + #define SIMDJSON_USE_COMPUTED_GOTO #endif // Align to N-byte boundary @@ -60,54 +60,76 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024; #define ISALIGNED_N(ptr, n) (((uintptr_t)(ptr) & ((n)-1)) == 0) #ifdef _MSC_VER -#define really_inline __forceinline -#define never_inline __declspec(noinline) -#define UNUSED -#define WARN_UNUSED + #define really_inline __forceinline + #define never_inline __declspec(noinline) -#ifndef likely -#define likely(x) x -#endif -#ifndef unlikely -#define unlikely(x) x -#endif + #define UNUSED + #define WARN_UNUSED -#define SIMDJSON_PUSH_DISABLE_WARNINGS __pragma(warning( push )) -#define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS __pragma(warning( push, 0 )) -#define SIMDJSON_DISABLE_VS_WARNING(WARNING_NUMBER) __pragma(warning( disable : WARNING_NUMBER )) -#define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_VS_WARNING(4996) -#define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop )) + #ifndef likely + #define likely(x) x + #endif + #ifndef unlikely + #define unlikely(x) x + #endif + + #define SIMDJSON_PUSH_DISABLE_WARNINGS __pragma(warning( push )) + #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS __pragma(warning( push, 0 )) + #define SIMDJSON_DISABLE_VS_WARNING(WARNING_NUMBER) __pragma(warning( disable : WARNING_NUMBER )) + #define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_VS_WARNING(4996) + #define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop )) + + #if SIMDJSON_USING_LIBRARY + #define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport) + #else + #define SIMDJSON_DLLIMPORTEXPORT __declspec(dllexport) + #endif #else // MSC_VER + #define really_inline inline __attribute__((always_inline, unused)) + #define never_inline inline __attribute__((noinline, unused)) -#define really_inline inline __attribute__((always_inline, unused)) -#define never_inline inline __attribute__((noinline, unused)) + #define UNUSED __attribute__((unused)) + #define WARN_UNUSED __attribute__((warn_unused_result)) -#define UNUSED __attribute__((unused)) -#define WARN_UNUSED __attribute__((warn_unused_result)) + #ifndef likely + #define likely(x) __builtin_expect(!!(x), 1) + #endif + #ifndef unlikely + #define unlikely(x) __builtin_expect(!!(x), 0) + #endif -#ifndef likely -#define likely(x) __builtin_expect(!!(x), 1) -#endif -#ifndef unlikely -#define unlikely(x) __builtin_expect(!!(x), 0) -#endif + #define SIMDJSON_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push") + // gcc doesn't seem to disable all warnings with all and extra, add warnings here as necessary + #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \ + SIMDJSON_DISABLE_GCC_WARNING(-Wall) \ + SIMDJSON_DISABLE_GCC_WARNING(-Wextra) \ + SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \ + SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \ + SIMDJSON_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) + #define SIMDJSON_PRAGMA(P) _Pragma(#P) + #define SIMDJSON_DISABLE_GCC_WARNING(WARNING) SIMDJSON_PRAGMA(GCC diagnostic ignored #WARNING) + #define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wdeprecated-declarations) + #define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop") -#define SIMDJSON_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push") -// gcc doesn't seem to disable all warnings with all and extra, add warnings here as necessary -#define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \ - SIMDJSON_DISABLE_GCC_WARNING(-Wall) \ - SIMDJSON_DISABLE_GCC_WARNING(-Wextra) \ - SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \ - SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \ - SIMDJSON_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) -#define SIMDJSON_PRAGMA(P) _Pragma(#P) -#define SIMDJSON_DISABLE_GCC_WARNING(WARNING) SIMDJSON_PRAGMA(GCC diagnostic ignored #WARNING) -#define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wdeprecated-declarations) -#define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop") + #define SIMDJSON_DLLIMPORTEXPORT #endif // MSC_VER +// +// Backfill std::string_view using nonstd::string_view on C++11 +// +#if (!SIMDJSON_CPLUSPLUS17) + +SIMDJSON_PUSH_DISABLE_ALL_WARNINGS +#include "simdjson/nonstd/string_view.hpp" +SIMDJSON_POP_DISABLE_WARNINGS + +namespace std { + using string_view = nonstd::string_view; +} +#endif // if (SIMDJSON_CPLUSPLUS < 201703L) + #endif // SIMDJSON_COMMON_DEFS_H diff --git a/include/simdjson/compiler_check.h b/include/simdjson/compiler_check.h index 0bda00976..bf121dd9a 100644 --- a/include/simdjson/compiler_check.h +++ b/include/simdjson/compiler_check.h @@ -13,16 +13,23 @@ #endif #endif -// Backfill std::string_view using nonstd::string_view on C++11 -#ifndef SIMDJSON_INCLUDE_NONSTD_STRING_VIEW -#define SIMDJSON_INCLUDE_NONSTD_STRING_VIEW 1 -#endif // SIMDJSON_INCLUDE_NONSTD_STRING_VIEW -#if (SIMDJSON_CPLUSPLUS < 201703L and SIMDJSON_INCLUDE_NONSTD_STRING_VIEW) -// #error simdjson requires a compiler compliant with the C++17 standard -#include "nonstd/string_view.hpp" -namespace std { - using string_view=nonstd::string_view; -} +// C++ 17 +#if !defined(SIMDJSON_CPLUSPLUS17) && (SIMDJSON_CPLUSPLUS >= 201703L) +#define SIMDJSON_CPLUSPLUS17 1 +#endif + +// C++ 14 +#if !defined(SIMDJSON_CPLUSPLUS14) && (SIMDJSON_CPLUSPLUS >= 201402L) +#define SIMDJSON_CPLUSPLUS14 1 +#endif + +// C++ 11 +#if !defined(SIMDJSON_CPLUSPLUS11) && (SIMDJSON_CPLUSPLUS >= 201103L) +#define SIMDJSON_CPLUSPLUS11 1 +#endif + +#ifndef SIMDJSON_CPLUSPLUS11 +#error simdjson requires a compiler compliant with the C++11 standard #endif #endif // SIMDJSON_COMPILER_CHECK_H diff --git a/include/simdjson/implementation.h b/include/simdjson/implementation.h index 8ea75b0c2..6277e736e 100644 --- a/include/simdjson/implementation.h +++ b/include/simdjson/implementation.h @@ -223,14 +223,14 @@ private: /** * The list of available implementations compiled into simdjson. */ -extern const internal::available_implementation_list available_implementations; +extern SIMDJSON_DLLIMPORTEXPORT const internal::available_implementation_list available_implementations; /** * The active implementation. * * Automatically initialized on first use to the most advanced implementation supported by this hardware. */ -extern internal::atomic_ptr active_implementation; +extern SIMDJSON_DLLIMPORTEXPORT internal::atomic_ptr active_implementation; } // namespace simdjson diff --git a/include/simdjson/inline/error.h b/include/simdjson/inline/error.h index 3f4a27c14..5cece7a75 100644 --- a/include/simdjson/inline/error.h +++ b/include/simdjson/inline/error.h @@ -11,7 +11,7 @@ namespace simdjson::internal { std::string message; }; // These MUST match the codes in error_code. We check this constraint in basictests. - extern const error_code_info error_codes[]; + extern SIMDJSON_DLLIMPORTEXPORT const error_code_info error_codes[]; } // namespace simdjson::internal namespace simdjson { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 97386879b..239091a04 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -112,6 +112,10 @@ set_target_properties(${SIMDJSON_LIB_NAME} PROPERTIES MESSAGE( STATUS "Library output directory (does not apply to Visual Studio): " ${CMAKE_BINARY_DIR}) endif() +if((SIMDJSON_LIB_TYPE STREQUAL "SHARED")) + target_compile_definitions(${SIMDJSON_LIB_NAME} INTERFACE SIMDJSON_USING_LIBRARY=1) +endif() + if(MSVC AND (SIMDJSON_LIB_TYPE STREQUAL "SHARED")) if (CMAKE_VERSION VERSION_LESS 3.4) MESSAGE( STATUS "To build a Windows DLL using Visual Studio, you may need cmake 3.4 or better." ) diff --git a/src/arm64/simd.h b/src/arm64/simd.h index 78dd95927..404db8708 100644 --- a/src/arm64/simd.h +++ b/src/arm64/simd.h @@ -373,17 +373,17 @@ namespace simdjson::arm64::simd { really_inline simd8x64 bit_or(const T m) const { const simd8 mask = simd8::splat(m); - return this->map( [&](auto a) { return a | mask; } ); + return this->map( [&](simd8 a) { return a | mask; } ); } really_inline uint64_t eq(const T m) const { const simd8 mask = simd8::splat(m); - return this->map( [&](auto a) { return a == mask; } ).to_bitmask(); + return this->map( [&](simd8 a) { return a == mask; } ).to_bitmask(); } really_inline uint64_t lteq(const T m) const { const simd8 mask = simd8::splat(m); - return this->map( [&](auto a) { return a <= mask; } ).to_bitmask(); + return this->map( [&](simd8 a) { return a <= mask; } ).to_bitmask(); } }; // struct simd8x64 diff --git a/src/error.cpp b/src/error.cpp index 6b295d07d..0fbbff8ae 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -1,7 +1,7 @@ #include "simdjson/error.h" namespace simdjson::internal { - const error_code_info error_codes[] { + SIMDJSON_DLLIMPORTEXPORT const error_code_info error_codes[] { { SUCCESS, "No error" }, { SUCCESS_AND_HAS_MORE, "No error and buffer still has more data" }, { CAPACITY, "This parser can't support a document that big" }, diff --git a/src/generic/stage2_build_tape.h b/src/generic/stage2_build_tape.h index db0101299..6b30b9443 100644 --- a/src/generic/stage2_build_tape.h +++ b/src/generic/stage2_build_tape.h @@ -350,14 +350,14 @@ WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, pa case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': FAIL_IF( - parser.structurals.with_space_terminated_copy([&](auto copy, auto idx) { + parser.structurals.with_space_terminated_copy([&](const uint8_t *copy, size_t idx) { return parser.parse_number(©[idx], false); }) ); goto finish; case '-': FAIL_IF( - parser.structurals.with_space_terminated_copy([&](auto copy, auto idx) { + parser.structurals.with_space_terminated_copy([&](const uint8_t *copy, size_t idx) { return parser.parse_number(©[idx], true); }) ); diff --git a/src/generic/stage2_streaming_build_tape.h b/src/generic/stage2_streaming_build_tape.h index dcd12929e..c8afc23e6 100755 --- a/src/generic/stage2_streaming_build_tape.h +++ b/src/generic/stage2_streaming_build_tape.h @@ -63,14 +63,14 @@ WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, pa case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': FAIL_IF( - parser.structurals.with_space_terminated_copy([&](auto copy, auto idx) { + parser.structurals.with_space_terminated_copy([&](const uint8_t *copy, size_t idx) { return parser.parse_number(©[idx], false); }) ); goto finish; case '-': FAIL_IF( - parser.structurals.with_space_terminated_copy([&](auto copy, auto idx) { + parser.structurals.with_space_terminated_copy([&](const uint8_t *copy, size_t idx) { return parser.parse_number(©[idx], true); }) ); diff --git a/src/haswell/simd.h b/src/haswell/simd.h index 472423eef..2fb9f12cd 100644 --- a/src/haswell/simd.h +++ b/src/haswell/simd.h @@ -352,17 +352,17 @@ namespace simdjson::haswell::simd { really_inline simd8x64 bit_or(const T m) const { const simd8 mask = simd8::splat(m); - return this->map( [&](auto a) { return a | mask; } ); + return this->map( [&](simd8 a) { return a | mask; } ); } really_inline uint64_t eq(const T m) const { const simd8 mask = simd8::splat(m); - return this->map( [&](auto a) { return a == mask; } ).to_bitmask(); + return this->map( [&](simd8 a) { return a == mask; } ).to_bitmask(); } really_inline uint64_t lteq(const T m) const { const simd8 mask = simd8::splat(m); - return this->map( [&](auto a) { return a <= mask; } ).to_bitmask(); + return this->map( [&](simd8 a) { return a <= mask; } ).to_bitmask(); } }; // struct simd8x64 diff --git a/src/haswell/stage1_find_marks.h b/src/haswell/stage1_find_marks.h index 53eb580f3..f2f08cb39 100644 --- a/src/haswell/stage1_find_marks.h +++ b/src/haswell/stage1_find_marks.h @@ -47,7 +47,7 @@ really_inline json_character_block json_character_block::classify(const simd::si } really_inline bool is_ascii(simd8x64 input) { - simd8 bits = input.reduce([&](auto a,auto b) { return a|b; }); + simd8 bits = input.reduce([&](simd8 a,simd8 b) { return a|b; }); return !bits.any_bits_set_anywhere(0b10000000u); } diff --git a/src/implementation.cpp b/src/implementation.cpp index c027b8c75..0c0a51b30 100644 --- a/src/implementation.cpp +++ b/src/implementation.cpp @@ -127,6 +127,6 @@ const implementation *detect_best_supported_implementation_on_first_use::set_bes } // namespace simdjson::internal namespace simdjson { - const internal::available_implementation_list available_implementations{}; - internal::atomic_ptr active_implementation{&internal::detect_best_supported_implementation_on_first_use_singleton}; -} \ No newline at end of file + SIMDJSON_DLLIMPORTEXPORT const internal::available_implementation_list available_implementations{}; + SIMDJSON_DLLIMPORTEXPORT internal::atomic_ptr active_implementation{&internal::detect_best_supported_implementation_on_first_use_singleton}; +} diff --git a/src/westmere/simd.h b/src/westmere/simd.h index 8a5a1fcdc..3ed56f178 100644 --- a/src/westmere/simd.h +++ b/src/westmere/simd.h @@ -337,17 +337,17 @@ namespace simdjson::westmere::simd { really_inline simd8x64 bit_or(const T m) const { const simd8 mask = simd8::splat(m); - return this->map( [&](auto a) { return a | mask; } ); + return this->map( [&](simd8 a) { return a | mask; } ); } really_inline uint64_t eq(const T m) const { const simd8 mask = simd8::splat(m); - return this->map( [&](auto a) { return a == mask; } ).to_bitmask(); + return this->map( [&](simd8 a) { return a == mask; } ).to_bitmask(); } really_inline uint64_t lteq(const T m) const { const simd8 mask = simd8::splat(m); - return this->map( [&](auto a) { return a <= mask; } ).to_bitmask(); + return this->map( [&](simd8 a) { return a <= mask; } ).to_bitmask(); } }; // struct simd8x64 diff --git a/src/westmere/stage1_find_marks.h b/src/westmere/stage1_find_marks.h index e3eb303ff..aef173925 100644 --- a/src/westmere/stage1_find_marks.h +++ b/src/westmere/stage1_find_marks.h @@ -46,7 +46,7 @@ really_inline json_character_block json_character_block::classify(const simd::si } really_inline bool is_ascii(simd8x64 input) { - simd8 bits = input.reduce([&](auto a,auto b) { return a|b; }); + simd8 bits = input.reduce([&](simd8 a,simd8 b) { return a|b; }); return !bits.any_bits_set_anywhere(0b10000000u); } diff --git a/tests/readme_examples.cpp b/tests/readme_examples.cpp index 6ebe5a219..70624de2d 100644 --- a/tests/readme_examples.cpp +++ b/tests/readme_examples.cpp @@ -46,8 +46,8 @@ void basics_dom_1() { cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl; // Writing out all the information about the car - for (auto [key, value] : car) { - cout << "- " << key << ": " << value << endl; + for (auto field : car) { + cout << "- " << field.key << ": " << field.value << endl; } } } @@ -109,6 +109,29 @@ namespace treewalk_1 { } } +#if (SIMDJSON_CPLUSPLUS >= 201703L) +void basics_cpp17_1() { + dom::parser parser; + padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded; + auto [object, error] = parser.parse(json).get(); + for (auto [key, value] : object) { + cout << key << " = " << value << endl; + } +} +#endif + +void basics_cpp17_2() { + // C++ 11 version for comparison + dom::parser parser; + padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded; + dom::object object; + simdjson::error_code error; + parser.parse(json).get().tie(object, error); + for (dom::key_value_pair field : object) { + cout << field.key << " = " << field.value << endl; + } +} + void basics_ndjson() { dom::parser parser; for (dom::element doc : parser.load_many("x.txt")) { @@ -156,6 +179,7 @@ void performance_1() { cout << doc2 << endl; } +#if (SIMDJSON_CPLUSPLUS >= 201703L) // The web_request part of this is aspirational, so we compile as much as we can here void performance_2() { dom::parser parser(1024*1024); // Never grow past documents > 1MB @@ -180,6 +204,7 @@ void performance_3() { // ... // } } +#endif int main() { return 0; diff --git a/tests/readme_examples_noexceptions.cpp b/tests/readme_examples_noexceptions.cpp index d5ef0abf1..e6c965c8d 100644 --- a/tests/readme_examples_noexceptions.cpp +++ b/tests/readme_examples_noexceptions.cpp @@ -4,6 +4,7 @@ using namespace std; using namespace simdjson; +#if (SIMDJSON_CPLUSPLUS >= 201703L) void basics_error_1() { dom::parser parser; auto json = "1"_padded; @@ -12,6 +13,7 @@ void basics_error_1() { if (error) { cerr << error << endl; exit(1); } // Use document here now that we've checked for the error } +#endif void basics_error_2() { dom::parser parser; @@ -23,6 +25,59 @@ void basics_error_2() { } void basics_error_3() { + auto cars_json = R"( [ + { "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] }, + { "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] }, + { "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] } + ] )"_padded; + dom::parser parser; + dom::array cars; + simdjson::error_code error; + parser.parse(cars_json).get().tie(cars, error); + if (error) { cerr << error << endl; exit(1); } + + // Iterating through an array of objects + for (dom::element car_element : cars) { + dom::object car; + car_element.get().tie(car, error); + if (error) { cerr << error << endl; exit(1); } + + // Accessing a field by name + dom::element make, model; + car["make"].tie(make, error); + if (error) { cerr << error << endl; exit(1); } + car["model"].tie(model, error); + if (error) { cerr << error << endl; exit(1); } + cout << "Make/Model: " << make << "/" << model << endl; + + // Casting a JSON element to an integer + uint64_t year; + car["year"].get().tie(year, error); + if (error) { cerr << error << endl; exit(1); } + cout << "- This car is " << 2020 - year << "years old." << endl; + + // Iterating through an array of floats + double total_tire_pressure = 0; + dom::array tire_pressure_array; + car["tire_pressure"].get().tie(tire_pressure_array, error); + if (error) { cerr << error << endl; exit(1); } + for (dom::element tire_pressure_element : tire_pressure_array) { + double tire_pressure; + tire_pressure_element.get().tie(tire_pressure, error); + if (error) { cerr << error << endl; exit(1); } + total_tire_pressure += tire_pressure; + } + cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl; + + // Writing out all the information about the car + for (auto field : car) { + cout << "- " << field.key << ": " << field.value << endl; + } + } +} + +#if (SIMDJSON_CPLUSPLUS >= 201703L) +void basics_error_3_cpp17() { auto cars_json = R"( [ { "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] }, { "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] }, @@ -71,6 +126,7 @@ void basics_error_3() { } } } +#endif int main() { return 0; diff --git a/tools/cmake/FindOptions.cmake b/tools/cmake/FindOptions.cmake index 2c665a38a..b1ad85aaf 100644 --- a/tools/cmake/FindOptions.cmake +++ b/tools/cmake/FindOptions.cmake @@ -25,7 +25,9 @@ else() set(OPT_FLAGS "${OPT_FLAGS} -DSIMDJSON_EXCEPTIONS=0") endif() -if(NOT MSVC) +if(MSVC) +set(CXXSTD_FLAGS "/std:c++17") +else() set(CXXSTD_FLAGS "-std=c++17 -fPIC") endif()