csonpath 0.0.4__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.4/csonpath.egg-info → csonpath-0.1.0}/PKG-INFO +2 -2
- {csonpath-0.0.4 → csonpath-0.1.0}/README.md +1 -1
- {csonpath-0.0.4 → csonpath-0.1.0/csonpath.egg-info}/PKG-INFO +2 -2
- {csonpath-0.0.4 → csonpath-0.1.0}/csonpath.h +345 -230
- {csonpath-0.0.4 → csonpath-0.1.0}/csonpath_do.h +56 -22
- {csonpath-0.0.4 → csonpath-0.1.0}/csonpath_python.c +5 -0
- {csonpath-0.0.4 → csonpath-0.1.0}/pyproject.toml +1 -1
- {csonpath-0.0.4 → csonpath-0.1.0}/LICENSE +0 -0
- {csonpath-0.0.4 → csonpath-0.1.0}/MANIFEST.in +0 -0
- {csonpath-0.0.4 → csonpath-0.1.0}/csonpath.egg-info/SOURCES.txt +0 -0
- {csonpath-0.0.4 → csonpath-0.1.0}/csonpath.egg-info/dependency_links.txt +0 -0
- {csonpath-0.0.4 → csonpath-0.1.0}/csonpath.egg-info/requires.txt +0 -0
- {csonpath-0.0.4 → csonpath-0.1.0}/csonpath.egg-info/top_level.txt +0 -0
- {csonpath-0.0.4 → 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
|
|
|
@@ -31,6 +36,7 @@ enum csonpath_instuction_raw {
|
|
|
31
36
|
CSONPATH_INST_GET_ARRAY_BIG,
|
|
32
37
|
CSONPATH_INST_FILTER_KEY_EQ,
|
|
33
38
|
CSONPATH_INST_FILTER_KEY_NOT_EQ,
|
|
39
|
+
CSONPATH_INST_FILTER_KEY_REG_EQ,
|
|
34
40
|
CSONPATH_INST_FILTER_OPERAND_STR,
|
|
35
41
|
CSONPATH_INST_FILTER_OPERAND_BYTE, /* store the same way it's in ARRAY_SMALL */
|
|
36
42
|
CSONPATH_INST_FILTER_OPERAND_INT, /* store the same way it's in ARRAY_BIG */
|
|
@@ -49,6 +55,8 @@ CSONPATH_UNUSED static const char *csonpath_instuction_str[] = {
|
|
|
49
55
|
"GET_ARRAY_SMALL",
|
|
50
56
|
"GET_ARRAY_BIG",
|
|
51
57
|
"FILTER_KEY_EQ",
|
|
58
|
+
"FILTER_KEY_NOT_EQ",
|
|
59
|
+
"FILTER_KEY_REG_EQ",
|
|
52
60
|
"FILTER_OPERAND_STR",
|
|
53
61
|
"FILTER_OPERAND_BYTE",
|
|
54
62
|
"FILTER_OPERAND_INT",
|
|
@@ -66,9 +74,12 @@ enum {
|
|
|
66
74
|
};
|
|
67
75
|
|
|
68
76
|
struct csonpath_instruction {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
unsigned char inst;
|
|
78
|
+
union {
|
|
79
|
+
unsigned char filter_next;
|
|
80
|
+
unsigned char regex_idx;
|
|
81
|
+
};
|
|
82
|
+
short int next;
|
|
72
83
|
};
|
|
73
84
|
|
|
74
85
|
#define CSONPATH_INST_MIN_ALLOC (1 << 7)
|
|
@@ -80,6 +91,10 @@ struct csonpath {
|
|
|
80
91
|
int compiled;
|
|
81
92
|
int inst_idx;
|
|
82
93
|
int inst_size;
|
|
94
|
+
#ifndef CSONPATH_NO_REGEX
|
|
95
|
+
int regex_cnt;
|
|
96
|
+
regex_t *regexs;
|
|
97
|
+
#endif
|
|
83
98
|
};
|
|
84
99
|
|
|
85
100
|
struct csonpath_child_info {
|
|
@@ -90,30 +105,47 @@ struct csonpath_child_info {
|
|
|
90
105
|
};
|
|
91
106
|
};
|
|
92
107
|
|
|
108
|
+
#define CSONPATH_ERROR_MAX_SIZE 1024
|
|
109
|
+
#define CSONPATH_TMP_BUF_SIZE 256
|
|
110
|
+
|
|
93
111
|
/* I'm assuming error message won't be longer than 125 */
|
|
94
112
|
#define CSONPATH_COMPILE_ERR(tmp, idx, args...) do { \
|
|
95
113
|
int ltmp = strlen(tmp), lidx, oidx = idx; \
|
|
96
114
|
if (cjp->compile_error) \
|
|
97
115
|
free(cjp->compile_error); \
|
|
98
|
-
cjp->compile_error = malloc(ltmp * 2 +
|
|
99
|
-
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); \
|
|
100
118
|
strcpy(cjp->compile_error + lidx, tmp); \
|
|
101
119
|
ltmp += lidx; \
|
|
102
120
|
cjp->compile_error[ltmp++] = '\n'; \
|
|
103
121
|
for (; oidx; --oidx) {cjp->compile_error[ltmp++] = ' ';} \
|
|
104
|
-
snprintf(cjp->compile_error + ltmp,
|
|
122
|
+
snprintf(cjp->compile_error + ltmp, CSONPATH_ERROR_MAX_SIZE - lidx, "\\-- "args); \
|
|
105
123
|
goto error; \
|
|
106
124
|
} while (0)
|
|
107
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
|
+
|
|
108
140
|
static inline struct csonpath_child_info *csonpath_child_info_set(struct csonpath_child_info *child_info,
|
|
109
141
|
CSONPATH_JSON j, const intptr_t key)
|
|
110
142
|
{
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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;
|
|
117
149
|
}
|
|
118
150
|
|
|
119
151
|
static inline void csonpath_destroy(struct csonpath cjp[static 1])
|
|
@@ -121,57 +153,79 @@ static inline void csonpath_destroy(struct csonpath cjp[static 1])
|
|
|
121
153
|
free(cjp->path);
|
|
122
154
|
free(cjp->inst_lst);
|
|
123
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
|
+
}
|
|
124
162
|
*cjp = (struct csonpath){};
|
|
125
163
|
}
|
|
126
164
|
|
|
127
165
|
static inline int csonpath_init(struct csonpath cjp[static 1],
|
|
128
166
|
const char path[static 1]) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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;
|
|
136
174
|
}
|
|
137
175
|
|
|
138
176
|
static inline int csonpath_set_path(struct csonpath cjp[static 1],
|
|
139
177
|
const char path[static 1])
|
|
140
178
|
{
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
free(cjp->inst_lst);
|
|
144
|
-
return csonpath_init(cjp, path);
|
|
179
|
+
csonpath_destroy(cjp);
|
|
180
|
+
return csonpath_init(cjp, path);
|
|
145
181
|
}
|
|
146
182
|
|
|
147
|
-
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)
|
|
148
184
|
{
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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);
|
|
156
213
|
}
|
|
157
214
|
|
|
158
|
-
int csonpath_compile(struct csonpath cjp[static 1])
|
|
215
|
+
static int csonpath_compile(struct csonpath cjp[static 1])
|
|
159
216
|
{
|
|
160
217
|
char *walker = cjp->path;
|
|
161
218
|
char *orig = walker;
|
|
162
219
|
char *next;
|
|
163
220
|
char to_check;
|
|
164
|
-
char *tmp;
|
|
221
|
+
char *tmp; /* tmp is only here for debug */
|
|
165
222
|
|
|
166
223
|
if (cjp->compiled)
|
|
167
224
|
return 0;
|
|
168
225
|
|
|
169
226
|
tmp = strdup(cjp->path);
|
|
170
227
|
root_again:
|
|
171
|
-
|
|
172
|
-
CSONPATH_COMPILE_ERR(tmp, walker - orig, "%s", "'$' needed");
|
|
173
|
-
}
|
|
174
|
-
++walker;
|
|
228
|
+
CSONPATH_SKIP('$', walker);
|
|
175
229
|
csonpath_push_inst(cjp, CSONPATH_INST_ROOT);
|
|
176
230
|
cjp->inst_lst[cjp->inst_idx - 1].next = 1;
|
|
177
231
|
to_check = *walker;
|
|
@@ -180,227 +234,288 @@ again:
|
|
|
180
234
|
switch (to_check) {
|
|
181
235
|
case '[':
|
|
182
236
|
{
|
|
183
|
-
|
|
237
|
+
int end;
|
|
184
238
|
|
|
185
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;
|
|
186
260
|
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
187
261
|
++walker;
|
|
188
|
-
if (*walker == '
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
to_check = *walker;
|
|
196
|
-
goto again;
|
|
197
|
-
} else if (*walker == '?') {
|
|
198
|
-
int have_blank;
|
|
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)
|
|
199
269
|
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
+
}
|
|
210
287
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
+
}
|
|
214
294
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
to_check = *next;
|
|
218
|
-
++next;
|
|
219
|
-
}
|
|
295
|
+
walker = next;
|
|
296
|
+
have_blank = isblank(to_check);
|
|
220
297
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
298
|
+
for (++next; isblank(*next); ++next) {
|
|
299
|
+
have_blank = 1;
|
|
300
|
+
}
|
|
224
301
|
|
|
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
|
-
if (isblank(to_check)) {
|
|
285
|
-
for (next++; isblank(*next); ++next);
|
|
286
|
-
to_check = *next;
|
|
287
|
-
}
|
|
288
|
-
if (to_check != ']')
|
|
289
|
-
goto error;
|
|
290
|
-
/* skipp space */
|
|
291
|
-
cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
|
|
292
|
-
walker = next + 1;
|
|
293
|
-
to_check = *walker;
|
|
294
|
-
goto again;
|
|
295
|
-
} else if (*walker != '"' && *walker != '\'') {
|
|
296
|
-
int num;
|
|
297
|
-
|
|
298
|
-
next = walker;
|
|
299
|
-
do {
|
|
300
|
-
if (*next < '0' || *next > '9') {
|
|
301
|
-
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
302
|
-
"unexpected '%c', sting, filter or number require\n", *next);
|
|
303
|
-
}
|
|
304
|
-
next++;
|
|
305
|
-
} while (*next && *next != ']');
|
|
306
|
-
if (!*next) {
|
|
307
|
-
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
308
|
-
"%s", "unclose bracket\n");
|
|
309
|
-
}
|
|
310
|
-
*next = 0;
|
|
311
|
-
num = atoi(walker);
|
|
312
|
-
if (num < 100) {
|
|
313
|
-
csonpath_push_inst(cjp, CSONPATH_INST_GET_ARRAY_SMALL);
|
|
314
|
-
*walker = num;
|
|
315
|
-
} else {
|
|
316
|
-
union {
|
|
317
|
-
int n;
|
|
318
|
-
char c[4];
|
|
319
|
-
} u = {.n=num};
|
|
320
|
-
walker[0] = u.c[0];
|
|
321
|
-
walker[1] = u.c[1];
|
|
322
|
-
walker[2] = u.c[2];
|
|
323
|
-
walker[3] = u.c[3];
|
|
324
|
-
csonpath_push_inst(cjp, CSONPATH_INST_GET_ARRAY_BIG);
|
|
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;
|
|
325
361
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
362
|
+
}
|
|
363
|
+
#endif
|
|
364
|
+
++next;
|
|
365
|
+
to_check = *next;
|
|
330
366
|
} else {
|
|
331
|
-
|
|
332
|
-
|
|
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
|
+
}
|
|
333
397
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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 == '\\')
|
|
343
454
|
++next;
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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);
|
|
347
462
|
|
|
348
|
-
|
|
349
|
-
|
|
463
|
+
csonpath_push_inst(cjp, CSONPATH_INST_GET_OBJ);
|
|
464
|
+
cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
|
|
350
465
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
466
|
+
walker = next + 1;
|
|
467
|
+
to_check = *walker;
|
|
468
|
+
goto again;
|
|
469
|
+
}
|
|
355
470
|
}
|
|
356
471
|
case '.':
|
|
357
472
|
{
|
|
358
|
-
|
|
473
|
+
int inst = CSONPATH_INST_GET_OBJ;
|
|
359
474
|
|
|
475
|
+
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
476
|
+
++walker;
|
|
477
|
+
if (*walker == '.') {
|
|
478
|
+
inst = CSONPATH_INST_FIND_ALL;
|
|
360
479
|
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
361
480
|
++walker;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
inst = CSONPATH_INST_GET_ALL;
|
|
368
|
-
++walker;
|
|
369
|
-
if (*walker != '.' && *walker != '[' && *walker != '\0')
|
|
370
|
-
CSONPATH_COMPILE_ERR(tmp, walker - orig, "unsuported characters '%c' after '*'", *walker);
|
|
371
|
-
csonpath_push_inst(cjp, inst);
|
|
372
|
-
to_check = *walker;
|
|
373
|
-
goto again;
|
|
374
|
-
}
|
|
375
|
-
for (next = walker; *next && *next != '[' && *next != '.' && *next != '|';
|
|
376
|
-
++next);
|
|
377
|
-
if (next == walker) {
|
|
378
|
-
if (*next == '[')
|
|
379
|
-
goto do_array;
|
|
380
|
-
CSONPATH_COMPILE_ERR(tmp, walker - orig, "empty getter");
|
|
381
|
-
}
|
|
382
|
-
to_check = *next;
|
|
383
|
-
*next = 0;
|
|
384
|
-
|
|
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);
|
|
385
486
|
csonpath_push_inst(cjp, inst);
|
|
386
|
-
|
|
387
|
-
walker = next;
|
|
487
|
+
to_check = *walker;
|
|
388
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;
|
|
389
504
|
}
|
|
390
505
|
case '|':
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
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;
|
|
396
511
|
}
|
|
397
512
|
if (*walker == 0) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
513
|
+
csonpath_push_inst(cjp, CSONPATH_INST_END);
|
|
514
|
+
cjp->compiled = 1;
|
|
515
|
+
free(tmp);
|
|
516
|
+
return 0;
|
|
402
517
|
}
|
|
403
|
-
error:
|
|
518
|
+
error:
|
|
404
519
|
cjp->inst_lst[0] = (struct csonpath_instruction){.inst=CSONPATH_INST_BROKEN};
|
|
405
520
|
free(tmp);
|
|
406
521
|
return -1;
|
|
@@ -161,38 +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:
|
|
164
165
|
case CSONPATH_INST_FILTER_KEY_NOT_EQ:
|
|
165
166
|
{
|
|
166
167
|
CSONPATH_JSON el;
|
|
167
|
-
char *filter_key = walker;
|
|
168
168
|
int operation = cjp->inst_lst[idx].inst;
|
|
169
169
|
walker += cjp->inst_lst[idx].next;
|
|
170
|
-
|
|
170
|
+
char *owalker;
|
|
171
|
+
int filter_next = cjp->inst_lst[idx].filter_next;
|
|
172
|
+
int in_idx = idx + 1;
|
|
171
173
|
|
|
172
174
|
CSONPATH_DO_FILTER_PRE_LOOP;
|
|
173
175
|
CSONPATH_FOREACH(tmp, el, {
|
|
174
176
|
if (CSONPATH_IS_OBJ(el)) {
|
|
175
|
-
CSONPATH_JSON el2;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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;
|
|
193
216
|
}
|
|
194
|
-
|
|
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;
|
|
195
227
|
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
196
230
|
});
|
|
197
231
|
CSONPATH_DO_FILTER_OUT;
|
|
198
232
|
break;
|
|
@@ -265,7 +299,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
|
|
|
265
299
|
break;
|
|
266
300
|
}
|
|
267
301
|
default:
|
|
268
|
-
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);
|
|
269
303
|
}
|
|
270
304
|
next_inst:
|
|
271
305
|
++idx;
|
|
@@ -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)) { \
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|