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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.0.3
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)
@@ -114,4 +114,4 @@ Feel free to open issues or pull requests!
114
114
 
115
115
  ## 📜 License
116
116
  BSD 3-Clause. See [LICENSE](LICENSE).
117
-
117
+ 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
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
- char inst;
69
- char unused;
70
- short int next;
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 + 1024); \
98
- lidx = snprintf(cjp->compile_error, 1024, "colum %d:\n", oidx); \
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, 1024 - lidx, "\\-- "args); \
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
- if (CSONPATH_IS_OBJ(j)) {
111
- *child_info = (struct csonpath_child_info){.key=(const char *)key, .type=CSONPATH_STR};
112
- } else {
113
- *child_info = (struct csonpath_child_info){.idx=key, .type=CSONPATH_INTEGER};
114
- }
115
- return child_info;
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
- *cjp = (struct csonpath) {.path=strdup(path),
129
- .inst_size = CSONPATH_INST_MIN_ALLOC,
130
- .inst_lst = malloc(sizeof(*cjp->inst_lst) * CSONPATH_INST_MIN_ALLOC)};
131
- if (!cjp->path || !cjp->inst_lst) {
132
- return -ENOMEM;
133
- }
134
- return 0;
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
- free(cjp->path);
141
- free(cjp->compile_error);
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
- if (cjp->inst_idx + 1 > cjp->inst_size) {
149
- cjp->inst_size = cjp->inst_size << 1;
150
- cjp->inst_lst = realloc(cjp->inst_lst, cjp->inst_size);
151
- assert(cjp->inst_lst);
152
- }
153
- cjp->inst_lst[cjp->inst_idx] = (struct csonpath_instruction){.inst=inst};
154
- ++cjp->inst_idx;
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
- if (*walker != '$') {
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
- int end;
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
- csonpath_push_inst(cjp, CSONPATH_INST_GET_ALL);
188
- if (walker[1] != ']') {
189
- CSONPATH_COMPILE_ERR(tmp, walker - orig, "%s", "unclose bracket\n");
190
- }
191
- cjp->inst_lst[cjp->inst_idx - 1].next = 2;
192
- walker += 2;
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
- ++walker;
198
- for (next = walker; isalnum(*next); ++next);
199
- if (!*next) {
200
- goto error;
201
- }
202
- to_check = *next;
203
- *next = 0;
204
- for (++next; isblank(*next); ++next);
205
- if (!*next)
206
- goto error;
207
- /* = and == are the same here */
208
- if (to_check == '=') {
209
- csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_EQ);
210
- if (next[0] == '=')
211
- ++next;
212
- } else {
213
- goto error;
214
- }
215
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker;
216
- walker = next;
217
- if (*walker == '"' || *walker == '\'') {
218
- char end = *walker;
219
- ++walker;
220
- cjp->inst_lst[cjp->inst_idx - 1].next++;
221
- csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_STR);
222
- for (next = walker; *next && *next != end; ++next);
223
- if (!*next)
224
- goto error;
225
- *next = 0;
226
- ++next;
227
- to_check = *next;
228
- } else {
229
- int n;
230
-
231
- for (next = walker; isdigit(*next); ++next);
232
- if (next == walker)
233
- goto error;
234
- n = atoi(walker);
235
- if (n < 100) {
236
- *walker = n;
237
- csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_BYTE);
238
- } else {
239
- MAY_ALIAS int *walk_int = (void *)walker;
240
- *walk_int = n;
241
- csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_INT);
242
- }
243
- if (!*next) {
244
- goto error;
245
- }
246
- to_check = *next;
247
- *next = 0;
248
- }
249
- if (isblank(to_check)) {
250
- for (next++; isblank(*next); ++next);
251
- to_check = *next;
252
- }
253
- if (to_check != ']')
254
- goto error;
255
- /* skipp space */
256
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
257
- walker = next + 1;
258
- to_check = *walker;
259
- goto again;
260
- } else if (*walker != '"' && *walker != '\'') {
261
- int num;
262
-
263
- next = walker;
264
- do {
265
- if (*next < '0' || *next > '9') {
266
- CSONPATH_COMPILE_ERR(tmp, walker - orig,
267
- "unexpected '%c', sting, filter or number require\n", *next);
268
- }
269
- next++;
270
- } while (*next && *next != ']');
271
- if (!*next) {
272
- CSONPATH_COMPILE_ERR(tmp, walker - orig,
273
- "%s", "unclose bracket\n");
274
- }
275
- *next = 0;
276
- num = atoi(walker);
277
- if (num < 100) {
278
- csonpath_push_inst(cjp, CSONPATH_INST_GET_ARRAY_SMALL);
279
- *walker = num;
280
- } else {
281
- union {
282
- int n;
283
- char c[4];
284
- } u = {.n=num};
285
- walker[0] = u.c[0];
286
- walker[1] = u.c[1];
287
- walker[2] = u.c[2];
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
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
292
- walker = next + 1;
293
- to_check = *walker;
294
- goto again;
362
+ }
363
+ #endif
364
+ ++next;
365
+ to_check = *next;
295
366
  } else {
296
- end = *walker;
297
- cjp->inst_lst[cjp->inst_idx - 1].next += 1;
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
- ++walker;
300
- next = walker;
301
- while (*next++ != end) {
302
- /* \" should be ignored */
303
- while (*next == '\\')
304
- ++next;
305
- }
306
- --next;
307
- *next = 0;
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
- if (*next != ']')
310
- CSONPATH_COMPILE_ERR(tmp, walker - orig,
311
- "']' require instead of '%c'\n", *next);
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
- csonpath_push_inst(cjp, CSONPATH_INST_GET_OBJ);
314
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
463
+ csonpath_push_inst(cjp, CSONPATH_INST_GET_OBJ);
464
+ cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
315
465
 
316
- walker = next + 1;
317
- to_check = *walker;
318
- goto again;
319
- }
466
+ walker = next + 1;
467
+ to_check = *walker;
468
+ goto again;
469
+ }
320
470
  }
321
471
  case '.':
322
472
  {
323
- int inst = CSONPATH_INST_GET_OBJ;
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
- if (*walker == '.') {
328
- inst = CSONPATH_INST_FIND_ALL;
329
- cjp->inst_lst[cjp->inst_idx - 1].next += 1;
330
- ++walker;
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
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker;
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
- /* cjp->inst_lst[cjp->inst_idx - 1].next += 1; */
344
- csonpath_push_inst(cjp, CSONPATH_INST_OR);
345
- ++walker;
346
- cjp->inst_lst[cjp->inst_idx - 1].next += 1;
347
- goto root_again;
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
- csonpath_push_inst(cjp, CSONPATH_INST_END);
351
- cjp->compiled = 1;
352
- free(tmp);
353
- return 0;
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
- char *filter_key = walker;
168
+ int operation = cjp->inst_lst[idx].inst;
167
169
  walker += cjp->inst_lst[idx].next;
168
- ++idx;
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
- 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 comparaison with STR");
178
-
179
- CSONPATH_FOREACH_EXT(el, el2, {
180
- if (!strcmp((char *)neested_key, filter_key)) {
181
- if (CSONPATH_EQUAL_STR(el2, walker)) {
182
- CSONPATH_DO_RET_TYPE tret =
183
- csonpath_do_internal(cjp, origin, el, tmp, idx + 1,
184
- walker + cjp->inst_lst[idx].next
185
- CSONPATH_DO_EXTRA_ARGS_NEESTED);
186
-
187
- CSONPATH_DO_FILTER_FIND;
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
- }, neested_key)
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
  }
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "csonpath"
7
- version = "0.0.3"
7
+ version = "0.1.0"
8
8
  readme = "README.md"
9
9
 
10
10
  [tool.setuptools]
File without changes
File without changes
File without changes