375 Commits

Author SHA1 Message Date
Makkar 5db72ab9d3 add: C++26 annotations support for rename and skip (#2730) 2026-05-26 12:58:46 -04:00
wankun 1ae93a70d4 Bug fix for get_string() crash when parse incomplete json string (in option disabled my default) (#2720)
* get_string() crash when parse incomplete json string

* get_string() crash when parse incomplete json string

* Bug fix for RISC-V fail

* Update tests/ondemand/CMakeLists.txt

Co-authored-by: Daniel Lemire <daniel@lemire.me>

* Remove unnecessary changes

---------

Co-authored-by: Daniel Lemire <daniel@lemire.me>
2026-05-18 17:18:58 -04:00
吴杨帆 396ca141fd perf(builder): add LSX fast_needs_escaping for LoongArch (#2727)
Use LSX intrinsics for the string-builder escape scan on LoongArch,
matching the existing find_next_json_quotable_character LSX path.

Fixes #2603
2026-05-18 17:13:43 -04:00
Daniel Lemire ec49efa5da avoid unnecessary pointer member (#2715) 2026-05-08 00:26:57 -04:00
Daniel Lemire a16e5128fe pendantic guard 2026-05-07 23:13:40 -04:00
Alecto Irene Perez bd42858383 fix -Wunneeded-internal-declaration warning (#2714) 2026-05-07 21:46:52 -04:00
jmestwa-coder 7d30ff2574 JSON Pointer array index overflow handling (#2713) 2026-05-07 19:07:39 -04:00
Francisco Geiman Thiesen 42c047a927 builder: position-as-local writer for reflection serializer (#2708)
The dominant cost in the reflection serializer was the strict-aliasing
reload pattern: every char* write through `string_builder::buffer.get()`
forced the compiler to assume `string_builder::position` and `::capacity`
may have been clobbered, so it reloaded both members from memory after
each byte. perf annotate showed `ldr [position]` and `ldr [capacity]`
taking 15-20% of CITM serialization time.

This change refactors the reflection atom path to use an internal
`writer` struct (buffer pointer + position + capacity + back-ref to
string_builder). The writer lives as a stack-local in the top-level
append() entry point, threaded through the inlined atom() chain via
`writer&`. After SROA, the three fields are register-resident across
the entire serialization. The `pos` is never round-tripped through
memory between writes — it's a local size_t.

This mirrors the pattern Glaze uses (passing `B&& b, auto&& ix` through
every helper). The simdjson-specific bit is keeping the public
string_builder API intact: only the internal atom() family is
refactored to take `writer&`. The top-level append(string_builder&, T)
constructs a writer on the stack, threads it through atom(), then
syncs the local position back at the end.

For string fields specifically, the escape path is also inlined
through the writer — the existing `write_string_escaped(input, out)`
helper already takes a destination pointer and returns bytes-written,
so it composes cleanly with `w.ptr + w.pos`. Without this, sync/
reload around each string write was a real cost on Twitter (-7%).

Performance
===========

TRUE A/B in single docker invocation, 7 alternating rounds, byte-
identical output, all static_reflection_comprehensive_tests pass.
Build: clang-p2996 21.0.0git, -O3 -DNDEBUG, aarch64 Linux.

CITM Catalog (496 682 bytes):
  baseline (master): 4356 MB/s
  patched:           6776 MB/s   +55.5%
  Glaze:             4860 MB/s   simdjson now 39.4% AHEAD of Glaze

Twitter (81 927 bytes):
  baseline (master): 6437 MB/s
  patched:           6452 MB/s   +0.2% (break-even)
  Twitter is string-heavy; the writer's gain over the existing
  member-based path is small here, but it no longer regresses.

Default initial capacity is unchanged at 1024.
2026-05-07 13:28:03 -04:00
Alecto Irene Perez 376ef7e8e9 Add support for writing NaN/Infinity if SIMDJSON_ENABLE_NAN_INF is enabled (#2711)
* Add tests for dumping out NaN/Infinity to the json builder

* If SIMDJSON_ENABLE_NAN_INF is set, write out NaN and Infinity

* Add tests for dumping out NaN/Infinity when serializing DOM

* If SIMDJSON_ENABLE_NAN_INF, use 'NaN' and 'Infinity' for nan/inf

* Fix bug where 'Inf' as a root atom + spaces of padding parses incorrectly

* Update FracturedJson printers so tables containing NaN/Infinity are aligned
2026-05-07 13:11:03 -04:00
Daniel Lemire 9803884546 overflow patch. 2026-05-06 17:37:18 -04:00
Alecto Irene Perez b9b20be80e Add support for parsing NaN and Infinity as requested in #1540, #2414, and #2540 (#2696)
* add compile option 'SIMDJSON_ENABLE_NAN_INF' but disable by default

* extend parser to support NaN/Infinity when SIMDJSON_ENABLE_NAN_INF=1

* update tests to check parsing of NaN/Infinity, when enabled

* update minefield tests: mark nan/inf tests as passing when nan/inf is ON

* update CI/CD to run tests with extensions for NaN/Infinity enabled
2026-05-04 15:24:26 -04:00
Francisco Geiman Thiesen f902769b35 builder: force-inline atom templates and replace integer writer (#2707)
* builder: force-inline atom templates and replace integer writer

Two complementary changes that together speed up reflection-driven JSON
serialization by ~28% on integer-heavy structs (CITM) and ~12% on
string-heavy structs (Twitter).

(1) Add simdjson_really_inline (always_inline) to the hot atom<T>
    template overloads (arithmetic, struct, container, optional,
    string-like). The constexpr-only declaration was only a hint; the
    compiler routinely chose to leave atom<unsigned long> as a real
    out-of-line function.

(2) Replace string_builder::append<UInt> body with a forward
    cascade-on-magnitude integer writer. The old code computed
    digit_count(v) upfront and wrote backward in a loop; the new code is
    a straight-line if/else cascade that writes digits forward, no loop,
    no helper call.

Either change alone gives only modest gains. Together they unlock the
compiler's cross-call optimization: with all atoms inlined and the
integer writer reduced to straight-line code, the compiler can hoist
b.position into a register across the whole struct serialization, fold
redundant capacity_check calls, and eliminate the strict-aliasing
penalty that otherwise forces b.position/b.capacity reloads after every
char* write.

Output is byte-identical to master on CITM (496682 bytes) and Twitter
(81927 bytes). All static_reflection_comprehensive_tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* builder: de-recurse write_uint_jeaiii so always_inline applies on g++/MSVC

g++ ('inlining failed in call to always_inline ...: function not
considered for inlining') and MSVC ('warning C4714: __forceinline not
inlined' under warnings-as-errors) both refuse to inline recursive
functions marked simdjson_really_inline. The original write_uint_jeaiii
called itself in the >=10^4 branches.

Refactor into a non-recursive DAG of helpers: write_lt100, write_lt10000,
write_4_digits, write_lt1e8, write_uint_jeaiii. Each calls strictly
smaller-domain helpers, no cycles. Same straight-line cascade behavior,
same byte output, but every node is now a candidate for always_inline on
all compilers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* builder: port signed-int append to jeaiii writer and drop digit_count helpers

The signed-integer branch in string_builder::append was structurally
identical to the OLD unsigned branch — same digit_count() upfront +
backward 4-digit batched loop. Port it to use the same forward
write_uint_jeaiii() helper as the unsigned branch (write '-'
unconditionally and advance position only if negative — branchless).

This makes int_log2 / fast_digit_count_32 / fast_digit_count_64 /
digit_count fully unused (verified via grep across include/ and src/);
remove them, ~80 lines of dead code.

The signed write path now benefits from the same compiler-level
optimization (full inlining, capacity-check fusion, no opaque-loop
boundary) as the unsigned path. Signed-int microbench (200 × 100k
values, mixed magnitude and sign): 2272 → 2685 MB/s (+18.2%).
CITM and Twitter benchmarks unchanged in shape and remain byte-identical
to baseline output.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix tests

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Daniel Lemire <daniel@lemire.me>
2026-05-04 13:55:49 -04:00
Francisco Geiman Thiesen 32b52e3f34 builder: coalesce per-field separator+key+colon into one constexpr write (#2698)
Each non-first field in a reflection-driven struct serialization was
emitting three separate string_builder::append calls (',', "\"key\"", ':'),
each going through capacity_check + a small write. Combine them into a
single compile-time string per field so each field does one capacity_check
and one memcpy. Same pattern fixed in atom(), append(), and extract_from().

Measured under clang-p2996 -O3 -DNDEBUG -freflection -std=c++26
(median of 5 contemporaneous runs, output byte-identical to baseline):

  CITM serialization (496682 bytes):
    simdjson_reuse_buffer:        3192 -> 3673 MB/s  (+15.1%)
    simdjson_static_reflection:   3014 -> 3443 MB/s  (+14.2%)
    simdjson_to:                  2717 -> 3234 MB/s  (+19.0%)
    simdjson_to_reuse:            2836 -> 3226 MB/s  (+13.7%)

  Twitter serialization (81927 bytes):
    simdjson_reuse_buffer:        6637 -> 7162 MB/s   (+7.9%)
    simdjson_static_reflection:   5527 -> 5915 MB/s   (+7.0%)
    simdjson_to:                  5070 -> 5350 MB/s   (+5.5%)
    simdjson_to_reuse:            4976 -> 5303 MB/s   (+6.6%)

  extract_from (out-of-tree micro-bench, 100 records per call):
    User 4-of-9 fields:           1833 -> 1888 MB/s   (+3.0%)
    Status 3-of-6 fields:         4286 -> 4334 MB/s   (+1.1%)

Parsing benchmarks unchanged. tests/builder/static_reflection_comprehensive_tests
still passes (round-trip through extract_from / extract_into is verified).
2026-04-30 21:02:41 -04:00
jmestwa-coder b3fe96cdb2 Align source() output for comma-delimited streams with json_sequence behavior (#2699) 2026-04-29 13:05:45 -04:00
Daniel Lemire 3b782fab7a fixes 2690 (typo) 2026-04-20 12:09:39 -04:00
Daniel Lemire df16e96767 fix: ondemand for wildcard matches (#2686)
* fixing issue 2684

* simplifying.

* update

* more fixes

* moving example

* adding forward declaration
2026-04-17 14:20:57 -04:00
Daniel Lemire 2e7ad956eb Merge branch 'master' of github.com:simdjson/simdjson 2026-04-15 12:52:47 -04:00
Daniel Lemire 30d7204312 pedantic guard 2026-04-15 12:52:31 -04:00
metsw24-max b6af1a0456 Fix undefined behavior in document_stream parsing due to unsafe std::isspace usage (#2680) 2026-04-14 23:03:44 -04:00
Daniel Lemire 7cc60672e3 Merge branch 'master' of github.com:simdjson/simdjson 2026-04-13 17:55:05 -04:00
Daniel Lemire 3ecda9ee99 pedantic checks for 32-bit systems who try to allocate enormous
capacities.
2026-04-13 17:54:35 -04:00
Daniel Lemire b648a5fc0a Add std::ranges support for On-Demand API (variant) (#2678)
* add std::ranges support for On-Demand API (#2382)

Add zero-cost range wrappers (array_range, object_range) that satisfy
std::ranges::input_range, enabling std::views::transform and other
C++20 range adaptors with the On-Demand parser.

Uses direct forwarding via simdjson_inline with no value buffering,
avoiding the per-element overhead (~20%) of the previous approach.
Guarded by SIMDJSON_SUPPORTS_RANGES.

* fix: replace non-ASCII em dash in test comment

The just_ascii CI check flags any non-ASCII characters in source files.

* let us see what we get with this...

* minor tweak

* minor update

* update doc

---------

Co-authored-by: Justin Li <justin53@bu.edu>
2026-04-13 15:25:02 -04:00
Daniel Lemire 94c429aa70 finishing up the new streaming (#2674)
* finishing up the new streaming

* fixed silly warnings.

* tweak

* adding more tests

* minor fixes

* more fixes
2026-04-11 14:16:43 -04:00
Jaël Champagne Gareau 72e51a9a81 Add support for RFC 7464 JSON text sequences and comma-delimited documents (#2664)
* add support for RFC 7464 documents

* add threaded comma-delimited parse_many support

* fix failing tests in CI
2026-04-10 20:26:00 -04:00
Daniel Lemire 1a57afec1f Various guards (#2673)
* adding a guard in document::allocate.

Co-authored-by: jmestwa-coder jmestwa@gmail.com

* adding a max depth

Co-authored-by: jmestwa-coder jmestwa@gmail.com
2026-04-10 20:19:46 -04:00
Daniel Lemire 73e69a5e84 Get reflection working without warnings under GCC 16 (#2658)
* wip gcc16

* progress

* minor gcc16 fixes

* final step

* Update include/simdjson/padded_string-inl.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update include/simdjson/padded_string.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* renaming test function

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-03 15:32:42 -04:00
Eyüp Can Akman 12fb30ae9c add get_int32() and get_uint32() to the On Demand API (#2638)
* add get_int32() and get_uint32() to the On Demand API

Add convenience methods that call get_int64()/get_uint64() and
range-check the result, returning NUMBER_OUT_OF_RANGE on overflow.

Added to value, document, document_reference, and their
simdjson_result wrappers.

Closes #1890

* fix document_reference streaming for get_int32/get_uint32

The document_reference getters delegated to document::get_int32/get_uint32
which call get_root_int64/get_root_uint64 with allow_trailing_content=true,
rejecting the next document in a stream as trailing content.

Call get_root_value_iterator().get_root_int64/get_root_uint64(false) directly
to allow trailing content, matching get_int64/get_uint64.

Add streaming tests for both getters.

* add get_int32/get_uint32 to basics.md

* add get_int32/get_uint32 to wrong-type error tests

* add get<uint32_t>/get<int32_t> template specializations

Wire the 32-bit getters into the generic get<T>() and get(T&)
dispatch so that doc.get<uint32_t>() compiles on C++11/14/17
without requiring the C++20 concepts path in std_deserialize.h.
2026-03-30 10:16:31 -04:00
jmestwa-coder afb1c9f4b1 correct inverted clamp in set_max_capacity (#2651) 2026-03-29 15:54:28 -04:00
Levi Zim a1ff05a5e8 Fix RISC-V compilation without RVV (#2637)
#2617 introduced an RVV check that only checks if the compiler supports RVV intrinsics without checking if RVV is enabled at compile time.

This has caused compilation failure of node.js on riscv64. Fix it by appending a check for __riscv_vector.
2026-03-20 11:11:38 -04:00
Daniel Lemire 781ea4b495 fixing issue https://github.com/nodejs/node/pull/62257 (#2631) 2026-03-17 12:38:11 -04:00
Daniel Lemire 2922822622 altivec version of find_next_json_quotable_character (#2622)
* altivec version of find_next_json_quotable_character

* simplify

* saving.
2026-03-08 14:06:01 -04:00
Sudhanshu Shukla ec675d9c61 Add RISC-V RVV support for find_next_json_quotable_character (#2617) 2026-02-28 13:11:47 -05:00
Daniel Lemire 3cd9875f1f simplifying the find_next_json_quotable_character fnc for neon processors (#2613) 2026-02-25 01:06:08 -05:00
Sudhanshu Shukla 817f10dd7d Add LoongArch LSX support for find_next_json_quotable_character (#2608) 2026-02-23 15:00:26 -05:00
Daniel Lemire dbe0c1543e fix bad hint (#2610) 2026-02-20 16:16:37 -05:00
Daniel Lemire 95d8c81810 When using C++11, we could violate the one definition rule (#2606)
* When using C++11, we could violate the one definition rule

* fix

* simplifying

* disabling new 'test' when using shared libs
2026-02-18 20:08:53 -05:00
Francisco Geiman Thiesen af2a43610e perf: SIMD string escaping and batch integer formatting optimizations (#2605)
* perf(serialization): SIMD-accelerated string escape position finding

Profiling revealed that string serialization was performing redundant
scanning: first calling fast_needs_escaping() (SIMD scan to check IF
escape needed), then find_next_json_quotable_character() (scalar
byte-by-byte scan to find WHERE).

Profile data from Twitter benchmark showed:
- 54.76% time in atom<std::string> (string serialization)
- 24.85% time in find_next_json_quotable_character (scalar position finding)

This optimization unifies both operations into a single SIMD pass that
directly locates the first quotable character position:

- NEON (ARM64): Uses vceqq_u8/vcltq_u8 for character detection, then
  extracts position via __builtin_ctzll on 64-bit vector lanes
- SSE2 (x86-64): Uses _mm_cmpeq_epi8/_mm_subs_epu8 for detection, then
  _mm_movemask_epi8 + __builtin_ctz for position extraction

The write_string_escaped function now uses the position finder directly,
eliminating the separate fast_needs_escaping check.

Benchmark results (ARM64, Apple Silicon via Docker with p2996 clang):
- Twitter (string-heavy): 4330 -> 5723 MB/s (+32%)
- CITM (numeric-heavy): ~neutral (expected, few strings)

* perf(serialization): batch integer formatting with 4-digit processing

Profiling with perf annotate revealed that the integer-to-string
conversion loop was a significant hotspot in numeric-heavy workloads.
The original implementation processed 2 digits per iteration:

    while (pv >= 100) {
        memcpy(write_pointer - 1, &decimal_table[(pv % 100) * 2], 2);
        write_pointer -= 2;
        pv /= 100;
    }

Profile data from CITM benchmark showed:
- 31.20% time in atom<unsigned long> (integer formatting)
- 39.07% of integer formatting time in the 2-byte store instruction
  (sturh on ARM64)
- CITM integers average 8.8 digits, meaning 4+ store operations per number

This optimization processes 4 digits per iteration, reducing both store
operations and division count by approximately half for large numbers:

    while (pv >= 10000) {
        q = pv / 10000;
        r = pv % 10000;
        r_hi = r / 100;  // High 2 digits
        r_lo = r % 100;  // Low 2 digits
        memcpy(write_pointer - 1, &decimal_table[r_lo * 2], 2);
        memcpy(write_pointer - 3, &decimal_table[r_hi * 2], 2);
        write_pointer -= 4;
        pv = q;
    }

The division by 10000 compiles to an efficient multiply-high instruction
(umulh on ARM64). Applied to both unsigned and signed integer paths.

Benchmark results (ARM64, Apple Silicon via Docker with p2996 clang):
- Twitter: ~neutral (few integers)
- CITM (numeric-heavy): 2912 -> 3086 MB/s (+6%)

* fix(build): add MSVC compatibility for bit manipulation intrinsics

MSVC does not have __builtin_ctz/__builtin_ctzll. Use _BitScanForward
and _BitScanForward64 from <intrin.h> on MSVC instead.

This fixes the build on all Windows configurations (x64, ARM64, Win32).

* refactor: clean up comments to be implementation-focused

Remove references to specific benchmarks and previous implementations
from code comments. Comments now describe what the code does rather
than historical context.
2026-02-16 11:50:27 -05:00
Daniel Lemire 8c5cc8c443 updating the reflection benchmarks (#2598)
* updating the reflection benchmarks

* removing exception during parsing.

* saving.
2026-02-02 11:28:08 -05:00
Daniel Lemire e532d61e16 when calling get_string with a mutable string parameter, we want to only use the string buffer (#2595)
as scratch space
2026-01-22 10:23:39 -05:00
Olaf Bernstein db93de2a21 add rvv-vls backend (#2593) 2026-01-21 10:13:50 -05:00
Francisco Geiman Thiesen fc57c09cf0 Add FracturedJson formatting support for DOM serialization (#2580)
* Add FracturedJson formatting support for DOM serialization

Implements FracturedJson formatting as requested in issue #2576.
FracturedJson produces human-readable yet compact JSON output by
intelligently choosing between different layout strategies based on
content complexity, length, and structure similarity.

Key features:
- Four layout modes: inline, compact multiline, table, and expanded
- Structure analysis pass to compute metrics before formatting
- Table formatting for arrays of similar objects with column alignment
- Configurable options for line length, indentation, padding, etc.

New files:
- fractured_json.h: Public API with fractured_json_options struct
- fractured_json-inl.h: Implementation (~1000 lines)
- json_structure_analyzer.h: Structure analysis for layout decisions
- fractured_formatter.h: Formatter class using CRTP pattern

Usage:
  dom::parser parser;
  element doc = parser.parse(json_string);
  std::cout << fractured_json(doc) << std::endl;

  // Or with custom options:
  fractured_json_options opts;
  opts.indent_spaces = 2;
  std::cout << fractured_json(doc, opts) << std::endl;

  // Or format any JSON string (useful with reflection API):
  auto formatted = fractured_json_string(minified_json);

Resolves #2576

* Add comprehensive tests for FracturedJson formatter

Adds 27 test cases covering all aspects of the FracturedJson formatter:

Core functionality tests (13):
- Roundtrip parsing verification
- Inline formatting for simple arrays and objects
- Expanded formatting for complex nested structures
- Compact multiline arrays with configurable items per line
- Table formatting for uniform arrays of objects
- Empty container handling
- All scalar types (string, int, uint, double, bool, null)
- String escaping (quotes, backslashes, control characters)
- Custom indentation options
- Deep nesting (10+ levels)
- Mixed type arrays

Edge case tests (11):
- Unicode strings (Chinese, emoji, Arabic, Russian, accented chars)
- Boundary numbers (INT64_MIN/MAX, UINT64_MAX, DBL_MIN/MAX)
- Nested arrays (arrays of arrays)
- Empty string values
- Keys with special characters (spaces, quotes, colons, etc.)
- Non-uniform arrays (should not trigger table mode)
- Very long strings (500+ chars)
- Large arrays (100 elements)
- Reflection API workflow simulation
- Control characters (tab, newline, CR, null)
- Single element containers

Option tests (3):
- Disable compact multiline mode
- Disable table format mode
- Disable all padding options

* Add FracturedJson integration with builder/reflection API

Extends FracturedJson to work seamlessly with the builder API, enabling
formatted output directly from C++ structs using static reflection.

New functions:
- to_fractured_json_string(obj, opts) - serialize struct to formatted JSON
- to_fractured_json(obj, output, opts) - same with output parameter
- extract_fractured_json<fields...>(obj, opts) - format only specific fields

These functions combine the builder's reflection-based serialization with
FracturedJson formatting in a single convenient call:

  struct User { int id; std::string name; bool active; };
  User user{1, "Alice", true};

  // Minified output (existing):
  auto minified = to_json_string(user);
  // {"id":1,"name":"Alice","active":true}

  // Formatted output (new):
  auto formatted = to_fractured_json_string(user);
  // { "id": 1, "name": "Alice", "active": true }

  // Partial extraction with formatting:
  auto partial = extract_fractured_json<"id", "name">(user);
  // { "id": 1, "name": "Alice" }

New files:
- generic/builder/fractured_json_builder.h - builder integration
- tests/builder/static_reflection_fractured_json_tests.cpp - 7 tests

* Fix INT64_MIN overflow and implement table_similarity_threshold

- Fix undefined behavior when negating INT64_MIN in estimate_number_length()
  and measure_value_length() by returning 20 (the exact length of the
  string representation) directly
- Actually use table_similarity_threshold in check_array_uniformity() by
  calling compute_object_similarity() to compare objects against the first
  object in the array

* Fix -Werror=effc++ member initialization warnings

Initialize all member variables in member initialization lists to
satisfy GCC's -Werror=effc++ flag:
- element_metrics::common_keys - add {} default initializer
- structure_analyzer - add default constructor with member init list
- fractured_formatter - add column_widths_{} to constructor
- fractured_string_builder - add analyzer_{} to constructor

* Add Rule of Five to structure_analyzer class

The class has a pointer member (current_opts_) which triggers
-Werror=effc++ requiring explicit copy/move operations. Delete
copy operations (class shouldn't be copied due to cache) and
default move operations.

* Fix Windows build: wrap std::max to avoid macro conflict

Windows.h defines max/min macros that interfere with std::max/std::min.
Wrapping in parentheses as (std::max)(...) prevents macro expansion.

* Fix GCC 15 false positive -Wfree-nonheap-object warning

GCC 15 on MINGW64 gives a false positive warning in parser_moving_parser()
when the std::vector<std::string> goes out of scope. Suppress this
specific warning with a pragma for GCC builds.

* Fix metrics cache key bug by passing metrics through recursion

The cache was using element addresses as keys, but dom::element objects
are lightweight wrappers that get copied during iteration, causing
different addresses between analysis and formatting phases. This resulted
in cache misses and fallback to empty metrics.

Solution: Store child metrics in the element_metrics struct and pass
them through recursive calls, eliminating the need for address-based
caching entirely.

Changes:
- Add children vector to element_metrics for hierarchical metrics
- Remove metrics_cache_ and related get_metrics/has_metrics methods
- Update all format functions to accept and pass child metrics
- Add public analyze_array/analyze_object overloads for standalone use

* Add ignore patterns for Node.js, Rust, and generated files

Add entries for node_modules, package-lock.json, Rust target
directories, local ablation artifacts, and generated documentation
files.

* Refactor: extract analyze_scalar helper to reduce code duplication

Extract common scalar type handling (STRING, INT64, UINT64, DOUBLE,
BOOL, NULL_VALUE) into a dedicated analyze_scalar method. Each scalar
type shares the same initialization pattern for complexity, child_count,
can_inline, and recommended_layout.

Also simplify boolean formatting in format_scalar to use ternary operator.

* Fix formatting and duplicate error message in amalgamate.py

Reformat cramped is_amalgamator condition to multi-line for readability.
Fix duplicate error message text in _included_filename_root and use
correct variable name (relative_root instead of root).

* Refactor: add count_newlines helper in fractured_json tests

Extract repeated newline counting loop into a reusable static helper
function, used by inline_array_test, inline_object_test, and
expanded_test.

* Revert "Add ignore patterns for Node.js, Rust, and generated files"

This reverts commit 4760ea7cd0.

* various minor changes

---------

Co-authored-by: Daniel Lemire <daniel@lemire.me>
2026-01-20 10:32:24 -05:00
Daniel Lemire feb1e7feb6 work on the ondemand iterators (#2590)
* work on the ondemand iterators

* guarding two SIMDJSON_ASSUME

* simplify following @jkeiser's comment

* adding safety rails to the iterators

* silencing a warning.

* updating the amalgamation files
2026-01-17 21:15:18 -05:00
Daniel Lemire 8b69401d8a moving the builder files in their own directory (#2578) 2026-01-07 18:08:11 -05:00
Daniel Lemire f504e57e7a Add runtime dispatching for loongarch (#2575)
* loongarch runtime dispatching

* remove CMake config for Loongarch.

* make lasx available

* flipping

* moving...

* fixing minor logic error

* minor fixes

* flipping

* adding hackish header

* better comment and reordering

* adding dispatch
2026-01-02 14:28:23 -05:00
Dirk Stolle ad3cd71ca2 fix a few typos (#2568) 2025-12-19 21:56:32 -05:00
Daniel Lemire 7ad9fe63a6 fixing issue 2549 (#2567)
* fixing issue 2549

* saving.
2025-12-17 20:32:36 -05:00
Daniel Lemire 5e871f6724 improving slightly the documentation. 2025-12-12 19:04:34 -05:00
Jake S. Del Mastro 4e9ff03af5 Make it possible to provide custom serializers for range types ( (#2550)
If you provide a custom serializer for range types it is currently never used due to the requires clause for string_builder::append with ranges is overly broad
2025-12-12 17:50:52 -05:00
Muhammad Rizal Nurromdhoni 19549c60ec string_builder range-based append fix (#2544)
* Use std::ranges::range_value_t on range

* Add ranges test
2025-11-11 14:15:00 -05:00
Daniel Lemire 19ff7a572d adding concept examples to the compile-time JSON. (#2538) 2025-11-04 15:06:40 -05:00