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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.0.2
3
+ Version: 0.0.4
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.0.2
3
+ Version: 0.0.4
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -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
- #define CSONPATH_FOREACH(obj, el, code) \
5
- CSONPATH_FOREACH_EXT(obj, el, code, key_idx)
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
- char *path;
58
- struct csonpath_instruction *inst_lst;
59
- int compiled;
60
- int inst_idx;
61
- int inst_size;
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
- #define CSONPATH_CLASSIC_ERR(args...) do { \
73
- fprintf(stderr, args); \
74
- goto error; \
75
- } while (0)
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
- const CSONPATH_JSON j, const intptr_t key)
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->path = NULL;
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
- root_again:
168
+
169
+ tmp = strdup(cjp->path);
170
+ root_again:
134
171
  if (*walker != '$') {
135
- CSONPATH_CLASSIC_ERR("'$' needed");
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
- CSONPATH_CLASSIC_ERR("unclose bracket\n");
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
- for (++next; isblank(*next); ++next);
169
- if (!*next)
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
- CSONPATH_CLASSIC_ERR("unexpected '%c', sting, filter or number require\n", *next);
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
- CSONPATH_CLASSIC_ERR("unclose bracket\n");
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
- CSONPATH_CLASSIC_ERR("']' require instead of '%c'\n", *next);
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
- CSONPATH_JSON ret_ar = CSONPATH_NEW_ARRAY();
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 CSONPATH_JSON
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 , CSONPATH_JSON ret_ar
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
- if (cjp->inst_lst[idx].inst != CSONPATH_INST_FILTER_OPERAND_STR)
177
- CSONPATH_GETTER_ERR("filter support only comparaiso with STR");
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
- if (CSONPATH_EQUAL_STR(el2, walker)) {
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
- PyErr_Format(PyExc_ValueError, "Fail to compile %s", s);
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;
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "csonpath"
7
- version = "0.0.2"
7
+ version = "0.0.4"
8
8
  readme = "README.md"
9
9
 
10
10
  [tool.setuptools]
File without changes
File without changes
File without changes
File without changes