Commit Graph

352 Commits

Author SHA1 Message Date
Daniel Lemire 9b71acf803 new feature tests, etc. 2026-04-09 14:55:02 -04:00
Raju1173 325db34d41 added build macros to toggle DOM and On-Demand APIs 2026-04-09 14:54:35 -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
Daniel Lemire 2b9c8977af using _json for compile-time JSON strings. (#2536) 2025-11-03 11:03:21 -05:00
Francisco Geiman Thiesen 86bfbaada7 Merge pull request #2534 from simdjson/francisco/compile-time-parsing_daniel
Compile-time parsing (C++26)
2025-11-01 22:19:37 -07:00
Daniel Lemire ccac6403d9 fixing support for pre-C++17 2025-11-01 17:28:17 -04:00
Daniel Lemire 3319815e25 bringing back compatibility with pre-C++17 2025-11-01 16:46:34 -04:00
hiteshmk05 a24f845bd7 Feature/ondemand wildcard support (#2533)
* Add feature for ondemand-wildcard-JSONQueries

* fix wildcard_test

* fix: extra whitespace
2025-11-01 16:46:08 -04:00
Daniel Lemire 8589509d1e Merge branch 'master' into francisco/compile-time-parsing_daniel 2025-10-31 18:47:42 -04:00
Daniel Lemire 62803512e4 saving. 2025-10-31 15:58:51 -04:00
Francisco Geiman Thiesen 58c92d6d82 Adding support for compiled json path + json pointer (reflection based) (#2483)
* Adding compile time json path

* using string_view

* Adding support for compile-time json pointer as well.

* Removing unnecessary comment

* Tests now working, still will re-review.

* Adding documentation on the compile-time json path/pointer parsing feature.

* Adding benchmark showing the significant performance advantage of using compiled paths whenever you have them a priori.

* going for JSONPath (correct wording).

* minor update (mostly doc)

---------

Co-authored-by: Daniel Lemire <daniel@lemire.me>
2025-10-27 16:52:41 -04:00
Daniel Lemire 781a7d6c89 removing an unnecessary branch (#2530)
* removing an unnecessary branch

* fixing typo
2025-10-27 14:19:58 -04:00
Daniel Lemire def2b6efd2 still not good 2025-10-19 22:23:43 -04:00
Daniel Lemire c3d1d62dfe use cpp 2025-10-17 20:45:57 -04:00
Daniel Lemire ec352430a0 JSONPath is now an RFC (#2517)
* JSONPath is now an RFC

* up
2025-10-17 13:35:04 -04:00
Francisco Geiman Thiesen d326f2ce9f Working! 2025-10-10 21:32:10 -07:00
Francisco Geiman Thiesen ca42a49fba Compile-time support for parsing json objects! 2025-10-10 18:40:09 -07:00
Francisco Geiman Thiesen c7b70de070 Merge branch 'master' into francisco/extract_from 2025-09-29 03:23:02 -07:00
Francisco Geiman Thiesen 6aa7eea334 Adding extract_from functionality + unit tests 2025-09-26 19:48:16 -07:00
Daniel Lemire bd0e9c1336 tweak 2025-09-26 21:04:53 -04:00
Daniel Lemire 7bf82b02d5 this completes the extra_into work. 2025-09-26 21:00:46 -04:00
Francisco Geiman Thiesen 88a1b3e83b Merge pull request #2471 from simdjson/francisco/extract_into
Adding extract_into functionality + test (targets simdjson >= 4.0 as it relies on reflection)
2025-09-26 01:29:33 -07:00
Francisco Geiman Thiesen c72954eade Addressing reviews. 2025-09-25 21:08:38 -07:00
Francisco Geiman Thiesen 4456a10469 Francisco/using iterators for containers (#2470)
* Using iterators instead of subscript operators and size. This helps us work with a broader range of containers.

* Adding list test

* Using std::ranges::input_range<T> as suggested by moisrex
2025-09-25 17:30:42 -04:00
Francisco Geiman Thiesen d8ed2417ad Adding coverage for extract_into with types that have custom serialization 2025-09-25 03:35:46 -07:00
Francisco Geiman Thiesen 5517df7aee Adding extract_into functionality + test 2025-09-24 22:58:23 -07:00