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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.0.4
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.4
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
- char inst;
70
- char unused;
71
- short int next;
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 + 1024); \
99
- 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); \
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, 1024 - lidx, "\\-- "args); \
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
- if (CSONPATH_IS_OBJ(j)) {
112
- *child_info = (struct csonpath_child_info){.key=(const char *)key, .type=CSONPATH_STR};
113
- } else {
114
- *child_info = (struct csonpath_child_info){.idx=key, .type=CSONPATH_INTEGER};
115
- }
116
- 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;
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
- *cjp = (struct csonpath) {.path=strdup(path),
130
- .inst_size = CSONPATH_INST_MIN_ALLOC,
131
- .inst_lst = malloc(sizeof(*cjp->inst_lst) * CSONPATH_INST_MIN_ALLOC)};
132
- if (!cjp->path || !cjp->inst_lst) {
133
- return -ENOMEM;
134
- }
135
- 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;
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
- free(cjp->path);
142
- free(cjp->compile_error);
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
- if (cjp->inst_idx + 1 > cjp->inst_size) {
150
- cjp->inst_size = cjp->inst_size << 1;
151
- cjp->inst_lst = realloc(cjp->inst_lst, cjp->inst_size);
152
- assert(cjp->inst_lst);
153
- }
154
- cjp->inst_lst[cjp->inst_idx] = (struct csonpath_instruction){.inst=inst};
155
- ++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);
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
- if (*walker != '$') {
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
- int end;
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
- csonpath_push_inst(cjp, CSONPATH_INST_GET_ALL);
190
- if (walker[1] != ']') {
191
- CSONPATH_COMPILE_ERR(tmp, walker - orig, "%s", "unclose bracket\n");
192
- }
193
- cjp->inst_lst[cjp->inst_idx - 1].next = 2;
194
- walker += 2;
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
- ++walker;
201
- for (next = walker; isalnum(*next); ++next);
202
- if (!*next) {
203
- CSONPATH_COMPILE_ERR(tmp, walker - orig,
204
- "filter miss condition");
205
- goto error;
206
- }
207
- to_check = *next;
208
- *next = 0;
209
- have_blank = isblank(to_check);
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
- for (++next; isblank(*next); ++next) {
212
- have_blank = 1;
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
- if (*next && have_blank &&
216
- to_check != '=' && to_check != '!') {
217
- to_check = *next;
218
- ++next;
219
- }
295
+ walker = next;
296
+ have_blank = isblank(to_check);
220
297
 
221
- if (!*next) {
222
- CSONPATH_COMPILE_ERR(tmp, next - orig,
223
- "filter miss condition");
298
+ for (++next; isblank(*next); ++next) {
299
+ have_blank = 1;
300
+ }
224
301
 
225
- goto error;
226
- }
227
- /* = and == are the same here */
228
- if (to_check == '=') {
229
- csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_EQ);
230
- if (next[0] == '=')
231
- ++next;
232
- } else if (to_check == '!' && next[0] == '=') {
233
- csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_NOT_EQ);
234
- ++next;
235
- } else {
236
- CSONPATH_COMPILE_ERR(tmp, next - orig,
237
- "'%c': unsuported operation", to_check);
238
- goto error;
239
- }
240
- for (;isblank(*next); ++next);
241
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker;
242
- walker = next;
243
- if (*walker == '"' || *walker == '\'') {
244
- char end = *walker;
245
- ++walker;
246
- cjp->inst_lst[cjp->inst_idx - 1].next++;
247
- csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_STR);
248
- for (next = walker; *next && *next != end; ++next);
249
- if (!*next) {
250
- CSONPATH_COMPILE_ERR(tmp, walker - orig,
251
- "broken filter");
252
- goto error;
253
- }
254
- *next = 0;
255
- ++next;
256
- to_check = *next;
257
- } else {
258
- int n;
259
-
260
- for (next = walker; isdigit(*next); ++next);
261
- if (next == walker) {
262
- CSONPATH_COMPILE_ERR(tmp, walker - orig,
263
- "'%c': broken filter with number",
264
- *walker);
265
- goto error;
266
- }
267
- n = atoi(walker);
268
- if (n < 100) {
269
- *walker = n;
270
- csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_BYTE);
271
- } else {
272
- MAY_ALIAS int *walk_int = (void *)walker;
273
- *walk_int = n;
274
- csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_INT);
275
- }
276
- if (!*next) {
277
- CSONPATH_COMPILE_ERR(tmp, walker - orig,
278
- "compilation error");
279
- goto error;
280
- }
281
- to_check = *next;
282
- *next = 0;
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
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
327
- walker = next + 1;
328
- to_check = *walker;
329
- goto again;
362
+ }
363
+ #endif
364
+ ++next;
365
+ to_check = *next;
330
366
  } else {
331
- end = *walker;
332
- 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
+ }
333
397
 
334
- ++walker;
335
- next = walker;
336
- while (*next++ != end) {
337
- /* \" should be ignored */
338
- while (*next == '\\')
339
- ++next;
340
- }
341
- --next;
342
- *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 == '\\')
343
454
  ++next;
344
- if (*next != ']')
345
- CSONPATH_COMPILE_ERR(tmp, walker - orig,
346
- "']' 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);
347
462
 
348
- csonpath_push_inst(cjp, CSONPATH_INST_GET_OBJ);
349
- 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;
350
465
 
351
- walker = next + 1;
352
- to_check = *walker;
353
- goto again;
354
- }
466
+ walker = next + 1;
467
+ to_check = *walker;
468
+ goto again;
469
+ }
355
470
  }
356
471
  case '.':
357
472
  {
358
- int inst = CSONPATH_INST_GET_OBJ;
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
- if (*walker == '.') {
363
- inst = CSONPATH_INST_FIND_ALL;
364
- cjp->inst_lst[cjp->inst_idx - 1].next += 1;
365
- ++walker;
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
- }
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
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker;
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
- /* cjp->inst_lst[cjp->inst_idx - 1].next += 1; */
392
- csonpath_push_inst(cjp, CSONPATH_INST_OR);
393
- ++walker;
394
- cjp->inst_lst[cjp->inst_idx - 1].next += 1;
395
- 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;
396
511
  }
397
512
  if (*walker == 0) {
398
- csonpath_push_inst(cjp, CSONPATH_INST_END);
399
- cjp->compiled = 1;
400
- free(tmp);
401
- return 0;
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
- ++idx;
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
- CSONPATH_DO_FILTER_LOOP_PRE_SET
178
- if (cjp->inst_lst[idx].inst != CSONPATH_INST_FILTER_OPERAND_STR)
179
- CSONPATH_GETTER_ERR("filter support only comparaison with STR");
180
-
181
- CSONPATH_FOREACH_EXT(el, el2, {
182
- if (!strcmp((char *)neested_key, filter_key)) {
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)) {
186
- CSONPATH_DO_RET_TYPE tret =
187
- csonpath_do_internal(cjp, origin, el, tmp, idx + 1,
188
- walker + cjp->inst_lst[idx].next
189
- CSONPATH_DO_EXTRA_ARGS_NEESTED);
190
-
191
- CSONPATH_DO_FILTER_FIND;
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
- }, 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;
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)) { \
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "csonpath"
7
- version = "0.0.4"
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