csonpath 0.13.0__tar.gz → 0.14.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.13.0 → csonpath-0.14.0}/Makefile +11 -3
  2. {csonpath-0.13.0/csonpath.egg-info → csonpath-0.14.0}/PKG-INFO +1 -1
  3. {csonpath-0.13.0 → csonpath-0.14.0/csonpath.egg-info}/PKG-INFO +1 -1
  4. {csonpath-0.13.0 → csonpath-0.14.0}/csonpath.h +241 -99
  5. {csonpath-0.13.0 → csonpath-0.14.0}/csonpath_do.h +12 -6
  6. {csonpath-0.13.0 → csonpath-0.14.0}/csonpath_json-c.h +6 -0
  7. {csonpath-0.13.0 → csonpath-0.14.0}/csonpath_python.c +20 -2
  8. {csonpath-0.13.0 → csonpath-0.14.0}/csonpath_yyjson.h +6 -0
  9. {csonpath-0.13.0 → csonpath-0.14.0}/pyproject.toml +2 -2
  10. {csonpath-0.13.0 → csonpath-0.14.0}/LICENSE +0 -0
  11. {csonpath-0.13.0 → csonpath-0.14.0}/MANIFEST.in +0 -0
  12. {csonpath-0.13.0 → csonpath-0.14.0}/README.md +0 -0
  13. {csonpath-0.13.0 → csonpath-0.14.0}/configure +0 -0
  14. {csonpath-0.13.0 → csonpath-0.14.0}/csonpath.egg-info/SOURCES.txt +0 -0
  15. {csonpath-0.13.0 → csonpath-0.14.0}/csonpath.egg-info/dependency_links.txt +0 -0
  16. {csonpath-0.13.0 → csonpath-0.14.0}/csonpath.egg-info/requires.txt +0 -0
  17. {csonpath-0.13.0 → csonpath-0.14.0}/csonpath.egg-info/top_level.txt +0 -0
  18. {csonpath-0.13.0 → csonpath-0.14.0}/setup.cfg +0 -0
  19. {csonpath-0.13.0 → csonpath-0.14.0}/setup.py +0 -0
  20. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/.git +0 -0
  21. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/.github/workflows/c-cpp.yml +0 -0
  22. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/.gitignore +0 -0
  23. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/LICENSE +0 -0
  24. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/Makefile +0 -0
  25. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/README.md +0 -0
  26. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/clib.json +0 -0
  27. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/formal_verification.md +0 -0
  28. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/re.c +0 -0
  29. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/re.h +0 -0
  30. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/scripts/exrex.py +0 -0
  31. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/scripts/regex_test.py +0 -0
  32. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/scripts/regex_test_neg.py +0 -0
  33. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/tests/test1.c +0 -0
  34. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/tests/test2.c +0 -0
  35. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/tests/test3.c +0 -0
  36. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/tests/test_compile.c +0 -0
  37. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/tests/test_print.c +0 -0
  38. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/tests/test_rand.c +0 -0
  39. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/tests/test_rand_neg.c +0 -0
  40. {csonpath-0.13.0 → csonpath-0.14.0}/tiny-regex-c/tests/test_thread.c +0 -0
@@ -3,7 +3,7 @@ JSON_C_LDFLAGS=$(shell pkg-config --libs json-c)
3
3
 
4
4
  include config.mk
5
5
 
6
- all: test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root
6
+ 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
7
7
 
8
8
  bench:
9
9
  make -C bench
@@ -30,12 +30,20 @@ test-json-filter: tests/json-c/filter.c csonpath_json-c.h csonpath.h csonpath_do
30
30
  test-json-subpath: tests/json-c/subpath.c csonpath_json-c.h csonpath.h csonpath_do.h
31
31
  $(CC) tests/json-c/subpath.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-subpath $(JSON_C_LDFLAGS) $(LDFLAGS)
32
32
 
33
- tests-c: test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root
33
+ test-json-filter-and-missing-key: tests/json-c/filter-and-missing-key.c csonpath_json-c.h csonpath.h csonpath_do.h
34
+ $(CC) tests/json-c/filter-and-missing-key.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-filter-and-missing-key $(JSON_C_LDFLAGS) $(LDFLAGS)
35
+
36
+ test-json-get-array-big-index: tests/json-c/get-array-big-index.c csonpath_json-c.h csonpath.h csonpath_do.h
37
+ $(CC) tests/json-c/get-array-big-index.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-get-array-big-index $(JSON_C_LDFLAGS) $(LDFLAGS)
38
+
39
+ 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
34
40
  ./test-json-c-get-a
35
41
  ./test-json-update
36
42
  ./test-json-filter
37
43
  ./test-json-subpath
38
44
  ./test-json-c-array-root
45
+ ./test-json-filter-and-missing-key
46
+ ./test-json-get-array-big-index
39
47
 
40
48
  pip-dev:
41
49
  pip install -e .[dev] --force-reinstall
@@ -46,5 +54,5 @@ tests-py: pip-dev
46
54
  tests: tests-py tests-c
47
55
 
48
56
  clean:
49
- rm -rvf test-json-c-get-a test-json-update test-json-filter test-json-subpath
57
+ 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
50
58
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.13.0
3
+ Version: 0.14.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.13.0
3
+ Version: 0.14.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -25,32 +25,6 @@ typedef regex_t csonpath_reg_t;
25
25
  typedef regex_t csonpath_reg_t;
26
26
  # endif
27
27
 
28
- # if defined CSONPATH_TINY_REGEX
29
- static inline int csonpath_reg_compile(csonpath_reg_t *out, const char *pat) {
30
- *out = re_compile(pat);
31
- return *out ? 0 : -1;
32
- }
33
- static inline _Bool csonpath_reg_exec(csonpath_reg_t reg, const char *str) {
34
- int match_len = 0;
35
- re_matchp(reg, str, &match_len);
36
- return !!match_len;
37
- }
38
- static inline void csonpath_reg_free(csonpath_reg_t reg) {
39
- free(reg);
40
- }
41
- # elif !defined CSONPATH_PCRE2
42
- static inline int csonpath_reg_compile(csonpath_reg_t *out, const char *pat)
43
- {
44
- return regcomp(out, pat, 0);
45
- }
46
- static inline _Bool csonpath_reg_exec(csonpath_reg_t reg, const char *str)
47
- {
48
- return regexec(&reg, str, 0, NULL, 0) == 0;
49
- }
50
- static inline void csonpath_reg_free(csonpath_reg_t reg) { regfree(&reg); }
51
- # endif
52
- #endif
53
-
54
28
  #if defined CSONPATH_TINY_REGEX
55
29
  # define CSONPATH_HAVE_TINY_REGEX 1
56
30
  #else
@@ -97,12 +71,16 @@ enum csonpath_instuction_raw {
97
71
  CSONPATH_INST_GET_SUBPATH,
98
72
  CSONPATH_INST_GET_ARRAY_SMALL,
99
73
  CSONPATH_INST_GET_ARRAY_BIG,
74
+ CSONPATH_INST_FILTER_KEY_EXIST,
75
+ CSONPATH_INST_FILTER_KEY_TRUE,
76
+ CSONPATH_INST_FILTER_KEY_FALSE,
77
+ CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ,
78
+ CSONPATH_INST_FILTER_KEY_INFERIOR_EQ,
100
79
  CSONPATH_INST_FILTER_KEY_SUPERIOR,
101
80
  CSONPATH_INST_FILTER_KEY_INFERIOR,
102
81
  CSONPATH_INST_FILTER_KEY_EQ,
103
82
  CSONPATH_INST_FILTER_KEY_NOT_EQ,
104
83
  CSONPATH_INST_FILTER_KEY_REG_EQ,
105
- CSONPATH_INST_FILTER_OPERAND_STR,
106
84
  CSONPATH_INST_FILTER_AND,
107
85
  CSONPATH_INST_GET_ALL,
108
86
  CSONPATH_INST_FIND_ALL,
@@ -115,22 +93,26 @@ enum csonpath_instuction_raw {
115
93
  static int csonpath_instuction_len[] = {
116
94
  1, /* 0 CSONPATH_INST_ROOT */
117
95
  -1, /* 1 CSONPATH_INST_GET_OBJ */
118
- 1, /* 1 CSONPATH_INST_GET_SUBPATH */
119
- 2, /* 2 CSONPATH_INST_GET_ARRAY_SMALL */
120
- 5, /* 3 CSONPATH_INST_GET_ARRAY_BIG */
121
- 2, /* 4 CSONPATH_INST_FILTER_KEY_SUPERIOR */
122
- 2, /* 5 CSONPATH_INST_FILTER_KEY_INFERIOR */
123
- 2, /* 6 CSONPATH_INST_FILTER_KEY_EQ */
124
- 2, /* 7 CSONPATH_INST_FILTER_KEY_NOT_EQ */
125
- 2, /* 8 CSONPATH_INST_FILTER_KEY_REG_EQ */
126
- -1, /* 9 CSONPATH_INST_FILTER_OPERAND_STR */
127
- 1, /* 10 CSONPATH_INST_FILTER_AND */
128
- 1, /* 11 CSONPATH_INST_GET_ALL */
129
- -1, /* 12 CSONPATH_INST_FIND_ALL */
130
- 1, /* 13 CSONPATH_INST_RANGE */
131
- 1, /* 14 CSONPATH_INST_OR */
132
- 1, /* 15 CSONPATH_INST_END */
133
- 1, /* 16 CSONPATH_INST_BROKEN */
96
+ 1, /* 2 CSONPATH_INST_GET_SUBPATH */
97
+ 2, /* 3 CSONPATH_INST_GET_ARRAY_SMALL */
98
+ 5, /* 4 CSONPATH_INST_GET_ARRAY_BIG */
99
+ 1, /* 4.5 CSONPATH_INST_FILTER_KEY_EXIST */
100
+ 1, /* 4.6 CSONPATH_INST_FILTER_KEY_TRUE */
101
+ 1, /* 4.7 CSONPATH_INST_FILTER_KEY_FALSE */
102
+ 2, /* 5 CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ */
103
+ 2, /* 6 CSONPATH_INST_FILTER_KEY_INFERIOR_EQ */
104
+ 2, /* 7 CSONPATH_INST_FILTER_KEY_SUPERIOR */
105
+ 2, /* 8 CSONPATH_INST_FILTER_KEY_INFERIOR */
106
+ 2, /* 9 CSONPATH_INST_FILTER_KEY_EQ */
107
+ 2, /* A CSONPATH_INST_FILTER_KEY_NOT_EQ */
108
+ 2, /* B CSONPATH_INST_FILTER_KEY_REG_EQ */
109
+ 1, /* D CSONPATH_INST_FILTER_AND */
110
+ 1, /* E CSONPATH_INST_GET_ALL */
111
+ -1, /* F CSONPATH_INST_FIND_ALL */
112
+ 1, /* 10 CSONPATH_INST_RANGE */
113
+ 1, /* 11 CSONPATH_INST_OR */
114
+ 1, /* 12 CSONPATH_INST_END */
115
+ 1, /* 13 CSONPATH_INST_BROKEN */
134
116
  };
135
117
 
136
118
  /* this should be in an include, but doing so, would break the
@@ -141,12 +123,16 @@ CSONPATH_UNUSED static const char *csonpath_instuction_str[] = {
141
123
  "GET_SUBPATH",
142
124
  "GET_ARRAY_SMALL",
143
125
  "GET_ARRAY_BIG",
126
+ "FILTER_KEY_EXIST",
127
+ "FILTER_KEY_TRUE",
128
+ "FILTER_KEY_FALSE",
129
+ "FILTER_KEY_SUPERIOR_EQ",
130
+ "FILTER_KEY_INFERIOR_EQ",
144
131
  "FILTER_KEY_SUPERIOR",
145
132
  "FILTER_KEY_INFERIOR",
146
133
  "FILTER_KEY_EQ",
147
134
  "FILTER_KEY_NOT_EQ",
148
135
  "FILTER_KEY_REG_EQ",
149
- "FILTER_OPERAND_STR",
150
136
  "FILTER_AND",
151
137
  "GET_ALL",
152
138
  "FIND_ALL",
@@ -175,6 +161,56 @@ struct csonpath {
175
161
  char data[];
176
162
  };
177
163
 
164
+ # if defined CSONPATH_TINY_REGEX
165
+ static inline int csonpath_reg_compile(struct csonpath *cjp, int idx, const char *pat, char **errbuff) {
166
+ (void)errbuff;
167
+ cjp->regexs[idx] = re_compile(pat);
168
+ return cjp->regexs[idx] ? 0 : -1;
169
+ }
170
+ static inline _Bool csonpath_reg_exec(csonpath_reg_t reg, const char *str) {
171
+ int match_len = 0;
172
+ re_matchp(reg, str, &match_len);
173
+ return !!match_len;
174
+ }
175
+ static inline void csonpath_reg_free(csonpath_reg_t reg) {
176
+ free(reg);
177
+ }
178
+ # elif !defined CSONPATH_PCRE2
179
+ static inline int csonpath_reg_compile(struct csonpath *cjp, int idx, const char *pat, char **errbuff)
180
+ {
181
+ (void)errbuff;
182
+ return regcomp(&cjp->regexs[idx], pat, 0);
183
+ }
184
+
185
+ static inline _Bool csonpath_reg_exec(csonpath_reg_t reg, const char *str)
186
+ {
187
+ return regexec(&reg, str, 0, NULL, 0) == 0;
188
+ }
189
+ static inline void csonpath_reg_free(csonpath_reg_t reg) { regfree(&reg); }
190
+ # else
191
+ static inline int csonpath_reg_compile(struct csonpath *cjp, int regex_idx,
192
+ const char *pat, char **errbuff)
193
+ {
194
+ int errorcode;
195
+ PCRE2_SIZE erroroffset;
196
+
197
+ cjp->regexs[regex_idx] = pcre2_compile((unsigned char *)pat,
198
+ PCRE2_ZERO_TERMINATED, 0,
199
+ &errorcode, &erroroffset, NULL);
200
+ if (!cjp->regexs[regex_idx]) {
201
+ static PCRE2_UCHAR buffer[256];
202
+ pcre2_get_error_message(errorcode, buffer, sizeof(buffer));
203
+ *errbuff = (char *)buffer;
204
+ return -1;
205
+ }
206
+ cjp->match_datas[regex_idx] = pcre2_match_data_create_from_pattern(cjp->regexs[regex_idx],
207
+ NULL);
208
+ pcre2_jit_compile(cjp->regexs[regex_idx], PCRE2_JIT_COMPLETE);
209
+ return 0;
210
+ }
211
+ # endif
212
+ #endif
213
+
178
214
  struct csonpath_child_info {
179
215
  int type;
180
216
  MAY_ALIAS union {
@@ -320,8 +356,13 @@ static void csonpath_print_instruction(const struct csonpath cjp[const static 1]
320
356
  printf("0: BROKEN\n");
321
357
  return;
322
358
  }
359
+ int cnt = 0;
323
360
  for (;*walker != CSONPATH_INST_END; walker = csonpath_walker_next_inst(walker)) {
324
361
  printf("%d: %s\n", (int)(intptr_t)(walker - origin), csonpath_instuction_str[(int)*walker]);
362
+ if (cnt++ == 1000) {
363
+ printf("%d: TOO MUCH INSTRUCTION, BAIL OUT\n", (int)(intptr_t)(walker - origin));
364
+ return;
365
+ }
325
366
  }
326
367
  printf("%d: END\n", (int)(intptr_t)(walker - origin));
327
368
  }
@@ -385,6 +426,17 @@ static int csonpath_compile_(struct csonpath *cjp, const char path[static 1], in
385
426
  return ret;
386
427
  }
387
428
 
429
+ static void push_filter_getter(struct csonpath *cjp, int *inst_idx, int nb_getter_inst,
430
+ char filter_getter[static nb_getter_inst])
431
+ {
432
+ char *filter_end = &cjp->data[(*inst_idx)++];
433
+ for (int i = 0; i < nb_getter_inst; ++i) {
434
+ csonpath_push_char(cjp, filter_getter[i], inst_idx);
435
+ }
436
+ *filter_end = (nb_getter_inst - 1);
437
+
438
+ }
439
+
388
440
  static int csonpath_compile_do(struct csonpath *cjp, const char orig[static 1],
389
441
  const char walker[static 1], char tmp[static 1],
390
442
  int *inst_idx, int flag, int end_path,
@@ -459,6 +511,14 @@ root_again:
459
511
  } else if (*walker == '[') {
460
512
  ++walker;
461
513
  getter_end = *walker;
514
+ } else if (*walker == '@') {
515
+ ++walker;
516
+ if (*walker == '[') {
517
+ ++walker;
518
+ getter_end = *walker;
519
+ } else {
520
+ CSONPATH_SKIP('.', walker);
521
+ }
462
522
  }
463
523
  filter_again:
464
524
  if (getter_end) {
@@ -519,17 +579,14 @@ root_again:
519
579
  ++next;
520
580
  }
521
581
 
522
- if (!*next) {
523
- CSONPATH_COMPILE_ERR(tmp, next - orig,
524
- "filter miss condition");
525
-
526
- goto error;
527
- }
528
582
  /* = and == are the same here */
529
583
  if (to_check == '=') {
530
584
  if (next[0] == '=') {
531
- csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_EQ, inst_idx);
532
585
  ++next;
586
+ /* some implementation support === */
587
+ if (next[0] == '=')
588
+ ++next;
589
+ csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_EQ, inst_idx);
533
590
  }
534
591
  #ifndef CSONPATH_NO_REGEX
535
592
  else if (next[0] == '~') {
@@ -545,33 +602,48 @@ root_again:
545
602
  csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_NOT_EQ, inst_idx);
546
603
  ++next;
547
604
  } else if (to_check == '>') {
548
- csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_SUPERIOR, inst_idx);
605
+ if (next[0] == '=') {
606
+ csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ, inst_idx);
607
+ ++next;
608
+ } else {
609
+ csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_SUPERIOR, inst_idx);
610
+ }
549
611
  } else if (to_check == '<') {
550
- csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_INFERIOR, inst_idx);
612
+ if (next[0] == '=') {
613
+ csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_INFERIOR_EQ, inst_idx);
614
+ ++next;
615
+ } else {
616
+ csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_INFERIOR, inst_idx);
617
+ }
618
+ } else if (to_check == ']') {
619
+ if (have_parentesis > 0)
620
+ CSONPATH_COMPILE_ERR(tmp, next - orig, "too many open parentesis");
621
+ csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_EXIST, inst_idx);
622
+ for (;isblank(*next); ++next);
623
+ push_filter_getter(cjp, inst_idx, nb_getter_inst, filter_getter);
624
+ walker = next;
625
+ to_check = *walker;
626
+ goto again;
551
627
  } else {
552
628
  CSONPATH_COMPILE_ERR(tmp, next - orig,
553
629
  "'%c': unsuported operation", to_check);
554
630
  goto error;
555
631
  }
632
+ if (!*next) {
633
+ CSONPATH_COMPILE_ERR(tmp, next - orig,
634
+ "filter miss operand");
635
+
636
+ goto error;
637
+ }
556
638
  operand_instruction = cjp->data[(*inst_idx) - 1];
557
639
  for (;isblank(*next); ++next);
558
- char *filter_end = &cjp->data[(*inst_idx)++];
559
- for (int i = 0; i < nb_getter_inst; ++i) {
560
- csonpath_push_char(cjp, filter_getter[i], inst_idx);
561
- }
562
- *filter_end = (nb_getter_inst - 1);
640
+ push_filter_getter(cjp, inst_idx, nb_getter_inst, filter_getter);
563
641
  walker = next;
564
642
  if (*walker == '"' || *walker == '\'' || *walker == '/') {
565
- if (operand_instruction == CSONPATH_INST_FILTER_KEY_SUPERIOR ||
566
- operand_instruction == CSONPATH_INST_FILTER_KEY_INFERIOR) {
567
- CSONPATH_COMPILE_ERR(tmp, walker - orig, "string unsuported here");
568
- goto error;
569
- }
570
-
571
643
  char end = *walker;
572
644
  ++walker;
573
645
  if (regex_idx < 0) {
574
- csonpath_push_char(cjp, CSONPATH_INST_FILTER_OPERAND_STR, inst_idx);
646
+ csonpath_push_char(cjp, CSONPATH_INST_GET_OBJ, inst_idx);
575
647
  for (next = walker; *next && *next != end; ++next)
576
648
  csonpath_push_char(cjp, *next, inst_idx);
577
649
  csonpath_push_char(cjp, 0, inst_idx);
@@ -594,32 +666,17 @@ root_again:
594
666
  for (next = walker; *next && *next != end; ++next);
595
667
  char *reg_tmp = malloc(next - walker + 1);
596
668
  char *crawler = reg_tmp;
669
+ char *errbuff = NULL;
597
670
  for (next = walker; *next && *next != end; ++next, ++crawler)
598
671
  *crawler = *next;
599
672
  *crawler = 0;
600
- # if defined CSONPATH_PCRE2
601
- int errorcode;
602
- PCRE2_SIZE erroroffset;
603
-
604
- cjp->regexs[regex_idx] = pcre2_compile((unsigned char *)reg_tmp,
605
- PCRE2_ZERO_TERMINATED, 0,
606
- &errorcode, &erroroffset, NULL);
607
- if (!cjp->regexs[regex_idx]) {
608
- PCRE2_UCHAR buffer[256];
609
- pcre2_get_error_message(errorcode, buffer, sizeof(buffer));
610
- CSONPATH_COMPILE_ERR(tmp, next - orig, "regex has error: \"%s\"\n", buffer);
611
- goto error;
612
- }
613
- cjp->match_datas[regex_idx] = pcre2_match_data_create_from_pattern(cjp->regexs[regex_idx],
614
- NULL);
615
- pcre2_jit_compile(cjp->regexs[regex_idx], PCRE2_JIT_COMPLETE);
616
- # else
617
- int e = csonpath_reg_compile(&cjp->regexs[regex_idx], reg_tmp);
673
+
674
+ int e = csonpath_reg_compile(cjp, regex_idx, reg_tmp, &errbuff);
618
675
  if (e) {
619
- CSONPATH_COMPILE_ERR(tmp, next - orig, "regex has error\n");
676
+ CSONPATH_COMPILE_ERR(tmp, next - orig, "regex has error: %s\n",
677
+ errbuff ? errbuff : "(unknow)");
620
678
  goto error;
621
679
  }
622
- # endif
623
680
  free(reg_tmp);
624
681
  }
625
682
  #endif
@@ -627,6 +684,11 @@ root_again:
627
684
  to_check = *next;
628
685
  } else if (*walker == '$') { /* handle subpath here */
629
686
  const char *end_sentinel;
687
+
688
+ if (operand_instruction == CSONPATH_INST_FILTER_KEY_REG_EQ) {
689
+ CSONPATH_COMPILE_ERR(tmp, walker - orig, "subpath unsuported for regex");
690
+ goto error;
691
+ }
630
692
  csonpath_push_char(cjp, CSONPATH_INST_GET_SUBPATH, inst_idx);
631
693
  int ret = csonpath_compile_do(cjp, orig, walker, tmp,
632
694
  inst_idx, flag, ']', &end_sentinel);
@@ -635,6 +697,18 @@ root_again:
635
697
  walker = end_sentinel;
636
698
  next = walker;
637
699
  to_check = *next;
700
+ } else if (!strncmp(walker, "null", 4) && !isalnum(walker[4])) {
701
+ next = walker + 4;
702
+ to_check = *next;
703
+ csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_EXIST, inst_idx);
704
+ } else if (!strncmp(walker, "true", 4) && !isalnum(walker[4])) {
705
+ next = walker + 4;
706
+ to_check = *next;
707
+ csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_TRUE, inst_idx);
708
+ } else if (!strncmp(walker, "false", 5) && !isalnum(walker[5])) {
709
+ next = walker + 5;
710
+ to_check = *next;
711
+ csonpath_push_char(cjp, CSONPATH_INST_FILTER_KEY_FALSE, inst_idx);
638
712
  } else {
639
713
  int n;
640
714
 
@@ -827,7 +901,23 @@ static int csonpath_compile(struct csonpath *cjp, const char path[static 1])
827
901
  static _Bool csonpath_do_match(int operand_instruction, CSONPATH_JSON el2, const char **owalker)
828
902
  {
829
903
  switch (operand_instruction) {
830
- case CSONPATH_INST_FILTER_OPERAND_STR:
904
+ case CSONPATH_INST_FILTER_KEY_TRUE:
905
+ {
906
+ if (!CSONPATH_IS_BOOL(el2))
907
+ return 0;
908
+ return CSONPATH_GET_BOOL(el2) == 1;
909
+ }
910
+ case CSONPATH_INST_FILTER_KEY_FALSE:
911
+ {
912
+ if (!CSONPATH_IS_BOOL(el2))
913
+ return 0;
914
+ return CSONPATH_GET_BOOL(el2) == 0;
915
+ }
916
+ case CSONPATH_INST_FILTER_KEY_EXIST:
917
+ {
918
+ return CSONPATH_IS_NULL(el2);
919
+ }
920
+ case CSONPATH_INST_GET_OBJ:
831
921
  {
832
922
  _Bool ret = CSONPATH_EQUAL_STR(el2, *owalker);
833
923
  *owalker += strlen(*owalker) + 1;
@@ -863,9 +953,8 @@ static CSONPATH_JSON cosnpath_crawl_filter_el(const struct csonpath cjp[const st
863
953
  switch (**owalker) {
864
954
  case CSONPATH_INST_GET_OBJ:
865
955
  ++*owalker;
866
- el2 = CSONPATH_GET(el2, *owalker);
867
- if (!el2)
868
- return NULL;
956
+ if (el2)
957
+ el2 = CSONPATH_GET(el2, *owalker);
869
958
  break;
870
959
  default:
871
960
  CSONPATH_FORMAT_EXCEPTION("unsuported %s inst",
@@ -1240,6 +1329,11 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
1240
1329
  const char **owalker, int operation)
1241
1330
  {
1242
1331
  int operand_instruction = **owalker;
1332
+
1333
+ if (operation == CSONPATH_INST_FILTER_KEY_EXIST) {
1334
+ return el2 != CSONPATH_NULL;
1335
+ }
1336
+
1243
1337
  if (operand_instruction == CSONPATH_INST_GET_SUBPATH) {
1244
1338
  const char *end_sentinel;
1245
1339
  *owalker = csonpath_walker_next_inst(*owalker);
@@ -1261,13 +1355,27 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
1261
1355
  if (CSONPATH_IS_STR(el2) && CSONPATH_IS_STR(jret))
1262
1356
  return (!strcmp(CSONPATH_GET_STR(el2), CSONPATH_GET_STR(jret)));
1263
1357
  return 0;
1358
+ case CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ:
1264
1359
  case CSONPATH_INST_FILTER_KEY_SUPERIOR:
1265
1360
  if (CSONPATH_IS_NUM(el2) && CSONPATH_IS_NUM(jret))
1361
+ if (operation == CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ)
1362
+ return CSONPATH_GET_NUM(el2) >= CSONPATH_GET_NUM(jret);
1266
1363
  return CSONPATH_GET_NUM(el2) > CSONPATH_GET_NUM(jret);
1364
+ if (CSONPATH_IS_STR(el2) && CSONPATH_IS_STR(jret))
1365
+ if (operation == CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ)
1366
+ return strcmp(CSONPATH_GET_STR(el2), CSONPATH_GET_STR(jret)) >= 0;
1367
+ return strcmp(CSONPATH_GET_STR(el2), CSONPATH_GET_STR(jret)) > 0;
1267
1368
  return 0;
1268
1369
  case CSONPATH_INST_FILTER_KEY_INFERIOR:
1370
+ case CSONPATH_INST_FILTER_KEY_INFERIOR_EQ:
1269
1371
  if (CSONPATH_IS_NUM(el2) && CSONPATH_IS_NUM(jret))
1372
+ if (operation == CSONPATH_INST_FILTER_KEY_INFERIOR_EQ)
1373
+ return CSONPATH_GET_NUM(el2) <= CSONPATH_GET_NUM(jret);
1270
1374
  return CSONPATH_GET_NUM(el2) < CSONPATH_GET_NUM(jret);
1375
+ if (CSONPATH_IS_STR(el2) && CSONPATH_IS_STR(jret))
1376
+ if (operation == CSONPATH_INST_FILTER_KEY_INFERIOR_EQ)
1377
+ return strcmp(CSONPATH_GET_STR(el2), CSONPATH_GET_STR(jret)) <= 0;
1378
+ return strcmp(CSONPATH_GET_STR(el2), CSONPATH_GET_STR(jret)) < 0;
1271
1379
  return 0;
1272
1380
  default:
1273
1381
  return 0;
@@ -1275,8 +1383,6 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
1275
1383
  }
1276
1384
  ++*owalker;
1277
1385
 
1278
- if (el2 == CSONPATH_NULL)
1279
- return 0;
1280
1386
  _Bool match = 0;
1281
1387
  switch (operation) {
1282
1388
  case CSONPATH_INST_FILTER_KEY_NOT_EQ:
@@ -1286,22 +1392,58 @@ static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
1286
1392
  match = csonpath_do_match(operand_instruction, el2, owalker);
1287
1393
  break;
1288
1394
  case CSONPATH_INST_FILTER_KEY_SUPERIOR:
1289
- if (!CSONPATH_IS_NUM(el2))
1290
- break;
1291
- match = csonpath_int_from_walker(operand_instruction, owalker) <
1292
- CSONPATH_GET_NUM(el2);
1395
+ case CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ:
1396
+ if (el2 == CSONPATH_NULL)
1397
+ return 0;
1398
+ if (operand_instruction == CSONPATH_INST_GET_OBJ) {
1399
+ if (!CSONPATH_IS_STR(el2))
1400
+ break;
1401
+ if (operation == CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ)
1402
+ match = strcmp(CSONPATH_GET_STR(el2), *owalker) >= 0;
1403
+ else
1404
+ match = strcmp(CSONPATH_GET_STR(el2), *owalker) > 0;
1405
+ *owalker += strlen(*owalker) + 1;
1406
+ } else {
1407
+ if (!CSONPATH_IS_NUM(el2))
1408
+ break;
1409
+ if (operation == CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ)
1410
+ match = csonpath_int_from_walker(operand_instruction, owalker) <=
1411
+ CSONPATH_GET_NUM(el2);
1412
+ else
1413
+ match = csonpath_int_from_walker(operand_instruction, owalker) <
1414
+ CSONPATH_GET_NUM(el2);
1415
+ }
1293
1416
  break;
1417
+ case CSONPATH_INST_FILTER_KEY_INFERIOR_EQ:
1294
1418
  case CSONPATH_INST_FILTER_KEY_INFERIOR:
1295
- if (!CSONPATH_IS_NUM(el2))
1296
- break;
1297
- match = csonpath_int_from_walker(operand_instruction, owalker) >
1298
- CSONPATH_GET_NUM(el2);
1419
+ if (el2 == CSONPATH_NULL)
1420
+ return 0;
1421
+ if (operand_instruction == CSONPATH_INST_GET_OBJ) {
1422
+ if (!CSONPATH_IS_STR(el2))
1423
+ break;
1424
+ if (operation == CSONPATH_INST_FILTER_KEY_INFERIOR_EQ)
1425
+ match = strcmp(CSONPATH_GET_STR(el2), *owalker) <= 0;
1426
+ else
1427
+ match = strcmp(CSONPATH_GET_STR(el2), *owalker) < 0;
1428
+ *owalker += strlen(*owalker) + 1;
1429
+ } else {
1430
+ if (!CSONPATH_IS_NUM(el2))
1431
+ break;
1432
+ if (operation == CSONPATH_INST_FILTER_KEY_INFERIOR_EQ)
1433
+ match = csonpath_int_from_walker(operand_instruction, owalker) >=
1434
+ CSONPATH_GET_NUM(el2);
1435
+ else
1436
+ match = csonpath_int_from_walker(operand_instruction, owalker) >
1437
+ CSONPATH_GET_NUM(el2);
1438
+ }
1299
1439
  break;
1300
1440
  case CSONPATH_INST_FILTER_KEY_REG_EQ:
1301
1441
  #if defined CSONPATH_NO_REGEX
1302
1442
  fprintf(stderr, "regex deactivate");
1303
1443
  return 0;
1304
1444
  #else
1445
+ if (el2 == CSONPATH_NULL)
1446
+ return 0;
1305
1447
 
1306
1448
  if (CSONPATH_IS_STR(el2)) {
1307
1449
  int regex_idx = **owalker;
@@ -161,7 +161,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_dotdot(const struct csonpath cjp[const s
161
161
  CSONPATH_DO_FIND_ALL;
162
162
  }
163
163
  }
164
- } else {
164
+ } else if (CSONPATH_IS_ARRAY(tmp)) {
165
165
  CSONPATH_FOREACH_ARRAY(tmp, el, key_idx) {
166
166
  CSONPATH_DO_FOREACH_PRE_SET;
167
167
  if (CSONPATH_IS_OBJ(el) || CSONPATH_IS_ARRAY(el)) {
@@ -197,11 +197,14 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
197
197
  ctx = CSONPATH_NULL;
198
198
  }
199
199
  break;
200
+ case CSONPATH_INST_FILTER_KEY_EXIST:
200
201
  case CSONPATH_INST_FILTER_KEY_EQ:
201
202
  case CSONPATH_INST_FILTER_KEY_REG_EQ:
202
203
  case CSONPATH_INST_FILTER_KEY_NOT_EQ:
203
204
  case CSONPATH_INST_FILTER_KEY_SUPERIOR:
204
205
  case CSONPATH_INST_FILTER_KEY_INFERIOR:
206
+ case CSONPATH_INST_FILTER_KEY_SUPERIOR_EQ:
207
+ case CSONPATH_INST_FILTER_KEY_INFERIOR_EQ:
205
208
  {
206
209
  CSONPATH_JSON el;
207
210
  int operation_in = *walker, operation = *walker;
@@ -212,9 +215,15 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
212
215
 
213
216
  (void) foreach_idx;
214
217
  CSONPATH_DO_FILTER_PRE_LOOP;
218
+ if (!CSONPATH_IS_ARRAY(tmp)) {
219
+ CSONPATH_DO_FILTER_OUT;
220
+ break;
221
+ }
215
222
  CSONPATH_FOREACH_ARRAY(tmp, el, foreach_idx)
216
223
  {
217
224
  intptr_t key_idx = foreach_idx;
225
+ filter_next = filter_next_in;
226
+ operation = operation_in;
218
227
  (void)key_idx;
219
228
  owalker = next;
220
229
  match_and_or_or:
@@ -226,7 +235,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
226
235
 
227
236
  if (csonpath_make_match(cjp, origin, el2, &owalker, operation)) {
228
237
  if (*owalker == CSONPATH_INST_FILTER_AND) {
229
- ++owalker; /* skip next */
238
+ ++owalker; /* skip and */
230
239
  operation = *owalker;
231
240
  ++owalker;
232
241
  filter_next = *owalker;
@@ -237,9 +246,6 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
237
246
  csonpath_do_internal(cjp, origin, el, tmp, owalker
238
247
  CSONPATH_DO_EXTRA_ARGS_NEESTED);
239
248
  CSONPATH_DO_FILTER_FIND;
240
- } else {
241
- operation = operation_in;
242
- filter_next = filter_next_in;
243
249
  }
244
250
  }
245
251
  }
@@ -385,7 +391,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const
385
391
  this_idx = to_num.n;
386
392
  CSONPATH_PRE_GET(this_idx);
387
393
  tmp = CSONPATH_AT(tmp, to_num.n);
388
- walker += 5;
394
+ walker += 4;
389
395
  if (tmp == CSONPATH_NULL) {
390
396
  CSONPATH_DO_GET_NOTFOUND(this_idx);
391
397
  }
@@ -31,6 +31,8 @@ typedef void (*json_c_callback)(json_object *, struct csonpath_child_info *, jso
31
31
 
32
32
  #define CSONPATH_REMOVE(o) json_object_put(o)
33
33
 
34
+ #define CSONPATH_IS_NULL(o) (o == NULL || json_object_is_type(o, json_type_null))
35
+
34
36
  #define CSONPATH_IS_OBJ(o) json_object_is_type(o, json_type_object)
35
37
 
36
38
  #define CSONPATH_IS_ARRAY(o) json_object_is_type(o, json_type_array)
@@ -39,6 +41,10 @@ typedef void (*json_c_callback)(json_object *, struct csonpath_child_info *, jso
39
41
 
40
42
  #define CSONPATH_IS_NUM(o) json_object_is_type(o, json_type_int)
41
43
 
44
+ #define CSONPATH_IS_BOOL(o) json_object_is_type(o, json_type_boolean)
45
+
46
+ #define CSONPATH_GET_BOOL(o) json_object_get_boolean(o)
47
+
42
48
  #define CSONPATH_GET_STR(obj) \
43
49
  json_object_get_string(obj)
44
50
 
@@ -23,6 +23,13 @@
23
23
 
24
24
  #define CSONPATH_IS_NUM(o) PyLong_Check(o)
25
25
 
26
+ #define CSONPATH_IS_NULL(o) (o == Py_None)
27
+
28
+ #define CSONPATH_IS_BOOL(o) PyBool_Check(o)
29
+
30
+ /* that one assume CSONPATH_IS_BOOL have been called before calling CSONPATH_GET_BOOL */
31
+ #define CSONPATH_GET_BOOL(o) (o == Py_True)
32
+
26
33
  #define CSONPATH_GET_STR(obj) \
27
34
  PyUnicode_AsUTF8(obj)
28
35
 
@@ -264,6 +271,8 @@ static PyObject *find_all(PyCsonPathObject *self, PyObject* args)
264
271
  BAD_ARG();
265
272
 
266
273
  PyObject *ret = csonpath_find_all(self->cp, json);
274
+ if (PyErr_Occurred())
275
+ return NULL;
267
276
 
268
277
  return ret;
269
278
  }
@@ -276,6 +285,8 @@ static PyObject *find_first(PyCsonPathObject *self, PyObject* args)
276
285
  BAD_ARG();
277
286
 
278
287
  PyObject *ret = csonpath_find_first(self->cp, json);
288
+ if (PyErr_Occurred())
289
+ return NULL;
279
290
 
280
291
  Py_INCREF(ret);
281
292
  return ret;
@@ -284,7 +295,7 @@ static PyObject *find_first(PyCsonPathObject *self, PyObject* args)
284
295
  static PyObject *print_instructions(PyCsonPathObject *self, PyObject *args, PyObject *kwds)
285
296
  {
286
297
  csonpath_print_instruction(self->cp);
287
- return Py_None;
298
+ Py_RETURN_NONE;
288
299
  }
289
300
 
290
301
  static PyObject *callback(PyCsonPathObject *self, PyObject* args)
@@ -294,6 +305,8 @@ static PyObject *callback(PyCsonPathObject *self, PyObject* args)
294
305
  if (!PyArg_ParseTuple(args, "OO|O", &json, &callback, &udata))
295
306
  BAD_ARG();
296
307
  int ret = csonpath_callback(self->cp, json, callback, udata);
308
+ if (PyErr_Occurred())
309
+ return NULL;
297
310
  return PyLong_FromLong(ret);
298
311
  }
299
312
 
@@ -304,6 +317,8 @@ static PyObject *do_remove(PyCsonPathObject *self, PyObject* args)
304
317
  if (!PyArg_ParseTuple(args, "O", &json))
305
318
  BAD_ARG();
306
319
  int ret = csonpath_remove(self->cp, json);
320
+ if (PyErr_Occurred())
321
+ return NULL;
307
322
  return PyLong_FromLong(ret);
308
323
  }
309
324
 
@@ -315,7 +330,7 @@ static PyObject *update_or_create(PyCsonPathObject *self, PyObject* args)
315
330
  if (!PyArg_ParseTuple(args, "OO", &json, &value))
316
331
  BAD_ARG();
317
332
  int ret = csonpath_update_or_create(self->cp, json, value);
318
- if (ret < 0) {
333
+ if (PyErr_Occurred() || ret < 0) {
319
334
  return NULL;
320
335
  }
321
336
  return PyLong_FromLong(ret);
@@ -328,6 +343,9 @@ static PyObject *update_or_create_callback(PyCsonPathObject *self, PyObject* arg
328
343
  if (!PyArg_ParseTuple(args, "OO|O", &json, &callback, &udata))
329
344
  BAD_ARG();
330
345
  int ret = csonpath_update_or_create_callback(self->cp, json, callback, udata);
346
+ if (PyErr_Occurred() || ret < 0) {
347
+ return NULL;
348
+ }
331
349
  return PyLong_FromLong(ret);
332
350
  }
333
351
 
@@ -28,6 +28,12 @@
28
28
  #define CSONPATH_IS_STR(obj) (yyjson_get_type(obj) == YYJSON_TYPE_STR)
29
29
  #define CSONPATH_IS_NUM(o) (yyjson_get_type(o) == YYJSON_TYPE_NUM)
30
30
 
31
+ #define CSONPATH_IS_NULL(o) (o == NULL || yyjson_get_type(o) == YYJSON_TYPE_NULL)
32
+
33
+ #define CSONPATH_IS_BOOL(o) (yyjson_get_type(o) == YYJSON_TYPE_BOOL)
34
+
35
+ #define CSONPATH_GET_BOOL(o) yyjson_get_bool(o)
36
+
31
37
  struct csonpath_child_info;
32
38
  typedef void (*yyjson_val_callback)(yyjson_val *, struct csonpath_child_info *, yyjson_val *, void *);
33
39
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "csonpath"
7
- version = "0.13.0"
7
+ version = "0.14.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.13.0"
30
+ current_version = "0.14.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
File without changes
File without changes