csonpath 0.15.0__tar.gz → 0.16.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 (40) hide show
  1. {csonpath-0.15.0 → csonpath-0.16.0}/Makefile +11 -3
  2. {csonpath-0.15.0/csonpath.egg-info → csonpath-0.16.0}/PKG-INFO +3 -2
  3. {csonpath-0.15.0 → csonpath-0.16.0}/README.md +2 -1
  4. {csonpath-0.15.0 → csonpath-0.16.0}/configure +5 -0
  5. {csonpath-0.15.0 → csonpath-0.16.0/csonpath.egg-info}/PKG-INFO +3 -2
  6. {csonpath-0.15.0 → csonpath-0.16.0}/csonpath.h +92 -53
  7. {csonpath-0.15.0 → csonpath-0.16.0}/csonpath_do.h +7 -7
  8. {csonpath-0.15.0 → csonpath-0.16.0}/csonpath_json-c.h +11 -9
  9. {csonpath-0.15.0 → csonpath-0.16.0}/csonpath_python.c +62 -30
  10. {csonpath-0.15.0 → csonpath-0.16.0}/csonpath_yyjson.h +3 -3
  11. {csonpath-0.15.0 → csonpath-0.16.0}/pyproject.toml +2 -2
  12. {csonpath-0.15.0 → csonpath-0.16.0}/LICENSE +0 -0
  13. {csonpath-0.15.0 → csonpath-0.16.0}/MANIFEST.in +0 -0
  14. {csonpath-0.15.0 → csonpath-0.16.0}/csonpath.egg-info/SOURCES.txt +0 -0
  15. {csonpath-0.15.0 → csonpath-0.16.0}/csonpath.egg-info/dependency_links.txt +0 -0
  16. {csonpath-0.15.0 → csonpath-0.16.0}/csonpath.egg-info/requires.txt +0 -0
  17. {csonpath-0.15.0 → csonpath-0.16.0}/csonpath.egg-info/top_level.txt +0 -0
  18. {csonpath-0.15.0 → csonpath-0.16.0}/setup.cfg +0 -0
  19. {csonpath-0.15.0 → csonpath-0.16.0}/setup.py +0 -0
  20. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/.git +0 -0
  21. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/.github/workflows/c-cpp.yml +0 -0
  22. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/.gitignore +0 -0
  23. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/LICENSE +0 -0
  24. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/Makefile +0 -0
  25. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/README.md +0 -0
  26. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/clib.json +0 -0
  27. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/formal_verification.md +0 -0
  28. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/re.c +0 -0
  29. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/re.h +0 -0
  30. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/scripts/exrex.py +0 -0
  31. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/scripts/regex_test.py +0 -0
  32. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/scripts/regex_test_neg.py +0 -0
  33. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/tests/test1.c +0 -0
  34. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/tests/test2.c +0 -0
  35. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/tests/test3.c +0 -0
  36. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/tests/test_compile.c +0 -0
  37. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/tests/test_print.c +0 -0
  38. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/tests/test_rand.c +0 -0
  39. {csonpath-0.15.0 → csonpath-0.16.0}/tiny-regex-c/tests/test_rand_neg.c +0 -0
  40. {csonpath-0.15.0 → csonpath-0.16.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
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
9
9
 
10
10
  YYJSON_TESTS=test-yyjson
11
11
 
@@ -43,10 +43,16 @@ test-json-get-array-big-index: tests/json-c/get-array-big-index.c csonpath_json-
43
43
  test-json-union: tests/json-c/union.c csonpath_json-c.h csonpath.h csonpath_do.h
44
44
  $(CC) tests/json-c/union.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-union $(JSON_C_LDFLAGS) $(LDFLAGS)
45
45
 
46
+ test-json-audit-bugs: tests/json-c/audit-bugs.c csonpath_json-c.h csonpath.h csonpath_do.h
47
+ $(CC) tests/json-c/audit-bugs.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-audit-bugs $(JSON_C_LDFLAGS) $(LDFLAGS)
48
+
49
+ test-json-crash-vectors: tests/json-c/crash-vectors.c csonpath_json-c.h csonpath.h csonpath_do.h
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
+
46
52
  test-yyjson: tests/yyjson/test-yyjson.c csonpath_yyjson.h csonpath.h csonpath_do.h
47
53
  $(CC) tests/yyjson/test-yyjson.c $(EXTRA_FILES) $(YYJSON_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-yyjson $(YYJSON_LDFLAGS) $(LDFLAGS)
48
54
 
49
- 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-yyjson
55
+ 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
50
56
  ./test-json-c-get-a
51
57
  ./test-json-update
52
58
  ./test-json-filter
@@ -55,6 +61,8 @@ test-yyjson: tests/yyjson/test-yyjson.c csonpath_yyjson.h csonpath.h csonpath_do
55
61
  ./test-json-filter-and-missing-key
56
62
  ./test-json-get-array-big-index
57
63
  ./test-json-union
64
+ ./test-json-audit-bugs
65
+ ./test-json-crash-vectors
58
66
  ./test-yyjson
59
67
 
60
68
  pip-dev:
@@ -66,5 +74,5 @@ tests-py: pip-dev
66
74
  tests: tests-py tests-c
67
75
 
68
76
  clean:
69
- 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-yyjson
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
70
78
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -30,7 +30,8 @@ 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
- | Union `\|` / `,` | `$.a \| $.b` or `$['a','b']` | Match multiple paths at once |
33
+ | Union `,` (inside brackets) | `$['a','b']`, `$.array[0,1]`, `$.items[?n==1, ?n==2]` | Match all listed selectors at once |
34
+ | 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. |
34
35
  | Filters | `$.items[?price > 10]` | Filter array elements |
35
36
  | Regex filters | `$.items[?name =~ "foo"]` | POSIX regex-based filtering |
36
37
  | Multiple filters (`&`) | `$.items[?a=1 & b=2]` | Combine conditions |
@@ -21,7 +21,8 @@ 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
- | Union `\|` / `,` | `$.a \| $.b` or `$['a','b']` | Match multiple paths at once |
24
+ | Union `,` (inside brackets) | `$['a','b']`, `$.array[0,1]`, `$.items[?n==1, ?n==2]` | Match all listed selectors at once |
25
+ | 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. |
25
26
  | Filters | `$.items[?price > 10]` | Filter array elements |
26
27
  | Regex filters | `$.items[?name =~ "foo"]` | POSIX regex-based filtering |
27
28
  | Multiple filters (`&`) | `$.items[?a=1 & b=2]` | Combine conditions |
@@ -21,12 +21,17 @@ for arg in $@; do
21
21
  CFLAGS="${CFLAGS} -DCSONPATH_PCRE2_POSIX $(pkg-config --cflags libpcre2-posix)"
22
22
  LDFLAGS="${LDFLAGS} $(pkg-config --libs libpcre2-posix)"
23
23
  fi
24
+ if [ "--asan" = $arg ]; then
25
+ CFLAGS="${CFLAGS} -fsanitize=address -fno-omit-frame-pointer"
26
+ LDFLAGS="${LDFLAGS} -fsanitize=address"
27
+ fi
24
28
  if [ "--help" = $arg ]; then
25
29
  echo "help"
26
30
  echo " --tiny-regex"
27
31
  echo " --pcre2-regex"
28
32
  echo " --pcre2-posix"
29
33
  echo " --no-regex"
34
+ echo " --asan"
30
35
  fi
31
36
  done
32
37
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -30,7 +30,8 @@ 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
- | Union `\|` / `,` | `$.a \| $.b` or `$['a','b']` | Match multiple paths at once |
33
+ | Union `,` (inside brackets) | `$['a','b']`, `$.array[0,1]`, `$.items[?n==1, ?n==2]` | Match all listed selectors at once |
34
+ | 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. |
34
35
  | Filters | `$.items[?price > 10]` | Filter array elements |
35
36
  | Regex filters | `$.items[?name =~ "foo"]` | POSIX regex-based filtering |
36
37
  | Multiple filters (`&`) | `$.items[?a=1 & b=2]` | Combine conditions |
@@ -5,7 +5,7 @@
5
5
  !defined(CSONPATH_EQUAL_STR) || !defined(CSONPATH_CALL_CALLBACK) || \
6
6
  !defined(CSONPATH_FOREACH_EXT) || !defined(CSONPATH_APPEND_AT) || \
7
7
  !defined(CSONPATH_REMOVE_CHILD) || !defined(CSONPATH_NEED_FOREACH_REDO) || \
8
- !defined(CSONPATH_ARRAY_APPEND_INCREF) || !defined(CSONPATH_REMOVE)
8
+ !defined(CSONPATH_ARRAY_APPEND) || !defined(CSONPATH_REMOVE)
9
9
  # error "some definitions are missing"
10
10
  #endif
11
11
 
@@ -48,10 +48,6 @@ typedef regex_t csonpath_reg_t;
48
48
  #define CSONPATH_FIND_ALL_RET_INIT CSONPATH_NEW_ARRAY
49
49
  #endif
50
50
 
51
- #ifndef CSONPATH_DECREF
52
- #define CSONPATH_DECREF(obj)
53
- #endif
54
-
55
51
  #ifndef CSONPATH_FORMAT_EXCEPTION
56
52
  #define CSONPATH_FORMAT_EXCEPTION(args...) fprintf(stderr, args)
57
53
  #endif
@@ -231,6 +227,14 @@ struct csonpath_child_info {
231
227
  #define CSONPATH_ERROR_MAX_SIZE 1024
232
228
  #define CSONPATH_TMP_BUF_SIZE 256
233
229
 
230
+ #define CSONPATH_FILTER_PUSH(dst, cnt, c, walk_ptr) do { \
231
+ if ((cnt + 1) >= CSONPATH_TMP_BUF_SIZE) { \
232
+ CSONPATH_COMPILE_ERR(tmp, walk_ptr - orig, "%s", "filter key too long"); \
233
+ goto error; \
234
+ } \
235
+ (dst)[(cnt)++] = (c); \
236
+ } while (0)
237
+
234
238
  /* I'm assuming error message won't be longer than 125 */
235
239
  #define CSONPATH_COMPILE_ERR(tmp, idx, args...) do { \
236
240
  int ltmp = strlen(tmp), lidx, oidx = idx; \
@@ -455,7 +459,15 @@ static void push_filter_getter(struct csonpath *cjp, int *inst_idx, int nb_gette
455
459
  csonpath_push_char(cjp, filter_getter[i], inst_idx);
456
460
  }
457
461
  *filter_end = (nb_getter_inst - 1);
462
+ }
458
463
 
464
+ static _Bool consonpath_check_tmp_walker(const char tmp_walk[static 1], int cnt_brackets)
465
+ {
466
+ if (!*tmp_walk)
467
+ return 0;
468
+ if (cnt_brackets)
469
+ return 1;
470
+ return (*tmp_walk != ']');
459
471
  }
460
472
 
461
473
  static int csonpath_compile_do(struct csonpath *cjp, const char orig[static 1],
@@ -492,8 +504,9 @@ root_again:
492
504
  do_array:
493
505
  if (!in_union) {
494
506
  int cnt_brackets = 0;
495
- for (const char *tmp_walk = walker + 1;
496
- *tmp_walk && *tmp_walk != ']' && !cnt_brackets;
507
+ const char *tmp_walk;
508
+ for (tmp_walk = walker + 1;
509
+ consonpath_check_tmp_walker(tmp_walk, cnt_brackets);
497
510
  ++tmp_walk) {
498
511
  if (!cnt_brackets && *tmp_walk == ',') {
499
512
  csonpath_push_char(cjp, CSONPATH_INST_GET_UNION, inst_idx);
@@ -504,10 +517,16 @@ root_again:
504
517
  ++cnt_brackets;
505
518
  if (cnt_brackets && *tmp_walk == ']')
506
519
  --cnt_brackets;
507
- if (*tmp_walk == '"')
520
+ if (*tmp_walk == '"') {
508
521
  for (++tmp_walk; *tmp_walk != '"' && *tmp_walk; ++tmp_walk);
509
- if (*tmp_walk == '\'')
510
- for (++tmp_walk; *tmp_walk != '\'' && *tmp_walk; ++tmp_walk);
522
+ }
523
+ else if (*tmp_walk == '\'') {
524
+ for (++tmp_walk; *tmp_walk != '\'' && *tmp_walk; ++tmp_walk);
525
+ }
526
+ if (!*tmp_walk) break;
527
+ }
528
+ if (!tmp_walk[0]) {
529
+ CSONPATH_COMPILE_ERR(tmp, walker - orig, "unclose union");
511
530
  }
512
531
  }
513
532
  ++walker;
@@ -547,7 +566,7 @@ root_again:
547
566
  }
548
567
  filter_again_root:
549
568
  inst = CSONPATH_INST_GET_OBJ;
550
- filter_getter[nb_getter_inst++] = CSONPATH_INST_GET_OBJ;
569
+ CSONPATH_FILTER_PUSH(filter_getter, nb_getter_inst, CSONPATH_INST_GET_OBJ, walker);
551
570
  ++walker;
552
571
 
553
572
  /* skipp blank */
@@ -585,12 +604,12 @@ root_again:
585
604
  }
586
605
  ++walker;
587
606
  for (next = walker; *next != getter_end; ++next)
588
- filter_getter[nb_getter_inst++] = *next;
589
- filter_getter[nb_getter_inst++] = 0;
607
+ CSONPATH_FILTER_PUSH(filter_getter, nb_getter_inst, *next, next);
608
+ CSONPATH_FILTER_PUSH(filter_getter, nb_getter_inst, 0, next);
590
609
  } else {
591
610
  for (next = walker; csonpath_is_dot_operand(*next); ++next)
592
- filter_getter[nb_getter_inst++] = *next;
593
- filter_getter[nb_getter_inst++] = 0;
611
+ CSONPATH_FILTER_PUSH(filter_getter, nb_getter_inst, *next, next);
612
+ CSONPATH_FILTER_PUSH(filter_getter, nb_getter_inst, 0, next);
594
613
  }
595
614
  if (!*next) {
596
615
  CSONPATH_COMPILE_ERR(tmp, next - orig,
@@ -606,11 +625,11 @@ root_again:
606
625
  }
607
626
  if (to_check == '.') {
608
627
  walker = next + 1;
609
- filter_getter[nb_getter_inst++] = CSONPATH_INST_GET_OBJ;
628
+ CSONPATH_FILTER_PUSH(filter_getter, nb_getter_inst, CSONPATH_INST_GET_OBJ, walker);
610
629
  goto filter_again;
611
630
  } else if (to_check == '[') {
612
631
  walker = next + 1;
613
- filter_getter[nb_getter_inst++] = CSONPATH_INST_GET_OBJ;
632
+ CSONPATH_FILTER_PUSH(filter_getter, nb_getter_inst, CSONPATH_INST_GET_OBJ, walker);
614
633
  getter_end = *walker;
615
634
  goto filter_again;
616
635
  }
@@ -896,13 +915,17 @@ root_again:
896
915
  ++walker;
897
916
  next = walker;
898
917
  csonpath_push_char(cjp, inst, inst_idx);
899
- while (*next != end) {
900
- /* \" should be ignored */
918
+ while (*next && *next != end) {
919
+ /* TODO: \" should be ignored */
901
920
  csonpath_push_char(cjp, *next, inst_idx);
902
921
  ++next;
903
922
  while (*next == '\\')
904
923
  ++next;
905
924
  }
925
+ if (!*next) {
926
+ CSONPATH_COMPILE_ERR(tmp, walker - orig,
927
+ "unclosed string in bracket");
928
+ }
906
929
  ++next; // skipp end
907
930
  csonpath_push_char(cjp, 0, inst_idx);
908
931
  if (in_union && *next == ',') {
@@ -1103,7 +1126,7 @@ need_reloop_in = 0;
1103
1126
 
1104
1127
  #define CSONPATH_DO_FIND_ALL_OUT if (end_sentinel) *end_sentinel = walker; return CSONPATH_NULL
1105
1128
 
1106
- #define CSONPATH_DO_EXTRA_DECLATION , const char **end_sentinel
1129
+ #define CSONPATH_DO_EXTRA_DECLARATION , const char **end_sentinel
1107
1130
  #define CSONPATH_DO_EXTRA_ARGS_IN , NULL
1108
1131
  #define CSONPATH_DO_EXTRA_ARGS_NEESTED , end_sentinel
1109
1132
 
@@ -1122,7 +1145,7 @@ need_reloop_in = 0;
1122
1145
 
1123
1146
  #define CSONPATH_DO_FUNC_NAME find_all
1124
1147
  #define CSONPATH_DO_RET_TYPE CSONPATH_FIND_ALL_RET
1125
- #define CSONPATH_DO_RETURN ({CSONPATH_ARRAY_APPEND_INCREF(ret_ar, tmp); return ret_ar;})
1148
+ #define CSONPATH_DO_RETURN ({CSONPATH_ARRAY_APPEND(ret_ar, tmp); return ret_ar;})
1126
1149
 
1127
1150
  #define CSONPATH_DO_FIND_ALL \
1128
1151
  if (tret) ++nb_res; \
@@ -1136,7 +1159,7 @@ need_reloop_in = 0;
1136
1159
  return ret_ar;
1137
1160
 
1138
1161
  #define CSONPATH_DO_EXTRA_ARGS_IN , ret_ar
1139
- #define CSONPATH_DO_EXTRA_DECLATION , CSONPATH_FIND_ALL_RET ret_ar
1162
+ #define CSONPATH_DO_EXTRA_DECLARATION , CSONPATH_FIND_ALL_RET ret_ar
1140
1163
 
1141
1164
  #include "csonpath_do.h"
1142
1165
 
@@ -1158,10 +1181,12 @@ need_reloop_in = 0;
1158
1181
 
1159
1182
  #define CSONPATH_DO_RET_TYPE int
1160
1183
  #define CSONPATH_DO_RETURN \
1161
- ({if (ctx == in_ctx && need_reloop && \
1162
- CSONPATH_NEED_FOREACH_REDO(ctx)) \
1163
- *need_reloop = 1; \
1164
- CSONPATH_REMOVE_CHILD(ctx, child_info); return 1;})
1184
+ ({if (ctx == in_ctx && need_reloop && \
1185
+ CSONPATH_NEED_FOREACH_REDO(ctx)) \
1186
+ *need_reloop = 1; \
1187
+ if (child_info.type == CSONPATH_NONE) \
1188
+ return 0; \
1189
+ CSONPATH_REMOVE_CHILD(ctx, child_info); return 1;})
1165
1190
 
1166
1191
  #define CSONPATH_PRE_GET_OBJ(val) \
1167
1192
  const char *to_del = val;
@@ -1200,7 +1225,7 @@ need_reloop_in = 0;
1200
1225
  nb_res += tret; \
1201
1226
  })
1202
1227
 
1203
- #define CSONPATH_DO_EXTRA_DECLATION , struct csonpath_child_info child_info, int *need_reloop
1228
+ #define CSONPATH_DO_EXTRA_DECLARATION , struct csonpath_child_info child_info, int *need_reloop
1204
1229
 
1205
1230
  #define CSONPATH_DO_EXTRA_ARGS_IN , (struct csonpath_child_info) {.type = CSONPATH_NONE}, NULL
1206
1231
 
@@ -1260,9 +1285,9 @@ again:
1260
1285
  if (child_info->type != CSONPATH_NONE) { \
1261
1286
  if (need_reloop) *need_reloop = 1; \
1262
1287
  if (child_info->type == CSONPATH_INTEGER) \
1263
- return CSONPATH_APPEND_AT(ctx, child_info->idx, to_update); \
1288
+ return CSONPATH_APPEND_AT(ctx, child_info->idx, to_update, 1); \
1264
1289
  else \
1265
- return CSONPATH_APPEND_AT(ctx, child_info->key, to_update); \
1290
+ return CSONPATH_APPEND_AT(ctx, child_info->key, to_update, 1); \
1266
1291
  return 1; \
1267
1292
  } \
1268
1293
  return 0;
@@ -1273,7 +1298,7 @@ again:
1273
1298
  csonpath_child_info_set(&(struct csonpath_child_info ){}, tmp, (intptr_t)key_idx), &need_reloop_in
1274
1299
  #define CSONPATH_DO_EXTRA_ARGS , CSONPATH_JSON to_update
1275
1300
  #define CSONPATH_DO_EXTRA_ARGS_IN , to_update, &(struct csonpath_child_info ){}, NULL
1276
- #define CSONPATH_DO_EXTRA_DECLATION CSONPATH_DO_EXTRA_ARGS, struct csonpath_child_info *child_info, int *need_reloop
1301
+ #define CSONPATH_DO_EXTRA_DECLARATION CSONPATH_DO_EXTRA_ARGS, struct csonpath_child_info *child_info, int *need_reloop
1277
1302
  #define CSONPATH_DO_FIND_ALL nb_res += tret;
1278
1303
  #define CSONPATH_DO_FILTER_FIND CSONPATH_GOTO_ON_RELOOP(filter_again)
1279
1304
 
@@ -1318,7 +1343,7 @@ static int csonpath_sync_root_array(CSONPATH_JSON parent, CSONPATH_JSON to_updat
1318
1343
  (void) idx;
1319
1344
  CSONPATH_ARRAY_CLEAR(parent);
1320
1345
  CSONPATH_FOREACH_ARRAY(to_update, child, idx) {
1321
- if (CSONPATH_APPEND_AT(parent, idx, child) < 0)
1346
+ if (CSONPATH_APPEND_AT(parent, idx, child, 1) < 0)
1322
1347
  return -1;
1323
1348
  }
1324
1349
  return 1;
@@ -1332,7 +1357,7 @@ static int csonpath_sync_root_obj(CSONPATH_JSON parent, CSONPATH_JSON to_update)
1332
1357
  (void )key;
1333
1358
  CSONPATH_OBJ_CLEAR(parent);
1334
1359
  CSONPATH_FOREACH_OBJ(to_update, child, key) {
1335
- if (CSONPATH_APPEND_AT(parent, key, child) < 0)
1360
+ if (CSONPATH_APPEND_AT(parent, key, child, 1) < 0)
1336
1361
  return -1;
1337
1362
  }
1338
1363
  return 1;
@@ -1342,14 +1367,14 @@ static int csonpath_sync_root_obj(CSONPATH_JSON parent, CSONPATH_JSON to_update)
1342
1367
  #define CSONPATH_UPDATE_CHECK_EXIST(mk_cnt) \
1343
1368
  if (tmp == CSONPATH_NULL) { \
1344
1369
  int append_ret = 0; \
1370
+ if (child_info->type == CSONPATH_NONE) \
1371
+ CSONPATH_GETTER_ERR("CSONPATH_NONE is nope\n"); \
1345
1372
  tmp = mk_cnt(); \
1346
1373
  if (child_info->type == CSONPATH_INTEGER) \
1347
- append_ret = CSONPATH_APPEND_AT(ctx, child_info->idx, tmp); \
1374
+ append_ret = CSONPATH_APPEND_AT(ctx, child_info->idx, tmp, 1); \
1348
1375
  else if (child_info->type == CSONPATH_STR) \
1349
- append_ret = CSONPATH_APPEND_AT(ctx, child_info->key, tmp); \
1350
- else \
1351
- CSONPATH_GETTER_ERR("CSONPATH_NONE is nope\n"); \
1352
- CSONPATH_DECREF(tmp); \
1376
+ append_ret = CSONPATH_APPEND_AT(ctx, child_info->key, tmp, 1); \
1377
+ CSONPATH_REMOVE(tmp); \
1353
1378
  if (append_ret < 0) return append_ret; \
1354
1379
  ctx = tmp; \
1355
1380
  }
@@ -1370,7 +1395,6 @@ static int csonpath_sync_root_obj(CSONPATH_JSON parent, CSONPATH_JSON to_update)
1370
1395
  csonpath_child_info_set(child_info, tmp, this_idx);
1371
1396
 
1372
1397
 
1373
-
1374
1398
  #include "csonpath_do.h"
1375
1399
 
1376
1400
  /* callback */
@@ -1381,18 +1405,26 @@ static int csonpath_sync_root_obj(CSONPATH_JSON parent, CSONPATH_JSON to_update)
1381
1405
  #define CSONPATH_DO_RET_TYPE int
1382
1406
  #define CSONPATH_DO_FUNC_NAME callback
1383
1407
  #define CSONPATH_DO_RETURN do { \
1384
- CSONPATH_CALL_CALLBACK(callback, ctx, child_info, tmp, udata); return 1;} \
1385
- while (0)
1408
+ if (CSONPATH_CALL_CALLBACK(callback, ctx, child_info, tmp, udata) < 0) \
1409
+ return -1; \
1410
+ return 1;} \
1411
+ while (0)
1412
+
1413
+ #define CSONPATH_DO_PRE_OPERATION \
1414
+ if (callback == NULL) { \
1415
+ CSONPATH_GETTER_ERR("callback is NULL\n"); \
1416
+ return -1; \
1417
+ }
1386
1418
 
1387
1419
  #define CSONPATH_DO_EXTRA_ARGS_FIND_ALL , callback, udata, child_info
1388
1420
  #define CSONPATH_DO_EXTRA_ARGS_NEESTED , callback, udata, \
1389
1421
  csonpath_child_info_set(child_info, tmp, (intptr_t)key_idx)
1390
1422
  #define CSONPATH_DO_EXTRA_ARGS , CSONPATH_CALLBACK callback, CSONPATH_CALLBACK_DATA udata
1391
1423
  #define CSONPATH_DO_EXTRA_ARGS_IN , callback, udata, &(struct csonpath_child_info ){}
1392
- #define CSONPATH_DO_EXTRA_DECLATION CSONPATH_DO_EXTRA_ARGS, struct csonpath_child_info *child_info
1424
+ #define CSONPATH_DO_EXTRA_DECLARATION CSONPATH_DO_EXTRA_ARGS, struct csonpath_child_info *child_info
1393
1425
 
1394
- #define CSONPATH_DO_FIND_ALL nb_res += tret;
1395
- #define CSONPATH_DO_FILTER_FIND nb_res += tret;
1426
+ #define CSONPATH_DO_FIND_ALL do { if (tret < 0) return tret; nb_res += tret; } while (0)
1427
+ #define CSONPATH_DO_FILTER_FIND do { if (tret < 0) return tret; nb_res += tret; } while (0)
1396
1428
 
1397
1429
  #define CSONPATH_DO_FIND_ALL_OUT return nb_res;
1398
1430
 
@@ -1408,24 +1440,31 @@ static int csonpath_sync_root_obj(CSONPATH_JSON parent, CSONPATH_JSON to_update)
1408
1440
  #define CSONPATH_DO_DECLARATION \
1409
1441
  int nb_res = 0;
1410
1442
 
1443
+ #define CSONPATH_DO_PRE_OPERATION \
1444
+ if (callback == NULL) { \
1445
+ CSONPATH_GETTER_ERR("callback is NULL\n"); \
1446
+ return -1; \
1447
+ }
1448
+
1411
1449
  #define CSONPATH_DO_RET_TYPE int
1412
1450
  #define CSONPATH_DO_FUNC_NAME update_or_create_callback
1413
1451
  #define CSONPATH_DO_RETURN \
1414
- if (tmp == value) { \
1415
- *need_reloop = 1; \
1416
- } \
1417
- CSONPATH_CALL_CALLBACK(callback, ctx, child_info, tmp, udata); \
1418
- return 1;
1452
+ if (need_reloop && tmp == value) { \
1453
+ *need_reloop = 1; \
1454
+ } \
1455
+ if (CSONPATH_CALL_CALLBACK(callback, ctx, child_info, tmp, udata) < 0) \
1456
+ return -1; \
1457
+ return 1;
1419
1458
 
1420
1459
  #define CSONPATH_DO_EXTRA_ARGS_FIND_ALL , callback, udata, NULL, need_reloop
1421
- #define CSONPATH_DO_EXTRA_ARGS_NEESTED , callback, udata, \
1460
+ #define CSONPATH_DO_EXTRA_ARGS_NEESTED , callback, udata, \
1422
1461
  csonpath_child_info_set(&(struct csonpath_child_info ){}, tmp, (intptr_t)key_idx), \
1423
1462
  &need_reloop_in
1424
1463
  #define CSONPATH_DO_EXTRA_ARGS , CSONPATH_CALLBACK callback, CSONPATH_CALLBACK_DATA udata
1425
1464
  #define CSONPATH_DO_EXTRA_ARGS_IN , callback, udata, &(struct csonpath_child_info ){}, NULL
1426
- #define CSONPATH_DO_EXTRA_DECLATION CSONPATH_DO_EXTRA_ARGS, struct csonpath_child_info *child_info, int *need_reloop
1427
- #define CSONPATH_DO_FIND_ALL nb_res += tret;
1428
- #define CSONPATH_DO_FILTER_FIND CSONPATH_GOTO_ON_RELOOP(filter_again)
1465
+ #define CSONPATH_DO_EXTRA_DECLARATION CSONPATH_DO_EXTRA_ARGS, struct csonpath_child_info *child_info, int *need_reloop
1466
+ #define CSONPATH_DO_FIND_ALL do { if (tret < 0) return tret; nb_res += tret; } while (0)
1467
+ #define CSONPATH_DO_FILTER_FIND do { if (tret < 0) return tret; CSONPATH_GOTO_ON_RELOOP(filter_again); } while (0)
1429
1468
 
1430
1469
  #define CSONPATH_DO_FIND_ALL_PRE_LOOP int need_reloop_in = 0;
1431
1470
 
@@ -1434,7 +1473,7 @@ static int csonpath_sync_root_obj(CSONPATH_JSON parent, CSONPATH_JSON to_update)
1434
1473
  #define CSONPATH_DO_FIND_ALL_OUT return nb_res;
1435
1474
 
1436
1475
  #define CSONPATH_PRE_GET_ROOT \
1437
- int to_check = *walker; \
1476
+ int to_check = walker[1]; \
1438
1477
  if (csonpath_is_endish_inst(to_check)) { \
1439
1478
  CSONPATH_GETTER_ERR("can't update root ($)\n"); \
1440
1479
  return CSONPATH_NONE_FOUND_RET; \
@@ -36,8 +36,8 @@
36
36
  #define CSONPATH_DO_POST_FIND_ARRAY
37
37
  #endif
38
38
 
39
- #ifndef CSONPATH_DO_EXTRA_DECLATION
40
- #define CSONPATH_DO_EXTRA_DECLATION
39
+ #ifndef CSONPATH_DO_EXTRA_DECLARATION
40
+ #define CSONPATH_DO_EXTRA_DECLARATION
41
41
  #endif
42
42
 
43
43
  #ifndef CSONPATH_DO_FIND_ALL_CLEAUP
@@ -121,7 +121,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
121
121
  CSONPATH_JSON origin,
122
122
  CSONPATH_JSON value,
123
123
  CSONPATH_JSON ctx,
124
- const char *walker CSONPATH_DO_EXTRA_DECLATION);
124
+ const char *walker CSONPATH_DO_EXTRA_DECLARATION);
125
125
 
126
126
 
127
127
  #define csonpath_do_dotdot__(name) CATCAT(csonpath_, name, _dotdot)
@@ -132,7 +132,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_dotdot(const struct csonpath cjp[const s
132
132
  CSONPATH_JSON origin,
133
133
  CSONPATH_JSON tmp,
134
134
  CSONPATH_JSON ctx,
135
- const char *walker CSONPATH_DO_EXTRA_DECLATION)
135
+ const char *walker CSONPATH_DO_EXTRA_DECLARATION)
136
136
  {
137
137
  CSONPATH_JSON el;
138
138
  CSONPATH_DO_DECLARATION;
@@ -181,7 +181,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
181
181
  CSONPATH_JSON origin,
182
182
  CSONPATH_JSON value,
183
183
  CSONPATH_JSON ctx,
184
- const char *walker CSONPATH_DO_EXTRA_DECLATION)
184
+ const char *walker CSONPATH_DO_EXTRA_DECLARATION)
185
185
  {
186
186
  CSONPATH_JSON tmp = value;
187
187
  CSONPATH_DO_DECLARATION;
@@ -218,7 +218,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
218
218
  CSONPATH_JSON el;
219
219
  int operation_in = *walker, operation = *walker;
220
220
  const char *owalker;
221
- int filter_next_in = *(walker+1), filter_next = *(walker+1);
221
+ int filter_next_in = (unsigned char)*(walker+1), filter_next = (unsigned char)*(walker+1);
222
222
  const char *next = walker + 2;
223
223
  int foreach_idx;
224
224
 
@@ -504,7 +504,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_(struct csonpath cjp[static 1],
504
504
  #undef CSONPATH_DO_EXTRA_ARGS_IN
505
505
  #undef CSONPATH_DO_EXTRA_ARGS_FIND_ALL
506
506
  #undef CSONPATH_DO_EXTRA_ARGS
507
- #undef CSONPATH_DO_EXTRA_DECLATION
507
+ #undef CSONPATH_DO_EXTRA_DECLARATION
508
508
  #undef CSONPATH_DO_FIND_ALL_PRE_LOOP
509
509
  #undef CSONPATH_DO_FOREACH_PRE_SET
510
510
  #undef CSONPATH_DO_GET_ALL_OUT
@@ -23,7 +23,7 @@ typedef void (*json_c_callback)(json_object *, struct csonpath_child_info *, jso
23
23
  #define CSONPATH_CALLBACK_DATA void *
24
24
 
25
25
  #define CSONPATH_CALL_CALLBACK(callback, ctx, child_info, tmp, udata) \
26
- callback(ctx, child_info, tmp, udata)
26
+ (callback(ctx, child_info, tmp, udata), 0)
27
27
 
28
28
 
29
29
  #define CSONPATH_NEED_FOREACH_REDO(o) \
@@ -122,27 +122,29 @@ typedef void (*json_c_callback)(json_object *, struct csonpath_child_info *, jso
122
122
  #define CSONPATH_NEW_OBJECT() json_object_new_object()
123
123
 
124
124
  static int json_object_try_object_add(struct json_object *obj, const char * const at,
125
- struct json_object *el)
125
+ struct json_object *el, int do_incref)
126
126
  {
127
127
  if (!CSONPATH_IS_OBJ(obj)) {
128
128
  return -1;
129
129
  }
130
+ if (do_incref) json_object_get(el);
130
131
  json_object_object_add(obj, at, el);
131
132
  return 1;
132
133
  }
133
134
 
134
135
  static int json_array_try_put(struct json_object *obj, int at,
135
- struct json_object *el)
136
+ struct json_object *el, int do_incref)
136
137
  {
137
138
  if (!CSONPATH_IS_ARRAY(obj)) {
138
139
  return -1;
139
140
  }
141
+ if (do_incref) json_object_get(el);
140
142
  json_object_array_put_idx(obj, at, el);
141
143
  return 1;
142
144
  }
143
145
 
144
- #define CSONPATH_APPEND_AT(array, at, el) \
145
- _Generic((at), \
146
+ #define CSONPATH_APPEND_AT(array, at, el, do_incref) \
147
+ _Generic((at), \
146
148
  int: json_array_try_put, \
147
149
  unsigned int: json_array_try_put, \
148
150
  long: json_array_try_put, \
@@ -151,11 +153,11 @@ static int json_array_try_put(struct json_object *obj, int at,
151
153
  unsigned long long: json_array_try_put, \
152
154
  const char *: json_object_try_object_add, \
153
155
  char *: json_object_try_object_add \
154
- ) (array, at, el)
156
+ ) (array, at, el, do_incref)
155
157
 
156
- #define CSONPATH_ARRAY_APPEND_INCREF(array, el) ({ \
157
- json_object_get(el); \
158
- json_object_array_add(array, el); \
158
+ #define CSONPATH_ARRAY_APPEND(array, el) ({ \
159
+ json_object_get(el); \
160
+ json_object_array_add(array, el); \
159
161
  })
160
162
 
161
163
  static struct json_object *csonpath_json_c_get(struct json_object *obj,
@@ -33,9 +33,6 @@
33
33
  #define CSONPATH_GET_STR(obj) \
34
34
  PyUnicode_AsUTF8(obj)
35
35
 
36
- #define CSONPATH_DECREF(obj) \
37
- Py_DECREF(obj);
38
-
39
36
  #define CSONPATH_GET_NUM(obj) \
40
37
  PyLong_AsLong(obj)
41
38
 
@@ -68,15 +65,23 @@
68
65
 
69
66
  #define CSONPATH_CALLBACK_DATA PyObject *
70
67
 
71
- #define CSONPATH_CALL_CALLBACK(callback, ctx, child_info, tmp, udata) do { \
68
+ #define CSONPATH_CALL_CALLBACK(callback, ctx, child_info, tmp, udata) \
69
+ ({ \
70
+ int _cb_ok = 0; \
72
71
  PyObject *arglist; \
72
+ PyObject *_cb_ret; \
73
73
  if (child_info->type == CSONPATH_STR) \
74
74
  arglist = Py_BuildValue("(OsOO)", ctx, child_info->key, tmp, udata); \
75
75
  else \
76
76
  arglist = Py_BuildValue("(OiOO)", ctx, child_info->idx, tmp, udata); \
77
- PyObject_CallObject(callback, arglist); \
77
+ _cb_ret = PyObject_CallObject(callback, arglist); \
78
78
  Py_DECREF(arglist); \
79
- } while (0)
79
+ if (!_cb_ret) \
80
+ _cb_ok = -1; \
81
+ else \
82
+ Py_DECREF(_cb_ret); \
83
+ _cb_ok; \
84
+ })
80
85
 
81
86
  /* assuming each modification of the object need to go out of the loop */
82
87
  #define CSONPATH_NEED_FOREACH_REDO(o) 1
@@ -90,13 +95,10 @@
90
95
 
91
96
  #define CSONPATH_ARRAY_APPEND(list, el) PyList_Append(list, el)
92
97
 
93
- /* I don't think incrref is needed with python */
94
- #define CSONPATH_ARRAY_APPEND_INCREF(array, el) ({ \
95
- PyList_Append(array, el); \
96
- })
97
98
 
98
- static int pydict_try_setitemstring(PyObject *obj, const char * const at, PyObject *el)
99
+ static int pydict_try_setitemstring(PyObject *obj, const char * const at, PyObject *el, int do_incref)
99
100
  {
101
+ (void)do_incref;
100
102
  if (!PyDict_Check(obj)) {
101
103
  PyObject* repr = PyObject_Repr(obj);
102
104
  PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
@@ -107,12 +109,18 @@ static int pydict_try_setitemstring(PyObject *obj, const char * const at, PyObj
107
109
  Py_XDECREF(str);
108
110
  return -1;
109
111
  }
110
- PyDict_SetItemString(obj, at, el);
112
+ if (!at) {
113
+ PyErr_SetString(PyExc_TypeError, "dict keys must be strings");
114
+ return -1;
115
+ }
116
+ if (PyDict_SetItemString(obj, at, el) < 0)
117
+ return -1;
111
118
  return 1;
112
119
  }
113
120
 
114
- static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *el)
121
+ static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *el, int do_incref)
115
122
  {
123
+ (void)do_incref;
116
124
  if (!PyList_Check(array)) {
117
125
  PyErr_Format(PyExc_ValueError, "Unable to follow path: List expected");
118
126
  return -1;
@@ -125,23 +133,25 @@ static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *
125
133
  PyList_Insert(array, at, el);
126
134
  } else {
127
135
  Py_INCREF(el);
128
- if (PyList_SetItem(array, at, el) < 0)
129
- Py_DECREF(el);
136
+ if (PyList_SetItem(array, at, el) < 0) {
137
+ Py_DECREF(el);
138
+ return -1;
139
+ }
130
140
  }
131
141
  return 1;
132
142
  }
133
143
 
134
- #define CSONPATH_APPEND_AT(array, at, el) \
135
- _Generic((at), \
136
- int: python_set_or_insert_item, \
137
- unsigned int: python_set_or_insert_item, \
138
- long: python_set_or_insert_item, \
139
- unsigned long: python_set_or_insert_item, \
140
- long long: python_set_or_insert_item, \
141
- unsigned long long: python_set_or_insert_item, \
142
- const char *: pydict_try_setitemstring, \
143
- char *: pydict_try_setitemstring \
144
- ) (array, at, el)
144
+ #define CSONPATH_APPEND_AT(array, at, el, do_incref) \
145
+ _Generic((at), \
146
+ int: python_set_or_insert_item, \
147
+ unsigned int: python_set_or_insert_item, \
148
+ long: python_set_or_insert_item, \
149
+ unsigned long: python_set_or_insert_item, \
150
+ long long: python_set_or_insert_item, \
151
+ unsigned long long: python_set_or_insert_item, \
152
+ const char *: pydict_try_setitemstring, \
153
+ char *: pydict_try_setitemstring \
154
+ ) (array, at, el, do_incref)
145
155
 
146
156
 
147
157
  #ifdef __TINYC__
@@ -193,6 +203,11 @@ static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *
193
203
  CSONPATH_PRAGMA("GCC unroll 8") \
194
204
  for (intptr_t key_idx = 0; key_idx < array_len_; ++key_idx) { \
195
205
  el = PyList_GetItem(obj, key_idx); \
206
+ if (!el) { \
207
+ PyErr_SetString(PyExc_RuntimeError, \
208
+ "list was modified during iteration"); \
209
+ break; \
210
+ } \
196
211
  code \
197
212
  } \
198
213
  }
@@ -298,6 +313,10 @@ static PyObject *find_first(PyCsonPathObject *self, PyObject* args)
298
313
 
299
314
  static PyObject *print_instructions(PyCsonPathObject *self, PyObject *args, PyObject *kwds)
300
315
  {
316
+ if (!self->cp) {
317
+ PyErr_SetString(PyExc_RuntimeError, "compiled path is NULL");
318
+ return NULL;
319
+ }
301
320
  csonpath_print_instruction(self->cp);
302
321
  Py_RETURN_NONE;
303
322
  }
@@ -309,8 +328,9 @@ static PyObject *callback(PyCsonPathObject *self, PyObject* args)
309
328
  if (!PyArg_ParseTuple(args, "OO|O", &json, &callback, &udata))
310
329
  BAD_ARG();
311
330
  int ret = csonpath_callback(self->cp, json, callback, udata);
312
- if (PyErr_Occurred())
331
+ if (PyErr_Occurred() || ret < 0) {
313
332
  return NULL;
333
+ }
314
334
  return PyLong_FromLong(ret);
315
335
  }
316
336
 
@@ -321,7 +341,7 @@ static PyObject *do_remove(PyCsonPathObject *self, PyObject* args)
321
341
  if (!PyArg_ParseTuple(args, "O", &json))
322
342
  BAD_ARG();
323
343
  int ret = csonpath_remove(self->cp, json);
324
- if (PyErr_Occurred())
344
+ if (PyErr_Occurred() || ret < 0)
325
345
  return NULL;
326
346
  return PyLong_FromLong(ret);
327
347
  }
@@ -365,10 +385,22 @@ static void PyCsonPath_dealloc(PyCsonPathObject *self) {
365
385
  static PyObject *PyCsonPath_set_path(PyCsonPathObject *self, PyObject* args) {
366
386
  const char *new_path;
367
387
  if (!PyArg_ParseTuple(args, "s", &new_path))
368
- return Py_False;
388
+ return NULL;
369
389
  if (!new_path) return Py_False;
370
390
 
371
- self->cp = csonpath_set_path(self->cp, new_path);
391
+ struct csonpath *new_cjp = csonpath_new_ex(new_path, CSONPATH_NO_DETROY);
392
+ if (!new_cjp) {
393
+ PyErr_NoMemory();
394
+ return NULL;
395
+ }
396
+ if (new_cjp->compile_error) {
397
+ PyErr_Format(PyExc_ValueError, "compilation fail %s",
398
+ new_cjp->compile_error);
399
+ csonpath_destroy(new_cjp);
400
+ return NULL;
401
+ }
402
+ csonpath_destroy(self->cp);
403
+ self->cp = new_cjp;
372
404
  return Py_True;
373
405
  }
374
406
 
@@ -63,7 +63,7 @@ typedef void (*yyjson_val_callback)(yyjson_val *, struct csonpath_child_info *,
63
63
  })
64
64
 
65
65
  #define CSONPATH_CALL_CALLBACK(callback, ctx, child_info, tmp, udata) \
66
- callback(ctx, child_info, tmp, udata)
66
+ (callback(ctx, child_info, tmp, udata), 0)
67
67
 
68
68
 
69
69
  #define CSONPATH_FOREACH(obj, el, code) \
@@ -111,7 +111,7 @@ typedef void (*yyjson_val_callback)(yyjson_val *, struct csonpath_child_info *,
111
111
  #define CSONPATH_OBJ_CLEAR(o) \
112
112
  fail_on_non_mut(NULL)
113
113
 
114
- #define CSONPATH_APPEND_AT(array, at, el) \
114
+ #define CSONPATH_APPEND_AT(array, at, el, do_incref) \
115
115
  fail_on_non_mut(NULL) \
116
116
 
117
117
 
@@ -134,7 +134,7 @@ struct find_all_ret {
134
134
 
135
135
  #define CSONPATH_FIND_ALL_RET struct find_all_ret *
136
136
 
137
- #define CSONPATH_ARRAY_APPEND_INCREF(ar, o) \
137
+ #define CSONPATH_ARRAY_APPEND(ar, o) \
138
138
  _Generic(ar, \
139
139
  struct find_all_ret *: find_all_append, \
140
140
  yyjson_val *: fail_on_non_mut)(ar, o)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "csonpath"
7
- version = "0.15.0"
7
+ version = "0.16.0"
8
8
  readme = "README.md"
9
9
 
10
10
  [tool.setuptools]
@@ -27,7 +27,7 @@ test-command = "pytest {project}/tests/python"
27
27
  before-build = "choco install mingw -y"
28
28
 
29
29
  [tool.bumpversion]
30
- current_version = "0.15.0"
30
+ current_version = "0.16.0"
31
31
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
32
32
  serialize = ["{major}.{minor}.{patch}"]
33
33
  search = "{current_version}"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes