Make parsing from std::istream and FILE* fast (#5828)

* Make parsing from std::istream and FILE* fast

Squashed onto develop cd6b428ef (CI fixes from #5860). Original commits:

- Let the lexer's bulk fast paths run on a window of the input
- Scan the get area of an input stream in bulk
- Lock a FILE once per parse instead of once per character
- Add benchmarks for parsing from a FILE* and for many values from a stream
- Avoid implicit unsigned char to char conversion in stream tests
- Make file_input_adapter::unlock() safe to call on a moved-from adapter

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* Add ABI tags for JSON_DISABLE_STREAM_BULK_SCAN and JSON_DISABLE_UNLOCKED_FILE_IO

Both macros select between two definitions of an input adapter, so
translation units compiled with different settings violated the ODR when
linked together. Like the other ABI-affecting macros, they now append a
tag to the inline namespace: _dsbs and _dufio. Their defaults move to
abi_macros.hpp so that json_fwd.hpp sees them, and the natvis file is
regenerated for the new namespaces.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* Skip the exception-only checks of the stream input tests without exceptions

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann authored and GitHub committed 2026-10-19 22:00:58 +02:00
1 parent a2248ed5d5
commit 4da932f518
29 files changed
+115869 -83

No files matched your search

+31
View File
@@ -285,6 +285,10 @@ if (JSON_TestSimdutf)
endif()
endif()
# test-file_input checks from a second thread that parsing from a FILE* releases the file's lock
find_package(Threads REQUIRED)
json_test_set_test_options("test-file_input;test-file_input_unlocked_io_disabled" LINK_LIBRARIES Threads::Threads)
# *DO* use json_test_set_test_options() above this line
json_test_should_build_32bit_test(json_32bit_test json_32bit_test_only "${JSON_32bitTest}")
@@ -369,6 +373,33 @@ json_test_add_test_for(src/unit-diagnostic-positions.cpp
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
)
# test reading from a std::istream again without scanning the get area in bulk
json_test_set_test_options(test-stream-bulk-scan_disabled
COMPILE_DEFINITIONS JSON_DISABLE_STREAM_BULK_SCAN=1
)
json_test_add_test_for(src/unit-stream-bulk-scan.cpp
NAME test-stream-bulk-scan_disabled
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
)
# test reading from a std::istream again with JSON_PRECISE_STREAM_POSITION
json_test_set_test_options(test-stream-bulk-scan_precise
COMPILE_DEFINITIONS JSON_PRECISE_STREAM_POSITION=1
)
json_test_add_test_for(src/unit-stream-bulk-scan.cpp
NAME test-stream-bulk-scan_precise
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
)
# test reading from a FILE* again with the locking stdio functions
json_test_set_test_options(test-file_input_unlocked_io_disabled
COMPILE_DEFINITIONS JSON_DISABLE_UNLOCKED_FILE_IO=1
)
json_test_add_test_for(src/unit-file_input.cpp
NAME test-file_input_unlocked_io_disabled
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
)
endif()
# *DO NOT* use json_test_set_test_options() below this line