csonpath 0.17.0__tar.gz → 0.19.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.19.0}/Makefile +46 -6
  2. {csonpath-0.17.0/csonpath.egg-info → csonpath-0.19.0}/PKG-INFO +78 -24
  3. {csonpath-0.17.0 → csonpath-0.19.0}/README.md +77 -23
  4. {csonpath-0.17.0 → csonpath-0.19.0/csonpath.egg-info}/PKG-INFO +78 -24
  5. {csonpath-0.17.0 → csonpath-0.19.0}/csonpath.egg-info/SOURCES.txt +3 -0
  6. {csonpath-0.17.0 → csonpath-0.19.0}/csonpath.h +339 -158
  7. {csonpath-0.17.0 → csonpath-0.19.0}/csonpath_do.h +59 -11
  8. {csonpath-0.17.0 → csonpath-0.19.0}/csonpath_json-c.h +12 -0
  9. {csonpath-0.17.0 → csonpath-0.19.0}/csonpath_python.c +104 -24
  10. csonpath-0.19.0/csonpath_undef.h +44 -0
  11. csonpath-0.19.0/csonpath_yyjson.h +19 -0
  12. csonpath-0.17.0/csonpath_yyjson.h → csonpath-0.19.0/csonpath_yyjson_const.h +20 -4
  13. csonpath-0.19.0/csonpath_yyjson_mut.h +223 -0
  14. {csonpath-0.17.0 → csonpath-0.19.0}/pyproject.toml +2 -2
  15. {csonpath-0.17.0 → csonpath-0.19.0}/LICENSE +0 -0
  16. {csonpath-0.17.0 → csonpath-0.19.0}/MANIFEST.in +0 -0
  17. {csonpath-0.17.0 → csonpath-0.19.0}/configure +0 -0
  18. {csonpath-0.17.0 → csonpath-0.19.0}/csonpath.egg-info/dependency_links.txt +0 -0
  19. {csonpath-0.17.0 → csonpath-0.19.0}/csonpath.egg-info/requires.txt +0 -0
  20. {csonpath-0.17.0 → csonpath-0.19.0}/csonpath.egg-info/top_level.txt +0 -0
  21. {csonpath-0.17.0 → csonpath-0.19.0}/csonpath_my_fuzzing.h +0 -0
  22. {csonpath-0.17.0 → csonpath-0.19.0}/setup.cfg +0 -0
  23. {csonpath-0.17.0 → csonpath-0.19.0}/setup.py +0 -0
  24. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/.git +0 -0
  25. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/.github/workflows/c-cpp.yml +0 -0
  26. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/.gitignore +0 -0
  27. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/LICENSE +0 -0
  28. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/Makefile +0 -0
  29. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/README.md +0 -0
  30. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/clib.json +0 -0
  31. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/formal_verification.md +0 -0
  32. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/re.c +0 -0
  33. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/re.h +0 -0
  34. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/scripts/exrex.py +0 -0
  35. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/scripts/regex_test.py +0 -0
  36. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/scripts/regex_test_neg.py +0 -0
  37. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/tests/test1.c +0 -0
  38. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/tests/test2.c +0 -0
  39. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/tests/test3.c +0 -0
  40. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/tests/test_compile.c +0 -0
  41. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/tests/test_print.c +0 -0
  42. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/tests/test_rand.c +0 -0
  43. {csonpath-0.17.0 → csonpath-0.19.0}/tiny-regex-c/tests/test_rand_neg.c +0 -0
  44. {csonpath-0.17.0 → csonpath-0.19.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,36 @@ 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
+ $(MAKE) CFLAGS='--coverage -O0 -g' LDFLAGS='--coverage' csonpath
105
+ bash tests/cli/run.sh ./csonpath
106
+ CFLAGS='--coverage -O0' LDFLAGS='--coverage' python setup.py build_ext --inplace --force
107
+ python -m coverage run -m pytest
108
+ python -m coverage html -d coverage-py
109
+ python -m gcovr -r . \
110
+ --gcov-object-directory "$$(ls -d build/temp.* 2>/dev/null | head -1)" \
111
+ --filter 'csonpath\.h' --filter 'csonpath_do\.h' --filter 'csonpath_python\.c' \
112
+ --html-details coverage-c.html
113
+ PATH="$$HOME/.cargo/bin:$$PATH" \
114
+ LLVM_COV="$$(find $$HOME/.rustup/toolchains -name llvm-cov -print -quit)" \
115
+ LLVM_PROFDATA="$$(find $$HOME/.rustup/toolchains -name llvm-profdata -print -quit)" \
116
+ cargo llvm-cov --manifest-path rust/Cargo.toml --html --output-dir coverage-rust
117
+ @echo "Coverage reports:"
118
+ @echo " coverage-c.html"
119
+ @echo " coverage-py/index.html"
120
+ @echo " coverage-rust/html/index.html"
121
+
122
+ tests: tests-py tests-c tests-cli tests-rust
85
123
 
86
124
  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
125
+ 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
126
+ find . -name '*.gcda' -delete
127
+ find . -name '*.gcno' -delete
88
128
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.17.0
3
+ Version: 0.19.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
 
@@ -30,6 +30,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
30
30
  | Array index | `$.array[0]` | Access by zero-based index |
31
31
  | Wildcard `[*]` | `$.array[*].field` | Iterate all array elements |
32
32
  | Recursive descent `..` | `$..name` | Search recursively for a key |
33
+ | Recursive descent wildcard `..*` | `$..*` | Return all descendants |
33
34
  | Union `,` (inside brackets) | `$['a','b']`, `$.array[0,1]`, `$.items[?n==1, ?n==2]` | Match all listed selectors at once |
34
35
  | OR fallback `\|` | `$.a \| $.b` | Try the left path first; fall back to the right one if it does not match. Only the first successful path is used. |
35
36
  | Filters | `$.items[?price > 10]` | Filter array elements |
@@ -37,6 +38,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
37
38
  | Multiple filters (`&`) | `$.items[?a=1 & b=2]` | Combine conditions |
38
39
  | Subpath expressions | `$.obj[$.key]` | Use JSON values as dynamic path keys |
39
40
  | `@` current object | `$.items[?@.price > 10]` | Reference the current element in filters |
41
+ | Type selectors | `$..["@odata.id"]@string()`, `$.*@integer()` | Filter matches by JSON type (`string`, `integer`, `null`) |
40
42
 
41
43
  ### Operations
42
44
  - **Find First** — retrieve the first match.
@@ -63,6 +65,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
63
65
  - [C API Reference](#-c-api-reference)
64
66
  - [Python API Reference](#-python-api-reference)
65
67
  - [CLI](#%EF%B8%8F-cli)
68
+ - [Using Multiple Backends](#-using-multiple-backends)
66
69
  - [Custom Backends](#-custom-backends)
67
70
  - [Running Tests](#-running-tests)
68
71
  - [Directory Structure](#-directory-structure)
@@ -73,12 +76,12 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
73
76
 
74
77
  ## 📦 Installation
75
78
 
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)
79
+ csonpath is a C library at its core. Pick the instructions for the language you want to use it from.
80
80
 
81
81
  ### C (json-c)
82
+
83
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [json-c](https://github.com/json-c/json-c).
84
+
82
85
  Just include the header in your project. There is no separate install step required:
83
86
  ```c
84
87
  #include "csonpath_json-c.h"
@@ -88,21 +91,23 @@ Make sure to link against `json-c` when compiling:
88
91
  gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
89
92
  ```
90
93
 
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.
94
+ ### C (yyjson)
93
95
 
94
- ```sh
95
- cd rust
96
- cargo build
97
- cargo test
98
- ```
96
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [yyjson](https://github.com/ibireme/yyjson).
99
97
 
100
- To use it from C, include the backend header and link against the produced static library:
101
98
  ```c
102
- #include "rust/csonpath_rust_backend.h"
99
+ #include "csonpath_yyjson.h"
100
+ ```
101
+
102
+ Link against `yyjson` when compiling:
103
+ ```sh
104
+ gcc myapp.c -o myapp $(pkg-config --cflags --libs yyjson)
103
105
  ```
104
106
 
105
107
  ### Python
108
+
109
+ **Prerequisites:** Python 3.x.
110
+
106
111
  Install from PyPI:
107
112
  ```sh
108
113
  pip install csonpath
@@ -115,6 +120,23 @@ pip install .
115
120
  make pip-dev
116
121
  ```
117
122
 
123
+ ### Rust
124
+
125
+ **Prerequisites:** Rust toolchain.
126
+
127
+ The Rust crate is located in `rust/`. Build and test it with:
128
+ ```sh
129
+ cd rust
130
+ cargo build
131
+ cargo test
132
+ ```
133
+
134
+ To depend on it from another Rust project:
135
+ ```toml
136
+ [dependencies]
137
+ csonpath = { path = "rust" }
138
+ ```
139
+
118
140
  ---
119
141
 
120
142
  ## 🛠️ Usage
@@ -195,6 +217,8 @@ p.update_or_create_callback(dst, my_sync_fn, userdata)
195
217
 
196
218
  ## 📘 C API Reference
197
219
 
220
+ 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.
221
+
198
222
  ```c
199
223
  struct csonpath *csonpath_new(const char *path);
200
224
  ```
@@ -337,17 +361,47 @@ echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
337
361
 
338
362
  ---
339
363
 
364
+ ## 🧩 Using Multiple Backends
365
+
366
+ 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.
367
+
368
+ For example, to use both json-c and the immutable yyjson backend in the same file:
369
+
370
+ ```c
371
+ #define CSONPATH_USE_PREFIX
372
+ #include "csonpath_json-c.h"
373
+
374
+ #undef CSONPATH_USE_PREFIX
375
+ #include "csonpath_yyjson_const.h"
376
+ ```
377
+
378
+ To use both yyjson backends (immutable and mutable) together, include the aggregator header:
379
+
380
+ ```c
381
+ #include "csonpath_yyjson.h"
382
+ ```
383
+
384
+ When using the mutable yyjson backend, assign the document pointer to `backend_ctx` before mutable operations:
385
+
386
+ ```c
387
+ struct csonpath *mp = yyjson_mut_csonpath_new("$.a");
388
+ mp->backend_ctx = mdoc;
389
+ yyjson_mut_csonpath_update_or_create(mp, mroot, new_val);
390
+ ```
391
+
392
+ ---
393
+
340
394
  ## 🔌 Custom Backends
341
395
 
342
- csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
396
+ 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
397
 
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.
398
+ 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
399
 
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
400
+ Existing backend adapters:
401
+ - `csonpath_json-c.h` — json-c values
402
+ - `csonpath_yyjson.h` — yyjson values
403
+ - `csonpath_python.c` — Python C API values (used by the Python bindings)
404
+ - `rust/csonpath_rust_backend.h` — Rust `serde_json::Value` (used by the Rust crate)
351
405
 
352
406
  ---
353
407
 
@@ -384,7 +438,7 @@ make tests
384
438
  | `csonpath_json-c.h` | json-c backend |
385
439
  | `csonpath_yyjson.h` | yyjson backend |
386
440
  | `csonpath_python.c` | Python C extension backend |
387
- | `rust/` | Rust backend (safe API, FFI, C glue) |
441
+ | `rust/` | Rust crate and its C backend adapter |
388
442
  | `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
389
443
  | `tests/` | C and Python test suites |
390
444
  | `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
 
@@ -21,6 +21,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
21
21
  | Array index | `$.array[0]` | Access by zero-based index |
22
22
  | Wildcard `[*]` | `$.array[*].field` | Iterate all array elements |
23
23
  | Recursive descent `..` | `$..name` | Search recursively for a key |
24
+ | Recursive descent wildcard `..*` | `$..*` | Return all descendants |
24
25
  | Union `,` (inside brackets) | `$['a','b']`, `$.array[0,1]`, `$.items[?n==1, ?n==2]` | Match all listed selectors at once |
25
26
  | OR fallback `\|` | `$.a \| $.b` | Try the left path first; fall back to the right one if it does not match. Only the first successful path is used. |
26
27
  | Filters | `$.items[?price > 10]` | Filter array elements |
@@ -28,6 +29,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
28
29
  | Multiple filters (`&`) | `$.items[?a=1 & b=2]` | Combine conditions |
29
30
  | Subpath expressions | `$.obj[$.key]` | Use JSON values as dynamic path keys |
30
31
  | `@` current object | `$.items[?@.price > 10]` | Reference the current element in filters |
32
+ | Type selectors | `$..["@odata.id"]@string()`, `$.*@integer()` | Filter matches by JSON type (`string`, `integer`, `null`) |
31
33
 
32
34
  ### Operations
33
35
  - **Find First** — retrieve the first match.
@@ -54,6 +56,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
54
56
  - [C API Reference](#-c-api-reference)
55
57
  - [Python API Reference](#-python-api-reference)
56
58
  - [CLI](#%EF%B8%8F-cli)
59
+ - [Using Multiple Backends](#-using-multiple-backends)
57
60
  - [Custom Backends](#-custom-backends)
58
61
  - [Running Tests](#-running-tests)
59
62
  - [Directory Structure](#-directory-structure)
@@ -64,12 +67,12 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
64
67
 
65
68
  ## 📦 Installation
66
69
 
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)
70
+ csonpath is a C library at its core. Pick the instructions for the language you want to use it from.
71
71
 
72
72
  ### C (json-c)
73
+
74
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [json-c](https://github.com/json-c/json-c).
75
+
73
76
  Just include the header in your project. There is no separate install step required:
74
77
  ```c
75
78
  #include "csonpath_json-c.h"
@@ -79,21 +82,23 @@ Make sure to link against `json-c` when compiling:
79
82
  gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
80
83
  ```
81
84
 
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.
85
+ ### C (yyjson)
84
86
 
85
- ```sh
86
- cd rust
87
- cargo build
88
- cargo test
89
- ```
87
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [yyjson](https://github.com/ibireme/yyjson).
90
88
 
91
- To use it from C, include the backend header and link against the produced static library:
92
89
  ```c
93
- #include "rust/csonpath_rust_backend.h"
90
+ #include "csonpath_yyjson.h"
91
+ ```
92
+
93
+ Link against `yyjson` when compiling:
94
+ ```sh
95
+ gcc myapp.c -o myapp $(pkg-config --cflags --libs yyjson)
94
96
  ```
95
97
 
96
98
  ### Python
99
+
100
+ **Prerequisites:** Python 3.x.
101
+
97
102
  Install from PyPI:
98
103
  ```sh
99
104
  pip install csonpath
@@ -106,6 +111,23 @@ pip install .
106
111
  make pip-dev
107
112
  ```
108
113
 
114
+ ### Rust
115
+
116
+ **Prerequisites:** Rust toolchain.
117
+
118
+ The Rust crate is located in `rust/`. Build and test it with:
119
+ ```sh
120
+ cd rust
121
+ cargo build
122
+ cargo test
123
+ ```
124
+
125
+ To depend on it from another Rust project:
126
+ ```toml
127
+ [dependencies]
128
+ csonpath = { path = "rust" }
129
+ ```
130
+
109
131
  ---
110
132
 
111
133
  ## 🛠️ Usage
@@ -186,6 +208,8 @@ p.update_or_create_callback(dst, my_sync_fn, userdata)
186
208
 
187
209
  ## 📘 C API Reference
188
210
 
211
+ 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.
212
+
189
213
  ```c
190
214
  struct csonpath *csonpath_new(const char *path);
191
215
  ```
@@ -328,17 +352,47 @@ echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
328
352
 
329
353
  ---
330
354
 
355
+ ## 🧩 Using Multiple Backends
356
+
357
+ 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.
358
+
359
+ For example, to use both json-c and the immutable yyjson backend in the same file:
360
+
361
+ ```c
362
+ #define CSONPATH_USE_PREFIX
363
+ #include "csonpath_json-c.h"
364
+
365
+ #undef CSONPATH_USE_PREFIX
366
+ #include "csonpath_yyjson_const.h"
367
+ ```
368
+
369
+ To use both yyjson backends (immutable and mutable) together, include the aggregator header:
370
+
371
+ ```c
372
+ #include "csonpath_yyjson.h"
373
+ ```
374
+
375
+ When using the mutable yyjson backend, assign the document pointer to `backend_ctx` before mutable operations:
376
+
377
+ ```c
378
+ struct csonpath *mp = yyjson_mut_csonpath_new("$.a");
379
+ mp->backend_ctx = mdoc;
380
+ yyjson_mut_csonpath_update_or_create(mp, mroot, new_val);
381
+ ```
382
+
383
+ ---
384
+
331
385
  ## 🔌 Custom Backends
332
386
 
333
- csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
387
+ 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
388
 
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.
389
+ 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
390
 
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
391
+ Existing backend adapters:
392
+ - `csonpath_json-c.h` — json-c values
393
+ - `csonpath_yyjson.h` — yyjson values
394
+ - `csonpath_python.c` — Python C API values (used by the Python bindings)
395
+ - `rust/csonpath_rust_backend.h` — Rust `serde_json::Value` (used by the Rust crate)
342
396
 
343
397
  ---
344
398
 
@@ -375,7 +429,7 @@ make tests
375
429
  | `csonpath_json-c.h` | json-c backend |
376
430
  | `csonpath_yyjson.h` | yyjson backend |
377
431
  | `csonpath_python.c` | Python C extension backend |
378
- | `rust/` | Rust backend (safe API, FFI, C glue) |
432
+ | `rust/` | Rust crate and its C backend adapter |
379
433
  | `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
380
434
  | `tests/` | C and Python test suites |
381
435
  | `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.19.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
 
@@ -30,6 +30,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
30
30
  | Array index | `$.array[0]` | Access by zero-based index |
31
31
  | Wildcard `[*]` | `$.array[*].field` | Iterate all array elements |
32
32
  | Recursive descent `..` | `$..name` | Search recursively for a key |
33
+ | Recursive descent wildcard `..*` | `$..*` | Return all descendants |
33
34
  | Union `,` (inside brackets) | `$['a','b']`, `$.array[0,1]`, `$.items[?n==1, ?n==2]` | Match all listed selectors at once |
34
35
  | OR fallback `\|` | `$.a \| $.b` | Try the left path first; fall back to the right one if it does not match. Only the first successful path is used. |
35
36
  | Filters | `$.items[?price > 10]` | Filter array elements |
@@ -37,6 +38,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
37
38
  | Multiple filters (`&`) | `$.items[?a=1 & b=2]` | Combine conditions |
38
39
  | Subpath expressions | `$.obj[$.key]` | Use JSON values as dynamic path keys |
39
40
  | `@` current object | `$.items[?@.price > 10]` | Reference the current element in filters |
41
+ | Type selectors | `$..["@odata.id"]@string()`, `$.*@integer()` | Filter matches by JSON type (`string`, `integer`, `null`) |
40
42
 
41
43
  ### Operations
42
44
  - **Find First** — retrieve the first match.
@@ -63,6 +65,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
63
65
  - [C API Reference](#-c-api-reference)
64
66
  - [Python API Reference](#-python-api-reference)
65
67
  - [CLI](#%EF%B8%8F-cli)
68
+ - [Using Multiple Backends](#-using-multiple-backends)
66
69
  - [Custom Backends](#-custom-backends)
67
70
  - [Running Tests](#-running-tests)
68
71
  - [Directory Structure](#-directory-structure)
@@ -73,12 +76,12 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
73
76
 
74
77
  ## 📦 Installation
75
78
 
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)
79
+ csonpath is a C library at its core. Pick the instructions for the language you want to use it from.
80
80
 
81
81
  ### C (json-c)
82
+
83
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [json-c](https://github.com/json-c/json-c).
84
+
82
85
  Just include the header in your project. There is no separate install step required:
83
86
  ```c
84
87
  #include "csonpath_json-c.h"
@@ -88,21 +91,23 @@ Make sure to link against `json-c` when compiling:
88
91
  gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
89
92
  ```
90
93
 
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.
94
+ ### C (yyjson)
93
95
 
94
- ```sh
95
- cd rust
96
- cargo build
97
- cargo test
98
- ```
96
+ **Prerequisites:** C compiler (`gcc`, `clang`, or `tcc`), [yyjson](https://github.com/ibireme/yyjson).
99
97
 
100
- To use it from C, include the backend header and link against the produced static library:
101
98
  ```c
102
- #include "rust/csonpath_rust_backend.h"
99
+ #include "csonpath_yyjson.h"
100
+ ```
101
+
102
+ Link against `yyjson` when compiling:
103
+ ```sh
104
+ gcc myapp.c -o myapp $(pkg-config --cflags --libs yyjson)
103
105
  ```
104
106
 
105
107
  ### Python
108
+
109
+ **Prerequisites:** Python 3.x.
110
+
106
111
  Install from PyPI:
107
112
  ```sh
108
113
  pip install csonpath
@@ -115,6 +120,23 @@ pip install .
115
120
  make pip-dev
116
121
  ```
117
122
 
123
+ ### Rust
124
+
125
+ **Prerequisites:** Rust toolchain.
126
+
127
+ The Rust crate is located in `rust/`. Build and test it with:
128
+ ```sh
129
+ cd rust
130
+ cargo build
131
+ cargo test
132
+ ```
133
+
134
+ To depend on it from another Rust project:
135
+ ```toml
136
+ [dependencies]
137
+ csonpath = { path = "rust" }
138
+ ```
139
+
118
140
  ---
119
141
 
120
142
  ## 🛠️ Usage
@@ -195,6 +217,8 @@ p.update_or_create_callback(dst, my_sync_fn, userdata)
195
217
 
196
218
  ## 📘 C API Reference
197
219
 
220
+ 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.
221
+
198
222
  ```c
199
223
  struct csonpath *csonpath_new(const char *path);
200
224
  ```
@@ -337,17 +361,47 @@ echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
337
361
 
338
362
  ---
339
363
 
364
+ ## 🧩 Using Multiple Backends
365
+
366
+ 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.
367
+
368
+ For example, to use both json-c and the immutable yyjson backend in the same file:
369
+
370
+ ```c
371
+ #define CSONPATH_USE_PREFIX
372
+ #include "csonpath_json-c.h"
373
+
374
+ #undef CSONPATH_USE_PREFIX
375
+ #include "csonpath_yyjson_const.h"
376
+ ```
377
+
378
+ To use both yyjson backends (immutable and mutable) together, include the aggregator header:
379
+
380
+ ```c
381
+ #include "csonpath_yyjson.h"
382
+ ```
383
+
384
+ When using the mutable yyjson backend, assign the document pointer to `backend_ctx` before mutable operations:
385
+
386
+ ```c
387
+ struct csonpath *mp = yyjson_mut_csonpath_new("$.a");
388
+ mp->backend_ctx = mdoc;
389
+ yyjson_mut_csonpath_update_or_create(mp, mroot, new_val);
390
+ ```
391
+
392
+ ---
393
+
340
394
  ## 🔌 Custom Backends
341
395
 
342
- csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
396
+ 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
397
 
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.
398
+ 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
399
 
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
400
+ Existing backend adapters:
401
+ - `csonpath_json-c.h` — json-c values
402
+ - `csonpath_yyjson.h` — yyjson values
403
+ - `csonpath_python.c` — Python C API values (used by the Python bindings)
404
+ - `rust/csonpath_rust_backend.h` — Rust `serde_json::Value` (used by the Rust crate)
351
405
 
352
406
  ---
353
407
 
@@ -384,7 +438,7 @@ make tests
384
438
  | `csonpath_json-c.h` | json-c backend |
385
439
  | `csonpath_yyjson.h` | yyjson backend |
386
440
  | `csonpath_python.c` | Python C extension backend |
387
- | `rust/` | Rust backend (safe API, FFI, C glue) |
441
+ | `rust/` | Rust crate and its C backend adapter |
388
442
  | `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
389
443
  | `tests/` | C and Python test suites |
390
444
  | `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