cjsonx 1.2.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cjsonx-1.2.5/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jirawat Siripuk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
cjsonx-1.2.5/PKG-INFO ADDED
@@ -0,0 +1,556 @@
1
+ Metadata-Version: 2.4
2
+ Name: cjsonx
3
+ Version: 1.2.5
4
+ Summary: High-performance C11 JSON parser python bindings
5
+ Author: jirawat siripuk
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Dynamic: license-file
10
+
11
+ <p align="center">
12
+ <img src="https://raw.githubusercontent.com/tiw302/cjsonx/master/assets/images/logo.png" width="355" alt="cjsonx Logo">
13
+ <br>
14
+ <b>Extreme-performance JSON parser for C11/C++ featuring a 16-byte ultra-compact DOM.</b>
15
+ </p>
16
+
17
+ # cjsonx
18
+
19
+ [![Linux](https://github.com/tiw302/cjsonx/actions/workflows/linux.yml/badge.svg)](https://github.com/tiw302/cjsonx/actions)
20
+ [![macOS](https://github.com/tiw302/cjsonx/actions/workflows/macos.yml/badge.svg)](https://github.com/tiw302/cjsonx/actions)
21
+ [![Windows](https://github.com/tiw302/cjsonx/actions/workflows/windows.yml/badge.svg)](https://github.com/tiw302/cjsonx/actions)
22
+ [![WASM](https://github.com/tiw302/cjsonx/actions/workflows/wasm.yml/badge.svg)](https://github.com/tiw302/cjsonx/actions)
23
+ [![Sanitizers](https://github.com/tiw302/cjsonx/actions/workflows/sanitizers.yml/badge.svg)](https://github.com/tiw302/cjsonx/actions)
24
+ [![Fuzzing](https://github.com/tiw302/cjsonx/actions/workflows/cflite_pr.yml/badge.svg)](https://github.com/tiw302/cjsonx/actions)
25
+
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
27
+ [![Language](https://img.shields.io/badge/Language-C11-00599C.svg)](https://en.wikipedia.org/wiki/C11_(C_standard_revision))
28
+ [![Header-Only](https://img.shields.io/badge/Library-Header--Only-brightgreen.svg)](#installation)
29
+ [![Dependencies](https://img.shields.io/badge/Dependencies-None-blueviolet.svg)](#introduction)
30
+ [![npm](https://img.shields.io/npm/v/%40tiw302%2Fcjsonx.svg?label=npm)](https://www.npmjs.com/package/@tiw302/cjsonx)
31
+ [![PyPI](https://img.shields.io/pypi/v/cjsonx.svg)](https://pypi.org/project/cjsonx/)
32
+
33
+ **[Read the Official Documentation: docs/index.md](https://tiw302.github.io/cjsonx/)**<br>
34
+ **[Try the Live WebAssembly Demo: https://tiw302.github.io/cjsonx/demo/](https://tiw302.github.io/cjsonx/demo/)**
35
+
36
+ > **Verified Compatibility — Cross-Platform Passing**
37
+
38
+ | Architecture | Platform | Verified Backend |
39
+ | :--- | :--- | :--- |
40
+ | **x86_64 (Modern)** | Linux / Windows | **AVX2** (Vectorized) |
41
+ | **ARM64 (Apple)** | macOS (M1/M2/M3) | **NEON** (Vectorized) |
42
+ | **WebAssembly** | Chrome / Node.js | **WASM-SIMD128** |
43
+ | **RISC-V64** | Linux (QEMU) | **Scalar** C11 |
44
+ | **General Desktop** | Linux / Windows | **Scalar** C11 Fallback |
45
+
46
+ ---
47
+
48
+ ## Table of Contents
49
+
50
+ - [Introduction](#introduction)
51
+ - [Why cjsonx?](#why-cjsonx)
52
+ - [Trade-offs & Alternatives](#trade-offs--alternatives-when-not-to-use-cjsonx)
53
+ - [Design Philosophy](#design-philosophy)
54
+ - [Limits & Guarantees](#limits--guarantees)
55
+ - [Requirements](#requirements)
56
+ - [Verified Toolchains](#verified-toolchains)
57
+ - [Build and Installation](#build-and-installation)
58
+ - [Single-Header Distribution](#single-header-distribution-recommended)
59
+ - [CMake (System Install)](#cmake-system-install)
60
+ - [Python / PyPI](#python--pypi)
61
+ - [Node.js / npm](#nodejs--npm)
62
+ - [Developer Build Flags](#developer-build-flags)
63
+ - [Configuration Macros](#configuration-macros)
64
+ - [API Reference](#api-reference)
65
+ - [Core Parsing](#core-parsing)
66
+ - [Owned-Copy Parsing](#owned-copy-parsing)
67
+ - [DOM Access](#dom-access)
68
+ - [Iteration](#iteration)
69
+ - [Mutation & Builder API](#mutation--builder-api)
70
+ - [File I/O Utilities](#file-io-utilities)
71
+ - [Type Aliases](#type-aliases)
72
+ - [Documentation](#documentation)
73
+ - [Examples](#examples)
74
+ - [Quick Start: Basic Parsing & Iteration](#quick-start-basic-parsing--iteration)
75
+ - [Quick Start: Zero-Allocation Mode](#quick-start-zero-allocation-mode-embeddedrtos)
76
+ - [Benchmark Results](#benchmark-results)
77
+ - [Development Methodology & AI Assistance](#development-methodology--ai-assistance)
78
+ - [Author's Note](#authors-note)
79
+ - [License](#license)
80
+
81
+ ---
82
+
83
+ ## Introduction
84
+
85
+ **cjsonx** is a header-only C library for parsing JSON. It is designed to achieve high parsing speeds (exceeding 1.0 GB/s on modern hardware) while offering a fully mutable, ultra-compact 16-byte Flat-DOM.
86
+
87
+ Built on top of a highly optimized dual-stage architecture, `cjsonx` validates structural characters using SIMD bitmasks (AVX2/NEON/WASM-SIMD) before applying a recursive descent parsing phase that utilizes the state-of-the-art Eisel-Lemire algorithm for blazing-fast 64-bit IEEE 754 floating-point numerical conversions.
88
+
89
+ ---
90
+
91
+ ## Why cjsonx?
92
+
93
+ Standard JSON parsers often face specific limitations: they can be slower due to heavy heap allocation per node (using `malloc` recursively), or they consume excessive memory per node (e.g., standard parsers often require 56-64 bytes per node).
94
+
95
+ `cjsonx` was built to address these specific use cases by providing a fully mutable DOM while drastically reducing memory overhead and maximizing computational throughput:
96
+
97
+ | Parser | Speed (Large Payload) | DOM Node Size | Allocation Strategy | Portability |
98
+ |---|---|---|---|---|
99
+ | `cJSON` | ~130 MB/s | ~64 bytes | Heavy (O(N) Malloc) | Universal |
100
+ | `jsmn` | ~600 MB/s | Tokenizer Only | None | Universal |
101
+ | `yyjson` | ~1000+ MB/s | 16-24 bytes | Arena | High |
102
+ | **cjsonx** | **~1000+ MB/s** | **16 bytes (Fixed)** | **Flat Arena** | **Universal** |
103
+
104
+ cjsonx aims to provide an alternative: **delivering high throughput and a fully mutable DOM while maintaining an incredibly dense 16-byte memory footprint.**
105
+
106
+ ---
107
+
108
+ ## Trade-offs & Alternatives (When NOT to use cjsonx)
109
+
110
+ We believe in engineering honesty. `cjsonx` is built for a specific niche and is *not* a silver bullet. You should evaluate alternatives if your requirements match the following:
111
+
112
+ - **Need the absolute fastest C++ parser?** Use [simdjson](https://github.com/simdjson/simdjson). It runs at 3-6 GB/s and is the industry gold standard for C++ server backends. `cjsonx` is pure C11 and cannot compete with their multi-year optimized C++ engine.
113
+ - **Need a battle-tested, general-purpose C parser?** Use [yyjson](https://github.com/ibireme/yyjson). It is incredibly fast, highly optimized for general use cases, and has a massive community.
114
+ - **Need to drop in a ubiquitous, legacy C parser?** Use [cJSON](https://github.com/DaveGamble/cJSON). It's older and much slower, but it works on ancient C89 compilers and has no modern standard requirements. (Note: `cjsonx` also runs without SIMD on any platform via its Scalar fallback, but requires a C11-compliant compiler).
115
+
116
+ **So when *should* you use cjsonx?**
117
+
118
+ 1. **High-Performance Mutable Data:** You need a pure C11 parser that allows you to read, edit, add, and remove JSON nodes rapidly, and stringify them back to JSON text without rebuilding the entire document.
119
+ 2. **Strict Memory Constraints (IoT/RTOS):** You need high-speed parsing but absolutely **refuse to waste memory**. Our 16-byte nodes use 4x less RAM than traditional parsers like cJSON. Additionally, `cjsonx_parse_with_buffer()` provides a True Zero-Allocation mode for embedded systems.
120
+ 3. **WASM / Node.js / Browser:** The `@tiw302/cjsonx` npm package brings full DOM querying to JavaScript. After parsing, you can walk the tree field-by-field via `getRoot()`, `.get(key)`, `.getIndex(i)`, `.pointer(path)`, and `.toJS()` — no JSON.parse re-serialization needed.
121
+
122
+ ---
123
+
124
+ ## Design Philosophy
125
+
126
+ The library is built around three strict constraints:
127
+
128
+ **Flat Arena DOM.** There are no calls to `malloc` per node. The entire document tree is parsed sequentially into a continuous array of 16-byte structs. This guarantees cache locality and enables O(1) skipping over complex objects and arrays during iteration.
129
+
130
+ **State-of-the-art Number Parsing.** `cjsonx` incorporates the Eisel-Lemire fast float algorithm directly into its lexical analysis phase. It parses 99.9% of all IEEE 754 floating-point numbers natively using a single fast path, falling back to strict standard library parsing only on extreme mathematical edge cases.
131
+
132
+ **Zero OS-Dependencies.** The library is built entirely on standard C11. It does not rely on OS-specific file I/O or POSIX headers. It compiles seamlessly to WebAssembly, embedded ARM targets, and standard desktop operating systems.
133
+
134
+ **True Zero-Allocation Mode.** For strict embedded constraints, the `cjsonx_parse_with_buffer()` API completely bypasses `malloc` by parsing the JSON entirely into a user-provided fixed-size stack buffer or RTOS memory pool.
135
+
136
+ ---
137
+
138
+ ## Limits & Guarantees
139
+
140
+ Professional-grade software requires transparent technical boundaries. Here is exactly what `cjsonx` guarantees, and where it draws the line:
141
+
142
+ - **RFC 8259 Compliance:** `cjsonx` strictly adheres to RFC 8259 and ECMA-404. It correctly rejects structural anomalies, unescaped control characters, and deeply nested bombs.
143
+ - **Thread Safety:** The core parsing engine is entirely stateless. Multiple threads can safely parse different JSON documents concurrently without any mutexes or locks.
144
+ - **Length Limit:** The maximum byte length of any single string or serialized container is 16MB (specifically, 16,777,215 bytes, due to the 24-bit length field packed in the 16-byte DOM node structure).
145
+ - **Nesting Depth Limit:** The maximum nesting depth is 1000 (`CJSONX_MAX_DEPTH`) to prevent stack overflow on deeply nested documents. This value is compile-time configurable.
146
+ - **Builder Performance:** Pushing elements to an array via `cjsonx_array_push` is an O(N) operation because it traverses the list of siblings to locate the end of the array. Repeated sequential pushes to build large arrays will result in O(N^2) complexity.
147
+ - **Static Buffer Read-Only:** Documents parsed with `cjsonx_parse_with_buffer()` are marked `is_static = true`. The entire DOM is read-only — calling any Builder API function (e.g., `cjsonx_object_set`, `cjsonx_array_push`) on a static document will return failure, as the internal node array cannot grow. `cjsonx_doc_free()` on a static document is a safe no-op.
148
+
149
+ ---
150
+
151
+ ## Requirements
152
+
153
+ | Component | Requirement |
154
+ |---|---|
155
+ | C Standard | C11 or later |
156
+ | Compiler | GCC 4.9+, Clang 3.5+, MSVC 2019+, Emscripten 3.0+ |
157
+ | Dependencies| None (Standard C Library only) |
158
+
159
+ ---
160
+
161
+ ## Verified Toolchains
162
+
163
+ The following toolchains are tested on every commit via GitHub Actions:
164
+
165
+ | Toolchain | Platform | Backend |
166
+ |---|---|---|
167
+ | GCC | Linux x86_64 | Scalar, AVX2 |
168
+ | GCC (riscv64-linux-gnu) | Linux RISC-V64 (QEMU) | Scalar |
169
+ | Clang | macOS Apple Silicon | NEON |
170
+ | MSVC | Windows x64 | Scalar, AVX2 |
171
+ | Emscripten | WASM (Node.js) | WASM-SIMD, Scalar |
172
+
173
+ ---
174
+
175
+ ## Build and Installation
176
+
177
+ `cjsonx` is entirely header-only.
178
+
179
+ ### Single-Header Distribution (Recommended)
180
+
181
+ The simplest integration is copying the amalgamated `single_include/cjsonx.h` into your project. Define the implementation macro in **exactly one** C file to compile the core functions:
182
+
183
+ ```c
184
+ #define CJSONX_IMPLEMENTATION
185
+ #include "cjsonx.h"
186
+ ```
187
+
188
+ All other translation units should include the header without the macro.
189
+
190
+ ### CMake (System Install)
191
+
192
+ You can build the test suites and install the library system-wide:
193
+
194
+ ```bash
195
+ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
196
+ cmake --build build
197
+ sudo cmake --install build
198
+ ```
199
+
200
+ Then in your project's `CMakeLists.txt`:
201
+
202
+ ```cmake
203
+ find_package(cjsonx REQUIRED)
204
+ target_link_libraries(my_app PRIVATE cjsonx::cjsonx)
205
+ ```
206
+
207
+ ### Python / PyPI
208
+
209
+ Install the Python bindings via pip — no build tools required, wheels are pre-built for Linux, macOS, and Windows:
210
+
211
+ ```bash
212
+ pip install cjsonx
213
+ ```
214
+
215
+ Then use it directly from Python:
216
+
217
+ ```python
218
+ import cjsonx
219
+
220
+ doc = cjsonx.parse('{"name": "alice", "scores": [10, 20, 30]}')
221
+ print(doc["name"]) # alice
222
+ print(doc["scores"][0]) # 10
223
+ print(doc.get("/scores/2")) # 30 (json pointer)
224
+ ```
225
+
226
+ ### Node.js / npm
227
+
228
+ Install the pre-built WebAssembly package — no native compilation or Emscripten required:
229
+
230
+ ```bash
231
+ npm install @tiw302/cjsonx
232
+ ```
233
+
234
+ Then query the DOM directly from JavaScript:
235
+
236
+ ```js
237
+ const cjsonx = require('@tiw302/cjsonx');
238
+ await cjsonx.ready;
239
+
240
+ const ok = cjsonx.parse('{"name": "alice", "scores": [10, 20, 30]}');
241
+ if (ok) {
242
+ const root = cjsonx.getRoot();
243
+ const name = root.get('name').str; // 'alice'
244
+ const first = root.get('scores').getIndex(0).num; // 10
245
+ const obj = root.toJS(); // plain JS object
246
+ cjsonx.free();
247
+ }
248
+ ```
249
+
250
+ ### Developer Build Flags
251
+
252
+ The CMake build exposes optional flags for contributors and CI pipelines:
253
+
254
+ ```bash
255
+ # Enable AddressSanitizer + UndefinedBehaviorSanitizer
256
+ cmake -B build_san -DCJSONX_ENABLE_SANITIZERS=ON
257
+ cmake --build build_san
258
+ ctest --test-dir build_san
259
+
260
+ # Enable gcov code coverage instrumentation
261
+ cmake -B build_cov -DCJSONX_ENABLE_COVERAGE=ON
262
+ cmake --build build_cov
263
+ ctest --test-dir build_cov
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Configuration Macros
269
+
270
+ All constants can be overridden at compile time by defining them **before** including the header (or passing them as `-D` flags to your compiler). The defaults are suitable for most workloads.
271
+
272
+ | Macro | Default | Description |
273
+ |---|---|---|
274
+ | `CJSONX_MAX_DEPTH` | `1000` | Maximum JSON nesting depth. Documents exceeding this during parsing are rejected to prevent stack overflow. |
275
+ | `CJSONX_ARENA_CHUNK_SIZE` | `4096` | Byte size of each chunk allocated by the string arena. Increase for documents with many long escaped strings. |
276
+ | `CJSONX_INITIAL_TAPE_CAP` | `1024` | Initial capacity (in entries) of the Stage 1 structural token tape. |
277
+ | `CJSONX_INITIAL_CONTAINER_CAP` | `16` | Initial capacity (in nodes) of the flat DOM node array. |
278
+
279
+ **Example — embedded target with a tiny nesting limit:**
280
+
281
+ ```c
282
+ #define CJSONX_MAX_DEPTH 32
283
+ #define CJSONX_ARENA_CHUNK_SIZE 512
284
+ #define CJSONX_IMPLEMENTATION
285
+ #include "cjsonx.h"
286
+ ```
287
+
288
+ ---
289
+
290
+ ## API Reference
291
+
292
+ ### Core Parsing
293
+
294
+ | Function | Signature | Description |
295
+ |---|---|---|
296
+ | `cjsonx_parse` | `cjsonx_doc_t* cjsonx_parse(const char* json, size_t length)` | Parses a JSON string into a managed document tree. **Zero-copy** — the input buffer must outlive the document. Returns `NULL` on fatal memory error. Check `doc->is_valid` for syntax status. |
297
+ | `cjsonx_parse_ex` | `cjsonx_doc_t* cjsonx_parse_ex(const char* json, size_t length, cjsonx_allocator_t* alloc)` | Parses a JSON string using custom memory allocation hooks. |
298
+ | `cjsonx_parse_with_buffer` | `cjsonx_doc_t* cjsonx_parse_with_buffer(const char* json, size_t length, void* buffer, size_t buffer_size)` | Zero-allocation mode. Parses JSON into a user-provided buffer. Result is read-only (`is_static = true`); Builder API calls will fail on this document. |
299
+ | `cjsonx_doc_free` | `void cjsonx_doc_free(cjsonx_doc_t* doc)` | Frees the entire document arena in a single call. |
300
+ | `cjsonx_error_string` | `const char* cjsonx_error_string(cjsonx_error_t err)` | Translates an error code into a human-readable string. |
301
+
302
+ ### Owned-Copy Parsing
303
+
304
+ Use these when you don't want to manage the lifetime of the input buffer yourself. The document takes ownership of an internal copy of the JSON string — you can free or modify the original buffer immediately after the call.
305
+
306
+ | Function | Signature | Description |
307
+ |---|---|---|
308
+ | `cjsonx_parse_copy` | `cjsonx_doc_t* cjsonx_parse_copy(const char* json, size_t length)` | Copies the input buffer and parses it. The document owns the copy. |
309
+ | `cjsonx_parse_copy_ex` | `cjsonx_doc_t* cjsonx_parse_copy_ex(const char* json, size_t length, cjsonx_allocator_t* alloc)` | Same as above, but with a custom allocator. |
310
+ | `cjsonx_parse_copy_cstr` | `cjsonx_doc_t* cjsonx_parse_copy_cstr(const char* json)` | Convenience wrapper for null-terminated strings. |
311
+
312
+ ### DOM Access
313
+
314
+ | Function | Signature | Description |
315
+ |---|---|---|
316
+ | `cjsonx_get` | `cjsonx_val_t cjsonx_get(cjsonx_val_t obj, const char* key)` | Retrieves a child node from an Object by its exact null-terminated string key. O(N) linear scan. |
317
+ | `cjsonx_get_len` | `cjsonx_val_t cjsonx_get_len(cjsonx_val_t obj, const char* key, size_t key_len)` | Same as `cjsonx_get` but accepts a key with explicit length. Useful for keys that are **not** null-terminated. |
318
+ | `cjsonx_get_index` | `cjsonx_val_t cjsonx_get_index(cjsonx_val_t arr, size_t index)` | Retrieves a child node from an Array by its index. O(N) sibling walk. |
319
+ | `cjsonx_get_type` | `cjsonx_type_t cjsonx_get_type(cjsonx_val_t val)` | Returns the type of the node (`CJSONX_STRING`, `CJSONX_NUMBER`, etc.). |
320
+ | `cjsonx_num` | `double cjsonx_num(cjsonx_val_t val)` | Retrieves the numerical value as a float. |
321
+ | `cjsonx_int` | `int64_t cjsonx_int(cjsonx_val_t val)` | Retrieves the numerical value as a 64-bit integer. |
322
+ | `cjsonx_str` | `const char* cjsonx_str(cjsonx_val_t val)` | Retrieves the string pointer. Note: zero-copy strings are **not** null-terminated — always use `cjsonx_str_len()` to bound the read. |
323
+ | `cjsonx_str_len` | `size_t cjsonx_str_len(cjsonx_val_t val)` | Returns the exact byte length of the string. |
324
+ | `cjsonx_size` | `size_t cjsonx_size(cjsonx_val_t val)` | Returns the element count of an Array or Object. |
325
+ | `cjsonx_bool` | `bool cjsonx_bool(cjsonx_val_t val)` | Retrieves the boolean value. |
326
+ | `cjsonx_is_null` | `bool cjsonx_is_null(cjsonx_val_t val)` | Returns `true` if the node is explicitly a JSON `null` or is empty/invalid. |
327
+ | `cjsonx_pointer_get` | `cjsonx_val_t cjsonx_pointer_get(cjsonx_val_t root, const char* path)` | Retrieves a node using a RFC 6901 JSON Pointer path. |
328
+
329
+ ### Iteration
330
+
331
+ | Function | Signature | Description |
332
+ |---|---|---|
333
+ | `cjsonx_iter_init` | `cjsonx_iter_t cjsonx_iter_init(cjsonx_val_t val)` | Initializes a lightweight iterator for an Array or Object. |
334
+ | `cjsonx_iter_next` | `bool cjsonx_iter_next(cjsonx_iter_t* iter)` | Advances the iterator to the next element or key-value pair. |
335
+
336
+ ### Mutation & Builder API
337
+
338
+ | Function | Signature | Description |
339
+ |---|---|---|
340
+ | `cjsonx_create_null` | `cjsonx_val_t cjsonx_create_null(cjsonx_doc_t* doc)` | Creates a `null` node. |
341
+ | `cjsonx_create_bool` | `cjsonx_val_t cjsonx_create_bool(cjsonx_doc_t* doc, bool val)` | Creates a boolean node. |
342
+ | `cjsonx_create_number` | `cjsonx_val_t cjsonx_create_number(cjsonx_doc_t* doc, double val)` | Creates a number node. |
343
+ | `cjsonx_create_string` | `cjsonx_val_t cjsonx_create_string(cjsonx_doc_t* doc, const char* str)` | Creates a string node (copies string to arena). |
344
+ | `cjsonx_create_object` | `cjsonx_val_t cjsonx_create_object(cjsonx_doc_t* doc)` | Creates an empty Object node. |
345
+ | `cjsonx_create_array` | `cjsonx_val_t cjsonx_create_array(cjsonx_doc_t* doc)` | Creates an empty Array node. |
346
+ | `cjsonx_object_set` | `bool cjsonx_object_set(cjsonx_val_t obj, const char* key, cjsonx_val_t val)` | Inserts or overwrites a key-value pair in an Object. |
347
+ | `cjsonx_array_push` | `bool cjsonx_array_push(cjsonx_val_t arr, cjsonx_val_t val)` | Appends a value to an Array. |
348
+ | `cjsonx_object_remove` | `bool cjsonx_object_remove(cjsonx_val_t obj, const char* key)` | Removes a key-value pair from an Object. |
349
+ | `cjsonx_array_remove` | `bool cjsonx_array_remove(cjsonx_val_t arr, size_t index)` | Removes a value at the given index from an Array. |
350
+ | `cjsonx_clone_val` | `cjsonx_val_t cjsonx_clone_val(cjsonx_doc_t* dest_doc, cjsonx_val_t src_val)` | Recursively clones a value node and its children into another document arena. |
351
+ | `cjsonx_merge_patch` | `cjsonx_val_t cjsonx_merge_patch(cjsonx_val_t target, cjsonx_val_t patch)` | Applies an RFC 7396 JSON Merge Patch to a target node. |
352
+ | `cjsonx_stringify` | `char* cjsonx_stringify(cjsonx_doc_t* doc)` | Converts document to minified JSON string (malloc'd). |
353
+ | `cjsonx_stringify_format` | `char* cjsonx_stringify_format(cjsonx_doc_t* doc, int indent)` | Converts document to pretty JSON string with indent spaces. |
354
+
355
+ ### File I/O Utilities
356
+
357
+ | Function | Signature | Description |
358
+ |---|---|---|
359
+ | `cjsonx_read_file` | `cjsonx_doc_t* cjsonx_read_file(const char* path)` | Reads and parses a JSON file. |
360
+ | `cjsonx_read_file_ex` | `cjsonx_doc_t* cjsonx_read_file_ex(const char* path, cjsonx_allocator_t* alloc)` | Reads and parses a JSON file using a custom allocator. |
361
+ | `cjsonx_write_file` | `bool cjsonx_write_file(const char* path, cjsonx_doc_t* doc)` | Serializes a document to a file (minified). |
362
+ | `cjsonx_write_file_format` | `bool cjsonx_write_file_format(const char* path, cjsonx_doc_t* doc, int indent)` | Serializes a document to a file (pretty printed). |
363
+
364
+ ### Type Aliases
365
+
366
+ All core types have `_t`-suffix canonical names and shorter aliases for convenience. Both forms compile identically and can be used interchangeably:
367
+
368
+ | Canonical (`_t`) | Short Alias | Description |
369
+ |---|---|---|
370
+ | `cjsonx_doc_t` | `cjsonx_doc` | Parsed document handle |
371
+ | `cjsonx_val_t` | `cjsonx_val` | Value / node handle |
372
+ | `cjsonx_iter_t` | `cjsonx_iter` | Iterator state |
373
+ | `cjsonx_type_t` | `cjsonx_type` | Node type enum |
374
+ | `cjsonx_allocator_t` | `cjsonx_alc` | Custom allocator struct |
375
+
376
+ ---
377
+
378
+ ## Documentation
379
+
380
+ Check out the `docs/` directory for deep-dives into the architecture and API:
381
+
382
+ - [The cjsonx Algorithm](docs/algorithm.md): Detailed explanation of the 2-stage SIMD scanning and Eisel-Lemire numerical parsing engine.
383
+ - [API Reference](docs/api_reference.md): Complete guide to all functions, structures, and memory safety guarantees.
384
+
385
+ ## Examples
386
+
387
+ Runnable examples are provided in the `examples/` directory:
388
+
389
+ - **[simple_parse.c](file:///home/tiw/Public/cjsonx/examples/simple_parse.c)** — Demonstrates standard parsing, key retrieval, array iteration, and type checking using the iterator API.
390
+ - **[dom_access.c](file:///home/tiw/Public/cjsonx/examples/dom_access.c)** — Demonstrates basic JSON object parsing and index-based array access.
391
+ - **[embedded_noalloc.c](file:///home/tiw/Public/cjsonx/examples/embedded_noalloc.c)** — Demonstrates zero-allocation memory parsing using a pre-allocated static stack buffer (true zero `malloc`).
392
+ - **[error_handling.c](file:///home/tiw/Public/cjsonx/examples/error_handling.c)** — Demonstrates detailed parse error diagnostics, showing how to extract byte offset and display a code pointer to the error source.
393
+ - **[float128_precision.c](file:///home/tiw/Public/cjsonx/examples/float128_precision.c)** — Demonstrates parsing extreme, high-precision float and massive integer formats safely.
394
+
395
+ ### Quick Start: Basic Parsing & Iteration
396
+
397
+ ```c
398
+ #define CJSONX_IMPLEMENTATION
399
+ #include "cjsonx.h"
400
+ #include <stdio.h>
401
+ #include <string.h>
402
+
403
+ int main(void) {
404
+ const char* json = "{\"name\": \"Alice\", \"skills\": [\"C\", \"SIMD\"]}";
405
+
406
+ // Parse the JSON string
407
+ cjsonx_doc* doc = cjsonx_parse(json, strlen(json));
408
+ if (!doc || !doc->is_valid) {
409
+ printf("Failed to parse JSON!\n");
410
+ return 1;
411
+ }
412
+
413
+ // Retrieve name and skills
414
+ cjsonx_val name = cjsonx_get(doc->root, "name");
415
+ cjsonx_val skills = cjsonx_get(doc->root, "skills");
416
+
417
+ printf("Name: %.*s\n", (int)cjsonx_str_len(name), cjsonx_str(name));
418
+
419
+ // Iterate array using flat DOM iterator
420
+ if (cjsonx_get_type(skills) == CJSONX_ARRAY) {
421
+ printf("Skills:\n");
422
+ cjsonx_iter iter = cjsonx_iter_init(skills);
423
+ while (cjsonx_iter_next(&iter)) {
424
+ printf(" - %.*s\n", (int)cjsonx_str_len(iter.value), cjsonx_str(iter.value));
425
+ }
426
+ }
427
+
428
+ cjsonx_doc_free(doc);
429
+ return 0;
430
+ }
431
+ ```
432
+
433
+ ### Quick Start: Zero-Allocation Mode (Embedded/RTOS)
434
+
435
+ ```c
436
+ #define CJSONX_IMPLEMENTATION
437
+ #include "cjsonx.h"
438
+ #include <stdio.h>
439
+ #include <string.h>
440
+
441
+ int main(void) {
442
+ const char* json = "{\"sensor\": \"temp\", \"value\": 24.5}";
443
+ uint8_t static_buffer[4096]; // Static buffer on the stack (zero malloc!)
444
+
445
+ cjsonx_doc* doc = cjsonx_parse_with_buffer(json, strlen(json), static_buffer, sizeof(static_buffer));
446
+ if (doc && doc->is_valid) {
447
+ cjsonx_val sensor = cjsonx_get(doc->root, "sensor");
448
+ cjsonx_val value = cjsonx_get(doc->root, "value");
449
+
450
+ printf("Sensor: %.*s, Value: %.1f\n", (int)cjsonx_str_len(sensor), cjsonx_str(sensor), cjsonx_num(value));
451
+ }
452
+
453
+ cjsonx_doc_free(doc); // No-op since we used static buffer
454
+ return 0;
455
+ }
456
+ ```
457
+
458
+ ---
459
+
460
+ ## Benchmark Results
461
+
462
+ Benchmarks were executed on a modern x86_64 CPU (GCC -O3 -march=native). We track **Parse Speed**, **Stringify Speed**, and the **Peak Memory** (Maximum RAM allocated during the parse operation).
463
+
464
+ > **Note on Memory**: `cjsonx` uses a Flat DOM approach with exactly 16 bytes per node. By optimizing initial node allocation capacity and performing a shrink-to-fit step at the end of parsing, `cjsonx` now achieves the lowest peak memory usage among tested libraries while maintaining high parsing throughput.
465
+
466
+ ### 1. `twitter.json` (0.60 MB)
467
+
468
+ | Library | Parse (MB/s) | Stringify (MB/s) | Peak Mem (MB) |
469
+ |---------|--------------|------------------|---------------|
470
+ | **cjsonx** | 611.63 | 1546.55 | **0.92** |
471
+ | yyjson | **756.00** | **3922.39** | 1.20 |
472
+ | cJSON | 283.91 | 414.75 | 1.23 |
473
+
474
+ ### 2. `citm_catalog.json` (1.65 MB)
475
+
476
+ | Library | Parse (MB/s) | Stringify (MB/s) | Peak Mem (MB) |
477
+ |---------|--------------|------------------|---------------|
478
+ | **cjsonx** | **1156.58** | 1990.31 | **2.13** |
479
+ | yyjson | 736.33 | **6539.28** | 3.29 |
480
+ | cJSON | 267.55 | 755.45 | 2.57 |
481
+
482
+ ### 3. `canada.json` (2.15 MB) - Heavy Floating-Point Arrays
483
+
484
+ | Library | Parse (MB/s) | Stringify (MB/s) | Peak Mem (MB) |
485
+ |---------|--------------|------------------|---------------|
486
+ | **cjsonx** | 303.56 | 272.62 | **4.76** |
487
+ | yyjson | **754.31** | **606.38** | 7.87 |
488
+ | cJSON | 71.25 | 24.91 | 10.20 |
489
+
490
+ <details>
491
+ <summary><b>View raw console output from bench_compare</b></summary>
492
+
493
+ ```console
494
+ tiw@tiw-CachyOS ~/Public/cjsonx (master)
495
+ ❯ ./build/bench_compare benchmarks/datasets/citm_catalog.json && ./build/bench_compare benchmarks/datasets/twitter.json && ./build/bench_compare benchmarks/datasets/canada.json
496
+
497
+ Dataset: benchmarks/datasets/citm_catalog.json (1.65 MB)
498
+ ========================================================================
499
+ Library | Parse (MB/s) | Stringify (MB/s) | Peak Mem (MB)
500
+ -----------|-----------------|------------------|-----------------------
501
+ cjsonx | 1156.58 | 1990.31 | 2.13
502
+ yyjson | 736.33 | 6539.28 | 3.29
503
+ cJSON | 267.55 | 755.45 | 2.57
504
+ ========================================================================
505
+ Dataset: benchmarks/datasets/twitter.json (0.60 MB)
506
+ ========================================================================
507
+ Library | Parse (MB/s) | Stringify (MB/s) | Peak Mem (MB)
508
+ -----------|-----------------|------------------|-----------------------
509
+ cjsonx | 611.63 | 1546.55 | 0.92
510
+ yyjson | 756.00 | 3922.39 | 1.20
511
+ cJSON | 283.91 | 414.75 | 1.23
512
+ ========================================================================
513
+ Dataset: benchmarks/datasets/canada.json (2.15 MB)
514
+ ========================================================================
515
+ Library | Parse (MB/s) | Stringify (MB/s) | Peak Mem (MB)
516
+ -----------|-----------------|------------------|-----------------------
517
+ cjsonx | 303.56 | 272.62 | 4.76
518
+ yyjson | 754.31 | 606.38 | 7.87
519
+ cJSON | 71.25 | 24.91 | 10.20
520
+ ========================================================================
521
+
522
+ tiw@tiw-CachyOS ~/Public/cjsonx (master)
523
+
524
+ ```
525
+
526
+ </details>
527
+
528
+ ### Analysis
529
+
530
+ `cjsonx` demonstrates significant parsing throughput on large payloads, measuring up to **1169.02 MB/s** on `citm_catalog.json`. This provides a performance profile comparable to, and often exceeding, modern parsers like `yyjson` during tree construction, while dramatically outperforming legacy standards like `cJSON` in computational speed and maintaining the lowest peak memory overhead.
531
+
532
+ ---
533
+
534
+ ## Development Methodology & AI Assistance
535
+
536
+ Building a memory-safe, SIMD-accelerated C parser from scratch involves handling incredibly complex edge cases—from vectorized bit-masking to IEEE 754 catastrophic cancellation bounds.
537
+
538
+ To achieve this level of stability and performance within a short timeframe, this project was architected and rigorously verified in collaboration with **Advanced Agentic AI**. AI was specifically utilized to:
539
+
540
+ - Stress-test the Eisel-Lemire numerical engine against extreme floating-point edge cases and LibFuzzer.
541
+ - Assist in planning the memory layout and cache-locality of the 16-byte arena DOM.
542
+ - Automate the generation of robust cross-platform CI/CD pipelines (Linux, macOS, Windows, WASM, ClusterFuzzLite).
543
+
544
+ However, **human agency remains at the core of this project**. Every single line of code generated or suggested was manually inspected, audited, and strictly verified. The core architecture, algorithms, and memory design were meticulously human-planned. This hybrid approach—combining human architectural vision with AI-driven debugging and verification—allowed us to push the boundaries of performance and reliability in a modern C library without compromising security or code ownership.
545
+
546
+ ---
547
+
548
+ ## Author's Note
549
+
550
+ I'm just a kid building projects as a hobby. Thank you for showing interest in my little library! It really means a lot to me. :)
551
+
552
+ ---
553
+
554
+ ## License
555
+
556
+ This project is licensed under the [MIT License](LICENSE) - see the [LICENSE](LICENSE) file for details.