From 73db3b5fdbacd2244646495504aea9fa569a08e7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 11 Nov 2026 22:21:47 +0100 Subject: [PATCH] docs: name the macros that turn off FILE* locking and bulk scans parse() and sax_parse() now say that the FILE* is locked unless JSON_DISABLE_UNLOCKED_FILE_IO is defined to 1, and the input-source table and the performance page name JSON_DISABLE_STREAM_BULK_SCAN and JSON_DISABLE_UNLOCKED_FILE_IO with what each turns off. Signed-off-by: Niels Lohmann --- docs/mkdocs/docs/api/basic_json/parse.md | 8 ++++---- docs/mkdocs/docs/api/basic_json/sax_parse.md | 4 ++-- docs/mkdocs/docs/features/parsing/index.md | 6 ++++++ docs/mkdocs/docs/features/performance.md | 7 +++++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/docs/mkdocs/docs/api/basic_json/parse.md b/docs/mkdocs/docs/api/basic_json/parse.md index 1ec40217c..dca49ea23 100644 --- a/docs/mkdocs/docs/api/basic_json/parse.md +++ b/docs/mkdocs/docs/api/basic_json/parse.md @@ -133,10 +133,10 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by ahead, so the stream is left exactly where it would be after reading one character at a time. With glibc and the Apple C library, the characters the `#!cpp FILE` holds in its buffer are scanned in bulk like a stream's; elsewhere a `#!cpp FILE*` is read one character at a time. Where the C library has unlocked stdio functions, the - file is locked only once, so other threads that use the same `FILE` object wait until parsing is done. See - [input sources and performance](../../features/parsing/index.md#input-sources-and-performance), - [`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md), and - [`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md). + file is locked only once, so other threads that use the same `FILE` object wait until parsing is done, unless + [`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md) is defined to `1`. See + [input sources and performance](../../features/parsing/index.md#input-sources-and-performance) and + [`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md). ## Examples diff --git a/docs/mkdocs/docs/api/basic_json/sax_parse.md b/docs/mkdocs/docs/api/basic_json/sax_parse.md index 2951d4bfd..134f0b3c6 100644 --- a/docs/mkdocs/docs/api/basic_json/sax_parse.md +++ b/docs/mkdocs/docs/api/basic_json/sax_parse.md @@ -124,8 +124,8 @@ consumer `sax` has a super-linear complexity. A UTF-8 byte order mark is silently ignored. -When reading from a `#!c FILE*`, where the C library has unlocked stdio functions (see -[`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md)), the file is locked while it is parsed. +When reading from a `#!c FILE*` where the C library has unlocked stdio functions, the file is locked while it is parsed, +unless [`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md) is defined to `1`. The lock is recursive, so the SAX handler may use the same file with stdio functions, but it must not wait for another thread that uses the same `FILE` object. diff --git a/docs/mkdocs/docs/features/parsing/index.md b/docs/mkdocs/docs/features/parsing/index.md index 3fbc9e083..32f4549e8 100644 --- a/docs/mkdocs/docs/features/parsing/index.md +++ b/docs/mkdocs/docs/features/parsing/index.md @@ -80,6 +80,12 @@ them faster than others: | `#!cpp FILE*` | with glibc and the Apple C library, the characters the `FILE` holds in its buffer are scanned in bulk like a stream's; elsewhere one character at a time; where the C library has unlocked stdio functions, the file is locked once for the whole parse | | other iterator ranges (e.g., `#!cpp std::list`, `#!cpp std::istreambuf_iterator`), wide strings | one character at a time | +Defining [`JSON_DISABLE_STREAM_BULK_SCAN`](../../api/macros/json_disable_stream_bulk_scan.md) to `1` turns off the bulk +scan of a stream buffer, so a `#!cpp std::istream` is read one character at a time. Defining +[`JSON_DISABLE_UNLOCKED_FILE_IO`](../../api/macros/json_disable_unlocked_file_io.md) to `1` makes a `#!cpp FILE*` read +every character with `std::fgetc`, without locking the file for the whole parse and without the bulk scan of its buffer +(which `JSON_DISABLE_STREAM_BULK_SCAN` does not affect). Neither changes any result. + Input in one block of memory is read even faster with the default options (no [parser callback](../../api/basic_json/parser_callback_t.md), no comments, no trailing commas, and for `sax_parse()` `strict = true`): `parse()`, `accept()`, and `sax_parse()` then read the grammar and the tokens in one loop over the diff --git a/docs/mkdocs/docs/features/performance.md b/docs/mkdocs/docs/features/performance.md index 62ebc5916..53cd4623d 100644 --- a/docs/mkdocs/docs/features/performance.md +++ b/docs/mkdocs/docs/features/performance.md @@ -29,8 +29,11 @@ up. Nothing is read ahead, so the stream is left exactly where it would be after [`operator>>`](../api/operator_gtgt.md) can still read several values from one stream. A stream buffer without a get area is read one character at a time. Where the C library has unlocked stdio functions, a `#!cpp FILE*` is locked once per parse instead of once per character, and with glibc and the Apple C library, the characters in its buffer are -scanned in bulk as a stream's get area is. See -[input sources and performance](parsing/index.md#input-sources-and-performance) for the full table. Parsing from a +scanned in bulk as a stream's get area is. +[`JSON_DISABLE_STREAM_BULK_SCAN`](../api/macros/json_disable_stream_bulk_scan.md) turns off the bulk scan of streams, and +[`JSON_DISABLE_UNLOCKED_FILE_IO`](../api/macros/json_disable_unlocked_file_io.md) both the single lock and the bulk scan +of a `#!cpp FILE*`. See [input sources and performance](parsing/index.md#input-sources-and-performance) for the full +table. Parsing from a stream takes about 1.15 to 1.45 times as long as parsing an equivalent `#!cpp std::string`, which `parse()` reads with a parser of its own (see there).