csonpath 0.8.0__tar.gz → 0.9.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -40,9 +40,10 @@ Dynamic: license-file
40
40
  - support `..`: `"$..non`
41
41
  - support `[*]`: `"$.array[*].obj[*].field"`
42
42
  - support filters:
43
- - with `>` or `<`: `"$.obj[?.field > 123]"`
44
- - with `=` or '!=': `"$.obj[?.field != "123"]"`
43
+ - with `>` or `<`: `"$.obj[?field > 123]"`
44
+ - with `=` or '!=': `"$.obj[?field != "123"]"`
45
45
  - with regex, using POSIX regcom: `"$.obj[?.field ~= "123"]"`
46
+ - with `&`: `"$.obj[?field != "123" & second = 1]"`
46
47
  - support `|`: `"$.obj | $.otherobj"`
47
48
  ### Functions
48
49
  - **Find First**: Retrieve the first value matching a path.
@@ -31,9 +31,10 @@
31
31
  - support `..`: `"$..non`
32
32
  - support `[*]`: `"$.array[*].obj[*].field"`
33
33
  - support filters:
34
- - with `>` or `<`: `"$.obj[?.field > 123]"`
35
- - with `=` or '!=': `"$.obj[?.field != "123"]"`
34
+ - with `>` or `<`: `"$.obj[?field > 123]"`
35
+ - with `=` or '!=': `"$.obj[?field != "123"]"`
36
36
  - with regex, using POSIX regcom: `"$.obj[?.field ~= "123"]"`
37
+ - with `&`: `"$.obj[?field != "123" & second = 1]"`
37
38
  - support `|`: `"$.obj | $.otherobj"`
38
39
  ### Functions
39
40
  - **Find First**: Retrieve the first value matching a path.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -40,9 +40,10 @@ Dynamic: license-file
40
40
  - support `..`: `"$..non`
41
41
  - support `[*]`: `"$.array[*].obj[*].field"`
42
42
  - support filters:
43
- - with `>` or `<`: `"$.obj[?.field > 123]"`
44
- - with `=` or '!=': `"$.obj[?.field != "123"]"`
43
+ - with `>` or `<`: `"$.obj[?field > 123]"`
44
+ - with `=` or '!=': `"$.obj[?field != "123"]"`
45
45
  - with regex, using POSIX regcom: `"$.obj[?.field ~= "123"]"`
46
+ - with `&`: `"$.obj[?field != "123" & second = 1]"`
46
47
  - support `|`: `"$.obj | $.otherobj"`
47
48
  ### Functions
48
49
  - **Find First**: Retrieve the first value matching a path.
@@ -33,6 +33,14 @@
33
33
  #define CSONPATH_DECREF(obj)
34
34
  #endif
35
35
 
36
+ #ifndef CSONPATH_FORMAT_EXCEPTION
37
+ #define CSONPATH_FORMAT_EXCEPTION(args...) fprintf(stderr, args)
38
+ #endif
39
+
40
+ #ifndef CSONPATH_EXCEPTION
41
+ #define CSONPATH_EXCEPTION(args...) CSONPATH_GETTER_ERR(args)
42
+ #endif
43
+
36
44
  enum csonpath_instuction_raw {
37
45
  CSONPATH_INST_ROOT,
38
46
  CSONPATH_INST_GET_OBJ,
@@ -46,6 +54,7 @@ enum csonpath_instuction_raw {
46
54
  CSONPATH_INST_FILTER_OPERAND_STR,
47
55
  CSONPATH_INST_FILTER_OPERAND_BYTE, /* store the same way it's in ARRAY_SMALL */
48
56
  CSONPATH_INST_FILTER_OPERAND_INT, /* store the same way it's in ARRAY_BIG */
57
+ CSONPATH_INST_FILTER_AND,
49
58
  CSONPATH_INST_GET_ALL,
50
59
  CSONPATH_INST_FIND_ALL,
51
60
  CSONPATH_INST_OR,
@@ -68,6 +77,7 @@ CSONPATH_UNUSED static const char *csonpath_instuction_str[] = {
68
77
  "FILTER_OPERAND_STR",
69
78
  "FILTER_OPERAND_BYTE",
70
79
  "FILTER_OPERAND_INT",
80
+ "FILTER_AND",
71
81
  "GET_ALL",
72
82
  "FIND_ALL",
73
83
  "OR",
@@ -244,13 +254,13 @@ static int csonpath_compile(struct csonpath cjp[static 1])
244
254
  return 0;
245
255
 
246
256
  tmp = strdup(cjp->path);
247
- root_again:
257
+ root_again:
248
258
  CSONPATH_SKIP('$', walker);
249
259
  csonpath_push_inst(cjp, CSONPATH_INST_ROOT, &inst_idx);
250
260
  cjp->inst_lst[inst_idx - 1].next = 1;
251
261
  to_check = *walker;
252
262
 
253
- again:
263
+ again:
254
264
  switch (to_check) {
255
265
  case '[':
256
266
  {
@@ -289,12 +299,18 @@ again:
289
299
  *walker);
290
300
  goto error;
291
301
  }
302
+ filter_again_root:
292
303
  inst = CSONPATH_INST_GET_OBJ;
293
304
  cjp->inst_lst[inst_idx - 1].next += 1;
294
305
  ++walker;
306
+
307
+ /* skipp blank */
308
+ for (; isblank(*walker); ++walker)
309
+ cjp->inst_lst[inst_idx - 1].next += 1;
310
+
295
311
  last_inst = &cjp->inst_lst[inst_idx - 1];
296
312
  if (*walker == '(') {
297
- have_parentesis = 1;
313
+ ++have_parentesis;
298
314
  ++walker;
299
315
  CSONPATH_SKIP('@', walker);
300
316
  if (*walker == '[') {
@@ -356,7 +372,7 @@ again:
356
372
  filter_getter[nb_getter_inst-1].next += 1;
357
373
  ++next;
358
374
  to_check = *next;
359
- have_parentesis = 0;
375
+ have_parentesis--;
360
376
  }
361
377
 
362
378
  walker = next;
@@ -478,19 +494,34 @@ again:
478
494
  csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_INT, &inst_idx);
479
495
  }
480
496
  }
497
+
498
+ /* skip space */
481
499
  if (isblank(to_check)) {
482
500
  for (next++; isblank(*next); ++next);
483
501
  to_check = *next;
484
502
  }
485
503
 
486
- if (have_parentesis) {
504
+ if (to_check == '&') {
505
+ if (next[1] == '&') {
506
+ ++next;
507
+ }
508
+ cjp->inst_lst[inst_idx - 1].next = next - walker + 1;
509
+ walker = next + 1;
510
+ to_check = *walker;
511
+ csonpath_push_inst(cjp, CSONPATH_INST_FILTER_AND, &inst_idx);
512
+ nb_getter_inst = 0;
513
+ goto filter_again_root;
514
+ }
515
+
516
+ while (have_parentesis) {
487
517
  CSONPATH_SKIP(')', next);
488
518
  to_check = *next;
519
+ --have_parentesis;
489
520
  }
521
+
490
522
  if (to_check != ']') {
491
523
  CSONPATH_REQUIRE_ERR(']', next);
492
524
  }
493
- /* skip space */
494
525
  cjp->inst_lst[inst_idx - 1].next = next - walker + 1;
495
526
  walker = next + 1;
496
527
  to_check = *walker;
@@ -656,6 +687,79 @@ static _Bool csonpath_do_match(int operand_instruction, CSONPATH_JSON el2, char
656
687
  return 0;
657
688
  }
658
689
 
690
+ static CSONPATH_JSON cosnpath_crawl_filter_el(struct csonpath cjp[static 1],
691
+ int *idx, char **owalker,
692
+ CSONPATH_JSON el2,
693
+ int filter_next)
694
+ {
695
+
696
+ for (; *idx < filter_next; ++(*idx)) {
697
+ switch (cjp->inst_lst[*idx].inst) {
698
+ case CSONPATH_INST_GET_OBJ:
699
+ el2 = CSONPATH_GET(el2, *owalker);
700
+ break;
701
+ default:
702
+ CSONPATH_FORMAT_EXCEPTION("unsuported %s inst",
703
+ csonpath_instuction_str[cjp->inst_lst[*idx].inst]);
704
+ return NULL;
705
+ }
706
+ (*owalker) += cjp->inst_lst[*idx].next;
707
+ }
708
+ return el2;
709
+ }
710
+
711
+
712
+ static _Bool csonpath_make_match(struct csonpath cjp[static 1],
713
+ struct csonpath_instruction inst[static 1],
714
+ CSONPATH_JSON el2, char *owalker, int operation)
715
+ {
716
+ int operand_instruction = inst->inst;
717
+
718
+ if (el2 == CSONPATH_NULL)
719
+ return 0;
720
+ _Bool match = 0;
721
+ switch (operation) {
722
+ case CSONPATH_INST_FILTER_KEY_NOT_EQ:
723
+ match = !csonpath_do_match(operand_instruction, el2, owalker);
724
+ break;
725
+ case CSONPATH_INST_FILTER_KEY_EQ:
726
+ match = csonpath_do_match(operand_instruction, el2, owalker);
727
+ break;
728
+ case CSONPATH_INST_FILTER_KEY_SUPERIOR:
729
+ if (!CSONPATH_IS_NUM(el2))
730
+ break;
731
+ match = csonpath_int_from_walker(operand_instruction, owalker) <
732
+ CSONPATH_GET_NUM(el2);
733
+ break;
734
+ case CSONPATH_INST_FILTER_KEY_INFERIOR:
735
+ if (!CSONPATH_IS_NUM(el2))
736
+ break;
737
+ match = csonpath_int_from_walker(operand_instruction, owalker) >
738
+ CSONPATH_GET_NUM(el2);
739
+ break;
740
+ case CSONPATH_INST_FILTER_KEY_REG_EQ:
741
+ #ifdef CSONPATH_NO_REGEX
742
+ CSONPATH_GETTER_ERR("regex deactivate\n");
743
+ return CSONPATH_NONE_FOUND_RET;
744
+ #else
745
+ if (CSONPATH_IS_STR(el2)) {
746
+ int regex_idx = inst->regex_idx;
747
+ regex_t *compiled = &cjp->regexs[regex_idx];
748
+ int match_len = regexec(compiled, CSONPATH_GET_STR(el2),
749
+ 0, NULL, 0);
750
+ match = match_len == 0;
751
+ }
752
+ break;
753
+ #endif
754
+ }
755
+ return match;
756
+ }
757
+
758
+ static _Bool csonpath_is_endish_inst(int instruction)
759
+ {
760
+ return instruction == CSONPATH_INST_END || instruction == CSONPATH_INST_OR;
761
+ }
762
+
659
763
  /* helper use multiple times */
660
764
  #define CSONPATH_DO_GET_NOTFOUND_UPDATER(this_idx) \
661
765
  do { \
@@ -674,7 +778,8 @@ static _Bool csonpath_do_match(int operand_instruction, CSONPATH_JSON el2, char
674
778
  goto next_inst; \
675
779
  } while (0)
676
780
 
677
- #define CSONPATH_GOTO_ON_RELOOP(where) \
781
+
782
+ #define CSONPATH_GOTO_ON_RELOOP(where) \
678
783
  nb_res += tret; if (need_reloop_in) goto where;
679
784
 
680
785
  #define CSONPATH_PREPARE_RELOOP(label) \
@@ -793,11 +898,11 @@ need_reloop_in = 0;
793
898
  again:
794
899
 
795
900
  #define CSONPATH_DO_FILTER_LOOP_PRE_SET \
796
- csonpath_child_info_set(&child_info, tmp, (intptr_t)key_idx);
901
+ csonpath_child_info_set(&child_info, tmp, foreach_idx);
797
902
 
798
903
  #define CSONPATH_DO_FOREACH_PRE_SET \
799
- need_reloop_in = 0; \
800
- csonpath_child_info_set(&child_info, tmp, (intptr_t)key_idx);
904
+ need_reloop_in = 0; \
905
+ csonpath_child_info_set(&child_info, tmp, (intptr_t)key_idx);
801
906
 
802
907
  #define CSONPATH_DO_EXTRA_ARGS_NEESTED , child_info, &need_reloop_in
803
908
 
@@ -846,6 +951,41 @@ again:
846
951
 
847
952
  #define CSONPATH_DO_FIND_ALL_OUT return nb_res;
848
953
 
954
+ static int csonpath_sync_root_array(CSONPATH_JSON parent, CSONPATH_JSON to_update)
955
+ {
956
+ CSONPATH_JSON child;
957
+ size_t idx;
958
+ (void) idx;
959
+
960
+ CSONPATH_ARRAY_CLEAR(parent);
961
+ CSONPATH_FOREACH_ARRAY(to_update, child, idx) {
962
+ CSONPATH_APPEND_AT(parent, idx, child);
963
+ }
964
+ return 1;
965
+ }
966
+
967
+ static int csonpath_sync_root_obj(CSONPATH_JSON parent, CSONPATH_JSON to_update)
968
+ {
969
+ CSONPATH_JSON child;
970
+ const char *key;
971
+
972
+ CSONPATH_OBJ_CLEAR(parent);
973
+ CSONPATH_FOREACH_OBJ(to_update, child, key) {
974
+ CSONPATH_APPEND_AT(parent, key, child);
975
+ }
976
+ return 1;
977
+ }
978
+
979
+ #define CSONPATH_PRE_GET_ROOT \
980
+ int to_check = cjp->inst_lst[idx + 1].inst; \
981
+ if (to_check == CSONPATH_INST_END || to_check == CSONPATH_INST_OR) { \
982
+ if (CSONPATH_IS_OBJ(origin) && CSONPATH_IS_OBJ(to_update)) \
983
+ return csonpath_sync_root_obj(origin, to_update); \
984
+ else if (CSONPATH_IS_ARRAY(origin) && CSONPATH_IS_ARRAY(to_update)) \
985
+ return csonpath_sync_root_array(origin, to_update); \
986
+ else \
987
+ CSONPATH_EXCEPTION("can't upate root ($)\n"); \
988
+ }
849
989
 
850
990
  #define CSONPATH_PRE_GET(this_idx) \
851
991
  int check_at = idx + 1; \
@@ -927,6 +1067,12 @@ again:
927
1067
 
928
1068
  #define CSONPATH_DO_FIND_ALL_OUT return nb_res;
929
1069
 
1070
+ #define CSONPATH_PRE_GET_ROOT \
1071
+ int to_check = cjp->inst_lst[idx + 1].inst; \
1072
+ if (to_check == CSONPATH_INST_END || to_check == CSONPATH_INST_OR) { \
1073
+ CSONPATH_GETTER_ERR("can't upate root ($)\n"); \
1074
+ return CSONPATH_NONE_FOUND_RET; \
1075
+ }
930
1076
 
931
1077
  #define CSONPATH_PRE_GET(this_idx) \
932
1078
  int check_at = idx + 1; \
@@ -17,6 +17,10 @@
17
17
  #define CSONPATH_PRE_GET(this_idx)
18
18
  #endif
19
19
 
20
+ #ifndef CSONPATH_PRE_GET_ROOT
21
+ #define CSONPATH_PRE_GET_ROOT
22
+ #endif
23
+
20
24
  #ifndef CSONPATH_DO_DECLARATION
21
25
  #define CSONPATH_DO_DECLARATION
22
26
  #endif
@@ -104,6 +108,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
104
108
  int idx,
105
109
  char *walker CSONPATH_DO_EXTRA_DECLATION);
106
110
 
111
+
107
112
  #define csonpath_do_dotdot__(name) CATCAT(csonpath_, name, _dotdot)
108
113
  #define csonpath_do_dotdot csonpath_do_dotdot__(CSONPATH_DO_FUNC_NAME)
109
114
 
@@ -155,11 +160,14 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
155
160
  cjp->inst_lst[idx].inst != CSONPATH_INST_OR) {
156
161
  switch (cjp->inst_lst[idx].inst) {
157
162
  case CSONPATH_INST_ROOT:
163
+ {
164
+ CSONPATH_PRE_GET_ROOT
158
165
  value = origin;
159
166
  tmp = value;
160
167
  ctx = CSONPATH_NULL;
161
168
  walker += cjp->inst_lst[idx].next;
162
- break;
169
+ }
170
+ break;
163
171
  case CSONPATH_INST_FILTER_KEY_EQ:
164
172
  case CSONPATH_INST_FILTER_KEY_REG_EQ:
165
173
  case CSONPATH_INST_FILTER_KEY_NOT_EQ:
@@ -167,83 +175,54 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
167
175
  case CSONPATH_INST_FILTER_KEY_INFERIOR:
168
176
  {
169
177
  CSONPATH_JSON el;
170
- int operation = cjp->inst_lst[idx].inst;
178
+ int operation_in = cjp->inst_lst[idx].inst, operation = cjp->inst_lst[idx].inst;
171
179
  walker += cjp->inst_lst[idx].next;
172
180
  char *owalker;
173
- int filter_next = cjp->inst_lst[idx].filter_next;
174
- int operand_instruction = -1;
175
- int in_idx = idx + 1;
181
+ int filter_next_in = cjp->inst_lst[idx].filter_next, filter_next = cjp->inst_lst[idx].filter_next;
182
+ int walker_idx = idx + 1, in_idx = idx + 1;
183
+ int foreach_idx;
176
184
 
185
+ (void) foreach_idx;
177
186
  CSONPATH_DO_FILTER_PRE_LOOP;
178
- CSONPATH_FOREACH(tmp, el, {
179
- if (CSONPATH_IS_OBJ(el)) {
180
- CSONPATH_JSON el2 = el;
181
-
182
- owalker = walker;
183
- idx = in_idx;
184
- CSONPATH_DO_FILTER_LOOP_PRE_SET;
185
- for (; idx < filter_next; ++idx) {
186
- switch (cjp->inst_lst[idx].inst) {
187
- case CSONPATH_INST_GET_OBJ:
188
- el2 = CSONPATH_GET(el2, owalker);
189
- break;
190
- default:
191
- CSONPATH_GETTER_ERR("unsuported");
192
- }
193
- owalker += cjp->inst_lst[idx].next;
194
- }
195
-
196
- if (operand_instruction < 0) {
197
- operand_instruction = cjp->inst_lst[idx].inst;
198
- }
199
-
200
- if (el2 != CSONPATH_NULL) {
201
- _Bool match = 0;
202
- switch (operation) {
203
- case CSONPATH_INST_FILTER_KEY_NOT_EQ:
204
- match = !csonpath_do_match(operand_instruction, el2, owalker);
205
- break;
206
- case CSONPATH_INST_FILTER_KEY_EQ:
207
- match = csonpath_do_match(operand_instruction, el2, owalker);
208
- break;
209
- case CSONPATH_INST_FILTER_KEY_SUPERIOR:
210
- if (!CSONPATH_IS_NUM(el2))
211
- break;
212
- match = csonpath_int_from_walker(operand_instruction, owalker) <
213
- CSONPATH_GET_NUM(el2);
214
- break;
215
- case CSONPATH_INST_FILTER_KEY_INFERIOR:
216
- if (!CSONPATH_IS_NUM(el2))
217
- break;
218
- match = csonpath_int_from_walker(operand_instruction, owalker) >
219
- CSONPATH_GET_NUM(el2);
220
- break;
221
- case CSONPATH_INST_FILTER_KEY_REG_EQ:
222
- #ifdef CSONPATH_NO_REGEX
223
- CSONPATH_GETTER_ERR("regex deactivate\n");
224
- return CSONPATH_NONE_FOUND_RET;
225
- #else
226
- if (CSONPATH_IS_STR(el2)) {
227
- int regex_idx = cjp->inst_lst[idx].regex_idx;
228
- regex_t *compiled = &cjp->regexs[regex_idx];
229
- int match_len = regexec(compiled, CSONPATH_GET_STR(el2),
230
- 0, NULL, 0);
231
- match = match_len == 0;
232
- }
233
- break;
234
- #endif
235
- }
236
- if (match) {
237
- CSONPATH_DO_RET_TYPE tret =
238
- csonpath_do_internal(cjp, origin, el, tmp, idx + 1,
239
- owalker + cjp->inst_lst[idx].next
240
- CSONPATH_DO_EXTRA_ARGS_NEESTED);
241
-
242
- CSONPATH_DO_FILTER_FIND;
243
- }
187
+ CSONPATH_FOREACH_ARRAY(tmp, el, foreach_idx)
188
+ {
189
+ intptr_t key_idx = foreach_idx;
190
+ (void)key_idx;
191
+ owalker = walker;
192
+ match_and_or_or:
193
+ if (CSONPATH_IS_OBJ(el)) {
194
+ CSONPATH_JSON el2 = el;
195
+
196
+ idx = walker_idx;
197
+ CSONPATH_DO_FILTER_LOOP_PRE_SET;
198
+ el2 = cosnpath_crawl_filter_el(cjp, &idx, &owalker, el2, filter_next);
199
+
200
+ if (csonpath_make_match(cjp, &cjp->inst_lst[idx], el2, owalker,
201
+ operation)) {
202
+ if (cjp->inst_lst[idx + 1].inst == CSONPATH_INST_FILTER_AND) {
203
+ ++idx; /* skip next */
204
+ if (csonpath_is_endish_inst(cjp->inst_lst[idx + 1].inst) ||
205
+ csonpath_is_endish_inst(cjp->inst_lst[idx + 2].inst))
206
+ goto fail_match;
207
+ operation = cjp->inst_lst[idx +1].inst;
208
+ filter_next = cjp->inst_lst[idx +1].filter_next;
209
+ owalker += cjp->inst_lst[idx].next + cjp->inst_lst[idx-1].next;
210
+ walker_idx = idx + 2;
211
+ goto match_and_or_or;
244
212
  }
213
+ CSONPATH_DO_RET_TYPE tret =
214
+ csonpath_do_internal(cjp, origin, el, tmp, idx + 1,
215
+ owalker + cjp->inst_lst[idx].next
216
+ CSONPATH_DO_EXTRA_ARGS_NEESTED);
217
+ CSONPATH_DO_FILTER_FIND;
218
+ } else {
219
+ fail_match:
220
+ operation = operation_in;
221
+ walker_idx = in_idx;
222
+ filter_next = filter_next_in;
245
223
  }
246
- });
224
+ }
225
+ }
247
226
  CSONPATH_DO_FILTER_OUT;
248
227
  break;
249
228
  }
@@ -356,6 +335,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_(struct csonpath cjp[static 1],
356
335
 
357
336
  #ifndef CSONPATH_NO_UNDEF
358
337
 
338
+ #undef CSONPATH_PRE_GET_ROOT
359
339
  #undef CSONPATH_PRE_GET
360
340
  #undef CSONPATH_DO_PRE_OPERATION
361
341
  #undef CSONPATH_DO_POST_OPERATION
@@ -50,6 +50,13 @@
50
50
  r; \
51
51
  })
52
52
 
53
+ #define CSONPATH_FORMAT_EXCEPTION(ARGS...) \
54
+ PyErr_Format(PyExc_ValueError, ARGS)
55
+
56
+ #define CSONPATH_EXCEPTION(ARGS...) \
57
+ PyErr_Format(PyExc_ValueError, ARGS); \
58
+ return -1;
59
+
53
60
  #define CSONPATH_CALLBACK PyObject *
54
61
 
55
62
  #define CSONPATH_CALLBACK_DATA PyObject *
@@ -84,7 +91,7 @@
84
91
  static int pydict_try_setitemstring(PyObject *obj, const char * const at, PyObject *el)
85
92
  {
86
93
  if (!PyDict_Check(obj)) {
87
- PyErr_Format(PyExc_ValueError, "Unable to follow path: Dict expected");
94
+ PyErr_Format(PyExc_ValueError, "Unable to follow path (%s): Dict expected", at);
88
95
  return -1;
89
96
  }
90
97
  PyDict_SetItemString(obj, at, el);
@@ -97,7 +104,7 @@ static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *
97
104
  PyErr_Format(PyExc_ValueError, "Unable to follow path: List expected");
98
105
  return -1;
99
106
  }
100
- Py_ssize_t s = PyList_Size(array);
107
+ Py_ssize_t s = PyList_Size(array);
101
108
  if (at >= s) {
102
109
  for (;s < at; ++s)
103
110
  PyList_Insert(array, s, Py_None);
@@ -124,6 +131,22 @@ static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *
124
131
  ) (array, at, el)
125
132
 
126
133
 
134
+ #define CSONPATH_ARRAY_CLEAR(o) PyList_Clear(o)
135
+
136
+ #define CSONPATH_OBJ_CLEAR(o) PyDict_Clear(o)
137
+
138
+ #define CSONPATH_FOREACH_ARRAY(obj, child, idx) \
139
+ for (intptr_t array_len = PyList_Size(obj), idx = 0; \
140
+ ({int r = idx < array_len; if (r) child = PyList_GetItem(obj, idx); r;}); ++idx)
141
+
142
+ #define CSONPATH_FOREACH_OBJ(obj, child, key) \
143
+ for (Py_ssize_t pos_ = 0; ({ \
144
+ PyObject *key_; \
145
+ _Bool r = PyDict_Next(obj, &pos_, &key_, &child); \
146
+ if (r) key = PyUnicode_AsUTF8AndSize(key_, NULL); \
147
+ r; \
148
+ });)
149
+
127
150
  #define CSONPATH_FOREACH_EXT(obj, el, code, key_idx) \
128
151
  if (PyDict_Check(obj)) { \
129
152
  PyObject *key_; \
@@ -223,6 +246,12 @@ static PyObject *find_first(PyCsonPathObject *self, PyObject* args)
223
246
  return ret;
224
247
  }
225
248
 
249
+ static PyObject *print_instructions(PyCsonPathObject *self, PyObject *args, PyObject *kwds)
250
+ {
251
+ csonpath_print_instruction(self->cp);
252
+ return Py_None;
253
+ }
254
+
226
255
  static PyObject *callback(PyCsonPathObject *self, PyObject* args)
227
256
  {
228
257
  PyObject *json, *callback, *udata = Py_None;
@@ -266,7 +295,6 @@ static PyObject *update_or_create_callback(PyCsonPathObject *self, PyObject* arg
266
295
  return PyLong_FromLong(ret);
267
296
  }
268
297
 
269
-
270
298
  static void PyCsonPath_dealloc(PyCsonPathObject *self) {
271
299
  if (self->cp) {
272
300
  csonpath_destroy(self->cp);
@@ -289,6 +317,7 @@ static PyObject *PyCsonPath_set_path(PyCsonPathObject *self, PyObject* args) {
289
317
  static PyMethodDef csonpath_py_method[] = {
290
318
  {"set_path", (PyCFunction)PyCsonPath_set_path, METH_VARARGS, "set_path"},
291
319
  {"callback", (PyCFunction)callback, METH_VARARGS, "callback"},
320
+ {"print_instructions", (PyCFunction)print_instructions, METH_NOARGS, "print_instructions"},
292
321
  {"update_or_create_callback", (PyCFunction)update_or_create_callback, METH_VARARGS, "update_or_create_callback"},
293
322
  {"find_first", (PyCFunction)find_first, METH_VARARGS, "find first elems"},
294
323
  {"find_all", (PyCFunction)find_all, METH_VARARGS, "find all elems, if one found, pout it in an array"},
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "csonpath"
7
- version = "0.8.0"
7
+ version = "0.9.0"
8
8
  readme = "README.md"
9
9
 
10
10
  [tool.setuptools]
@@ -22,7 +22,7 @@ dev = [
22
22
  testpaths = ["tests/python"]
23
23
 
24
24
  [tool.bumpversion]
25
- current_version = "0.8.0"
25
+ current_version = "0.9.0"
26
26
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
27
27
  serialize = ["{major}.{minor}.{patch}"]
28
28
  search = "{current_version}"
File without changes
File without changes
File without changes