csonpath 0.0.3__tar.gz → 0.1.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.0.3/csonpath.egg-info → csonpath-0.1.0}/PKG-INFO +2 -2
- {csonpath-0.0.3 → csonpath-0.1.0}/README.md +1 -1
- {csonpath-0.0.3 → csonpath-0.1.0/csonpath.egg-info}/PKG-INFO +2 -2
- {csonpath-0.0.3 → csonpath-0.1.0}/csonpath.h +352 -189
- {csonpath-0.0.3 → csonpath-0.1.0}/csonpath_do.h +60 -21
- {csonpath-0.0.3 → csonpath-0.1.0}/csonpath_python.c +6 -1
- {csonpath-0.0.3 → csonpath-0.1.0}/pyproject.toml +1 -1
- {csonpath-0.0.3 → csonpath-0.1.0}/LICENSE +0 -0
- {csonpath-0.0.3 → csonpath-0.1.0}/MANIFEST.in +0 -0
- {csonpath-0.0.3 → csonpath-0.1.0}/csonpath.egg-info/SOURCES.txt +0 -0
- {csonpath-0.0.3 → csonpath-0.1.0}/csonpath.egg-info/dependency_links.txt +0 -0
- {csonpath-0.0.3 → csonpath-0.1.0}/csonpath.egg-info/requires.txt +0 -0
- {csonpath-0.0.3 → csonpath-0.1.0}/csonpath.egg-info/top_level.txt +0 -0
- {csonpath-0.0.3 → csonpath-0.1.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csonpath
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Description-Content-Type: text/markdown
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Provides-Extra: dev
|
|
@@ -123,4 +123,4 @@ Feel free to open issues or pull requests!
|
|
|
123
123
|
|
|
124
124
|
## 📜 License
|
|
125
125
|
BSD 3-Clause. See [LICENSE](LICENSE).
|
|
126
|
-
|
|
126
|
+
remimu.h is under the CC0 1.0 Universal, original source is [here](https://github.com/wareya/Remimu)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csonpath
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Description-Content-Type: text/markdown
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Provides-Extra: dev
|
|
@@ -123,4 +123,4 @@ Feel free to open issues or pull requests!
|
|
|
123
123
|
|
|
124
124
|
## 📜 License
|
|
125
125
|
BSD 3-Clause. See [LICENSE](LICENSE).
|
|
126
|
-
|
|
126
|
+
remimu.h is under the CC0 1.0 Universal, original source is [here](https://github.com/wareya/Remimu)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#if !defined(CSONPATH_JSON) || !defined(CSONPATH_NULL) || !defined(CSONPATH_GET) || \
|
|
2
|
+
!defined(CSONPATH_IS_STR) || \
|
|
2
3
|
!defined(CSONPATH_AT) || !defined(CSONPATH_IS_OBJ) || !defined(CSONPATH_IS_ARRAY) || \
|
|
3
4
|
!defined(CSONPATH_CALLBACK) || !defined(CSONPATH_CALLBACK_DATA) || \
|
|
4
5
|
!defined(CSONPATH_EQUAL_STR) || !defined(CSONPATH_CALL_CALLBACK) || \
|
|
@@ -8,6 +9,10 @@
|
|
|
8
9
|
# error "some defined are missing"
|
|
9
10
|
#endif
|
|
10
11
|
|
|
12
|
+
#ifndef CSONPATH_NO_REGEX
|
|
13
|
+
#include <regex.h>
|
|
14
|
+
#endif
|
|
15
|
+
|
|
11
16
|
#define CSONPATH_UNUSED __attribute__((unused))
|
|
12
17
|
#define MAY_ALIAS __attribute__((__may_alias__))
|
|
13
18
|
|
|
@@ -30,6 +35,8 @@ enum csonpath_instuction_raw {
|
|
|
30
35
|
CSONPATH_INST_GET_ARRAY_SMALL,
|
|
31
36
|
CSONPATH_INST_GET_ARRAY_BIG,
|
|
32
37
|
CSONPATH_INST_FILTER_KEY_EQ,
|
|
38
|
+
CSONPATH_INST_FILTER_KEY_NOT_EQ,
|
|
39
|
+
CSONPATH_INST_FILTER_KEY_REG_EQ,
|
|
33
40
|
CSONPATH_INST_FILTER_OPERAND_STR,
|
|
34
41
|
CSONPATH_INST_FILTER_OPERAND_BYTE, /* store the same way it's in ARRAY_SMALL */
|
|
35
42
|
CSONPATH_INST_FILTER_OPERAND_INT, /* store the same way it's in ARRAY_BIG */
|
|
@@ -48,6 +55,8 @@ CSONPATH_UNUSED static const char *csonpath_instuction_str[] = {
|
|
|
48
55
|
"GET_ARRAY_SMALL",
|
|
49
56
|
"GET_ARRAY_BIG",
|
|
50
57
|
"FILTER_KEY_EQ",
|
|
58
|
+
"FILTER_KEY_NOT_EQ",
|
|
59
|
+
"FILTER_KEY_REG_EQ",
|
|
51
60
|
"FILTER_OPERAND_STR",
|
|
52
61
|
"FILTER_OPERAND_BYTE",
|
|
53
62
|
"FILTER_OPERAND_INT",
|
|
@@ -65,9 +74,12 @@ enum {
|
|
|
65
74
|
};
|
|
66
75
|
|
|
67
76
|
struct csonpath_instruction {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
77
|
+
unsigned char inst;
|
|
78
|
+
union {
|
|
79
|
+
unsigned char filter_next;
|
|
80
|
+
unsigned char regex_idx;
|
|
81
|
+
};
|
|
82
|
+
short int next;
|
|
71
83
|
};
|
|
72
84
|
|
|
73
85
|
#define CSONPATH_INST_MIN_ALLOC (1 << 7)
|
|
@@ -79,6 +91,10 @@ struct csonpath {
|
|
|
79
91
|
int compiled;
|
|
80
92
|
int inst_idx;
|
|
81
93
|
int inst_size;
|
|
94
|
+
#ifndef CSONPATH_NO_REGEX
|
|
95
|
+
int regex_cnt;
|
|
96
|
+
regex_t *regexs;
|
|
97
|
+
#endif
|
|
82
98
|
};
|
|
83
99
|
|
|
84
100
|
struct csonpath_child_info {
|
|
@@ -89,30 +105,47 @@ struct csonpath_child_info {
|
|
|
89
105
|
};
|
|
90
106
|
};
|
|
91
107
|
|
|
108
|
+
#define CSONPATH_ERROR_MAX_SIZE 1024
|
|
109
|
+
#define CSONPATH_TMP_BUF_SIZE 256
|
|
110
|
+
|
|
92
111
|
/* I'm assuming error message won't be longer than 125 */
|
|
93
112
|
#define CSONPATH_COMPILE_ERR(tmp, idx, args...) do { \
|
|
94
113
|
int ltmp = strlen(tmp), lidx, oidx = idx; \
|
|
95
114
|
if (cjp->compile_error) \
|
|
96
115
|
free(cjp->compile_error); \
|
|
97
|
-
cjp->compile_error = malloc(ltmp * 2 +
|
|
98
|
-
lidx = snprintf(cjp->compile_error,
|
|
116
|
+
cjp->compile_error = malloc(ltmp * 2 + CSONPATH_ERROR_MAX_SIZE); \
|
|
117
|
+
lidx = snprintf(cjp->compile_error, CSONPATH_ERROR_MAX_SIZE, "colum %d:\n", oidx); \
|
|
99
118
|
strcpy(cjp->compile_error + lidx, tmp); \
|
|
100
119
|
ltmp += lidx; \
|
|
101
120
|
cjp->compile_error[ltmp++] = '\n'; \
|
|
102
121
|
for (; oidx; --oidx) {cjp->compile_error[ltmp++] = ' ';} \
|
|
103
|
-
snprintf(cjp->compile_error + ltmp,
|
|
122
|
+
snprintf(cjp->compile_error + ltmp, CSONPATH_ERROR_MAX_SIZE - lidx, "\\-- "args); \
|
|
104
123
|
goto error; \
|
|
105
124
|
} while (0)
|
|
106
125
|
|
|
126
|
+
#define CSONPATH_REQUIRE_ERR(c, on) do { \
|
|
127
|
+
CSONPATH_COMPILE_ERR(tmp, on - orig, \
|
|
128
|
+
"'%c' require", c); \
|
|
129
|
+
goto error; \
|
|
130
|
+
} while (0)
|
|
131
|
+
|
|
132
|
+
#define CSONPATH_SKIP(c, on) do { \
|
|
133
|
+
if (*on != c) { \
|
|
134
|
+
CSONPATH_REQUIRE_ERR(c, on); \
|
|
135
|
+
} \
|
|
136
|
+
++on; \
|
|
137
|
+
} while (0)
|
|
138
|
+
|
|
139
|
+
|
|
107
140
|
static inline struct csonpath_child_info *csonpath_child_info_set(struct csonpath_child_info *child_info,
|
|
108
141
|
CSONPATH_JSON j, const intptr_t key)
|
|
109
142
|
{
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
143
|
+
if (CSONPATH_IS_OBJ(j)) {
|
|
144
|
+
*child_info = (struct csonpath_child_info){.key=(const char *)key, .type=CSONPATH_STR};
|
|
145
|
+
} else {
|
|
146
|
+
*child_info = (struct csonpath_child_info){.idx=key, .type=CSONPATH_INTEGER};
|
|
147
|
+
}
|
|
148
|
+
return child_info;
|
|
116
149
|
}
|
|
117
150
|
|
|
118
151
|
static inline void csonpath_destroy(struct csonpath cjp[static 1])
|
|
@@ -120,57 +153,79 @@ static inline void csonpath_destroy(struct csonpath cjp[static 1])
|
|
|
120
153
|
free(cjp->path);
|
|
121
154
|
free(cjp->inst_lst);
|
|
122
155
|
free(cjp->compile_error);
|
|
156
|
+
if (cjp->regex_cnt) {
|
|
157
|
+
for (int i = 0; i < cjp->regex_cnt; ++i) {
|
|
158
|
+
regfree(&cjp->regexs[i]);
|
|
159
|
+
}
|
|
160
|
+
free(cjp->regexs);
|
|
161
|
+
}
|
|
123
162
|
*cjp = (struct csonpath){};
|
|
124
163
|
}
|
|
125
164
|
|
|
126
165
|
static inline int csonpath_init(struct csonpath cjp[static 1],
|
|
127
166
|
const char path[static 1]) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
167
|
+
*cjp = (struct csonpath) {.path=strdup(path),
|
|
168
|
+
.inst_size = CSONPATH_INST_MIN_ALLOC,
|
|
169
|
+
.inst_lst = malloc(sizeof(*cjp->inst_lst) * CSONPATH_INST_MIN_ALLOC)};
|
|
170
|
+
if (!cjp->path || !cjp->inst_lst) {
|
|
171
|
+
return -ENOMEM;
|
|
172
|
+
}
|
|
173
|
+
return 0;
|
|
135
174
|
}
|
|
136
175
|
|
|
137
176
|
static inline int csonpath_set_path(struct csonpath cjp[static 1],
|
|
138
177
|
const char path[static 1])
|
|
139
178
|
{
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
free(cjp->inst_lst);
|
|
143
|
-
return csonpath_init(cjp, path);
|
|
179
|
+
csonpath_destroy(cjp);
|
|
180
|
+
return csonpath_init(cjp, path);
|
|
144
181
|
}
|
|
145
182
|
|
|
146
|
-
void csonpath_push_inst(struct csonpath cjp[static 1], int inst)
|
|
183
|
+
static inline void csonpath_push_inst(struct csonpath cjp[static 1], int inst)
|
|
147
184
|
{
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
185
|
+
if (cjp->inst_idx + 1 > cjp->inst_size) {
|
|
186
|
+
cjp->inst_size = cjp->inst_size << 1;
|
|
187
|
+
cjp->inst_lst = realloc(cjp->inst_lst, cjp->inst_size);
|
|
188
|
+
assert(cjp->inst_lst);
|
|
189
|
+
}
|
|
190
|
+
cjp->inst_lst[cjp->inst_idx] = (struct csonpath_instruction){.inst=inst};
|
|
191
|
+
++cjp->inst_idx;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
static inline void csonpath_push_inst_cpy(struct csonpath cjp[static 1],
|
|
195
|
+
struct csonpath_instruction inst)
|
|
196
|
+
{
|
|
197
|
+
if (cjp->inst_idx + 1 > cjp->inst_size) {
|
|
198
|
+
cjp->inst_size = cjp->inst_size << 1;
|
|
199
|
+
cjp->inst_lst = realloc(cjp->inst_lst, cjp->inst_size);
|
|
200
|
+
assert(cjp->inst_lst);
|
|
201
|
+
}
|
|
202
|
+
cjp->inst_lst[cjp->inst_idx] = inst;
|
|
203
|
+
++cjp->inst_idx;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
static void csonpath_print_instruction(struct csonpath cjp[static 1])
|
|
207
|
+
{
|
|
208
|
+
int idx = 0;
|
|
209
|
+
for (;cjp->inst_lst[idx].inst != CSONPATH_INST_END; ++idx) {
|
|
210
|
+
printf("%d: %s\n", idx, csonpath_instuction_str[(int)cjp->inst_lst[idx].inst]);
|
|
211
|
+
}
|
|
212
|
+
printf("%d: END\n", idx);
|
|
155
213
|
}
|
|
156
214
|
|
|
157
|
-
int csonpath_compile(struct csonpath cjp[static 1])
|
|
215
|
+
static int csonpath_compile(struct csonpath cjp[static 1])
|
|
158
216
|
{
|
|
159
217
|
char *walker = cjp->path;
|
|
160
218
|
char *orig = walker;
|
|
161
219
|
char *next;
|
|
162
220
|
char to_check;
|
|
163
|
-
char *tmp;
|
|
221
|
+
char *tmp; /* tmp is only here for debug */
|
|
164
222
|
|
|
165
223
|
if (cjp->compiled)
|
|
166
224
|
return 0;
|
|
167
225
|
|
|
168
226
|
tmp = strdup(cjp->path);
|
|
169
227
|
root_again:
|
|
170
|
-
|
|
171
|
-
CSONPATH_COMPILE_ERR(tmp, walker - orig, "%s", "'$' needed");
|
|
172
|
-
}
|
|
173
|
-
++walker;
|
|
228
|
+
CSONPATH_SKIP('$', walker);
|
|
174
229
|
csonpath_push_inst(cjp, CSONPATH_INST_ROOT);
|
|
175
230
|
cjp->inst_lst[cjp->inst_idx - 1].next = 1;
|
|
176
231
|
to_check = *walker;
|
|
@@ -179,180 +234,288 @@ again:
|
|
|
179
234
|
switch (to_check) {
|
|
180
235
|
case '[':
|
|
181
236
|
{
|
|
182
|
-
|
|
183
|
-
|
|
237
|
+
int end;
|
|
238
|
+
|
|
239
|
+
do_array:
|
|
240
|
+
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
241
|
+
++walker;
|
|
242
|
+
if (*walker == '*') {
|
|
243
|
+
csonpath_push_inst(cjp, CSONPATH_INST_GET_ALL);
|
|
244
|
+
if (walker[1] != ']') {
|
|
245
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig, "%s", "unclose bracket\n");
|
|
246
|
+
}
|
|
247
|
+
cjp->inst_lst[cjp->inst_idx - 1].next = 2;
|
|
248
|
+
walker += 2;
|
|
249
|
+
to_check = *walker;
|
|
250
|
+
goto again;
|
|
251
|
+
} else if (*walker == '?') {
|
|
252
|
+
int have_blank;
|
|
253
|
+
int have_parentesis = 0;
|
|
254
|
+
int nb_getter_inst = 0;
|
|
255
|
+
struct csonpath_instruction filter_getter[CSONPATH_TMP_BUF_SIZE];
|
|
256
|
+
int regex_idx = -1;
|
|
257
|
+
int inst;
|
|
258
|
+
|
|
259
|
+
inst = CSONPATH_INST_GET_OBJ;
|
|
184
260
|
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
185
261
|
++walker;
|
|
186
|
-
if (*walker == '
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
to_check = *walker;
|
|
194
|
-
goto again;
|
|
195
|
-
} else if (*walker == '?') {
|
|
262
|
+
if (*walker == '(') {
|
|
263
|
+
have_parentesis = 1;
|
|
264
|
+
++walker;
|
|
265
|
+
CSONPATH_SKIP('@', walker);
|
|
266
|
+
CSONPATH_SKIP('.', walker);
|
|
267
|
+
cjp->inst_lst[cjp->inst_idx - 1].next += 3;
|
|
268
|
+
for (; isblank(*walker); ++walker)
|
|
196
269
|
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
walker[3] = u.c[3];
|
|
289
|
-
csonpath_push_inst(cjp, CSONPATH_INST_GET_ARRAY_BIG);
|
|
270
|
+
}
|
|
271
|
+
filter_again:
|
|
272
|
+
for (next = walker; isalnum(*next) || *next == '_' || *next == '-'; ++next);
|
|
273
|
+
if (!*next) {
|
|
274
|
+
CSONPATH_COMPILE_ERR(tmp, next - orig,
|
|
275
|
+
"filter miss condition");
|
|
276
|
+
goto error;
|
|
277
|
+
}
|
|
278
|
+
to_check = *next;
|
|
279
|
+
*next = 0;
|
|
280
|
+
filter_getter[nb_getter_inst++] = (struct csonpath_instruction){.inst=inst,
|
|
281
|
+
.next=next - walker};
|
|
282
|
+
if (to_check == '.') {
|
|
283
|
+
filter_getter[nb_getter_inst-1].next += 1;
|
|
284
|
+
walker = next + 1;
|
|
285
|
+
goto filter_again;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (have_parentesis && to_check == ')') {
|
|
289
|
+
filter_getter[nb_getter_inst-1].next += 1;
|
|
290
|
+
++next;
|
|
291
|
+
to_check = *next;
|
|
292
|
+
have_parentesis = 0;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
walker = next;
|
|
296
|
+
have_blank = isblank(to_check);
|
|
297
|
+
|
|
298
|
+
for (++next; isblank(*next); ++next) {
|
|
299
|
+
have_blank = 1;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (*next && have_blank &&
|
|
303
|
+
to_check != '=' && to_check != '!') {
|
|
304
|
+
to_check = *next;
|
|
305
|
+
++next;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (!*next) {
|
|
309
|
+
CSONPATH_COMPILE_ERR(tmp, next - orig,
|
|
310
|
+
"filter miss condition");
|
|
311
|
+
|
|
312
|
+
goto error;
|
|
313
|
+
}
|
|
314
|
+
/* = and == are the same here */
|
|
315
|
+
if (to_check == '=') {
|
|
316
|
+
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_EQ);
|
|
317
|
+
if (next[0] == '=')
|
|
318
|
+
++next;
|
|
319
|
+
else if (next[0] == '~') {
|
|
320
|
+
cjp->inst_lst[cjp->inst_idx - 1].inst = CSONPATH_INST_FILTER_KEY_REG_EQ;
|
|
321
|
+
regex_idx = cjp->regex_cnt++;
|
|
322
|
+
++next;
|
|
323
|
+
}
|
|
324
|
+
} else if (to_check == '!' && next[0] == '=') {
|
|
325
|
+
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_NOT_EQ);
|
|
326
|
+
++next;
|
|
327
|
+
} else {
|
|
328
|
+
CSONPATH_COMPILE_ERR(tmp, next - orig,
|
|
329
|
+
"'%c': unsuported operation", to_check);
|
|
330
|
+
goto error;
|
|
331
|
+
}
|
|
332
|
+
for (;isblank(*next); ++next);
|
|
333
|
+
cjp->inst_lst[cjp->inst_idx - 1].next = 0;
|
|
334
|
+
cjp->inst_lst[cjp->inst_idx - 1].filter_next = cjp->inst_idx + nb_getter_inst;
|
|
335
|
+
for (int i = 0; i < nb_getter_inst; ++i) {
|
|
336
|
+
csonpath_push_inst_cpy(cjp, filter_getter[i]);
|
|
337
|
+
}
|
|
338
|
+
cjp->inst_lst[cjp->inst_idx - 1].next += next - walker;
|
|
339
|
+
walker = next;
|
|
340
|
+
if (*walker == '"' || *walker == '\'') {
|
|
341
|
+
char end = *walker;
|
|
342
|
+
++walker;
|
|
343
|
+
cjp->inst_lst[cjp->inst_idx - 1].next++;
|
|
344
|
+
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_STR);
|
|
345
|
+
for (next = walker; *next && *next != end; ++next);
|
|
346
|
+
if (!*next) {
|
|
347
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
348
|
+
"broken filter");
|
|
349
|
+
goto error;
|
|
350
|
+
}
|
|
351
|
+
*next = 0;
|
|
352
|
+
#ifndef CSONPATH_NO_REGEX
|
|
353
|
+
if (regex_idx >= 0) {
|
|
354
|
+
if (!regex_idx)
|
|
355
|
+
cjp->regexs = malloc(sizeof *cjp->regexs * 255);
|
|
356
|
+
int e = regcomp(&cjp->regexs[regex_idx], walker, 0);
|
|
357
|
+
cjp->inst_lst[cjp->inst_idx - 1].regex_idx = regex_idx;
|
|
358
|
+
if (e) {
|
|
359
|
+
CSONPATH_COMPILE_ERR(tmp, next - orig, "regex has error\n");
|
|
360
|
+
goto error;
|
|
290
361
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
362
|
+
}
|
|
363
|
+
#endif
|
|
364
|
+
++next;
|
|
365
|
+
to_check = *next;
|
|
295
366
|
} else {
|
|
296
|
-
|
|
297
|
-
|
|
367
|
+
int n;
|
|
368
|
+
|
|
369
|
+
for (next = walker; isdigit(*next); ++next);
|
|
370
|
+
if (next == walker) {
|
|
371
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
372
|
+
"'%c': broken filter with number",
|
|
373
|
+
*walker);
|
|
374
|
+
goto error;
|
|
375
|
+
}
|
|
376
|
+
n = atoi(walker);
|
|
377
|
+
if (n < 100) {
|
|
378
|
+
*walker = n;
|
|
379
|
+
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_BYTE);
|
|
380
|
+
} else {
|
|
381
|
+
MAY_ALIAS int *walk_int = (void *)walker;
|
|
382
|
+
*walk_int = n;
|
|
383
|
+
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_INT);
|
|
384
|
+
}
|
|
385
|
+
if (!*next) {
|
|
386
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
387
|
+
"compilation error");
|
|
388
|
+
goto error;
|
|
389
|
+
}
|
|
390
|
+
to_check = *next;
|
|
391
|
+
*next = 0;
|
|
392
|
+
}
|
|
393
|
+
if (isblank(to_check)) {
|
|
394
|
+
for (next++; isblank(*next); ++next);
|
|
395
|
+
to_check = *next;
|
|
396
|
+
}
|
|
298
397
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
398
|
+
if (have_parentesis) {
|
|
399
|
+
CSONPATH_SKIP(')', next);
|
|
400
|
+
to_check = *next;
|
|
401
|
+
}
|
|
402
|
+
if (to_check != ']') {
|
|
403
|
+
CSONPATH_REQUIRE_ERR(']', next);
|
|
404
|
+
}
|
|
405
|
+
/* skip space */
|
|
406
|
+
cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
|
|
407
|
+
walker = next + 1;
|
|
408
|
+
to_check = *walker;
|
|
409
|
+
goto again;
|
|
410
|
+
} else if (*walker != '"' && *walker != '\'') {
|
|
411
|
+
int num;
|
|
412
|
+
|
|
413
|
+
next = walker;
|
|
414
|
+
do {
|
|
415
|
+
if (*next < '0' || *next > '9') {
|
|
416
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
417
|
+
"unexpected '%c', sting, filter or number require\n", *next);
|
|
418
|
+
}
|
|
419
|
+
next++;
|
|
420
|
+
} while (*next && *next != ']');
|
|
421
|
+
if (!*next) {
|
|
422
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
423
|
+
"%s", "unclose bracket\n");
|
|
424
|
+
}
|
|
425
|
+
*next = 0;
|
|
426
|
+
num = atoi(walker);
|
|
427
|
+
if (num < 100) {
|
|
428
|
+
csonpath_push_inst(cjp, CSONPATH_INST_GET_ARRAY_SMALL);
|
|
429
|
+
*walker = num;
|
|
430
|
+
} else {
|
|
431
|
+
union {
|
|
432
|
+
int n;
|
|
433
|
+
char c[4];
|
|
434
|
+
} u = {.n=num};
|
|
435
|
+
walker[0] = u.c[0];
|
|
436
|
+
walker[1] = u.c[1];
|
|
437
|
+
walker[2] = u.c[2];
|
|
438
|
+
walker[3] = u.c[3];
|
|
439
|
+
csonpath_push_inst(cjp, CSONPATH_INST_GET_ARRAY_BIG);
|
|
440
|
+
}
|
|
441
|
+
cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
|
|
442
|
+
walker = next + 1;
|
|
443
|
+
to_check = *walker;
|
|
444
|
+
goto again;
|
|
445
|
+
} else {
|
|
446
|
+
end = *walker;
|
|
447
|
+
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
448
|
+
|
|
449
|
+
++walker;
|
|
450
|
+
next = walker;
|
|
451
|
+
while (*next++ != end) {
|
|
452
|
+
/* \" should be ignored */
|
|
453
|
+
while (*next == '\\')
|
|
308
454
|
++next;
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
455
|
+
}
|
|
456
|
+
--next;
|
|
457
|
+
*next = 0;
|
|
458
|
+
++next;
|
|
459
|
+
if (*next != ']')
|
|
460
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
461
|
+
"']' require instead of '%c'\n", *next);
|
|
312
462
|
|
|
313
|
-
|
|
314
|
-
|
|
463
|
+
csonpath_push_inst(cjp, CSONPATH_INST_GET_OBJ);
|
|
464
|
+
cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
|
|
315
465
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
466
|
+
walker = next + 1;
|
|
467
|
+
to_check = *walker;
|
|
468
|
+
goto again;
|
|
469
|
+
}
|
|
320
470
|
}
|
|
321
471
|
case '.':
|
|
322
472
|
{
|
|
323
|
-
|
|
473
|
+
int inst = CSONPATH_INST_GET_OBJ;
|
|
324
474
|
|
|
475
|
+
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
476
|
+
++walker;
|
|
477
|
+
if (*walker == '.') {
|
|
478
|
+
inst = CSONPATH_INST_FIND_ALL;
|
|
325
479
|
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
326
480
|
++walker;
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
for (next = walker; *next && *next != '[' && *next != '.' && *next != '|';
|
|
333
|
-
++next);
|
|
334
|
-
to_check = *next;
|
|
335
|
-
*next = 0;
|
|
336
|
-
|
|
481
|
+
} else if (*walker == '*') {
|
|
482
|
+
inst = CSONPATH_INST_GET_ALL;
|
|
483
|
+
++walker;
|
|
484
|
+
if (*walker != '.' && *walker != '[' && *walker != '\0')
|
|
485
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig, "unsuported characters '%c' after '*'", *walker);
|
|
337
486
|
csonpath_push_inst(cjp, inst);
|
|
338
|
-
|
|
339
|
-
walker = next;
|
|
487
|
+
to_check = *walker;
|
|
340
488
|
goto again;
|
|
489
|
+
}
|
|
490
|
+
for (next = walker; *next && *next != '[' && *next != '.' && *next != '|';
|
|
491
|
+
++next);
|
|
492
|
+
if (next == walker) {
|
|
493
|
+
if (*next == '[')
|
|
494
|
+
goto do_array;
|
|
495
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig, "empty getter");
|
|
496
|
+
}
|
|
497
|
+
to_check = *next;
|
|
498
|
+
*next = 0;
|
|
499
|
+
|
|
500
|
+
csonpath_push_inst(cjp, inst);
|
|
501
|
+
cjp->inst_lst[cjp->inst_idx - 1].next = next - walker;
|
|
502
|
+
walker = next;
|
|
503
|
+
goto again;
|
|
341
504
|
}
|
|
342
505
|
case '|':
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
506
|
+
/* cjp->inst_lst[cjp->inst_idx - 1].next += 1; */
|
|
507
|
+
csonpath_push_inst(cjp, CSONPATH_INST_OR);
|
|
508
|
+
++walker;
|
|
509
|
+
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
510
|
+
goto root_again;
|
|
348
511
|
}
|
|
349
512
|
if (*walker == 0) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
513
|
+
csonpath_push_inst(cjp, CSONPATH_INST_END);
|
|
514
|
+
cjp->compiled = 1;
|
|
515
|
+
free(tmp);
|
|
516
|
+
return 0;
|
|
354
517
|
}
|
|
355
|
-
error:
|
|
518
|
+
error:
|
|
356
519
|
cjp->inst_lst[0] = (struct csonpath_instruction){.inst=CSONPATH_INST_BROKEN};
|
|
357
520
|
free(tmp);
|
|
358
521
|
return -1;
|
|
@@ -161,34 +161,72 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
|
|
|
161
161
|
walker += cjp->inst_lst[idx].next;
|
|
162
162
|
break;
|
|
163
163
|
case CSONPATH_INST_FILTER_KEY_EQ:
|
|
164
|
+
case CSONPATH_INST_FILTER_KEY_REG_EQ:
|
|
165
|
+
case CSONPATH_INST_FILTER_KEY_NOT_EQ:
|
|
164
166
|
{
|
|
165
167
|
CSONPATH_JSON el;
|
|
166
|
-
|
|
168
|
+
int operation = cjp->inst_lst[idx].inst;
|
|
167
169
|
walker += cjp->inst_lst[idx].next;
|
|
168
|
-
|
|
170
|
+
char *owalker;
|
|
171
|
+
int filter_next = cjp->inst_lst[idx].filter_next;
|
|
172
|
+
int in_idx = idx + 1;
|
|
169
173
|
|
|
170
174
|
CSONPATH_DO_FILTER_PRE_LOOP;
|
|
171
175
|
CSONPATH_FOREACH(tmp, el, {
|
|
172
176
|
if (CSONPATH_IS_OBJ(el)) {
|
|
173
|
-
CSONPATH_JSON el2;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
177
|
+
CSONPATH_JSON el2 = el;
|
|
178
|
+
|
|
179
|
+
owalker = walker;
|
|
180
|
+
idx = in_idx;
|
|
181
|
+
CSONPATH_DO_FILTER_LOOP_PRE_SET;
|
|
182
|
+
for (; idx < filter_next; ++idx) {
|
|
183
|
+
switch (cjp->inst_lst[idx].inst) {
|
|
184
|
+
case CSONPATH_INST_GET_OBJ:
|
|
185
|
+
el2 = CSONPATH_GET(el2, owalker);
|
|
186
|
+
break;
|
|
187
|
+
default:
|
|
188
|
+
CSONPATH_GETTER_ERR("unsuported");
|
|
189
|
+
}
|
|
190
|
+
owalker += cjp->inst_lst[idx].next;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (cjp->inst_lst[idx].inst != CSONPATH_INST_FILTER_OPERAND_STR)
|
|
194
|
+
CSONPATH_GETTER_ERR("unsuported instruction '%s' only FILTER_OPERAND_STR is supported here", csonpath_instuction_str[(int)cjp->inst_lst[idx].inst]);
|
|
195
|
+
|
|
196
|
+
if (el2 != CSONPATH_NULL) {
|
|
197
|
+
_Bool match = 0;
|
|
198
|
+
switch (operation) {
|
|
199
|
+
case CSONPATH_INST_FILTER_KEY_NOT_EQ:
|
|
200
|
+
match = !CSONPATH_EQUAL_STR(el2, owalker);
|
|
201
|
+
break;
|
|
202
|
+
case CSONPATH_INST_FILTER_KEY_EQ:
|
|
203
|
+
match = CSONPATH_EQUAL_STR(el2, owalker);
|
|
204
|
+
break;
|
|
205
|
+
case CSONPATH_INST_FILTER_KEY_REG_EQ:
|
|
206
|
+
#ifdef CSONPATH_NO_REGEX
|
|
207
|
+
CSONPATH_GETTER_ERR("regex deactivate\n");
|
|
208
|
+
return CSONPATH_NONE_FOUND_RET;
|
|
209
|
+
#else
|
|
210
|
+
if (CSONPATH_IS_STR(el2)) {
|
|
211
|
+
int regex_idx = cjp->inst_lst[idx].regex_idx;
|
|
212
|
+
regex_t *compiled = &cjp->regexs[regex_idx];
|
|
213
|
+
int match_len = regexec(compiled, CSONPATH_GET_STR(el2),
|
|
214
|
+
0, NULL, 0);
|
|
215
|
+
match = match_len == 0;
|
|
189
216
|
}
|
|
190
|
-
|
|
217
|
+
break;
|
|
218
|
+
#endif
|
|
219
|
+
}
|
|
220
|
+
if (match) {
|
|
221
|
+
CSONPATH_DO_RET_TYPE tret =
|
|
222
|
+
csonpath_do_internal(cjp, origin, el, tmp, idx + 1,
|
|
223
|
+
owalker + cjp->inst_lst[idx].next
|
|
224
|
+
CSONPATH_DO_EXTRA_ARGS_NEESTED);
|
|
225
|
+
|
|
226
|
+
CSONPATH_DO_FILTER_FIND;
|
|
191
227
|
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
192
230
|
});
|
|
193
231
|
CSONPATH_DO_FILTER_OUT;
|
|
194
232
|
break;
|
|
@@ -261,7 +299,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
|
|
|
261
299
|
break;
|
|
262
300
|
}
|
|
263
301
|
default:
|
|
264
|
-
CSONPATH_GETTER_ERR("unimplemented %d\n", cjp->inst_lst[idx].inst);
|
|
302
|
+
CSONPATH_GETTER_ERR("unimplemented %d at idx %d\n", cjp->inst_lst[idx].inst, idx);
|
|
265
303
|
}
|
|
266
304
|
next_inst:
|
|
267
305
|
++idx;
|
|
@@ -281,7 +319,8 @@ static CSONPATH_DO_RET_TYPE csonpath_do_(struct csonpath cjp[static 1],
|
|
|
281
319
|
(void)ctx;
|
|
282
320
|
csonpath_compile(cjp);
|
|
283
321
|
if (cjp->inst_lst[0].inst == CSONPATH_INST_BROKEN) {
|
|
284
|
-
CSONPATH_GETTER_ERR("fail to compile: %s\n", cjp->compile_error
|
|
322
|
+
CSONPATH_GETTER_ERR("fail to compile: %s\n", cjp->compile_error ?
|
|
323
|
+
cjp->compile_error : "(unknow error)");
|
|
285
324
|
return CSONPATH_NONE_FOUND_RET;
|
|
286
325
|
}
|
|
287
326
|
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
|
|
19
19
|
#define CSONPATH_IS_ARRAY(o) PyList_Check(o)
|
|
20
20
|
|
|
21
|
+
#define CSONPATH_IS_STR(o) PyUnicode_Check(o)
|
|
22
|
+
|
|
23
|
+
#define CSONPATH_GET_STR(obj) \
|
|
24
|
+
PyUnicode_AsUTF8(obj)
|
|
25
|
+
|
|
21
26
|
#define CSONPATH_EQUAL_STR(obj, to_cmp) ({ \
|
|
22
27
|
_Bool r = 0; \
|
|
23
28
|
if (PyUnicode_Check(obj)) { \
|
|
@@ -149,7 +154,7 @@ static PyObject *PyCsonPath_new(PyTypeObject *subtype, PyObject* args,
|
|
|
149
154
|
|
|
150
155
|
if (csonpath_compile(ret) < 0) {
|
|
151
156
|
char *error = ret->compile_error;
|
|
152
|
-
PyErr_Format(PyExc_ValueError, "compilation fail %s", error);
|
|
157
|
+
PyErr_Format(PyExc_ValueError, "compilation fail %s", error ? error : "(unknow error)");
|
|
153
158
|
csonpath_destroy(ret);
|
|
154
159
|
return NULL;
|
|
155
160
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|