csonpath 0.16.0__tar.gz → 0.17.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.
- {csonpath-0.16.0 → csonpath-0.17.0}/Makefile +14 -4
- {csonpath-0.16.0/csonpath.egg-info → csonpath-0.17.0}/PKG-INFO +98 -2
- {csonpath-0.16.0 → csonpath-0.17.0}/README.md +97 -1
- {csonpath-0.16.0 → csonpath-0.17.0/csonpath.egg-info}/PKG-INFO +98 -2
- {csonpath-0.16.0 → csonpath-0.17.0}/csonpath.egg-info/SOURCES.txt +1 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/csonpath.h +41 -16
- {csonpath-0.16.0 → csonpath-0.17.0}/csonpath_do.h +2 -2
- {csonpath-0.16.0 → csonpath-0.17.0}/csonpath_json-c.h +10 -0
- csonpath-0.17.0/csonpath_my_fuzzing.h +440 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/csonpath_python.c +106 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/csonpath_yyjson.h +2 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/pyproject.toml +2 -2
- {csonpath-0.16.0 → csonpath-0.17.0}/LICENSE +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/MANIFEST.in +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/configure +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/csonpath.egg-info/dependency_links.txt +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/csonpath.egg-info/requires.txt +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/csonpath.egg-info/top_level.txt +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/setup.cfg +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/setup.py +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/.git +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/.github/workflows/c-cpp.yml +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/.gitignore +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/LICENSE +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/Makefile +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/README.md +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/clib.json +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/formal_verification.md +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/re.c +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/re.h +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/scripts/exrex.py +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/scripts/regex_test.py +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/scripts/regex_test_neg.py +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/tests/test1.c +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/tests/test2.c +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/tests/test3.c +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/tests/test_compile.c +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/tests/test_print.c +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/tests/test_rand.c +0 -0
- {csonpath-0.16.0 → csonpath-0.17.0}/tiny-regex-c/tests/test_rand_neg.c +0 -0
- {csonpath-0.16.0 → csonpath-0.17.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
|
|
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
|
|
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
|
|
18
|
+
.PHONY: all clean tests pip-dev pip-dev bench bench-clean tests-cli
|
|
19
19
|
|
|
20
20
|
CFLAGS+= -Wall -Wextra -Wno-unused-function -Wno-unused-parameter -O0 -g
|
|
21
21
|
|
|
@@ -49,10 +49,13 @@ test-json-audit-bugs: tests/json-c/audit-bugs.c csonpath_json-c.h csonpath.h cso
|
|
|
49
49
|
test-json-crash-vectors: tests/json-c/crash-vectors.c csonpath_json-c.h csonpath.h csonpath_do.h
|
|
50
50
|
$(CC) tests/json-c/crash-vectors.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-crash-vectors $(JSON_C_LDFLAGS) $(LDFLAGS)
|
|
51
51
|
|
|
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
|
+
$(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
|
+
|
|
52
55
|
test-yyjson: tests/yyjson/test-yyjson.c csonpath_yyjson.h csonpath.h csonpath_do.h
|
|
53
56
|
$(CC) tests/yyjson/test-yyjson.c $(EXTRA_FILES) $(YYJSON_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-yyjson $(YYJSON_LDFLAGS) $(LDFLAGS)
|
|
54
57
|
|
|
55
|
-
|
|
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
|
|
56
59
|
./test-json-c-get-a
|
|
57
60
|
./test-json-update
|
|
58
61
|
./test-json-filter
|
|
@@ -64,6 +67,13 @@ test-yyjson: tests/yyjson/test-yyjson.c csonpath_yyjson.h csonpath.h csonpath_do
|
|
|
64
67
|
./test-json-audit-bugs
|
|
65
68
|
./test-json-crash-vectors
|
|
66
69
|
./test-yyjson
|
|
70
|
+
./test-json-my-fuzz
|
|
71
|
+
|
|
72
|
+
csonpath: cli/csonpath_cli.c csonpath_json-c.h csonpath.h csonpath_do.h
|
|
73
|
+
$(CC) cli/csonpath_cli.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -I./ -o csonpath $(JSON_C_LDFLAGS) $(LDFLAGS)
|
|
74
|
+
|
|
75
|
+
tests-cli: csonpath
|
|
76
|
+
bash tests/cli/run.sh
|
|
67
77
|
|
|
68
78
|
pip-dev:
|
|
69
79
|
pip install -e .[dev] --force-reinstall
|
|
@@ -74,5 +84,5 @@ tests-py: pip-dev
|
|
|
74
84
|
tests: tests-py tests-c
|
|
75
85
|
|
|
76
86
|
clean:
|
|
77
|
-
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
|
|
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
|
|
78
88
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csonpath
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Description-Content-Type: text/markdown
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Provides-Extra: dev
|
|
@@ -15,7 +15,7 @@ Dynamic: license-file
|
|
|
15
15
|
|
|
16
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.
|
|
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)
|
|
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.
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
@@ -62,6 +62,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
|
|
|
62
62
|
- [Usage](#-usage)
|
|
63
63
|
- [C API Reference](#-c-api-reference)
|
|
64
64
|
- [Python API Reference](#-python-api-reference)
|
|
65
|
+
- [CLI](#%EF%B8%8F-cli)
|
|
65
66
|
- [Custom Backends](#-custom-backends)
|
|
66
67
|
- [Running Tests](#-running-tests)
|
|
67
68
|
- [Directory Structure](#-directory-structure)
|
|
@@ -87,6 +88,20 @@ Make sure to link against `json-c` when compiling:
|
|
|
87
88
|
gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
|
|
88
89
|
```
|
|
89
90
|
|
|
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.
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
cd rust
|
|
96
|
+
cargo build
|
|
97
|
+
cargo test
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
To use it from C, include the backend header and link against the produced static library:
|
|
101
|
+
```c
|
|
102
|
+
#include "rust/csonpath_rust_backend.h"
|
|
103
|
+
```
|
|
104
|
+
|
|
90
105
|
### Python
|
|
91
106
|
Install from PyPI:
|
|
92
107
|
```sh
|
|
@@ -252,6 +267,76 @@ Free the csonpath object.
|
|
|
252
267
|
|
|
253
268
|
---
|
|
254
269
|
|
|
270
|
+
## 🖥️ CLI
|
|
271
|
+
|
|
272
|
+
A standalone C CLI is available in `cli/csonpath_cli.c`. It links directly against `json-c` and the csonpath C core, so it works without Python.
|
|
273
|
+
|
|
274
|
+
```sh
|
|
275
|
+
make csonpath # build ./csonpath
|
|
276
|
+
make tests-cli # run shell tests
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
It reads JSON from stdin, a file (`-f`), or a string (`-s`) and exposes the library operations through action flags.
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
# Get the first match (default)
|
|
283
|
+
echo '{"a": "value", "array": [1, 2, 3]}' | ./csonpath '$.a'
|
|
284
|
+
# => "value"
|
|
285
|
+
|
|
286
|
+
# Find all matches
|
|
287
|
+
echo '{"items": [{"price": 5}, {"price": 15}]}' | ./csonpath -a '$.items[?price > 10]'
|
|
288
|
+
# => [{"price":15}]
|
|
289
|
+
|
|
290
|
+
# One match per line
|
|
291
|
+
echo '{"array": [1, 2, 3]}' | ./csonpath -a -o lines '$.array[*]'
|
|
292
|
+
# => 1
|
|
293
|
+
# => 2
|
|
294
|
+
# => 3
|
|
295
|
+
|
|
296
|
+
# Set or create a value
|
|
297
|
+
echo '{"a": 1}' | ./csonpath --set '42' '$.x.y.z'
|
|
298
|
+
# => {"a":1,"x":{"y":{"z":42}}}
|
|
299
|
+
|
|
300
|
+
# Or with a positional value
|
|
301
|
+
echo '{"a": 1}' | ./csonpath '$.x.y.z' '42'
|
|
302
|
+
|
|
303
|
+
# Remove matches
|
|
304
|
+
echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
|
|
305
|
+
# => {"a":1}
|
|
306
|
+
|
|
307
|
+
# Edit a file in place
|
|
308
|
+
./csonpath -f data.json -p -i --set '"2.0"' '$.version'
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Options
|
|
312
|
+
|
|
313
|
+
| Option | Description |
|
|
314
|
+
|---|---|
|
|
315
|
+
| `-a`, `--all` | Return all matches instead of the first one. |
|
|
316
|
+
| `-d`, `--delete` | Remove matches and print the modified JSON. |
|
|
317
|
+
| `--set VALUE` | Set `PATH` to `VALUE` (JSON). |
|
|
318
|
+
| `VALUE` (positional) | Alternative to `--set`. |
|
|
319
|
+
| `-r`, `--raw` | Treat the value as a raw string. |
|
|
320
|
+
| `-i`, `--in-place` | Edit `FILE` in place (requires `--file`). |
|
|
321
|
+
| `--strict` | Exit with an error if `--delete` removes nothing. |
|
|
322
|
+
| `-f FILE`, `--file FILE` | Read JSON from `FILE` instead of stdin. |
|
|
323
|
+
| `-s JSON`, `--string JSON` | Read JSON from a string. |
|
|
324
|
+
| `-j`, `--jq-like` | Allow jq-style paths without a leading `$`. |
|
|
325
|
+
| `-p`, `--pretty` | Pretty-print JSON output. |
|
|
326
|
+
| `-o {json,pretty,raw,lines}` | Output format (default: `json`). |
|
|
327
|
+
| `-e`, `--empty-array` | Return `[]` instead of nothing when `-a` matches nothing. |
|
|
328
|
+
|
|
329
|
+
### Exit codes
|
|
330
|
+
|
|
331
|
+
| Code | Meaning |
|
|
332
|
+
|---|---|
|
|
333
|
+
| `0` | Success. |
|
|
334
|
+
| `1` | No match found, or `--strict` delete found nothing. |
|
|
335
|
+
| `EINVAL` | Usage error, JSON parse error, JSONPath compilation error, or invalid JSON value. |
|
|
336
|
+
| `errno` | I/O error (e.g. `ENOENT`, `EACCES`). |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
255
340
|
## 🔌 Custom Backends
|
|
256
341
|
|
|
257
342
|
csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
|
|
@@ -260,7 +345,9 @@ To create a custom backend, define the required macros and types in a header fil
|
|
|
260
345
|
|
|
261
346
|
For more details, see the existing backend implementations:
|
|
262
347
|
- `csonpath_json-c.h` — json-c backend
|
|
348
|
+
- `csonpath_yyjson.h` — yyjson backend
|
|
263
349
|
- `csonpath_python.c` — Python backend
|
|
350
|
+
- `rust/csonpath_rust_backend.h` — Rust / serde_json backend
|
|
264
351
|
|
|
265
352
|
---
|
|
266
353
|
|
|
@@ -271,6 +358,12 @@ For more details, see the existing backend implementations:
|
|
|
271
358
|
make tests-c
|
|
272
359
|
```
|
|
273
360
|
|
|
361
|
+
### Rust Tests
|
|
362
|
+
```sh
|
|
363
|
+
cd rust
|
|
364
|
+
cargo test
|
|
365
|
+
```
|
|
366
|
+
|
|
274
367
|
### Python Tests
|
|
275
368
|
```sh
|
|
276
369
|
make tests-py
|
|
@@ -289,7 +382,10 @@ make tests
|
|
|
289
382
|
|---|---|
|
|
290
383
|
| `csonpath.h`, `csonpath_do.h` | Core implementation (header-only style) |
|
|
291
384
|
| `csonpath_json-c.h` | json-c backend |
|
|
385
|
+
| `csonpath_yyjson.h` | yyjson backend |
|
|
292
386
|
| `csonpath_python.c` | Python C extension backend |
|
|
387
|
+
| `rust/` | Rust backend (safe API, FFI, C glue) |
|
|
388
|
+
| `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
|
|
293
389
|
| `tests/` | C and Python test suites |
|
|
294
390
|
| `bench/` | Performance benchmarks |
|
|
295
391
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
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.
|
|
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)
|
|
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.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -53,6 +53,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
|
|
|
53
53
|
- [Usage](#-usage)
|
|
54
54
|
- [C API Reference](#-c-api-reference)
|
|
55
55
|
- [Python API Reference](#-python-api-reference)
|
|
56
|
+
- [CLI](#%EF%B8%8F-cli)
|
|
56
57
|
- [Custom Backends](#-custom-backends)
|
|
57
58
|
- [Running Tests](#-running-tests)
|
|
58
59
|
- [Directory Structure](#-directory-structure)
|
|
@@ -78,6 +79,20 @@ Make sure to link against `json-c` when compiling:
|
|
|
78
79
|
gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
|
|
79
80
|
```
|
|
80
81
|
|
|
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.
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
cd rust
|
|
87
|
+
cargo build
|
|
88
|
+
cargo test
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
To use it from C, include the backend header and link against the produced static library:
|
|
92
|
+
```c
|
|
93
|
+
#include "rust/csonpath_rust_backend.h"
|
|
94
|
+
```
|
|
95
|
+
|
|
81
96
|
### Python
|
|
82
97
|
Install from PyPI:
|
|
83
98
|
```sh
|
|
@@ -243,6 +258,76 @@ Free the csonpath object.
|
|
|
243
258
|
|
|
244
259
|
---
|
|
245
260
|
|
|
261
|
+
## 🖥️ CLI
|
|
262
|
+
|
|
263
|
+
A standalone C CLI is available in `cli/csonpath_cli.c`. It links directly against `json-c` and the csonpath C core, so it works without Python.
|
|
264
|
+
|
|
265
|
+
```sh
|
|
266
|
+
make csonpath # build ./csonpath
|
|
267
|
+
make tests-cli # run shell tests
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
It reads JSON from stdin, a file (`-f`), or a string (`-s`) and exposes the library operations through action flags.
|
|
271
|
+
|
|
272
|
+
```sh
|
|
273
|
+
# Get the first match (default)
|
|
274
|
+
echo '{"a": "value", "array": [1, 2, 3]}' | ./csonpath '$.a'
|
|
275
|
+
# => "value"
|
|
276
|
+
|
|
277
|
+
# Find all matches
|
|
278
|
+
echo '{"items": [{"price": 5}, {"price": 15}]}' | ./csonpath -a '$.items[?price > 10]'
|
|
279
|
+
# => [{"price":15}]
|
|
280
|
+
|
|
281
|
+
# One match per line
|
|
282
|
+
echo '{"array": [1, 2, 3]}' | ./csonpath -a -o lines '$.array[*]'
|
|
283
|
+
# => 1
|
|
284
|
+
# => 2
|
|
285
|
+
# => 3
|
|
286
|
+
|
|
287
|
+
# Set or create a value
|
|
288
|
+
echo '{"a": 1}' | ./csonpath --set '42' '$.x.y.z'
|
|
289
|
+
# => {"a":1,"x":{"y":{"z":42}}}
|
|
290
|
+
|
|
291
|
+
# Or with a positional value
|
|
292
|
+
echo '{"a": 1}' | ./csonpath '$.x.y.z' '42'
|
|
293
|
+
|
|
294
|
+
# Remove matches
|
|
295
|
+
echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
|
|
296
|
+
# => {"a":1}
|
|
297
|
+
|
|
298
|
+
# Edit a file in place
|
|
299
|
+
./csonpath -f data.json -p -i --set '"2.0"' '$.version'
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Options
|
|
303
|
+
|
|
304
|
+
| Option | Description |
|
|
305
|
+
|---|---|
|
|
306
|
+
| `-a`, `--all` | Return all matches instead of the first one. |
|
|
307
|
+
| `-d`, `--delete` | Remove matches and print the modified JSON. |
|
|
308
|
+
| `--set VALUE` | Set `PATH` to `VALUE` (JSON). |
|
|
309
|
+
| `VALUE` (positional) | Alternative to `--set`. |
|
|
310
|
+
| `-r`, `--raw` | Treat the value as a raw string. |
|
|
311
|
+
| `-i`, `--in-place` | Edit `FILE` in place (requires `--file`). |
|
|
312
|
+
| `--strict` | Exit with an error if `--delete` removes nothing. |
|
|
313
|
+
| `-f FILE`, `--file FILE` | Read JSON from `FILE` instead of stdin. |
|
|
314
|
+
| `-s JSON`, `--string JSON` | Read JSON from a string. |
|
|
315
|
+
| `-j`, `--jq-like` | Allow jq-style paths without a leading `$`. |
|
|
316
|
+
| `-p`, `--pretty` | Pretty-print JSON output. |
|
|
317
|
+
| `-o {json,pretty,raw,lines}` | Output format (default: `json`). |
|
|
318
|
+
| `-e`, `--empty-array` | Return `[]` instead of nothing when `-a` matches nothing. |
|
|
319
|
+
|
|
320
|
+
### Exit codes
|
|
321
|
+
|
|
322
|
+
| Code | Meaning |
|
|
323
|
+
|---|---|
|
|
324
|
+
| `0` | Success. |
|
|
325
|
+
| `1` | No match found, or `--strict` delete found nothing. |
|
|
326
|
+
| `EINVAL` | Usage error, JSON parse error, JSONPath compilation error, or invalid JSON value. |
|
|
327
|
+
| `errno` | I/O error (e.g. `ENOENT`, `EACCES`). |
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
246
331
|
## 🔌 Custom Backends
|
|
247
332
|
|
|
248
333
|
csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
|
|
@@ -251,7 +336,9 @@ To create a custom backend, define the required macros and types in a header fil
|
|
|
251
336
|
|
|
252
337
|
For more details, see the existing backend implementations:
|
|
253
338
|
- `csonpath_json-c.h` — json-c backend
|
|
339
|
+
- `csonpath_yyjson.h` — yyjson backend
|
|
254
340
|
- `csonpath_python.c` — Python backend
|
|
341
|
+
- `rust/csonpath_rust_backend.h` — Rust / serde_json backend
|
|
255
342
|
|
|
256
343
|
---
|
|
257
344
|
|
|
@@ -262,6 +349,12 @@ For more details, see the existing backend implementations:
|
|
|
262
349
|
make tests-c
|
|
263
350
|
```
|
|
264
351
|
|
|
352
|
+
### Rust Tests
|
|
353
|
+
```sh
|
|
354
|
+
cd rust
|
|
355
|
+
cargo test
|
|
356
|
+
```
|
|
357
|
+
|
|
265
358
|
### Python Tests
|
|
266
359
|
```sh
|
|
267
360
|
make tests-py
|
|
@@ -280,7 +373,10 @@ make tests
|
|
|
280
373
|
|---|---|
|
|
281
374
|
| `csonpath.h`, `csonpath_do.h` | Core implementation (header-only style) |
|
|
282
375
|
| `csonpath_json-c.h` | json-c backend |
|
|
376
|
+
| `csonpath_yyjson.h` | yyjson backend |
|
|
283
377
|
| `csonpath_python.c` | Python C extension backend |
|
|
378
|
+
| `rust/` | Rust backend (safe API, FFI, C glue) |
|
|
379
|
+
| `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
|
|
284
380
|
| `tests/` | C and Python test suites |
|
|
285
381
|
| `bench/` | Performance benchmarks |
|
|
286
382
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csonpath
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Description-Content-Type: text/markdown
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Provides-Extra: dev
|
|
@@ -15,7 +15,7 @@ Dynamic: license-file
|
|
|
15
15
|
|
|
16
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.
|
|
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)
|
|
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.
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
@@ -62,6 +62,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
|
|
|
62
62
|
- [Usage](#-usage)
|
|
63
63
|
- [C API Reference](#-c-api-reference)
|
|
64
64
|
- [Python API Reference](#-python-api-reference)
|
|
65
|
+
- [CLI](#%EF%B8%8F-cli)
|
|
65
66
|
- [Custom Backends](#-custom-backends)
|
|
66
67
|
- [Running Tests](#-running-tests)
|
|
67
68
|
- [Directory Structure](#-directory-structure)
|
|
@@ -87,6 +88,20 @@ Make sure to link against `json-c` when compiling:
|
|
|
87
88
|
gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
|
|
88
89
|
```
|
|
89
90
|
|
|
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.
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
cd rust
|
|
96
|
+
cargo build
|
|
97
|
+
cargo test
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
To use it from C, include the backend header and link against the produced static library:
|
|
101
|
+
```c
|
|
102
|
+
#include "rust/csonpath_rust_backend.h"
|
|
103
|
+
```
|
|
104
|
+
|
|
90
105
|
### Python
|
|
91
106
|
Install from PyPI:
|
|
92
107
|
```sh
|
|
@@ -252,6 +267,76 @@ Free the csonpath object.
|
|
|
252
267
|
|
|
253
268
|
---
|
|
254
269
|
|
|
270
|
+
## 🖥️ CLI
|
|
271
|
+
|
|
272
|
+
A standalone C CLI is available in `cli/csonpath_cli.c`. It links directly against `json-c` and the csonpath C core, so it works without Python.
|
|
273
|
+
|
|
274
|
+
```sh
|
|
275
|
+
make csonpath # build ./csonpath
|
|
276
|
+
make tests-cli # run shell tests
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
It reads JSON from stdin, a file (`-f`), or a string (`-s`) and exposes the library operations through action flags.
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
# Get the first match (default)
|
|
283
|
+
echo '{"a": "value", "array": [1, 2, 3]}' | ./csonpath '$.a'
|
|
284
|
+
# => "value"
|
|
285
|
+
|
|
286
|
+
# Find all matches
|
|
287
|
+
echo '{"items": [{"price": 5}, {"price": 15}]}' | ./csonpath -a '$.items[?price > 10]'
|
|
288
|
+
# => [{"price":15}]
|
|
289
|
+
|
|
290
|
+
# One match per line
|
|
291
|
+
echo '{"array": [1, 2, 3]}' | ./csonpath -a -o lines '$.array[*]'
|
|
292
|
+
# => 1
|
|
293
|
+
# => 2
|
|
294
|
+
# => 3
|
|
295
|
+
|
|
296
|
+
# Set or create a value
|
|
297
|
+
echo '{"a": 1}' | ./csonpath --set '42' '$.x.y.z'
|
|
298
|
+
# => {"a":1,"x":{"y":{"z":42}}}
|
|
299
|
+
|
|
300
|
+
# Or with a positional value
|
|
301
|
+
echo '{"a": 1}' | ./csonpath '$.x.y.z' '42'
|
|
302
|
+
|
|
303
|
+
# Remove matches
|
|
304
|
+
echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
|
|
305
|
+
# => {"a":1}
|
|
306
|
+
|
|
307
|
+
# Edit a file in place
|
|
308
|
+
./csonpath -f data.json -p -i --set '"2.0"' '$.version'
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Options
|
|
312
|
+
|
|
313
|
+
| Option | Description |
|
|
314
|
+
|---|---|
|
|
315
|
+
| `-a`, `--all` | Return all matches instead of the first one. |
|
|
316
|
+
| `-d`, `--delete` | Remove matches and print the modified JSON. |
|
|
317
|
+
| `--set VALUE` | Set `PATH` to `VALUE` (JSON). |
|
|
318
|
+
| `VALUE` (positional) | Alternative to `--set`. |
|
|
319
|
+
| `-r`, `--raw` | Treat the value as a raw string. |
|
|
320
|
+
| `-i`, `--in-place` | Edit `FILE` in place (requires `--file`). |
|
|
321
|
+
| `--strict` | Exit with an error if `--delete` removes nothing. |
|
|
322
|
+
| `-f FILE`, `--file FILE` | Read JSON from `FILE` instead of stdin. |
|
|
323
|
+
| `-s JSON`, `--string JSON` | Read JSON from a string. |
|
|
324
|
+
| `-j`, `--jq-like` | Allow jq-style paths without a leading `$`. |
|
|
325
|
+
| `-p`, `--pretty` | Pretty-print JSON output. |
|
|
326
|
+
| `-o {json,pretty,raw,lines}` | Output format (default: `json`). |
|
|
327
|
+
| `-e`, `--empty-array` | Return `[]` instead of nothing when `-a` matches nothing. |
|
|
328
|
+
|
|
329
|
+
### Exit codes
|
|
330
|
+
|
|
331
|
+
| Code | Meaning |
|
|
332
|
+
|---|---|
|
|
333
|
+
| `0` | Success. |
|
|
334
|
+
| `1` | No match found, or `--strict` delete found nothing. |
|
|
335
|
+
| `EINVAL` | Usage error, JSON parse error, JSONPath compilation error, or invalid JSON value. |
|
|
336
|
+
| `errno` | I/O error (e.g. `ENOENT`, `EACCES`). |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
255
340
|
## 🔌 Custom Backends
|
|
256
341
|
|
|
257
342
|
csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
|
|
@@ -260,7 +345,9 @@ To create a custom backend, define the required macros and types in a header fil
|
|
|
260
345
|
|
|
261
346
|
For more details, see the existing backend implementations:
|
|
262
347
|
- `csonpath_json-c.h` — json-c backend
|
|
348
|
+
- `csonpath_yyjson.h` — yyjson backend
|
|
263
349
|
- `csonpath_python.c` — Python backend
|
|
350
|
+
- `rust/csonpath_rust_backend.h` — Rust / serde_json backend
|
|
264
351
|
|
|
265
352
|
---
|
|
266
353
|
|
|
@@ -271,6 +358,12 @@ For more details, see the existing backend implementations:
|
|
|
271
358
|
make tests-c
|
|
272
359
|
```
|
|
273
360
|
|
|
361
|
+
### Rust Tests
|
|
362
|
+
```sh
|
|
363
|
+
cd rust
|
|
364
|
+
cargo test
|
|
365
|
+
```
|
|
366
|
+
|
|
274
367
|
### Python Tests
|
|
275
368
|
```sh
|
|
276
369
|
make tests-py
|
|
@@ -289,7 +382,10 @@ make tests
|
|
|
289
382
|
|---|---|
|
|
290
383
|
| `csonpath.h`, `csonpath_do.h` | Core implementation (header-only style) |
|
|
291
384
|
| `csonpath_json-c.h` | json-c backend |
|
|
385
|
+
| `csonpath_yyjson.h` | yyjson backend |
|
|
292
386
|
| `csonpath_python.c` | Python C extension backend |
|
|
387
|
+
| `rust/` | Rust backend (safe API, FFI, C glue) |
|
|
388
|
+
| `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
|
|
293
389
|
| `tests/` | C and Python test suites |
|
|
294
390
|
| `bench/` | Performance benchmarks |
|
|
295
391
|
|
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
# error "some definitions are missing"
|
|
10
10
|
#endif
|
|
11
11
|
|
|
12
|
+
/* Backends that never allocate in GET_STR leave this empty; backends that do
|
|
13
|
+
* (e.g. Rust) define it to the cleanup attribute, see CSONPATH_CLEANUP_STR. */
|
|
14
|
+
#ifndef CSONPATH_CLEANUP_STR
|
|
15
|
+
# define CSONPATH_CLEANUP_STR
|
|
16
|
+
#endif
|
|
17
|
+
|
|
12
18
|
#ifndef CSONPATH_NO_REGEX
|
|
13
19
|
# if defined CSONPATH_TINY_REGEX
|
|
14
20
|
# include <tiny-regex-c/re.h>
|
|
@@ -35,6 +41,10 @@ typedef regex_t csonpath_reg_t;
|
|
|
35
41
|
#define CSONPATH_UNUSED __attribute__((unused))
|
|
36
42
|
#define MAY_ALIAS __attribute__((__may_alias__))
|
|
37
43
|
|
|
44
|
+
#ifndef CSONPATH_STATINLINE
|
|
45
|
+
# define CSONPATH_STATINLINE static inline
|
|
46
|
+
#endif
|
|
47
|
+
|
|
38
48
|
#ifndef CSONPATH_FOREACH
|
|
39
49
|
# define CSONPATH_FOREACH(obj, el, code) \
|
|
40
50
|
CSONPATH_FOREACH_EXT(obj, el, code, key_idx)
|
|
@@ -280,7 +290,7 @@ static inline struct csonpath_child_info *csonpath_child_info_set(struct csonpat
|
|
|
280
290
|
return child_info;
|
|
281
291
|
}
|
|
282
292
|
|
|
283
|
-
|
|
293
|
+
CSONPATH_STATINLINE void csonpath_destroy(struct csonpath *cjp)
|
|
284
294
|
{
|
|
285
295
|
if (!cjp)
|
|
286
296
|
return;
|
|
@@ -314,7 +324,7 @@ static int csonpath_compile_do(struct csonpath *cjp, const char orig[static 1],
|
|
|
314
324
|
int *inst_idx, int flag, int end_path, const char **end_sentinel);
|
|
315
325
|
|
|
316
326
|
|
|
317
|
-
|
|
327
|
+
CSONPATH_STATINLINE struct csonpath *csonpath_new_ex(const char path[static 1], int flag) {
|
|
318
328
|
/*
|
|
319
329
|
* max inst is use so we know, we will never overflow.
|
|
320
330
|
*/
|
|
@@ -340,11 +350,11 @@ static inline struct csonpath *csonpath_new_ex(const char path[static 1], int fl
|
|
|
340
350
|
return ret;
|
|
341
351
|
}
|
|
342
352
|
|
|
343
|
-
|
|
353
|
+
CSONPATH_STATINLINE struct csonpath *csonpath_new(const char path[static 1]) {
|
|
344
354
|
return csonpath_new_ex(path, 0);
|
|
345
355
|
}
|
|
346
356
|
|
|
347
|
-
|
|
357
|
+
CSONPATH_STATINLINE struct csonpath *csonpath_set_path(struct csonpath cjp[static 1],
|
|
348
358
|
const char path[static 1])
|
|
349
359
|
{
|
|
350
360
|
csonpath_destroy(cjp);
|
|
@@ -1524,7 +1534,9 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
|
|
|
1524
1534
|
return CSONPATH_GET_NUM(el2) != CSONPATH_GET_NUM(jret);
|
|
1525
1535
|
}
|
|
1526
1536
|
if (CSONPATH_IS_STR(el2) && CSONPATH_IS_STR(jret)) {
|
|
1527
|
-
|
|
1537
|
+
CSONPATH_CLEANUP_STR const char *s1 = CSONPATH_GET_STR(el2);
|
|
1538
|
+
CSONPATH_CLEANUP_STR const char *s2 = CSONPATH_GET_STR(jret);
|
|
1539
|
+
return (!!strcmp(s1, s2));
|
|
1528
1540
|
}
|
|
1529
1541
|
return 0;
|
|
1530
1542
|
case CSONPATH_INST_FILTER_KEY_EQ:
|
|
@@ -1532,7 +1544,9 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
|
|
|
1532
1544
|
return CSONPATH_GET_NUM(el2) == CSONPATH_GET_NUM(jret);
|
|
1533
1545
|
}
|
|
1534
1546
|
if (CSONPATH_IS_STR(el2) && CSONPATH_IS_STR(jret)) {
|
|
1535
|
-
|
|
1547
|
+
CSONPATH_CLEANUP_STR const char *s1 = CSONPATH_GET_STR(el2);
|
|
1548
|
+
CSONPATH_CLEANUP_STR const char *s2 = CSONPATH_GET_STR(jret);
|
|
1549
|
+
return (!strcmp(s1, s2));
|
|
1536
1550
|
}
|
|
1537
1551
|
return 0;
|
|
1538
1552
|
case CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ:
|
|
@@ -1545,9 +1559,13 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
|
|
|
1545
1559
|
}
|
|
1546
1560
|
if (CSONPATH_IS_STR(el2) && CSONPATH_IS_STR(jret)) {
|
|
1547
1561
|
if (operation == CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ) {
|
|
1548
|
-
|
|
1562
|
+
CSONPATH_CLEANUP_STR const char *s1 = CSONPATH_GET_STR(el2);
|
|
1563
|
+
CSONPATH_CLEANUP_STR const char *s2 = CSONPATH_GET_STR(jret);
|
|
1564
|
+
return strcmp(s1, s2) >= 0;
|
|
1549
1565
|
}
|
|
1550
|
-
|
|
1566
|
+
CSONPATH_CLEANUP_STR const char *s1 = CSONPATH_GET_STR(el2);
|
|
1567
|
+
CSONPATH_CLEANUP_STR const char *s2 = CSONPATH_GET_STR(jret);
|
|
1568
|
+
return strcmp(s1, s2) > 0;
|
|
1551
1569
|
}
|
|
1552
1570
|
return 0;
|
|
1553
1571
|
case CSONPATH_INST_FILTER_KEY_INFERIOR:
|
|
@@ -1560,9 +1578,13 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
|
|
|
1560
1578
|
}
|
|
1561
1579
|
if (CSONPATH_IS_STR(el2) && CSONPATH_IS_STR(jret)) {
|
|
1562
1580
|
if (operation == CSONPATH_INST_FILTER_KEY_INFERIOR_EQ) {
|
|
1563
|
-
|
|
1581
|
+
CSONPATH_CLEANUP_STR const char *s1 = CSONPATH_GET_STR(el2);
|
|
1582
|
+
CSONPATH_CLEANUP_STR const char *s2 = CSONPATH_GET_STR(jret);
|
|
1583
|
+
return strcmp(s1, s2) <= 0;
|
|
1564
1584
|
}
|
|
1565
|
-
|
|
1585
|
+
CSONPATH_CLEANUP_STR const char *s1 = CSONPATH_GET_STR(el2);
|
|
1586
|
+
CSONPATH_CLEANUP_STR const char *s2 = CSONPATH_GET_STR(jret);
|
|
1587
|
+
return strcmp(s1, s2) < 0;
|
|
1566
1588
|
}
|
|
1567
1589
|
return 0;
|
|
1568
1590
|
default:
|
|
@@ -1586,10 +1608,11 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
|
|
|
1586
1608
|
if (operand_instruction == CSONPATH_INST_GET_OBJ) {
|
|
1587
1609
|
if (!CSONPATH_IS_STR(el2))
|
|
1588
1610
|
break;
|
|
1611
|
+
CSONPATH_CLEANUP_STR const char *s = CSONPATH_GET_STR(el2);
|
|
1589
1612
|
if (operation == CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ)
|
|
1590
|
-
match = strcmp(
|
|
1613
|
+
match = strcmp(s, *owalker) >= 0;
|
|
1591
1614
|
else
|
|
1592
|
-
match = strcmp(
|
|
1615
|
+
match = strcmp(s, *owalker) > 0;
|
|
1593
1616
|
*owalker += strlen(*owalker) + 1;
|
|
1594
1617
|
} else {
|
|
1595
1618
|
if (!CSONPATH_IS_NUM(el2))
|
|
@@ -1609,10 +1632,11 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
|
|
|
1609
1632
|
if (operand_instruction == CSONPATH_INST_GET_OBJ) {
|
|
1610
1633
|
if (!CSONPATH_IS_STR(el2))
|
|
1611
1634
|
break;
|
|
1635
|
+
CSONPATH_CLEANUP_STR const char *s = CSONPATH_GET_STR(el2);
|
|
1612
1636
|
if (operation == CSONPATH_INST_FILTER_KEY_INFERIOR_EQ)
|
|
1613
|
-
match = strcmp(
|
|
1637
|
+
match = strcmp(s, *owalker) <= 0;
|
|
1614
1638
|
else
|
|
1615
|
-
match = strcmp(
|
|
1639
|
+
match = strcmp(s, *owalker) < 0;
|
|
1616
1640
|
*owalker += strlen(*owalker) + 1;
|
|
1617
1641
|
} else {
|
|
1618
1642
|
if (!CSONPATH_IS_NUM(el2))
|
|
@@ -1636,10 +1660,11 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
|
|
|
1636
1660
|
if (CSONPATH_IS_STR(el2)) {
|
|
1637
1661
|
int regex_idx = **owalker;
|
|
1638
1662
|
++*owalker;
|
|
1663
|
+
CSONPATH_CLEANUP_STR const char *s = CSONPATH_GET_STR(el2);
|
|
1639
1664
|
# if !defined CSONPATH_PCRE2
|
|
1640
|
-
match = csonpath_reg_exec(cjp->regexs[regex_idx],
|
|
1665
|
+
match = csonpath_reg_exec(cjp->regexs[regex_idx], s);
|
|
1641
1666
|
# else
|
|
1642
|
-
const unsigned char *str = (const unsigned char *)
|
|
1667
|
+
const unsigned char *str = (const unsigned char *)s;
|
|
1643
1668
|
int ret = pcre2_match(cjp->regexs[regex_idx], str, PCRE2_ZERO_TERMINATED, 0,
|
|
1644
1669
|
0, cjp->match_datas[regex_idx], NULL);
|
|
1645
1670
|
|
|
@@ -384,7 +384,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
|
|
|
384
384
|
}
|
|
385
385
|
CSONPATH_DO_POST_FIND_ARRAY;
|
|
386
386
|
} else if (CSONPATH_IS_STR(jret)) {
|
|
387
|
-
const char *this_idx = CSONPATH_GET_STR(jret);
|
|
387
|
+
CSONPATH_CLEANUP_STR const char *this_idx = CSONPATH_GET_STR(jret);
|
|
388
388
|
CSONPATH_PRE_GET_OBJ(this_idx);
|
|
389
389
|
tmp = CSONPATH_GET(tmp, this_idx);
|
|
390
390
|
if (tmp == CSONPATH_NULL) {
|
|
@@ -462,7 +462,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
|
|
|
462
462
|
#define csonpath_do__(name) CAT(csonpath_, name)
|
|
463
463
|
#define csonpath_do_ csonpath_do__(CSONPATH_DO_FUNC_NAME)
|
|
464
464
|
|
|
465
|
-
|
|
465
|
+
CSONPATH_STATINLINE CSONPATH_DO_RET_TYPE csonpath_do_(struct csonpath cjp[static 1],
|
|
466
466
|
CSONPATH_JSON value CSONPATH_DO_EXTRA_ARGS)
|
|
467
467
|
{
|
|
468
468
|
char *walker = cjp->data;
|