csonpath 0.10.0__tar.gz → 0.11.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {csonpath-0.10.0/csonpath.egg-info → csonpath-0.11.0}/PKG-INFO +2 -1
- {csonpath-0.10.0 → csonpath-0.11.0}/README.md +1 -0
- {csonpath-0.10.0 → csonpath-0.11.0/csonpath.egg-info}/PKG-INFO +2 -1
- {csonpath-0.10.0 → csonpath-0.11.0}/csonpath.egg-info/SOURCES.txt +1 -0
- {csonpath-0.10.0 → csonpath-0.11.0}/csonpath.h +101 -20
- {csonpath-0.10.0 → csonpath-0.11.0}/csonpath_do.h +31 -12
- {csonpath-0.10.0 → csonpath-0.11.0}/csonpath_python.c +62 -29
- {csonpath-0.10.0 → csonpath-0.11.0}/pyproject.toml +3 -5
- csonpath-0.11.0/setup.py +33 -0
- {csonpath-0.10.0 → csonpath-0.11.0}/LICENSE +0 -0
- {csonpath-0.10.0 → csonpath-0.11.0}/MANIFEST.in +0 -0
- {csonpath-0.10.0 → csonpath-0.11.0}/csonpath.egg-info/dependency_links.txt +0 -0
- {csonpath-0.10.0 → csonpath-0.11.0}/csonpath.egg-info/requires.txt +0 -0
- {csonpath-0.10.0 → csonpath-0.11.0}/csonpath.egg-info/top_level.txt +0 -0
- {csonpath-0.10.0 → csonpath-0.11.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csonpath
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Description-Content-Type: text/markdown
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Provides-Extra: dev
|
|
@@ -144,6 +144,7 @@ print(o.find_first(d)) # Output: "value"
|
|
|
144
144
|
|
|
145
145
|
#### Avaible methodes:
|
|
146
146
|
- `CsonPath(path)`: create a new csonpath object.
|
|
147
|
+
- `CsonPath(path, return_empty_array)`: Create a new csonpath object and return an empty list instead of None (like jsonpath-ng).
|
|
147
148
|
- `OBJ.find_first(self, json)`: take a json, return first found occurrence.
|
|
148
149
|
- `OBJ.find_all(self, json)`: take a json, return all found occurrence in a list.
|
|
149
150
|
- `OBJ.remove(self, json)`: take a json, remove all found occurrence from it.
|
|
@@ -135,6 +135,7 @@ print(o.find_first(d)) # Output: "value"
|
|
|
135
135
|
|
|
136
136
|
#### Avaible methodes:
|
|
137
137
|
- `CsonPath(path)`: create a new csonpath object.
|
|
138
|
+
- `CsonPath(path, return_empty_array)`: Create a new csonpath object and return an empty list instead of None (like jsonpath-ng).
|
|
138
139
|
- `OBJ.find_first(self, json)`: take a json, return first found occurrence.
|
|
139
140
|
- `OBJ.find_all(self, json)`: take a json, return all found occurrence in a list.
|
|
140
141
|
- `OBJ.remove(self, json)`: take a json, remove all found occurrence from it.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csonpath
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Description-Content-Type: text/markdown
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Provides-Extra: dev
|
|
@@ -144,6 +144,7 @@ print(o.find_first(d)) # Output: "value"
|
|
|
144
144
|
|
|
145
145
|
#### Avaible methodes:
|
|
146
146
|
- `CsonPath(path)`: create a new csonpath object.
|
|
147
|
+
- `CsonPath(path, return_empty_array)`: Create a new csonpath object and return an empty list instead of None (like jsonpath-ng).
|
|
147
148
|
- `OBJ.find_first(self, json)`: take a json, return first found occurrence.
|
|
148
149
|
- `OBJ.find_all(self, json)`: take a json, return all found occurrence in a list.
|
|
149
150
|
- `OBJ.remove(self, json)`: take a json, remove all found occurrence from it.
|
|
@@ -10,7 +10,20 @@
|
|
|
10
10
|
#endif
|
|
11
11
|
|
|
12
12
|
#ifndef CSONPATH_NO_REGEX
|
|
13
|
-
#
|
|
13
|
+
# if defined CSONPATH_TINY_REGEX
|
|
14
|
+
# include <tiny-regex-c/re.h>
|
|
15
|
+
typedef char * csonpath_reg_t;
|
|
16
|
+
# elif defined CSONPATH_PCRE2
|
|
17
|
+
# define PCRE2_CODE_UNIT_WIDTH 8
|
|
18
|
+
# include <pcre2.h>
|
|
19
|
+
typedef pcre2_code * csonpath_reg_t;
|
|
20
|
+
# elif defined CSONPATH_PCRE2_POSIX
|
|
21
|
+
# include <pcre2posix.h>
|
|
22
|
+
typedef regex_t csonpath_reg_t;
|
|
23
|
+
# else
|
|
24
|
+
# include <regex.h>
|
|
25
|
+
typedef regex_t csonpath_reg_t;
|
|
26
|
+
# endif
|
|
14
27
|
#endif
|
|
15
28
|
|
|
16
29
|
#define CSONPATH_UNUSED __attribute__((unused))
|
|
@@ -109,8 +122,12 @@ struct csonpath {
|
|
|
109
122
|
int compiled;
|
|
110
123
|
#ifndef CSONPATH_NO_REGEX
|
|
111
124
|
int regex_cnt;
|
|
112
|
-
|
|
125
|
+
csonpath_reg_t *regexs;
|
|
126
|
+
#ifdef CSONPATH_PCRE2
|
|
127
|
+
pcre2_match_data **match_datas;
|
|
113
128
|
#endif
|
|
129
|
+
#endif
|
|
130
|
+
int return_empty_array;
|
|
114
131
|
};
|
|
115
132
|
|
|
116
133
|
struct csonpath_child_info {
|
|
@@ -172,12 +189,25 @@ static inline void csonpath_destroy(struct csonpath cjp[static 1])
|
|
|
172
189
|
free(cjp->path);
|
|
173
190
|
free(cjp->inst_lst);
|
|
174
191
|
free(cjp->compile_error);
|
|
192
|
+
#ifndef CSONPATH_NO_REGEX
|
|
175
193
|
if (cjp->regex_cnt) {
|
|
194
|
+
#ifndef CSONPATH_TINY_REGEX
|
|
176
195
|
for (int i = 0; i < cjp->regex_cnt; ++i) {
|
|
196
|
+
#ifdef CSONPATH_PCRE2
|
|
197
|
+
pcre2_code_free(cjp->regexs[i]);
|
|
198
|
+
pcre2_match_data_free(cjp->match_datas[i]);
|
|
199
|
+
#else
|
|
177
200
|
regfree(&cjp->regexs[i]);
|
|
201
|
+
#endif
|
|
202
|
+
|
|
178
203
|
}
|
|
204
|
+
#endif
|
|
205
|
+
#ifdef CSONPATH_PCRE2
|
|
206
|
+
free(cjp->match_datas);
|
|
207
|
+
#endif
|
|
179
208
|
free(cjp->regexs);
|
|
180
209
|
}
|
|
210
|
+
#endif
|
|
181
211
|
*cjp = (struct csonpath){};
|
|
182
212
|
}
|
|
183
213
|
|
|
@@ -204,6 +234,9 @@ static inline int csonpath_init(struct csonpath cjp[static 1],
|
|
|
204
234
|
if (!cjp->path || !cjp->inst_lst) {
|
|
205
235
|
return -ENOMEM;
|
|
206
236
|
}
|
|
237
|
+
|
|
238
|
+
cjp->return_empty_array = 0;
|
|
239
|
+
|
|
207
240
|
return 0;
|
|
208
241
|
}
|
|
209
242
|
|
|
@@ -228,7 +261,7 @@ static inline void csonpath_push_inst_cpy(struct csonpath cjp[static 1],
|
|
|
228
261
|
*inst_idx += 1;
|
|
229
262
|
}
|
|
230
263
|
|
|
231
|
-
static void csonpath_print_instruction(struct csonpath cjp[static 1])
|
|
264
|
+
static void csonpath_print_instruction(const struct csonpath cjp[const static 1])
|
|
232
265
|
{
|
|
233
266
|
int idx = 0;
|
|
234
267
|
for (;cjp->inst_lst[idx].inst != CSONPATH_INST_END; ++idx) {
|
|
@@ -436,13 +469,16 @@ static int csonpath_compile(struct csonpath cjp[static 1])
|
|
|
436
469
|
/* = and == are the same here */
|
|
437
470
|
if (to_check == '=') {
|
|
438
471
|
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_EQ, &inst_idx);
|
|
439
|
-
if (next[0] == '=')
|
|
472
|
+
if (next[0] == '=') {
|
|
440
473
|
++next;
|
|
474
|
+
}
|
|
475
|
+
#ifndef CSONPATH_NO_REGEX
|
|
441
476
|
else if (next[0] == '~') {
|
|
442
477
|
cjp->inst_lst[inst_idx - 1].inst = CSONPATH_INST_FILTER_KEY_REG_EQ;
|
|
443
478
|
regex_idx = cjp->regex_cnt++;
|
|
444
479
|
++next;
|
|
445
480
|
}
|
|
481
|
+
#endif
|
|
446
482
|
} else if (to_check == '!' && next[0] == '=') {
|
|
447
483
|
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_NOT_EQ, &inst_idx);
|
|
448
484
|
++next;
|
|
@@ -484,14 +520,38 @@ static int csonpath_compile(struct csonpath cjp[static 1])
|
|
|
484
520
|
*next = 0;
|
|
485
521
|
#ifndef CSONPATH_NO_REGEX
|
|
486
522
|
if (regex_idx >= 0) {
|
|
487
|
-
if (!regex_idx)
|
|
523
|
+
if (!regex_idx) {
|
|
488
524
|
cjp->regexs = malloc(sizeof *cjp->regexs * 255);
|
|
489
|
-
|
|
525
|
+
#ifdef CSONPATH_PCRE2
|
|
526
|
+
cjp->match_datas = malloc(sizeof *cjp->match_datas * 255);
|
|
527
|
+
#endif
|
|
528
|
+
}
|
|
490
529
|
cjp->inst_lst[inst_idx - 1].regex_idx = regex_idx;
|
|
530
|
+
# if defined CSONPATH_TINY_REGEX
|
|
531
|
+
cjp->regexs[regex_idx] = walker;
|
|
532
|
+
# elif defined CSONPATH_PCRE2
|
|
533
|
+
int errorcode;
|
|
534
|
+
PCRE2_SIZE erroroffset;
|
|
535
|
+
|
|
536
|
+
cjp->regexs[regex_idx] = pcre2_compile((unsigned char *)walker,
|
|
537
|
+
PCRE2_ZERO_TERMINATED, 0,
|
|
538
|
+
&errorcode, &erroroffset, NULL);
|
|
539
|
+
if (!cjp->regexs[regex_idx]) {
|
|
540
|
+
PCRE2_UCHAR buffer[256];
|
|
541
|
+
pcre2_get_error_message(errorcode, buffer, sizeof(buffer));
|
|
542
|
+
CSONPATH_COMPILE_ERR(tmp, next - orig, "regex has error: \"%s\"\n", buffer);
|
|
543
|
+
goto error;
|
|
544
|
+
}
|
|
545
|
+
cjp->match_datas[regex_idx] = pcre2_match_data_create_from_pattern(cjp->regexs[regex_idx],
|
|
546
|
+
NULL);
|
|
547
|
+
pcre2_jit_compile(cjp->regexs[regex_idx], PCRE2_JIT_COMPLETE);
|
|
548
|
+
# else
|
|
549
|
+
int e = regcomp(&cjp->regexs[regex_idx], walker, 0);
|
|
491
550
|
if (e) {
|
|
492
551
|
CSONPATH_COMPILE_ERR(tmp, next - orig, "regex has error\n");
|
|
493
552
|
goto error;
|
|
494
553
|
}
|
|
554
|
+
# endif
|
|
495
555
|
}
|
|
496
556
|
#endif
|
|
497
557
|
++next;
|
|
@@ -643,7 +703,7 @@ static int csonpath_compile(struct csonpath cjp[static 1])
|
|
|
643
703
|
csonpath_push_inst(cjp, inst, &inst_idx);
|
|
644
704
|
to_check = *walker;
|
|
645
705
|
goto again;
|
|
646
|
-
}
|
|
706
|
+
}
|
|
647
707
|
for (next = walker; csonpath_is_dot_operand(*next); ++next);
|
|
648
708
|
if (next == walker) {
|
|
649
709
|
if (*next == '[')
|
|
@@ -702,12 +762,11 @@ static _Bool csonpath_do_match(int operand_instruction, CSONPATH_JSON el2, char
|
|
|
702
762
|
return 0;
|
|
703
763
|
}
|
|
704
764
|
|
|
705
|
-
static CSONPATH_JSON cosnpath_crawl_filter_el(struct csonpath cjp[static 1],
|
|
765
|
+
static CSONPATH_JSON cosnpath_crawl_filter_el(const struct csonpath cjp[const static 1],
|
|
706
766
|
int *idx, char **owalker,
|
|
707
767
|
CSONPATH_JSON el2,
|
|
708
768
|
int filter_next)
|
|
709
769
|
{
|
|
710
|
-
|
|
711
770
|
for (; *idx < filter_next; ++(*idx)) {
|
|
712
771
|
switch (cjp->inst_lst[*idx].inst) {
|
|
713
772
|
case CSONPATH_INST_GET_OBJ:
|
|
@@ -724,12 +783,12 @@ static CSONPATH_JSON cosnpath_crawl_filter_el(struct csonpath cjp[static 1],
|
|
|
724
783
|
}
|
|
725
784
|
|
|
726
785
|
|
|
727
|
-
static _Bool csonpath_make_match(struct csonpath cjp[static 1],
|
|
786
|
+
static _Bool csonpath_make_match(const struct csonpath cjp[const static 1],
|
|
728
787
|
struct csonpath_instruction inst[static 1],
|
|
729
788
|
CSONPATH_JSON el2, char *owalker, int operation)
|
|
730
789
|
{
|
|
731
790
|
int operand_instruction = inst->inst;
|
|
732
|
-
|
|
791
|
+
|
|
733
792
|
if (el2 == CSONPATH_NULL)
|
|
734
793
|
return 0;
|
|
735
794
|
_Bool match = 0;
|
|
@@ -753,16 +812,38 @@ static _Bool csonpath_make_match(struct csonpath cjp[static 1],
|
|
|
753
812
|
CSONPATH_GET_NUM(el2);
|
|
754
813
|
break;
|
|
755
814
|
case CSONPATH_INST_FILTER_KEY_REG_EQ:
|
|
756
|
-
#
|
|
757
|
-
|
|
758
|
-
|
|
815
|
+
#if defined CSONPATH_NO_REGEX
|
|
816
|
+
fprintf(stderr, "regex deactivate");
|
|
817
|
+
return 0;
|
|
759
818
|
#else
|
|
760
819
|
if (CSONPATH_IS_STR(el2)) {
|
|
761
820
|
int regex_idx = inst->regex_idx;
|
|
821
|
+
#if defined CSONPATH_TINY_REGEX
|
|
822
|
+
int match_len = 0;
|
|
823
|
+
const char *str = CSONPATH_GET_STR(el2);
|
|
824
|
+
re_match(cjp->regexs[regex_idx], str, &match_len);
|
|
825
|
+
match = !!match_len;
|
|
826
|
+
#elif defined CSONPATH_PCRE2
|
|
827
|
+
const unsigned char *str = (const unsigned char *)CSONPATH_GET_STR(el2);
|
|
828
|
+
int ret = pcre2_match(cjp->regexs[regex_idx], str, PCRE2_ZERO_TERMINATED, 0,
|
|
829
|
+
0, cjp->match_datas[regex_idx], NULL);
|
|
830
|
+
|
|
831
|
+
if (ret >= 0) {
|
|
832
|
+
// match found
|
|
833
|
+
return 1;
|
|
834
|
+
} else if (ret == PCRE2_ERROR_NOMATCH) {
|
|
835
|
+
// no match
|
|
836
|
+
return 0;
|
|
837
|
+
} else {
|
|
838
|
+
fprintf(stderr, "pcre2 match error: %d\n", ret);
|
|
839
|
+
return 0;
|
|
840
|
+
}
|
|
841
|
+
#else
|
|
762
842
|
regex_t *compiled = &cjp->regexs[regex_idx];
|
|
763
843
|
int match_len = regexec(compiled, CSONPATH_GET_STR(el2),
|
|
764
844
|
0, NULL, 0);
|
|
765
845
|
match = match_len == 0;
|
|
846
|
+
#endif
|
|
766
847
|
}
|
|
767
848
|
break;
|
|
768
849
|
#endif
|
|
@@ -816,7 +897,7 @@ need_reloop_in = 0;
|
|
|
816
897
|
#define CSONPATH_DO_FUNC_NAME find_first
|
|
817
898
|
#define CSONPATH_DO_RETURN return tmp
|
|
818
899
|
|
|
819
|
-
#define CSONPATH_DO_FIND_ALL return tret
|
|
900
|
+
#define CSONPATH_DO_FIND_ALL if (tret) return tret
|
|
820
901
|
|
|
821
902
|
#define CSONPATH_DO_FILTER_FIND return tret
|
|
822
903
|
|
|
@@ -845,7 +926,7 @@ need_reloop_in = 0;
|
|
|
845
926
|
#define CSONPATH_DO_FILTER_FIND CSONPATH_DO_FIND_ALL
|
|
846
927
|
|
|
847
928
|
#define CSONPATH_DO_FIND_ALL_OUT \
|
|
848
|
-
|
|
929
|
+
if (!cjp->return_empty_array && !nb_res) { \
|
|
849
930
|
return CSONPATH_NONE_FOUND_RET; \
|
|
850
931
|
} \
|
|
851
932
|
return ret_ar;
|
|
@@ -853,7 +934,6 @@ need_reloop_in = 0;
|
|
|
853
934
|
#define CSONPATH_DO_EXTRA_ARGS_IN , ret_ar
|
|
854
935
|
#define CSONPATH_DO_EXTRA_DECLATION , CSONPATH_FIND_ALL_RET ret_ar
|
|
855
936
|
|
|
856
|
-
|
|
857
937
|
#include "csonpath_do.h"
|
|
858
938
|
|
|
859
939
|
/* Delete */
|
|
@@ -1005,12 +1085,13 @@ static int csonpath_sync_root_obj(CSONPATH_JSON parent, CSONPATH_JSON to_update)
|
|
|
1005
1085
|
#define CSONPATH_PRE_GET_ROOT \
|
|
1006
1086
|
int to_check = cjp->inst_lst[idx + 1].inst; \
|
|
1007
1087
|
if (to_check == CSONPATH_INST_END || to_check == CSONPATH_INST_OR) { \
|
|
1008
|
-
if (CSONPATH_IS_OBJ(origin) && CSONPATH_IS_OBJ(to_update)) \
|
|
1088
|
+
if (CSONPATH_IS_OBJ(origin) && CSONPATH_IS_OBJ(to_update)) { \
|
|
1009
1089
|
return csonpath_sync_root_obj(origin, to_update); \
|
|
1010
|
-
else if (CSONPATH_IS_ARRAY(origin) && CSONPATH_IS_ARRAY(to_update)) \
|
|
1090
|
+
} else if (CSONPATH_IS_ARRAY(origin) && CSONPATH_IS_ARRAY(to_update)) { \
|
|
1011
1091
|
return csonpath_sync_root_array(origin, to_update); \
|
|
1012
|
-
else
|
|
1092
|
+
} else { \
|
|
1013
1093
|
CSONPATH_EXCEPTION("can't upate root ($)\n"); \
|
|
1094
|
+
} \
|
|
1014
1095
|
}
|
|
1015
1096
|
|
|
1016
1097
|
#define CSONPATH_PRE_GET(this_idx) \
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
#define csonpath_do_internal__(name) CATCAT(csonpath_, name, _internal)
|
|
114
114
|
#define csonpath_do_internal csonpath_do_internal__(CSONPATH_DO_FUNC_NAME)
|
|
115
115
|
|
|
116
|
-
static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
|
|
116
|
+
static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const static 1],
|
|
117
117
|
CSONPATH_JSON origin,
|
|
118
118
|
CSONPATH_JSON value,
|
|
119
119
|
CSONPATH_JSON ctx,
|
|
@@ -125,7 +125,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
|
|
|
125
125
|
#define csonpath_do_dotdot csonpath_do_dotdot__(CSONPATH_DO_FUNC_NAME)
|
|
126
126
|
|
|
127
127
|
|
|
128
|
-
static CSONPATH_DO_RET_TYPE csonpath_do_dotdot(struct csonpath cjp[static 1],
|
|
128
|
+
static CSONPATH_DO_RET_TYPE csonpath_do_dotdot(const struct csonpath cjp[const static 1],
|
|
129
129
|
CSONPATH_JSON origin,
|
|
130
130
|
CSONPATH_JSON tmp,
|
|
131
131
|
CSONPATH_JSON ctx,
|
|
@@ -135,12 +135,17 @@ static CSONPATH_DO_RET_TYPE csonpath_do_dotdot(struct csonpath cjp[static 1],
|
|
|
135
135
|
CSONPATH_JSON el;
|
|
136
136
|
CSONPATH_DO_DECLARATION;
|
|
137
137
|
const int is_obj = CSONPATH_IS_OBJ(tmp);
|
|
138
|
+
intptr_t key_idx;
|
|
138
139
|
CSONPATH_DO_RET_TYPE tret = CSONPATH_NONE_FOUND_RET;
|
|
139
140
|
|
|
140
141
|
CSONPATH_DO_FIND_ALL_PRE_LOOP;
|
|
141
|
-
|
|
142
|
+
if (is_obj) {
|
|
143
|
+
const char *key;
|
|
144
|
+
CSONPATH_FOREACH_OBJ(tmp, el, key) {
|
|
145
|
+
key_idx = (intptr_t)key;
|
|
146
|
+
(void)key_idx;
|
|
142
147
|
CSONPATH_DO_FOREACH_PRE_SET;
|
|
143
|
-
if (
|
|
148
|
+
if (!strcmp(key, walker)) {
|
|
144
149
|
tret = csonpath_do_internal(cjp, origin, el, tmp, idx,
|
|
145
150
|
walker + cjp->inst_lst[idx].next
|
|
146
151
|
CSONPATH_DO_EXTRA_ARGS_NEESTED);
|
|
@@ -151,12 +156,22 @@ static CSONPATH_DO_RET_TYPE csonpath_do_dotdot(struct csonpath cjp[static 1],
|
|
|
151
156
|
CSONPATH_DO_EXTRA_ARGS_NEESTED);
|
|
152
157
|
CSONPATH_DO_FIND_ALL;
|
|
153
158
|
}
|
|
154
|
-
}
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
CSONPATH_FOREACH_ARRAY(tmp, el, key_idx) {
|
|
162
|
+
CSONPATH_DO_FOREACH_PRE_SET;
|
|
163
|
+
if (CSONPATH_IS_OBJ(el) || CSONPATH_IS_ARRAY(el)) {
|
|
164
|
+
tret = csonpath_do_dotdot(cjp, origin, el, tmp, idx, walker
|
|
165
|
+
CSONPATH_DO_EXTRA_ARGS_NEESTED);
|
|
166
|
+
CSONPATH_DO_FIND_ALL;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
155
170
|
CSONPATH_DO_FIND_ALL_OUT;
|
|
156
171
|
return tret;
|
|
157
172
|
}
|
|
158
173
|
|
|
159
|
-
static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
|
|
174
|
+
static CSONPATH_DO_RET_TYPE csonpath_do_internal(const struct csonpath cjp[const static 1],
|
|
160
175
|
CSONPATH_JSON origin,
|
|
161
176
|
CSONPATH_JSON value,
|
|
162
177
|
CSONPATH_JSON ctx,
|
|
@@ -240,11 +255,15 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
|
|
|
240
255
|
}
|
|
241
256
|
case CSONPATH_INST_FIND_ALL:
|
|
242
257
|
{
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
258
|
+
if (CSONPATH_IS_OBJ(tmp) || CSONPATH_IS_ARRAY(tmp)) {
|
|
259
|
+
CSONPATH_DO_RET_TYPE tret =
|
|
260
|
+
csonpath_do_dotdot(cjp, origin, tmp, ctx, idx + 1,
|
|
261
|
+
walker CSONPATH_DO_EXTRA_ARGS_FIND_ALL);
|
|
262
|
+
CSONPATH_DO_FIND_ALL_CLEAUP;
|
|
263
|
+
return tret;
|
|
264
|
+
} else {
|
|
265
|
+
return CSONPATH_NONE_FOUND_RET;
|
|
266
|
+
}
|
|
248
267
|
}
|
|
249
268
|
case CSONPATH_INST_RANGE:
|
|
250
269
|
{
|
|
@@ -382,7 +401,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_(struct csonpath cjp[static 1],
|
|
|
382
401
|
|
|
383
402
|
CSONPATH_DO_POST_OPERATION;
|
|
384
403
|
|
|
385
|
-
|
|
404
|
+
return ret;
|
|
386
405
|
}
|
|
387
406
|
|
|
388
407
|
#ifndef CSONPATH_NO_UNDEF
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include <Python.h>
|
|
2
|
+
#include <stdio.h>
|
|
2
3
|
|
|
3
4
|
#define CSONPATH_JSON PyObject *
|
|
4
5
|
|
|
@@ -27,7 +28,6 @@
|
|
|
27
28
|
|
|
28
29
|
#define CSONPATH_DECREF(obj) \
|
|
29
30
|
Py_DECREF(obj);
|
|
30
|
-
|
|
31
31
|
|
|
32
32
|
#define CSONPATH_GET_NUM(obj) \
|
|
33
33
|
PyLong_AsLong(obj)
|
|
@@ -131,6 +131,13 @@ static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *
|
|
|
131
131
|
) (array, at, el)
|
|
132
132
|
|
|
133
133
|
|
|
134
|
+
#ifdef __TINYC__
|
|
135
|
+
#define CSONPATH_PRAGMA(...)
|
|
136
|
+
#else
|
|
137
|
+
#define CSONPATH_PRAGMA(...) _Pragma(__VA_ARGS__)
|
|
138
|
+
#endif
|
|
139
|
+
|
|
140
|
+
|
|
134
141
|
#if PY_MAJOR_VERSION > 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13)
|
|
135
142
|
/* PyList_Clear was introduced in Python 3.13 */
|
|
136
143
|
#define CSONPATH_ARRAY_CLEAR(o) PyList_Clear(o)
|
|
@@ -147,6 +154,7 @@ static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *
|
|
|
147
154
|
#define CSONPATH_OBJ_CLEAR(o) PyDict_Clear(o)
|
|
148
155
|
|
|
149
156
|
#define CSONPATH_FOREACH_ARRAY(obj, child, idx) \
|
|
157
|
+
CSONPATH_PRAGMA("GCC unroll 8") \
|
|
150
158
|
for (intptr_t array_len = PyList_Size(obj), idx = 0; \
|
|
151
159
|
({int r = idx < array_len; if (r) child = PyList_GetItem(obj, idx); r;}); ++idx)
|
|
152
160
|
|
|
@@ -169,6 +177,7 @@ static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *
|
|
|
169
177
|
} \
|
|
170
178
|
} else if (PyList_Check(obj)) { \
|
|
171
179
|
int array_len_ = PyList_Size(obj); \
|
|
180
|
+
CSONPATH_PRAGMA("GCC unroll 8") \
|
|
172
181
|
for (intptr_t key_idx = 0; key_idx < array_len_; ++key_idx) { \
|
|
173
182
|
el = PyList_GetItem(obj, key_idx); \
|
|
174
183
|
code \
|
|
@@ -207,33 +216,53 @@ typedef struct {
|
|
|
207
216
|
|
|
208
217
|
|
|
209
218
|
static PyObject *PyCsonPath_new(PyTypeObject *subtype, PyObject* args,
|
|
210
|
-
PyObject*
|
|
219
|
+
PyObject* kwargs)
|
|
211
220
|
{
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
221
|
+
static char *kwlist[] = {"path", "return_empty_array", NULL};
|
|
222
|
+
PyCsonPathObject *self = (PyCsonPathObject *)subtype->tp_alloc(subtype, 0);
|
|
223
|
+
const char *s;
|
|
224
|
+
int return_empty_array = 0;
|
|
225
|
+
struct csonpath *ret = NULL;
|
|
226
|
+
PyObject *py_ret = NULL;
|
|
227
|
+
|
|
228
|
+
if (!self)
|
|
229
|
+
BAD_ARG();
|
|
230
|
+
|
|
231
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|p", kwlist,
|
|
232
|
+
&s, &return_empty_array)) {
|
|
233
|
+
goto error;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
ret = malloc(sizeof *ret);
|
|
237
|
+
if (!ret) {
|
|
238
|
+
PyErr_NoMemory();
|
|
239
|
+
goto error;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (csonpath_init(ret, s) < 0) {
|
|
243
|
+
py_ret = PyErr_NoMemory();
|
|
244
|
+
goto error_free_ret;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
ret->return_empty_array = return_empty_array;
|
|
248
|
+
|
|
249
|
+
if (csonpath_compile(ret) < 0) {
|
|
250
|
+
char *err_str = ret->compile_error;
|
|
251
|
+
PyErr_Format(PyExc_ValueError, "compilation fail %s",
|
|
252
|
+
err_str ? err_str : "(unknow error)");
|
|
253
|
+
goto error_destroy_ret;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
self->cp = ret;
|
|
257
|
+
return (PyObject *)self;
|
|
258
|
+
|
|
259
|
+
error_destroy_ret:
|
|
260
|
+
csonpath_destroy(ret);
|
|
261
|
+
error_free_ret:
|
|
262
|
+
free(ret);
|
|
263
|
+
error:
|
|
264
|
+
Py_DECREF(self);
|
|
265
|
+
return py_ret;
|
|
237
266
|
}
|
|
238
267
|
|
|
239
268
|
static PyObject *find_all(PyCsonPathObject *self, PyObject* args)
|
|
@@ -241,8 +270,10 @@ static PyObject *find_all(PyCsonPathObject *self, PyObject* args)
|
|
|
241
270
|
PyObject *json;
|
|
242
271
|
|
|
243
272
|
if (!PyArg_ParseTuple(args, "O", &json))
|
|
244
|
-
|
|
273
|
+
BAD_ARG();
|
|
274
|
+
|
|
245
275
|
PyObject *ret = csonpath_find_all(self->cp, json);
|
|
276
|
+
|
|
246
277
|
return ret;
|
|
247
278
|
}
|
|
248
279
|
|
|
@@ -251,8 +282,10 @@ static PyObject *find_first(PyCsonPathObject *self, PyObject* args)
|
|
|
251
282
|
PyObject *json;
|
|
252
283
|
|
|
253
284
|
if (!PyArg_ParseTuple(args, "O", &json))
|
|
254
|
-
|
|
285
|
+
BAD_ARG();
|
|
286
|
+
|
|
255
287
|
PyObject *ret = csonpath_find_first(self->cp, json);
|
|
288
|
+
|
|
256
289
|
Py_INCREF(ret);
|
|
257
290
|
return ret;
|
|
258
291
|
}
|
|
@@ -4,14 +4,12 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "csonpath"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.11.0"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
|
|
10
10
|
[tool.setuptools]
|
|
11
11
|
packages = [] # no Python packages, just an extension
|
|
12
|
-
|
|
13
|
-
{name="csonpath", sources = ["csonpath_python.c"]}
|
|
14
|
-
]
|
|
12
|
+
# Extension module is defined in setup.py for platform-specific sources
|
|
15
13
|
|
|
16
14
|
[project.optional-dependencies]
|
|
17
15
|
dev = [
|
|
@@ -22,7 +20,7 @@ dev = [
|
|
|
22
20
|
testpaths = ["tests/python"]
|
|
23
21
|
|
|
24
22
|
[tool.bumpversion]
|
|
25
|
-
current_version = "0.
|
|
23
|
+
current_version = "0.11.0"
|
|
26
24
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
27
25
|
serialize = ["{major}.{minor}.{patch}"]
|
|
28
26
|
search = "{current_version}"
|
csonpath-0.11.0/setup.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from setuptools import setup, Extension
|
|
5
|
+
|
|
6
|
+
# Force MinGW compiler on Windows
|
|
7
|
+
if platform.system() == "Windows":
|
|
8
|
+
# Set compiler before importing distutils
|
|
9
|
+
os.environ["CC"] = "gcc"
|
|
10
|
+
# Override distutils to use MinGW
|
|
11
|
+
from distutils.cygwinccompiler import Mingw32CCompiler
|
|
12
|
+
from distutils import sysconfig
|
|
13
|
+
sysconfig.get_config_vars()["CC"] = "gcc"
|
|
14
|
+
|
|
15
|
+
# Base sources
|
|
16
|
+
sources = ["csonpath_python.c"]
|
|
17
|
+
extra_compile_args=["-O3", "-I./"]
|
|
18
|
+
|
|
19
|
+
# On Windows, include tiny_regex.c for regex support
|
|
20
|
+
if platform.system() == "Windows":
|
|
21
|
+
sources.append("tiny-regex-c/re.c")
|
|
22
|
+
extra_compile_args.append("-DCSONPATH_TINY_REGEX")
|
|
23
|
+
extra_compile_args.append("-I./tiny-regex-c/")
|
|
24
|
+
|
|
25
|
+
extension = Extension(
|
|
26
|
+
"csonpath",
|
|
27
|
+
sources=sources,
|
|
28
|
+
extra_compile_args=extra_compile_args,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
setup(
|
|
32
|
+
ext_modules=[extension],
|
|
33
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|