csonpath 0.0.2__tar.gz → 0.0.4__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.2/csonpath.egg-info → csonpath-0.0.4}/PKG-INFO +1 -1
- {csonpath-0.0.2 → csonpath-0.0.4/csonpath.egg-info}/PKG-INFO +1 -1
- {csonpath-0.0.2 → csonpath-0.0.4}/csonpath.h +116 -27
- {csonpath-0.0.2 → csonpath-0.0.4}/csonpath_do.h +10 -5
- {csonpath-0.0.2 → csonpath-0.0.4}/csonpath_python.c +3 -1
- {csonpath-0.0.2 → csonpath-0.0.4}/pyproject.toml +1 -1
- {csonpath-0.0.2 → csonpath-0.0.4}/LICENSE +0 -0
- {csonpath-0.0.2 → csonpath-0.0.4}/MANIFEST.in +0 -0
- {csonpath-0.0.2 → csonpath-0.0.4}/README.md +0 -0
- {csonpath-0.0.2 → csonpath-0.0.4}/csonpath.egg-info/SOURCES.txt +0 -0
- {csonpath-0.0.2 → csonpath-0.0.4}/csonpath.egg-info/dependency_links.txt +0 -0
- {csonpath-0.0.2 → csonpath-0.0.4}/csonpath.egg-info/requires.txt +0 -0
- {csonpath-0.0.2 → csonpath-0.0.4}/csonpath.egg-info/top_level.txt +0 -0
- {csonpath-0.0.2 → csonpath-0.0.4}/setup.cfg +0 -0
|
@@ -1,9 +1,28 @@
|
|
|
1
|
+
#if !defined(CSONPATH_JSON) || !defined(CSONPATH_NULL) || !defined(CSONPATH_GET) || \
|
|
2
|
+
!defined(CSONPATH_AT) || !defined(CSONPATH_IS_OBJ) || !defined(CSONPATH_IS_ARRAY) || \
|
|
3
|
+
!defined(CSONPATH_CALLBACK) || !defined(CSONPATH_CALLBACK_DATA) || \
|
|
4
|
+
!defined(CSONPATH_EQUAL_STR) || !defined(CSONPATH_CALL_CALLBACK) || \
|
|
5
|
+
!defined(CSONPATH_FOREACH_EXT) || !defined(CSONPATH_APPEND_AT) || \
|
|
6
|
+
!defined(CSONPATH_REMOVE_CHILD) || !defined(CSONPATH_NEED_FOREACH_REDO) || \
|
|
7
|
+
!defined(CSONPATH_ARRAY_APPEND_INCREF) || !defined(CSONPATH_REMOVE)
|
|
8
|
+
# error "some defined are missing"
|
|
9
|
+
#endif
|
|
10
|
+
|
|
1
11
|
#define CSONPATH_UNUSED __attribute__((unused))
|
|
2
12
|
#define MAY_ALIAS __attribute__((__may_alias__))
|
|
3
13
|
|
|
4
|
-
#
|
|
5
|
-
|
|
14
|
+
#ifndef CSONPATH_FOREACH
|
|
15
|
+
# define CSONPATH_FOREACH(obj, el, code) \
|
|
16
|
+
CSONPATH_FOREACH_EXT(obj, el, code, key_idx)
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
#ifndef CSONPATH_FIND_ALL_RET
|
|
20
|
+
#define CSONPATH_FIND_ALL_RET CSONPATH_JSON
|
|
21
|
+
#endif
|
|
6
22
|
|
|
23
|
+
#ifndef CSONPATH_FIND_ALL_RET_INIT
|
|
24
|
+
#define CSONPATH_FIND_ALL_RET_INIT CSONPATH_NEW_ARRAY
|
|
25
|
+
#endif
|
|
7
26
|
|
|
8
27
|
enum csonpath_instuction_raw {
|
|
9
28
|
CSONPATH_INST_ROOT,
|
|
@@ -11,6 +30,7 @@ enum csonpath_instuction_raw {
|
|
|
11
30
|
CSONPATH_INST_GET_ARRAY_SMALL,
|
|
12
31
|
CSONPATH_INST_GET_ARRAY_BIG,
|
|
13
32
|
CSONPATH_INST_FILTER_KEY_EQ,
|
|
33
|
+
CSONPATH_INST_FILTER_KEY_NOT_EQ,
|
|
14
34
|
CSONPATH_INST_FILTER_OPERAND_STR,
|
|
15
35
|
CSONPATH_INST_FILTER_OPERAND_BYTE, /* store the same way it's in ARRAY_SMALL */
|
|
16
36
|
CSONPATH_INST_FILTER_OPERAND_INT, /* store the same way it's in ARRAY_BIG */
|
|
@@ -54,11 +74,12 @@ struct csonpath_instruction {
|
|
|
54
74
|
#define CSONPATH_INST_MIN_ALLOC (1 << 7)
|
|
55
75
|
|
|
56
76
|
struct csonpath {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
77
|
+
char *path;
|
|
78
|
+
char *compile_error;
|
|
79
|
+
struct csonpath_instruction *inst_lst;
|
|
80
|
+
int compiled;
|
|
81
|
+
int inst_idx;
|
|
82
|
+
int inst_size;
|
|
62
83
|
};
|
|
63
84
|
|
|
64
85
|
struct csonpath_child_info {
|
|
@@ -69,13 +90,23 @@ struct csonpath_child_info {
|
|
|
69
90
|
};
|
|
70
91
|
};
|
|
71
92
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
93
|
+
/* I'm assuming error message won't be longer than 125 */
|
|
94
|
+
#define CSONPATH_COMPILE_ERR(tmp, idx, args...) do { \
|
|
95
|
+
int ltmp = strlen(tmp), lidx, oidx = idx; \
|
|
96
|
+
if (cjp->compile_error) \
|
|
97
|
+
free(cjp->compile_error); \
|
|
98
|
+
cjp->compile_error = malloc(ltmp * 2 + 1024); \
|
|
99
|
+
lidx = snprintf(cjp->compile_error, 1024, "colum %d:\n", oidx); \
|
|
100
|
+
strcpy(cjp->compile_error + lidx, tmp); \
|
|
101
|
+
ltmp += lidx; \
|
|
102
|
+
cjp->compile_error[ltmp++] = '\n'; \
|
|
103
|
+
for (; oidx; --oidx) {cjp->compile_error[ltmp++] = ' ';} \
|
|
104
|
+
snprintf(cjp->compile_error + ltmp, 1024 - lidx, "\\-- "args); \
|
|
105
|
+
goto error; \
|
|
106
|
+
} while (0)
|
|
76
107
|
|
|
77
108
|
static inline struct csonpath_child_info *csonpath_child_info_set(struct csonpath_child_info *child_info,
|
|
78
|
-
|
|
109
|
+
CSONPATH_JSON j, const intptr_t key)
|
|
79
110
|
{
|
|
80
111
|
if (CSONPATH_IS_OBJ(j)) {
|
|
81
112
|
*child_info = (struct csonpath_child_info){.key=(const char *)key, .type=CSONPATH_STR};
|
|
@@ -89,7 +120,8 @@ static inline void csonpath_destroy(struct csonpath cjp[static 1])
|
|
|
89
120
|
{
|
|
90
121
|
free(cjp->path);
|
|
91
122
|
free(cjp->inst_lst);
|
|
92
|
-
cjp->
|
|
123
|
+
free(cjp->compile_error);
|
|
124
|
+
*cjp = (struct csonpath){};
|
|
93
125
|
}
|
|
94
126
|
|
|
95
127
|
static inline int csonpath_init(struct csonpath cjp[static 1],
|
|
@@ -107,6 +139,7 @@ static inline int csonpath_set_path(struct csonpath cjp[static 1],
|
|
|
107
139
|
const char path[static 1])
|
|
108
140
|
{
|
|
109
141
|
free(cjp->path);
|
|
142
|
+
free(cjp->compile_error);
|
|
110
143
|
free(cjp->inst_lst);
|
|
111
144
|
return csonpath_init(cjp, path);
|
|
112
145
|
}
|
|
@@ -125,14 +158,18 @@ void csonpath_push_inst(struct csonpath cjp[static 1], int inst)
|
|
|
125
158
|
int csonpath_compile(struct csonpath cjp[static 1])
|
|
126
159
|
{
|
|
127
160
|
char *walker = cjp->path;
|
|
161
|
+
char *orig = walker;
|
|
128
162
|
char *next;
|
|
129
163
|
char to_check;
|
|
164
|
+
char *tmp;
|
|
130
165
|
|
|
131
166
|
if (cjp->compiled)
|
|
132
167
|
return 0;
|
|
133
|
-
|
|
168
|
+
|
|
169
|
+
tmp = strdup(cjp->path);
|
|
170
|
+
root_again:
|
|
134
171
|
if (*walker != '$') {
|
|
135
|
-
|
|
172
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig, "%s", "'$' needed");
|
|
136
173
|
}
|
|
137
174
|
++walker;
|
|
138
175
|
csonpath_push_inst(cjp, CSONPATH_INST_ROOT);
|
|
@@ -145,37 +182,62 @@ again:
|
|
|
145
182
|
{
|
|
146
183
|
int end;
|
|
147
184
|
|
|
185
|
+
do_array:
|
|
148
186
|
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
149
187
|
++walker;
|
|
150
188
|
if (*walker == '*') {
|
|
151
189
|
csonpath_push_inst(cjp, CSONPATH_INST_GET_ALL);
|
|
152
190
|
if (walker[1] != ']') {
|
|
153
|
-
|
|
191
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig, "%s", "unclose bracket\n");
|
|
154
192
|
}
|
|
155
193
|
cjp->inst_lst[cjp->inst_idx - 1].next = 2;
|
|
156
194
|
walker += 2;
|
|
157
195
|
to_check = *walker;
|
|
158
196
|
goto again;
|
|
159
197
|
} else if (*walker == '?') {
|
|
198
|
+
int have_blank;
|
|
160
199
|
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
161
200
|
++walker;
|
|
162
201
|
for (next = walker; isalnum(*next); ++next);
|
|
163
202
|
if (!*next) {
|
|
203
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
204
|
+
"filter miss condition");
|
|
164
205
|
goto error;
|
|
165
206
|
}
|
|
166
207
|
to_check = *next;
|
|
167
208
|
*next = 0;
|
|
168
|
-
|
|
169
|
-
|
|
209
|
+
have_blank = isblank(to_check);
|
|
210
|
+
|
|
211
|
+
for (++next; isblank(*next); ++next) {
|
|
212
|
+
have_blank = 1;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (*next && have_blank &&
|
|
216
|
+
to_check != '=' && to_check != '!') {
|
|
217
|
+
to_check = *next;
|
|
218
|
+
++next;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!*next) {
|
|
222
|
+
CSONPATH_COMPILE_ERR(tmp, next - orig,
|
|
223
|
+
"filter miss condition");
|
|
224
|
+
|
|
170
225
|
goto error;
|
|
226
|
+
}
|
|
171
227
|
/* = and == are the same here */
|
|
172
228
|
if (to_check == '=') {
|
|
173
229
|
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_EQ);
|
|
174
230
|
if (next[0] == '=')
|
|
175
231
|
++next;
|
|
232
|
+
} else if (to_check == '!' && next[0] == '=') {
|
|
233
|
+
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_NOT_EQ);
|
|
234
|
+
++next;
|
|
176
235
|
} else {
|
|
236
|
+
CSONPATH_COMPILE_ERR(tmp, next - orig,
|
|
237
|
+
"'%c': unsuported operation", to_check);
|
|
177
238
|
goto error;
|
|
178
239
|
}
|
|
240
|
+
for (;isblank(*next); ++next);
|
|
179
241
|
cjp->inst_lst[cjp->inst_idx - 1].next = next - walker;
|
|
180
242
|
walker = next;
|
|
181
243
|
if (*walker == '"' || *walker == '\'') {
|
|
@@ -184,8 +246,11 @@ again:
|
|
|
184
246
|
cjp->inst_lst[cjp->inst_idx - 1].next++;
|
|
185
247
|
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_STR);
|
|
186
248
|
for (next = walker; *next && *next != end; ++next);
|
|
187
|
-
if (!*next)
|
|
249
|
+
if (!*next) {
|
|
250
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
251
|
+
"broken filter");
|
|
188
252
|
goto error;
|
|
253
|
+
}
|
|
189
254
|
*next = 0;
|
|
190
255
|
++next;
|
|
191
256
|
to_check = *next;
|
|
@@ -193,8 +258,12 @@ again:
|
|
|
193
258
|
int n;
|
|
194
259
|
|
|
195
260
|
for (next = walker; isdigit(*next); ++next);
|
|
196
|
-
if (next == walker)
|
|
261
|
+
if (next == walker) {
|
|
262
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
263
|
+
"'%c': broken filter with number",
|
|
264
|
+
*walker);
|
|
197
265
|
goto error;
|
|
266
|
+
}
|
|
198
267
|
n = atoi(walker);
|
|
199
268
|
if (n < 100) {
|
|
200
269
|
*walker = n;
|
|
@@ -205,6 +274,8 @@ again:
|
|
|
205
274
|
csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_INT);
|
|
206
275
|
}
|
|
207
276
|
if (!*next) {
|
|
277
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
278
|
+
"compilation error");
|
|
208
279
|
goto error;
|
|
209
280
|
}
|
|
210
281
|
to_check = *next;
|
|
@@ -227,12 +298,14 @@ again:
|
|
|
227
298
|
next = walker;
|
|
228
299
|
do {
|
|
229
300
|
if (*next < '0' || *next > '9') {
|
|
230
|
-
|
|
301
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
302
|
+
"unexpected '%c', sting, filter or number require\n", *next);
|
|
231
303
|
}
|
|
232
304
|
next++;
|
|
233
305
|
} while (*next && *next != ']');
|
|
234
306
|
if (!*next) {
|
|
235
|
-
|
|
307
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
308
|
+
"%s", "unclose bracket\n");
|
|
236
309
|
}
|
|
237
310
|
*next = 0;
|
|
238
311
|
num = atoi(walker);
|
|
@@ -269,7 +342,8 @@ again:
|
|
|
269
342
|
*next = 0;
|
|
270
343
|
++next;
|
|
271
344
|
if (*next != ']')
|
|
272
|
-
|
|
345
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig,
|
|
346
|
+
"']' require instead of '%c'\n", *next);
|
|
273
347
|
|
|
274
348
|
csonpath_push_inst(cjp, CSONPATH_INST_GET_OBJ);
|
|
275
349
|
cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
|
|
@@ -289,9 +363,22 @@ again:
|
|
|
289
363
|
inst = CSONPATH_INST_FIND_ALL;
|
|
290
364
|
cjp->inst_lst[cjp->inst_idx - 1].next += 1;
|
|
291
365
|
++walker;
|
|
292
|
-
}
|
|
366
|
+
} else if (*walker == '*') {
|
|
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
|
+
}
|
|
293
375
|
for (next = walker; *next && *next != '[' && *next != '.' && *next != '|';
|
|
294
376
|
++next);
|
|
377
|
+
if (next == walker) {
|
|
378
|
+
if (*next == '[')
|
|
379
|
+
goto do_array;
|
|
380
|
+
CSONPATH_COMPILE_ERR(tmp, walker - orig, "empty getter");
|
|
381
|
+
}
|
|
295
382
|
to_check = *next;
|
|
296
383
|
*next = 0;
|
|
297
384
|
|
|
@@ -310,10 +397,12 @@ again:
|
|
|
310
397
|
if (*walker == 0) {
|
|
311
398
|
csonpath_push_inst(cjp, CSONPATH_INST_END);
|
|
312
399
|
cjp->compiled = 1;
|
|
400
|
+
free(tmp);
|
|
313
401
|
return 0;
|
|
314
402
|
}
|
|
315
403
|
error:
|
|
316
404
|
cjp->inst_lst[0] = (struct csonpath_instruction){.inst=CSONPATH_INST_BROKEN};
|
|
405
|
+
free(tmp);
|
|
317
406
|
return -1;
|
|
318
407
|
}
|
|
319
408
|
|
|
@@ -362,7 +451,7 @@ need_reloop_in = 0;
|
|
|
362
451
|
/* Find All */
|
|
363
452
|
|
|
364
453
|
#define CSONPATH_DO_PRE_OPERATION \
|
|
365
|
-
|
|
454
|
+
CSONPATH_FIND_ALL_RET ret_ar = CSONPATH_FIND_ALL_RET_INIT();
|
|
366
455
|
|
|
367
456
|
#define CSONPATH_DO_POST_OPERATION \
|
|
368
457
|
if (ret == CSONPATH_NULL) CSONPATH_REMOVE(ret_ar)
|
|
@@ -371,7 +460,7 @@ need_reloop_in = 0;
|
|
|
371
460
|
int nb_res = 0;
|
|
372
461
|
|
|
373
462
|
#define CSONPATH_DO_FUNC_NAME find_all
|
|
374
|
-
#define CSONPATH_DO_RET_TYPE
|
|
463
|
+
#define CSONPATH_DO_RET_TYPE CSONPATH_FIND_ALL_RET
|
|
375
464
|
#define CSONPATH_DO_RETURN ({CSONPATH_ARRAY_APPEND_INCREF(ret_ar, tmp); return ret_ar;})
|
|
376
465
|
|
|
377
466
|
#define CSONPATH_DO_FIND_ALL \
|
|
@@ -385,7 +474,7 @@ need_reloop_in = 0;
|
|
|
385
474
|
return ret_ar;
|
|
386
475
|
|
|
387
476
|
#define CSONPATH_DO_EXTRA_ARGS_IN , ret_ar
|
|
388
|
-
#define CSONPATH_DO_EXTRA_DECLATION ,
|
|
477
|
+
#define CSONPATH_DO_EXTRA_DECLATION , CSONPATH_FIND_ALL_RET ret_ar
|
|
389
478
|
|
|
390
479
|
|
|
391
480
|
#include "csonpath_do.h"
|
|
@@ -134,7 +134,7 @@ static CSONPATH_DO_RET_TYPE csonpath_do_dotdot(struct csonpath cjp[static 1],
|
|
|
134
134
|
CSONPATH_DO_EXTRA_ARGS_NEESTED);
|
|
135
135
|
CSONPATH_DO_FIND_ALL;
|
|
136
136
|
}
|
|
137
|
-
})
|
|
137
|
+
})
|
|
138
138
|
CSONPATH_DO_FIND_ALL_OUT;
|
|
139
139
|
return tret;
|
|
140
140
|
}
|
|
@@ -161,9 +161,11 @@ 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_NOT_EQ:
|
|
164
165
|
{
|
|
165
166
|
CSONPATH_JSON el;
|
|
166
167
|
char *filter_key = walker;
|
|
168
|
+
int operation = cjp->inst_lst[idx].inst;
|
|
167
169
|
walker += cjp->inst_lst[idx].next;
|
|
168
170
|
++idx;
|
|
169
171
|
|
|
@@ -173,12 +175,14 @@ static CSONPATH_DO_RET_TYPE csonpath_do_internal(struct csonpath cjp[static 1],
|
|
|
173
175
|
CSONPATH_JSON el2;
|
|
174
176
|
|
|
175
177
|
CSONPATH_DO_FILTER_LOOP_PRE_SET
|
|
176
|
-
|
|
177
|
-
|
|
178
|
+
if (cjp->inst_lst[idx].inst != CSONPATH_INST_FILTER_OPERAND_STR)
|
|
179
|
+
CSONPATH_GETTER_ERR("filter support only comparaison with STR");
|
|
178
180
|
|
|
179
181
|
CSONPATH_FOREACH_EXT(el, el2, {
|
|
180
182
|
if (!strcmp((char *)neested_key, filter_key)) {
|
|
181
|
-
|
|
183
|
+
_Bool eq_ret = CSONPATH_EQUAL_STR(el2, walker);
|
|
184
|
+
if ((operation == CSONPATH_INST_FILTER_KEY_NOT_EQ && !eq_ret) ||
|
|
185
|
+
(operation == CSONPATH_INST_FILTER_KEY_EQ && eq_ret)) {
|
|
182
186
|
CSONPATH_DO_RET_TYPE tret =
|
|
183
187
|
csonpath_do_internal(cjp, origin, el, tmp, idx + 1,
|
|
184
188
|
walker + cjp->inst_lst[idx].next
|
|
@@ -281,7 +285,8 @@ static CSONPATH_DO_RET_TYPE csonpath_do_(struct csonpath cjp[static 1],
|
|
|
281
285
|
(void)ctx;
|
|
282
286
|
csonpath_compile(cjp);
|
|
283
287
|
if (cjp->inst_lst[0].inst == CSONPATH_INST_BROKEN) {
|
|
284
|
-
CSONPATH_GETTER_ERR("fail to compile\n"
|
|
288
|
+
CSONPATH_GETTER_ERR("fail to compile: %s\n", cjp->compile_error ?
|
|
289
|
+
cjp->compile_error : "(unknow error)");
|
|
285
290
|
return CSONPATH_NONE_FOUND_RET;
|
|
286
291
|
}
|
|
287
292
|
|
|
@@ -148,7 +148,9 @@ static PyObject *PyCsonPath_new(PyTypeObject *subtype, PyObject* args,
|
|
|
148
148
|
return PyErr_NoMemory();
|
|
149
149
|
|
|
150
150
|
if (csonpath_compile(ret) < 0) {
|
|
151
|
-
|
|
151
|
+
char *error = ret->compile_error;
|
|
152
|
+
PyErr_Format(PyExc_ValueError, "compilation fail %s", error ? error : "(unknow error)");
|
|
153
|
+
csonpath_destroy(ret);
|
|
152
154
|
return NULL;
|
|
153
155
|
}
|
|
154
156
|
self->cp = ret;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|