Files
json/single_include
Niels LohmannandClaude Opus 4.8 9eee7a7b9b Read binary strings/blobs in bulk chunks with a memcpy fast path
The binary reader read CBOR/MessagePack/BSON/UBJSON strings and byte
arrays one byte at a time via get()/push_back(), and the iterator input
adapter's get_elements() fallback was itself a per-byte loop, so even
contiguous inputs never benefited from a block copy.

Two changes:

1. iterator_input_adapter::get_elements() gains a contiguous fast path
   that copies the whole requested range with std::memcpy. Contiguity is
   detected via std::is_pointer (all standards) and, in C++20,
   std::contiguous_iterator (so std::vector/std::string iterators also
   qualify). Non-contiguous iterators keep the element-by-element loop.

2. get_string()/get_binary() now share get_bytes(), which reads into the
   result in bounded chunks through get_elements() instead of byte by
   byte. Capping the chunk size preserves the deliberate "do not
   reserve(len) for an untrusted length" DoS protection while turning the
   inner loop into block copies. The min(chunk_size, len) computation is
   width-safe so narrow length types (e.g. MessagePack ext-8's uint8_t)
   cannot truncate chunk_size to zero.

Microbenchmark (2 MiB string + 2 MiB blob + 2000x1 KiB strings, Apple
clang, -O2):

  C++20  from_cbor(vector)   20.1 ms -> 1.0 ms  (~20x)
         from_cbor(pointer)  18.9 ms -> 1.0 ms  (~19x)
  C++17  from_cbor(pointer)  18.7 ms -> 1.0 ms  (~19x, memcpy)
         from_cbor(vector)   18.7 ms -> 4.0 ms  (~4.6x, tight loop)

Behavior is unchanged: truncated input still throws parse_error.110 at
the same byte offset, and all binary-format unit tests pass.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 00:00:12 +02:00
..