csonpath 0.17.0__tar.gz → 0.18.0__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.
Files changed (44) hide show
  1. {csonpath-0.17.0 → csonpath-0.18.0}/Makefile +44 -6
  2. {csonpath-0.17.0/csonpath.egg-info → csonpath-0.18.0}/PKG-INFO +76 -24
  3. {csonpath-0.17.0 → csonpath-0.18.0}/README.md +75 -23
  4. {csonpath-0.17.0 → csonpath-0.18.0/csonpath.egg-info}/PKG-INFO +76 -24
  5. {csonpath-0.17.0 → csonpath-0.18.0}/csonpath.egg-info/SOURCES.txt +3 -0
  6. {csonpath-0.17.0 → csonpath-0.18.0}/csonpath.h +300 -157
  7. {csonpath-0.17.0 → csonpath-0.18.0}/csonpath_do.h +26 -10
  8. {csonpath-0.17.0 → csonpath-0.18.0}/csonpath_json-c.h +12 -0
  9. {csonpath-0.17.0 → csonpath-0.18.0}/csonpath_python.c +104 -24
  10. csonpath-0.18.0/csonpath_undef.h +44 -0
  11. csonpath-0.18.0/csonpath_yyjson.h +19 -0
  12. csonpath-0.17.0/csonpath_yyjson.h → csonpath-0.18.0/csonpath_yyjson_const.h +20 -4
  13. csonpath-0.18.0/csonpath_yyjson_mut.h +223 -0
  14. {csonpath-0.17.0 → csonpath-0.18.0}/pyproject.toml +2 -2
  15. {csonpath-0.17.0 → csonpath-0.18.0}/LICENSE +0 -0
  16. {csonpath-0.17.0 → csonpath-0.18.0}/MANIFEST.in +0 -0
  17. {csonpath-0.17.0 → csonpath-0.18.0}/configure +0 -0
  18. {csonpath-0.17.0 → csonpath-0.18.0}/csonpath.egg-info/dependency_links.txt +0 -0
  19. {csonpath-0.17.0 → csonpath-0.18.0}/csonpath.egg-info/requires.txt +0 -0
  20. {csonpath-0.17.0 → csonpath-0.18.0}/csonpath.egg-info/top_level.txt +0 -0
  21. {csonpath-0.17.0 → csonpath-0.18.0}/csonpath_my_fuzzing.h +0 -0
  22. {csonpath-0.17.0 → csonpath-0.18.0}/setup.cfg +0 -0
  23. {csonpath-0.17.0 → csonpath-0.18.0}/setup.py +0 -0
  24. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/.git +0 -0
  25. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/.github/workflows/c-cpp.yml +0 -0
  26. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/.gitignore +0 -0
  27. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/LICENSE +0 -0
  28. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/Makefile +0 -0
  29. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/README.md +0 -0
  30. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/clib.json +0 -0
  31. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/formal_verification.md +0 -0
  32. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/re.c +0 -0
  33. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/re.h +0 -0
  34. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/scripts/exrex.py +0 -0
  35. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/scripts/regex_test.py +0 -0
  36. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/scripts/regex_test_neg.py +0 -0
  37. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/tests/test1.c +0 -0
  38. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/tests/test2.c +0 -0
  39. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/tests/test3.c +0 -0
  40. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/tests/test_compile.c +0 -0
  41. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/tests/test_print.c +0 -0
  42. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/tests/test_rand.c +0 -0
  43. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/tests/test_rand_neg.c +0 -0
  44. {csonpath-0.17.0 → csonpath-0.18.0}/tiny-regex-c/tests/test_thread.c +0 -0
@@ -5,7 +5,7 @@ YYJSON_LDFLAGS=$(shell pkg-config --libs yyjson)
5
5
 
6
6
  include config.mk
7
7
 
8
- all: test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-json-audit-bugs test-json-crash-vectors test-json-my-fuzz
8
+ all: test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-json-audit-bugs test-json-crash-vectors test-json-my-fuzz test-json-regex-overflow
9
9
 
10
10
  YYJSON_TESTS=test-yyjson
11
11
 
@@ -15,7 +15,7 @@ bench:
15
15
  bench-clean:
16
16
  make -C bench clean
17
17
 
18
- .PHONY: all clean tests pip-dev pip-dev bench bench-clean tests-cli
18
+ .PHONY: all clean tests pip-dev pip-dev bench bench-clean tests-cli tests-rust cov
19
19
 
20
20
  CFLAGS+= -Wall -Wextra -Wno-unused-function -Wno-unused-parameter -O0 -g
21
21
 
@@ -52,10 +52,19 @@ test-json-crash-vectors: tests/json-c/crash-vectors.c csonpath_json-c.h csonpath
52
52
  test-json-my-fuzz: tests/json-c/my_fuzz.c csonpath_json-c.h csonpath_my_fuzzing.h csonpath.h csonpath_do.h
53
53
  $(CC) tests/json-c/my_fuzz.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-my-fuzz $(JSON_C_LDFLAGS) $(LDFLAGS)
54
54
 
55
- test-yyjson: tests/yyjson/test-yyjson.c csonpath_yyjson.h csonpath.h csonpath_do.h
55
+ test-json-regex-overflow: tests/json-c/regex-overflow.c csonpath_json-c.h csonpath.h csonpath_do.h
56
+ $(CC) tests/json-c/regex-overflow.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-regex-overflow $(JSON_C_LDFLAGS) $(LDFLAGS)
57
+
58
+ test-yyjson: tests/yyjson/test-yyjson.c csonpath_yyjson_const.h csonpath.h csonpath_do.h
56
59
  $(CC) tests/yyjson/test-yyjson.c $(EXTRA_FILES) $(YYJSON_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-yyjson $(YYJSON_LDFLAGS) $(LDFLAGS)
57
60
 
58
- tests-c: test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-json-audit-bugs test-json-crash-vectors test-yyjson test-json-my-fuzz
61
+ test-yyjson-mixed: tests/yyjson/test-yyjson-mixed.c csonpath_yyjson.h csonpath_yyjson_const.h csonpath_yyjson_mut.h csonpath.h csonpath_do.h
62
+ $(CC) tests/yyjson/test-yyjson-mixed.c $(EXTRA_FILES) $(YYJSON_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-yyjson-mixed $(YYJSON_LDFLAGS) $(LDFLAGS)
63
+
64
+ test-multi-backend-prefix: tests/multi-backend-prefix.c csonpath_json-c.h csonpath_yyjson.h csonpath_yyjson_const.h csonpath_yyjson_mut.h csonpath.h csonpath_do.h
65
+ $(CC) tests/multi-backend-prefix.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(YYJSON_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-multi-backend-prefix $(JSON_C_LDFLAGS) $(YYJSON_LDFLAGS) $(LDFLAGS)
66
+
67
+ tests-c: test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-json-audit-bugs test-json-crash-vectors test-yyjson test-yyjson-mixed test-json-my-fuzz test-multi-backend-prefix test-json-regex-overflow
59
68
  ./test-json-c-get-a
60
69
  ./test-json-update
61
70
  ./test-json-filter
@@ -67,7 +76,10 @@ tests-c: test-json-c-get-a test-json-update test-json-filter test-json-subpath t
67
76
  ./test-json-audit-bugs
68
77
  ./test-json-crash-vectors
69
78
  ./test-yyjson
79
+ ./test-yyjson-mixed
70
80
  ./test-json-my-fuzz
81
+ ./test-multi-backend-prefix
82
+ ./test-json-regex-overflow
71
83
 
72
84
  csonpath: cli/csonpath_cli.c csonpath_json-c.h csonpath.h csonpath_do.h
73
85
  $(CC) cli/csonpath_cli.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -I./ -o csonpath $(JSON_C_LDFLAGS) $(LDFLAGS)
@@ -81,8 +93,34 @@ pip-dev:
81
93
  tests-py: pip-dev
82
94
  python -m pytest
83
95
 
84
- tests: tests-py tests-c
96
+ tests-rust:
97
+ cargo test --manifest-path rust/Cargo.toml
98
+
99
+ cov:
100
+ $(MAKE) clean
101
+ rm -rf coverage-c coverage-c.html coverage-py coverage-rust build
102
+ find . -name '*.gcov' -delete
103
+ $(MAKE) CFLAGS='--coverage -O0 -g' LDFLAGS='--coverage' tests-c
104
+ CFLAGS='--coverage -O0' LDFLAGS='--coverage' python setup.py build_ext --inplace --force
105
+ python -m coverage run -m pytest
106
+ python -m coverage html -d coverage-py
107
+ python -m gcovr -r . \
108
+ --gcov-object-directory "$$(ls -d build/temp.* 2>/dev/null | head -1)" \
109
+ --filter 'csonpath\.h' --filter 'csonpath_do\.h' --filter 'csonpath_python\.c' \
110
+ --html-details coverage-c.html
111
+ PATH="$$HOME/.cargo/bin:$$PATH" \
112
+ LLVM_COV="$$(find $$HOME/.rustup/toolchains -name llvm-cov -print -quit)" \
113
+ LLVM_PROFDATA="$$(find $$HOME/.rustup/toolchains -name llvm-profdata -print -quit)" \
114
+ cargo llvm-cov --manifest-path rust/Cargo.toml --html --output-dir coverage-rust
115
+ @echo "Coverage reports:"
116
+ @echo " coverage-c.html"
117
+ @echo " coverage-py/index.html"
118
+ @echo " coverage-rust/html/index.html"
119
+
120
+ tests: tests-py tests-c tests-cli tests-rust
85
121
 
86
122
  clean:
87
- rm -rvf test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-json-audit-bugs test-json-crash-vectors test-yyjson test-json-my-fuzz csonpath
123
+ rm -rvf test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-json-audit-bugs test-json-crash-vectors test-yyjson test-yyjson-mixed test-json-my-fuzz test-multi-backend-prefix test-json-regex-overflow csonpath
124
+ find . -name '*.gcda' -delete
125
+ find . -name '*.gcno' -delete
88
126
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.17.0
3
+ Version: 0.18.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -13,9 +13,9 @@ Dynamic: license-file
13
13
 
14
14
  [![Project Sandbox](https://docs.outscale.com/fr/userguide/_images/Project-Sandbox-yellow.svg)](https://docs.outscale.com/en/userguide/Open-Source-Projects.html)
15
15
 
16
- **csonpath** is a partial [JSONPath](https://goessner.net/articles/JsonPath/) implementation in C, with Python bindings. It allows you to query, update, and remove data from JSON objects using path expressions.
16
+ **csonpath** is a partial [JSONPath](https://goessner.net/articles/JsonPath/) implementation in C. It is **backend-agnostic**: the same core engine can query, update, and remove data from any value representation that supports array, object, and scalar semantics—not just JSON.
17
17
 
18
- Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work with any C library or environment that manipulates array, object, and scalar types—not just JSON. Out of the box, backends for [json-c](https://github.com/json-c/json-c), [yyjson](https://github.com/ibireme/yyjson), Python and Rust (via `serde_json`) are provided.
18
+ Out of the box it ships with C backends for [json-c](https://github.com/json-c/json-c) and [yyjson](https://github.com/ibireme/yyjson), plus language bindings for **Python** and **Rust**.
19
19
 
20
20
  ---
21
21
 
@@ -63,6 +63,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
63
63
  - [C API Reference](#-c-api-reference)
64
64
  - [Python API Reference](#-python-api-reference)
65
65
  - [CLI](#%EF%B8%8F-cli)
66
+ - [Using Multiple Backends](#-using-multiple-backends)
66
67
  - [Custom Backends](#-custom-backends)
67
68
  - [Running Tests](#-running-tests)
68
69
  - [Directory Structure](#-directory-structure)
@@ -73,12 +74,12 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
73
74
 
74
75
  ## 📦 Installation
75
76
 
76
- ### Prerequisites
77
- - C compiler (`gcc` or `clang`)
78
- - [json-c](https://github.com/json-c/json-c) library (for C usage)
79
- - Python 3.x (for Python bindings)
77
+ csonpath is a C library at its core. Pick the instructions for the language you want to use it from.
80
78
 
81
79
  ### C (json-c)
80
+
81
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [json-c](https://github.com/json-c/json-c).
82
+
82
83
  Just include the header in your project. There is no separate install step required:
83
84
  ```c
84
85
  #include "csonpath_json-c.h"
@@ -88,21 +89,23 @@ Make sure to link against `json-c` when compiling:
88
89
  gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
89
90
  ```
90
91
 
91
- ### C (Rust backend)
92
- The Rust backend is located in `rust/`. It builds both a safe Rust API and the C glue required by the csonpath core.
92
+ ### C (yyjson)
93
93
 
94
- ```sh
95
- cd rust
96
- cargo build
97
- cargo test
98
- ```
94
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [yyjson](https://github.com/ibireme/yyjson).
99
95
 
100
- To use it from C, include the backend header and link against the produced static library:
101
96
  ```c
102
- #include "rust/csonpath_rust_backend.h"
97
+ #include "csonpath_yyjson.h"
98
+ ```
99
+
100
+ Link against `yyjson` when compiling:
101
+ ```sh
102
+ gcc myapp.c -o myapp $(pkg-config --cflags --libs yyjson)
103
103
  ```
104
104
 
105
105
  ### Python
106
+
107
+ **Prerequisites:** Python 3.x.
108
+
106
109
  Install from PyPI:
107
110
  ```sh
108
111
  pip install csonpath
@@ -115,6 +118,23 @@ pip install .
115
118
  make pip-dev
116
119
  ```
117
120
 
121
+ ### Rust
122
+
123
+ **Prerequisites:** Rust toolchain.
124
+
125
+ The Rust crate is located in `rust/`. Build and test it with:
126
+ ```sh
127
+ cd rust
128
+ cargo build
129
+ cargo test
130
+ ```
131
+
132
+ To depend on it from another Rust project:
133
+ ```toml
134
+ [dependencies]
135
+ csonpath = { path = "rust" }
136
+ ```
137
+
118
138
  ---
119
139
 
120
140
  ## 🛠️ Usage
@@ -195,6 +215,8 @@ p.update_or_create_callback(dst, my_sync_fn, userdata)
195
215
 
196
216
  ## 📘 C API Reference
197
217
 
218
+ The reference below uses the **json-c** backend as an example (`struct json_object *`). All backends expose the same functions with their own value type.
219
+
198
220
  ```c
199
221
  struct csonpath *csonpath_new(const char *path);
200
222
  ```
@@ -337,17 +359,47 @@ echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
337
359
 
338
360
  ---
339
361
 
362
+ ## 🧩 Using Multiple Backends
363
+
364
+ You can include more than one csonpath backend in the same translation unit, provided you prefix all but one of them to avoid symbol collisions. Define `CSONPATH_USE_PREFIX` before a backend header to prefix its API with the backend name.
365
+
366
+ For example, to use both json-c and the immutable yyjson backend in the same file:
367
+
368
+ ```c
369
+ #define CSONPATH_USE_PREFIX
370
+ #include "csonpath_json-c.h"
371
+
372
+ #undef CSONPATH_USE_PREFIX
373
+ #include "csonpath_yyjson_const.h"
374
+ ```
375
+
376
+ To use both yyjson backends (immutable and mutable) together, include the aggregator header:
377
+
378
+ ```c
379
+ #include "csonpath_yyjson.h"
380
+ ```
381
+
382
+ When using the mutable yyjson backend, assign the document pointer to `backend_ctx` before mutable operations:
383
+
384
+ ```c
385
+ struct csonpath *mp = yyjson_mut_csonpath_new("$.a");
386
+ mp->backend_ctx = mdoc;
387
+ yyjson_mut_csonpath_update_or_create(mp, mroot, new_val);
388
+ ```
389
+
390
+ ---
391
+
340
392
  ## 🔌 Custom Backends
341
393
 
342
- csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
394
+ csonpath is designed to be backend-agnostic. The C core manipulates opaque value pointers through a small set of macros, so it can work with any data structure that supports array, object, and scalar semantics.
343
395
 
344
- To create a custom backend, define the required macros and types in a header file (similar to `csonpath_json-c.h` or `csonpath_python.c`), then include your backend header before `csonpath.h`. This allows you to adapt csonpath for manipulating data in any format that supports array/object semantics, giving you full flexibility beyond just JSON.
396
+ A backend is an adapter that implements those macros for a concrete value representation. To create a custom backend, define the required macros and types in a header file (similar to `csonpath_json-c.h` or `csonpath_yyjson.h`), then include your backend header before `csonpath.h`.
345
397
 
346
- For more details, see the existing backend implementations:
347
- - `csonpath_json-c.h` — json-c backend
348
- - `csonpath_yyjson.h` — yyjson backend
349
- - `csonpath_python.c` — Python backend
350
- - `rust/csonpath_rust_backend.h` — Rust / serde_json backend
398
+ Existing backend adapters:
399
+ - `csonpath_json-c.h` — json-c values
400
+ - `csonpath_yyjson.h` — yyjson values
401
+ - `csonpath_python.c` — Python C API values (used by the Python bindings)
402
+ - `rust/csonpath_rust_backend.h` — Rust `serde_json::Value` (used by the Rust crate)
351
403
 
352
404
  ---
353
405
 
@@ -384,7 +436,7 @@ make tests
384
436
  | `csonpath_json-c.h` | json-c backend |
385
437
  | `csonpath_yyjson.h` | yyjson backend |
386
438
  | `csonpath_python.c` | Python C extension backend |
387
- | `rust/` | Rust backend (safe API, FFI, C glue) |
439
+ | `rust/` | Rust crate and its C backend adapter |
388
440
  | `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
389
441
  | `tests/` | C and Python test suites |
390
442
  | `bench/` | Performance benchmarks |
@@ -4,9 +4,9 @@
4
4
 
5
5
  [![Project Sandbox](https://docs.outscale.com/fr/userguide/_images/Project-Sandbox-yellow.svg)](https://docs.outscale.com/en/userguide/Open-Source-Projects.html)
6
6
 
7
- **csonpath** is a partial [JSONPath](https://goessner.net/articles/JsonPath/) implementation in C, with Python bindings. It allows you to query, update, and remove data from JSON objects using path expressions.
7
+ **csonpath** is a partial [JSONPath](https://goessner.net/articles/JsonPath/) implementation in C. It is **backend-agnostic**: the same core engine can query, update, and remove data from any value representation that supports array, object, and scalar semantics—not just JSON.
8
8
 
9
- Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work with any C library or environment that manipulates array, object, and scalar types—not just JSON. Out of the box, backends for [json-c](https://github.com/json-c/json-c), [yyjson](https://github.com/ibireme/yyjson), Python and Rust (via `serde_json`) are provided.
9
+ Out of the box it ships with C backends for [json-c](https://github.com/json-c/json-c) and [yyjson](https://github.com/ibireme/yyjson), plus language bindings for **Python** and **Rust**.
10
10
 
11
11
  ---
12
12
 
@@ -54,6 +54,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
54
54
  - [C API Reference](#-c-api-reference)
55
55
  - [Python API Reference](#-python-api-reference)
56
56
  - [CLI](#%EF%B8%8F-cli)
57
+ - [Using Multiple Backends](#-using-multiple-backends)
57
58
  - [Custom Backends](#-custom-backends)
58
59
  - [Running Tests](#-running-tests)
59
60
  - [Directory Structure](#-directory-structure)
@@ -64,12 +65,12 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
64
65
 
65
66
  ## 📦 Installation
66
67
 
67
- ### Prerequisites
68
- - C compiler (`gcc` or `clang`)
69
- - [json-c](https://github.com/json-c/json-c) library (for C usage)
70
- - Python 3.x (for Python bindings)
68
+ csonpath is a C library at its core. Pick the instructions for the language you want to use it from.
71
69
 
72
70
  ### C (json-c)
71
+
72
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [json-c](https://github.com/json-c/json-c).
73
+
73
74
  Just include the header in your project. There is no separate install step required:
74
75
  ```c
75
76
  #include "csonpath_json-c.h"
@@ -79,21 +80,23 @@ Make sure to link against `json-c` when compiling:
79
80
  gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
80
81
  ```
81
82
 
82
- ### C (Rust backend)
83
- The Rust backend is located in `rust/`. It builds both a safe Rust API and the C glue required by the csonpath core.
83
+ ### C (yyjson)
84
84
 
85
- ```sh
86
- cd rust
87
- cargo build
88
- cargo test
89
- ```
85
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [yyjson](https://github.com/ibireme/yyjson).
90
86
 
91
- To use it from C, include the backend header and link against the produced static library:
92
87
  ```c
93
- #include "rust/csonpath_rust_backend.h"
88
+ #include "csonpath_yyjson.h"
89
+ ```
90
+
91
+ Link against `yyjson` when compiling:
92
+ ```sh
93
+ gcc myapp.c -o myapp $(pkg-config --cflags --libs yyjson)
94
94
  ```
95
95
 
96
96
  ### Python
97
+
98
+ **Prerequisites:** Python 3.x.
99
+
97
100
  Install from PyPI:
98
101
  ```sh
99
102
  pip install csonpath
@@ -106,6 +109,23 @@ pip install .
106
109
  make pip-dev
107
110
  ```
108
111
 
112
+ ### Rust
113
+
114
+ **Prerequisites:** Rust toolchain.
115
+
116
+ The Rust crate is located in `rust/`. Build and test it with:
117
+ ```sh
118
+ cd rust
119
+ cargo build
120
+ cargo test
121
+ ```
122
+
123
+ To depend on it from another Rust project:
124
+ ```toml
125
+ [dependencies]
126
+ csonpath = { path = "rust" }
127
+ ```
128
+
109
129
  ---
110
130
 
111
131
  ## 🛠️ Usage
@@ -186,6 +206,8 @@ p.update_or_create_callback(dst, my_sync_fn, userdata)
186
206
 
187
207
  ## 📘 C API Reference
188
208
 
209
+ The reference below uses the **json-c** backend as an example (`struct json_object *`). All backends expose the same functions with their own value type.
210
+
189
211
  ```c
190
212
  struct csonpath *csonpath_new(const char *path);
191
213
  ```
@@ -328,17 +350,47 @@ echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
328
350
 
329
351
  ---
330
352
 
353
+ ## 🧩 Using Multiple Backends
354
+
355
+ You can include more than one csonpath backend in the same translation unit, provided you prefix all but one of them to avoid symbol collisions. Define `CSONPATH_USE_PREFIX` before a backend header to prefix its API with the backend name.
356
+
357
+ For example, to use both json-c and the immutable yyjson backend in the same file:
358
+
359
+ ```c
360
+ #define CSONPATH_USE_PREFIX
361
+ #include "csonpath_json-c.h"
362
+
363
+ #undef CSONPATH_USE_PREFIX
364
+ #include "csonpath_yyjson_const.h"
365
+ ```
366
+
367
+ To use both yyjson backends (immutable and mutable) together, include the aggregator header:
368
+
369
+ ```c
370
+ #include "csonpath_yyjson.h"
371
+ ```
372
+
373
+ When using the mutable yyjson backend, assign the document pointer to `backend_ctx` before mutable operations:
374
+
375
+ ```c
376
+ struct csonpath *mp = yyjson_mut_csonpath_new("$.a");
377
+ mp->backend_ctx = mdoc;
378
+ yyjson_mut_csonpath_update_or_create(mp, mroot, new_val);
379
+ ```
380
+
381
+ ---
382
+
331
383
  ## 🔌 Custom Backends
332
384
 
333
- csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
385
+ csonpath is designed to be backend-agnostic. The C core manipulates opaque value pointers through a small set of macros, so it can work with any data structure that supports array, object, and scalar semantics.
334
386
 
335
- To create a custom backend, define the required macros and types in a header file (similar to `csonpath_json-c.h` or `csonpath_python.c`), then include your backend header before `csonpath.h`. This allows you to adapt csonpath for manipulating data in any format that supports array/object semantics, giving you full flexibility beyond just JSON.
387
+ A backend is an adapter that implements those macros for a concrete value representation. To create a custom backend, define the required macros and types in a header file (similar to `csonpath_json-c.h` or `csonpath_yyjson.h`), then include your backend header before `csonpath.h`.
336
388
 
337
- For more details, see the existing backend implementations:
338
- - `csonpath_json-c.h` — json-c backend
339
- - `csonpath_yyjson.h` — yyjson backend
340
- - `csonpath_python.c` — Python backend
341
- - `rust/csonpath_rust_backend.h` — Rust / serde_json backend
389
+ Existing backend adapters:
390
+ - `csonpath_json-c.h` — json-c values
391
+ - `csonpath_yyjson.h` — yyjson values
392
+ - `csonpath_python.c` — Python C API values (used by the Python bindings)
393
+ - `rust/csonpath_rust_backend.h` — Rust `serde_json::Value` (used by the Rust crate)
342
394
 
343
395
  ---
344
396
 
@@ -375,7 +427,7 @@ make tests
375
427
  | `csonpath_json-c.h` | json-c backend |
376
428
  | `csonpath_yyjson.h` | yyjson backend |
377
429
  | `csonpath_python.c` | Python C extension backend |
378
- | `rust/` | Rust backend (safe API, FFI, C glue) |
430
+ | `rust/` | Rust crate and its C backend adapter |
379
431
  | `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
380
432
  | `tests/` | C and Python test suites |
381
433
  | `bench/` | Performance benchmarks |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.17.0
3
+ Version: 0.18.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -13,9 +13,9 @@ Dynamic: license-file
13
13
 
14
14
  [![Project Sandbox](https://docs.outscale.com/fr/userguide/_images/Project-Sandbox-yellow.svg)](https://docs.outscale.com/en/userguide/Open-Source-Projects.html)
15
15
 
16
- **csonpath** is a partial [JSONPath](https://goessner.net/articles/JsonPath/) implementation in C, with Python bindings. It allows you to query, update, and remove data from JSON objects using path expressions.
16
+ **csonpath** is a partial [JSONPath](https://goessner.net/articles/JsonPath/) implementation in C. It is **backend-agnostic**: the same core engine can query, update, and remove data from any value representation that supports array, object, and scalar semantics—not just JSON.
17
17
 
18
- Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work with any C library or environment that manipulates array, object, and scalar types—not just JSON. Out of the box, backends for [json-c](https://github.com/json-c/json-c), [yyjson](https://github.com/ibireme/yyjson), Python and Rust (via `serde_json`) are provided.
18
+ Out of the box it ships with C backends for [json-c](https://github.com/json-c/json-c) and [yyjson](https://github.com/ibireme/yyjson), plus language bindings for **Python** and **Rust**.
19
19
 
20
20
  ---
21
21
 
@@ -63,6 +63,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
63
63
  - [C API Reference](#-c-api-reference)
64
64
  - [Python API Reference](#-python-api-reference)
65
65
  - [CLI](#%EF%B8%8F-cli)
66
+ - [Using Multiple Backends](#-using-multiple-backends)
66
67
  - [Custom Backends](#-custom-backends)
67
68
  - [Running Tests](#-running-tests)
68
69
  - [Directory Structure](#-directory-structure)
@@ -73,12 +74,12 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
73
74
 
74
75
  ## 📦 Installation
75
76
 
76
- ### Prerequisites
77
- - C compiler (`gcc` or `clang`)
78
- - [json-c](https://github.com/json-c/json-c) library (for C usage)
79
- - Python 3.x (for Python bindings)
77
+ csonpath is a C library at its core. Pick the instructions for the language you want to use it from.
80
78
 
81
79
  ### C (json-c)
80
+
81
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [json-c](https://github.com/json-c/json-c).
82
+
82
83
  Just include the header in your project. There is no separate install step required:
83
84
  ```c
84
85
  #include "csonpath_json-c.h"
@@ -88,21 +89,23 @@ Make sure to link against `json-c` when compiling:
88
89
  gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
89
90
  ```
90
91
 
91
- ### C (Rust backend)
92
- The Rust backend is located in `rust/`. It builds both a safe Rust API and the C glue required by the csonpath core.
92
+ ### C (yyjson)
93
93
 
94
- ```sh
95
- cd rust
96
- cargo build
97
- cargo test
98
- ```
94
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [yyjson](https://github.com/ibireme/yyjson).
99
95
 
100
- To use it from C, include the backend header and link against the produced static library:
101
96
  ```c
102
- #include "rust/csonpath_rust_backend.h"
97
+ #include "csonpath_yyjson.h"
98
+ ```
99
+
100
+ Link against `yyjson` when compiling:
101
+ ```sh
102
+ gcc myapp.c -o myapp $(pkg-config --cflags --libs yyjson)
103
103
  ```
104
104
 
105
105
  ### Python
106
+
107
+ **Prerequisites:** Python 3.x.
108
+
106
109
  Install from PyPI:
107
110
  ```sh
108
111
  pip install csonpath
@@ -115,6 +118,23 @@ pip install .
115
118
  make pip-dev
116
119
  ```
117
120
 
121
+ ### Rust
122
+
123
+ **Prerequisites:** Rust toolchain.
124
+
125
+ The Rust crate is located in `rust/`. Build and test it with:
126
+ ```sh
127
+ cd rust
128
+ cargo build
129
+ cargo test
130
+ ```
131
+
132
+ To depend on it from another Rust project:
133
+ ```toml
134
+ [dependencies]
135
+ csonpath = { path = "rust" }
136
+ ```
137
+
118
138
  ---
119
139
 
120
140
  ## 🛠️ Usage
@@ -195,6 +215,8 @@ p.update_or_create_callback(dst, my_sync_fn, userdata)
195
215
 
196
216
  ## 📘 C API Reference
197
217
 
218
+ The reference below uses the **json-c** backend as an example (`struct json_object *`). All backends expose the same functions with their own value type.
219
+
198
220
  ```c
199
221
  struct csonpath *csonpath_new(const char *path);
200
222
  ```
@@ -337,17 +359,47 @@ echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
337
359
 
338
360
  ---
339
361
 
362
+ ## 🧩 Using Multiple Backends
363
+
364
+ You can include more than one csonpath backend in the same translation unit, provided you prefix all but one of them to avoid symbol collisions. Define `CSONPATH_USE_PREFIX` before a backend header to prefix its API with the backend name.
365
+
366
+ For example, to use both json-c and the immutable yyjson backend in the same file:
367
+
368
+ ```c
369
+ #define CSONPATH_USE_PREFIX
370
+ #include "csonpath_json-c.h"
371
+
372
+ #undef CSONPATH_USE_PREFIX
373
+ #include "csonpath_yyjson_const.h"
374
+ ```
375
+
376
+ To use both yyjson backends (immutable and mutable) together, include the aggregator header:
377
+
378
+ ```c
379
+ #include "csonpath_yyjson.h"
380
+ ```
381
+
382
+ When using the mutable yyjson backend, assign the document pointer to `backend_ctx` before mutable operations:
383
+
384
+ ```c
385
+ struct csonpath *mp = yyjson_mut_csonpath_new("$.a");
386
+ mp->backend_ctx = mdoc;
387
+ yyjson_mut_csonpath_update_or_create(mp, mroot, new_val);
388
+ ```
389
+
390
+ ---
391
+
340
392
  ## 🔌 Custom Backends
341
393
 
342
- csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
394
+ csonpath is designed to be backend-agnostic. The C core manipulates opaque value pointers through a small set of macros, so it can work with any data structure that supports array, object, and scalar semantics.
343
395
 
344
- To create a custom backend, define the required macros and types in a header file (similar to `csonpath_json-c.h` or `csonpath_python.c`), then include your backend header before `csonpath.h`. This allows you to adapt csonpath for manipulating data in any format that supports array/object semantics, giving you full flexibility beyond just JSON.
396
+ A backend is an adapter that implements those macros for a concrete value representation. To create a custom backend, define the required macros and types in a header file (similar to `csonpath_json-c.h` or `csonpath_yyjson.h`), then include your backend header before `csonpath.h`.
345
397
 
346
- For more details, see the existing backend implementations:
347
- - `csonpath_json-c.h` — json-c backend
348
- - `csonpath_yyjson.h` — yyjson backend
349
- - `csonpath_python.c` — Python backend
350
- - `rust/csonpath_rust_backend.h` — Rust / serde_json backend
398
+ Existing backend adapters:
399
+ - `csonpath_json-c.h` — json-c values
400
+ - `csonpath_yyjson.h` — yyjson values
401
+ - `csonpath_python.c` — Python C API values (used by the Python bindings)
402
+ - `rust/csonpath_rust_backend.h` — Rust `serde_json::Value` (used by the Rust crate)
351
403
 
352
404
  ---
353
405
 
@@ -384,7 +436,7 @@ make tests
384
436
  | `csonpath_json-c.h` | json-c backend |
385
437
  | `csonpath_yyjson.h` | yyjson backend |
386
438
  | `csonpath_python.c` | Python C extension backend |
387
- | `rust/` | Rust backend (safe API, FFI, C glue) |
439
+ | `rust/` | Rust crate and its C backend adapter |
388
440
  | `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
389
441
  | `tests/` | C and Python test suites |
390
442
  | `bench/` | Performance benchmarks |
@@ -8,7 +8,10 @@ csonpath_do.h
8
8
  csonpath_json-c.h
9
9
  csonpath_my_fuzzing.h
10
10
  csonpath_python.c
11
+ csonpath_undef.h
11
12
  csonpath_yyjson.h
13
+ csonpath_yyjson_const.h
14
+ csonpath_yyjson_mut.h
12
15
  pyproject.toml
13
16
  setup.py
14
17
  csonpath.egg-info/PKG-INFO