csonpath 0.0.4__tar.gz → 0.2.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.2.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.2.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,50 @@ 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_2(c, check, on) do { \
133
+ if (check) { \
134
+ CSONPATH_REQUIRE_ERR(c, on); \
135
+ } \
136
+ ++on; \
137
+ } while (0)
138
+
139
+ #define CSONPATH_SKIP(c, on) \
140
+ CSONPATH_SKIP_2(c, *on != c, on)
141
+
142
+
108
143
  static inline struct csonpath_child_info *csonpath_child_info_set(struct csonpath_child_info *child_info,
109
144
  CSONPATH_JSON j, const intptr_t key)
110
145
  {
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;
146
+ if (CSONPATH_IS_OBJ(j)) {
147
+ *child_info = (struct csonpath_child_info){.key=(const char *)key, .type=CSONPATH_STR};
148
+ } else {
149
+ *child_info = (struct csonpath_child_info){.idx=key, .type=CSONPATH_INTEGER};
150
+ }
151
+ return child_info;
117
152
  }
118
153
 
119
154
  static inline void csonpath_destroy(struct csonpath cjp[static 1])
@@ -121,57 +156,84 @@ static inline void csonpath_destroy(struct csonpath cjp[static 1])
121
156
  free(cjp->path);
122
157
  free(cjp->inst_lst);
123
158
  free(cjp->compile_error);
159
+ if (cjp->regex_cnt) {
160
+ for (int i = 0; i < cjp->regex_cnt; ++i) {
161
+ regfree(&cjp->regexs[i]);
162
+ }
163
+ free(cjp->regexs);
164
+ }
124
165
  *cjp = (struct csonpath){};
125
166
  }
126
167
 
127
168
  static inline int csonpath_init(struct csonpath cjp[static 1],
128
169
  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;
170
+ *cjp = (struct csonpath) {.path=strdup(path),
171
+ .inst_size = CSONPATH_INST_MIN_ALLOC,
172
+ .inst_lst = malloc(sizeof(*cjp->inst_lst) * CSONPATH_INST_MIN_ALLOC)};
173
+ if (!cjp->path || !cjp->inst_lst) {
174
+ return -ENOMEM;
175
+ }
176
+ return 0;
136
177
  }
137
178
 
138
179
  static inline int csonpath_set_path(struct csonpath cjp[static 1],
139
180
  const char path[static 1])
140
181
  {
141
- free(cjp->path);
142
- free(cjp->compile_error);
143
- free(cjp->inst_lst);
144
- return csonpath_init(cjp, path);
182
+ csonpath_destroy(cjp);
183
+ return csonpath_init(cjp, path);
145
184
  }
146
185
 
147
- void csonpath_push_inst(struct csonpath cjp[static 1], int inst)
186
+ static inline void csonpath_push_inst(struct csonpath cjp[static 1], int inst)
148
187
  {
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;
188
+ if (cjp->inst_idx + 1 > cjp->inst_size) {
189
+ cjp->inst_size = cjp->inst_size << 1;
190
+ cjp->inst_lst = realloc(cjp->inst_lst, cjp->inst_size);
191
+ assert(cjp->inst_lst);
192
+ }
193
+ cjp->inst_lst[cjp->inst_idx] = (struct csonpath_instruction){.inst=inst};
194
+ ++cjp->inst_idx;
195
+ }
196
+
197
+ static inline void csonpath_push_inst_cpy(struct csonpath cjp[static 1],
198
+ struct csonpath_instruction inst)
199
+ {
200
+ if (cjp->inst_idx + 1 > cjp->inst_size) {
201
+ cjp->inst_size = cjp->inst_size << 1;
202
+ cjp->inst_lst = realloc(cjp->inst_lst, cjp->inst_size);
203
+ assert(cjp->inst_lst);
204
+ }
205
+ cjp->inst_lst[cjp->inst_idx] = inst;
206
+ ++cjp->inst_idx;
207
+ }
208
+
209
+ static void csonpath_print_instruction(struct csonpath cjp[static 1])
210
+ {
211
+ int idx = 0;
212
+ for (;cjp->inst_lst[idx].inst != CSONPATH_INST_END; ++idx) {
213
+ printf("%d: %s\n", idx, csonpath_instuction_str[(int)cjp->inst_lst[idx].inst]);
214
+ }
215
+ printf("%d: END\n", idx);
156
216
  }
157
217
 
158
- int csonpath_compile(struct csonpath cjp[static 1])
218
+ static inline _Bool csonpath_is_dot_operand(int c)
219
+ {
220
+ return isalnum(c) || c == '_' || c == '-';
221
+ }
222
+
223
+ static int csonpath_compile(struct csonpath cjp[static 1])
159
224
  {
160
225
  char *walker = cjp->path;
161
226
  char *orig = walker;
162
227
  char *next;
163
228
  char to_check;
164
- char *tmp;
229
+ char *tmp; /* tmp is only here for debug */
165
230
 
166
231
  if (cjp->compiled)
167
232
  return 0;
168
233
 
169
234
  tmp = strdup(cjp->path);
170
235
  root_again:
171
- if (*walker != '$') {
172
- CSONPATH_COMPILE_ERR(tmp, walker - orig, "%s", "'$' needed");
173
- }
174
- ++walker;
236
+ CSONPATH_SKIP('$', walker);
175
237
  csonpath_push_inst(cjp, CSONPATH_INST_ROOT);
176
238
  cjp->inst_lst[cjp->inst_idx - 1].next = 1;
177
239
  to_check = *walker;
@@ -180,227 +242,329 @@ again:
180
242
  switch (to_check) {
181
243
  case '[':
182
244
  {
183
- int end;
245
+ int end;
184
246
 
185
247
  do_array:
248
+ cjp->inst_lst[cjp->inst_idx - 1].next += 1;
249
+ ++walker;
250
+ if (*walker == '*') {
251
+ csonpath_push_inst(cjp, CSONPATH_INST_GET_ALL);
252
+ if (walker[1] != ']') {
253
+ CSONPATH_COMPILE_ERR(tmp, walker - orig, "%s", "unclose bracket\n");
254
+ }
255
+ cjp->inst_lst[cjp->inst_idx - 1].next = 2;
256
+ walker += 2;
257
+ to_check = *walker;
258
+ goto again;
259
+ } else if (*walker == '?') {
260
+ int have_blank;
261
+ int have_parentesis = 0;
262
+ int nb_getter_inst = 0;
263
+ struct csonpath_instruction filter_getter[CSONPATH_TMP_BUF_SIZE];
264
+ struct csonpath_instruction *last_inst;
265
+ int regex_idx = -1;
266
+ int inst;
267
+ int getter_end = 0;
268
+
269
+ inst = CSONPATH_INST_GET_OBJ;
186
270
  cjp->inst_lst[cjp->inst_idx - 1].next += 1;
187
271
  ++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;
199
- cjp->inst_lst[cjp->inst_idx - 1].next += 1;
272
+ last_inst = &cjp->inst_lst[cjp->inst_idx - 1];
273
+ if (*walker == '(') {
274
+ have_parentesis = 1;
275
+ ++walker;
276
+ CSONPATH_SKIP('@', walker);
277
+ if (*walker == '[') {
200
278
  ++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);
279
+ getter_end = *walker;
280
+ } else {
281
+ CSONPATH_SKIP('.', walker);
282
+ }
283
+ cjp->inst_lst[cjp->inst_idx - 1].next += 3;
284
+ for (; isblank(*walker); ++walker)
285
+ cjp->inst_lst[cjp->inst_idx - 1].next += 1;
286
+ } else if (*walker == '[') {
287
+ ++walker;
288
+ last_inst->next++;
289
+ getter_end = *walker;
290
+ }
291
+ filter_again:
292
+ if (getter_end) {
293
+ if (getter_end != '\'' && getter_end != '"') {
294
+ CSONPATH_COMPILE_ERR(tmp, walker - orig,
295
+ "string require here, got '%c'", getter_end);
296
+ }
297
+ last_inst->next += 1;
298
+ ++walker;
299
+ for (next = walker; *next != getter_end; ++next);
300
+ } else {
301
+ for (next = walker; csonpath_is_dot_operand(*next); ++next);
302
+ }
303
+ if (!*next) {
304
+ CSONPATH_COMPILE_ERR(tmp, next - orig,
305
+ "filter miss condition");
306
+ goto error;
307
+ }
308
+ to_check = *next;
309
+ *next = 0;
310
+ if (getter_end) {
311
+ CSONPATH_SKIP_2(getter_end, to_check != getter_end, next);
312
+ CSONPATH_SKIP(']', next);
313
+ to_check = *next;
314
+ getter_end = 0;
315
+ }
316
+ filter_getter[nb_getter_inst++] = (struct csonpath_instruction){.inst=inst,
317
+ .next=next - walker};
318
+ last_inst = &filter_getter[nb_getter_inst - 1];
319
+ if (to_check == '.') {
320
+ filter_getter[nb_getter_inst - 1].next += 1;
321
+ walker = next + 1;
322
+ goto filter_again;
323
+ } else if (to_check == '[') {
324
+ filter_getter[nb_getter_inst - 1].next += 1;
325
+ walker = next + 1;
326
+ getter_end = *walker;
327
+ goto filter_again;
328
+ }
210
329
 
211
- for (++next; isblank(*next); ++next) {
212
- have_blank = 1;
213
- }
214
330
 
215
- if (*next && have_blank &&
216
- to_check != '=' && to_check != '!') {
217
- to_check = *next;
218
- ++next;
219
- }
331
+ if (have_parentesis && to_check == ')') {
332
+ filter_getter[nb_getter_inst-1].next += 1;
333
+ ++next;
334
+ to_check = *next;
335
+ have_parentesis = 0;
336
+ }
220
337
 
221
- if (!*next) {
222
- CSONPATH_COMPILE_ERR(tmp, next - orig,
223
- "filter miss condition");
338
+ walker = next;
339
+ have_blank = isblank(to_check);
224
340
 
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);
341
+ for (++next; isblank(*next); ++next) {
342
+ have_blank = 1;
343
+ }
344
+
345
+ if (*next && have_blank &&
346
+ to_check != '=' && to_check != '!') {
347
+ to_check = *next;
348
+ ++next;
349
+ }
350
+
351
+ if (!*next) {
352
+ CSONPATH_COMPILE_ERR(tmp, next - orig,
353
+ "filter miss condition");
354
+
355
+ goto error;
356
+ }
357
+ /* = and == are the same here */
358
+ if (to_check == '=') {
359
+ csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_EQ);
360
+ if (next[0] == '=')
361
+ ++next;
362
+ else if (next[0] == '~') {
363
+ cjp->inst_lst[cjp->inst_idx - 1].inst = CSONPATH_INST_FILTER_KEY_REG_EQ;
364
+ regex_idx = cjp->regex_cnt++;
365
+ ++next;
366
+ }
367
+ } else if (to_check == '!' && next[0] == '=') {
368
+ csonpath_push_inst(cjp, CSONPATH_INST_FILTER_KEY_NOT_EQ);
369
+ ++next;
370
+ } else {
371
+ CSONPATH_COMPILE_ERR(tmp, next - orig,
372
+ "'%c': unsuported operation", to_check);
373
+ goto error;
374
+ }
375
+ for (;isblank(*next); ++next);
376
+ cjp->inst_lst[cjp->inst_idx - 1].next = 0;
377
+ cjp->inst_lst[cjp->inst_idx - 1].filter_next = cjp->inst_idx + nb_getter_inst;
378
+ for (int i = 0; i < nb_getter_inst; ++i) {
379
+ csonpath_push_inst_cpy(cjp, filter_getter[i]);
380
+ }
381
+ cjp->inst_lst[cjp->inst_idx - 1].next += next - walker;
382
+ walker = next;
383
+ if (*walker == '"' || *walker == '\'' || *walker == '/') {
384
+ char end = *walker;
385
+ ++walker;
386
+ cjp->inst_lst[cjp->inst_idx - 1].next++;
387
+ csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_STR);
388
+ for (next = walker; *next && *next != end; ++next);
389
+ if (!*next) {
390
+ CSONPATH_COMPILE_ERR(tmp, walker - orig,
391
+ "broken filter");
392
+ goto error;
393
+ }
394
+ *next = 0;
395
+ #ifndef CSONPATH_NO_REGEX
396
+ if (regex_idx >= 0) {
397
+ if (!regex_idx)
398
+ cjp->regexs = malloc(sizeof *cjp->regexs * 255);
399
+ int e = regcomp(&cjp->regexs[regex_idx], walker, 0);
400
+ cjp->inst_lst[cjp->inst_idx - 1].regex_idx = regex_idx;
401
+ if (e) {
402
+ CSONPATH_COMPILE_ERR(tmp, next - orig, "regex has error\n");
403
+ goto error;
325
404
  }
326
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
327
- walker = next + 1;
328
- to_check = *walker;
329
- goto again;
405
+ }
406
+ #endif
407
+ ++next;
408
+ to_check = *next;
330
409
  } else {
331
- end = *walker;
332
- cjp->inst_lst[cjp->inst_idx - 1].next += 1;
410
+ int n;
411
+
412
+ for (next = walker; isdigit(*next); ++next);
413
+ if (next == walker) {
414
+ CSONPATH_COMPILE_ERR(tmp, walker - orig,
415
+ "'%c': broken filter with number",
416
+ *walker);
417
+ goto error;
418
+ }
419
+ n = atoi(walker);
420
+ if (n < 100) {
421
+ *walker = n;
422
+ csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_BYTE);
423
+ } else {
424
+ MAY_ALIAS int *walk_int = (void *)walker;
425
+ *walk_int = n;
426
+ csonpath_push_inst(cjp, CSONPATH_INST_FILTER_OPERAND_INT);
427
+ }
428
+ if (!*next) {
429
+ CSONPATH_COMPILE_ERR(tmp, walker - orig,
430
+ "compilation error");
431
+ goto error;
432
+ }
433
+ to_check = *next;
434
+ *next = 0;
435
+ }
436
+ if (isblank(to_check)) {
437
+ for (next++; isblank(*next); ++next);
438
+ to_check = *next;
439
+ }
333
440
 
334
- ++walker;
335
- next = walker;
336
- while (*next++ != end) {
337
- /* \" should be ignored */
338
- while (*next == '\\')
339
- ++next;
340
- }
341
- --next;
342
- *next = 0;
441
+ if (have_parentesis) {
442
+ CSONPATH_SKIP(')', next);
443
+ to_check = *next;
444
+ }
445
+ if (to_check != ']') {
446
+ CSONPATH_REQUIRE_ERR(']', next);
447
+ }
448
+ /* skip space */
449
+ cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
450
+ walker = next + 1;
451
+ to_check = *walker;
452
+ goto again;
453
+ } else if (*walker != '"' && *walker != '\'') {
454
+ int num;
455
+
456
+ next = walker;
457
+ do {
458
+ if (*next < '0' || *next > '9') {
459
+ CSONPATH_COMPILE_ERR(tmp, walker - orig,
460
+ "unexpected '%c', sting, filter or number require\n", *next);
461
+ }
462
+ next++;
463
+ } while (*next && *next != ']');
464
+ if (!*next) {
465
+ CSONPATH_COMPILE_ERR(tmp, walker - orig,
466
+ "%s", "unclose bracket\n");
467
+ }
468
+ *next = 0;
469
+ num = atoi(walker);
470
+ if (num < 100) {
471
+ csonpath_push_inst(cjp, CSONPATH_INST_GET_ARRAY_SMALL);
472
+ *walker = num;
473
+ } else {
474
+ union {
475
+ int n;
476
+ char c[4];
477
+ } u = {.n=num};
478
+ walker[0] = u.c[0];
479
+ walker[1] = u.c[1];
480
+ walker[2] = u.c[2];
481
+ walker[3] = u.c[3];
482
+ csonpath_push_inst(cjp, CSONPATH_INST_GET_ARRAY_BIG);
483
+ }
484
+ cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
485
+ walker = next + 1;
486
+ to_check = *walker;
487
+ goto again;
488
+ } else {
489
+ end = *walker;
490
+ cjp->inst_lst[cjp->inst_idx - 1].next += 1;
491
+
492
+ ++walker;
493
+ next = walker;
494
+ while (*next++ != end) {
495
+ /* \" should be ignored */
496
+ while (*next == '\\')
343
497
  ++next;
344
- if (*next != ']')
345
- CSONPATH_COMPILE_ERR(tmp, walker - orig,
346
- "']' require instead of '%c'\n", *next);
498
+ }
499
+ --next;
500
+ *next = 0;
501
+ ++next;
502
+ if (*next != ']')
503
+ CSONPATH_COMPILE_ERR(tmp, walker - orig,
504
+ "']' require instead of '%c'\n", *next);
347
505
 
348
- csonpath_push_inst(cjp, CSONPATH_INST_GET_OBJ);
349
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
506
+ csonpath_push_inst(cjp, CSONPATH_INST_GET_OBJ);
507
+ cjp->inst_lst[cjp->inst_idx - 1].next = next - walker + 1;
350
508
 
351
- walker = next + 1;
352
- to_check = *walker;
353
- goto again;
354
- }
509
+ walker = next + 1;
510
+ to_check = *walker;
511
+ goto again;
512
+ }
355
513
  }
356
514
  case '.':
357
515
  {
358
- int inst = CSONPATH_INST_GET_OBJ;
516
+ int inst = CSONPATH_INST_GET_OBJ;
359
517
 
518
+ cjp->inst_lst[cjp->inst_idx - 1].next += 1;
519
+ ++walker;
520
+ if (*walker == '.') {
521
+ inst = CSONPATH_INST_FIND_ALL;
360
522
  cjp->inst_lst[cjp->inst_idx - 1].next += 1;
361
523
  ++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
-
524
+ } else if (*walker == '*') {
525
+ inst = CSONPATH_INST_GET_ALL;
526
+ ++walker;
527
+ if (*walker != '.' && *walker != '[' && *walker != '\0')
528
+ CSONPATH_COMPILE_ERR(tmp, walker - orig, "unsuported characters '%c' after '*'", *walker);
385
529
  csonpath_push_inst(cjp, inst);
386
- cjp->inst_lst[cjp->inst_idx - 1].next = next - walker;
387
- walker = next;
530
+ to_check = *walker;
388
531
  goto again;
532
+ }
533
+ for (next = walker; csonpath_is_dot_operand(*next); ++next);
534
+ if (next == walker) {
535
+ if (*next == '[')
536
+ goto do_array;
537
+ CSONPATH_COMPILE_ERR(tmp, walker - orig, "empty getter");
538
+ }
539
+ to_check = *next;
540
+ *next = 0;
541
+
542
+ csonpath_push_inst(cjp, inst);
543
+ cjp->inst_lst[cjp->inst_idx - 1].next = next - walker;
544
+ walker = next;
545
+ goto again;
389
546
  }
390
547
  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;
548
+ /* cjp->inst_lst[cjp->inst_idx - 1].next += 1; */
549
+ csonpath_push_inst(cjp, CSONPATH_INST_OR);
550
+ ++walker;
551
+ cjp->inst_lst[cjp->inst_idx - 1].next += 1;
552
+ goto root_again;
396
553
  }
397
- if (*walker == 0) {
398
- csonpath_push_inst(cjp, CSONPATH_INST_END);
399
- cjp->compiled = 1;
400
- free(tmp);
401
- return 0;
554
+ if (isblank(*walker)) {
555
+ cjp->inst_lst[cjp->inst_idx - 1].next += 1;
556
+ ++walker;
557
+ goto again;
558
+ }
559
+ else if (*walker == 0) {
560
+ csonpath_push_inst(cjp, CSONPATH_INST_END);
561
+ cjp->compiled = 1;
562
+ free(tmp);
563
+ return 0;
564
+ } else {
565
+ CSONPATH_COMPILE_ERR(tmp, walker - orig, "unexpected char '%c'", to_check);
402
566
  }
403
- error:
567
+ error:
404
568
  cjp->inst_lst[0] = (struct csonpath_instruction){.inst=CSONPATH_INST_BROKEN};
405
569
  free(tmp);
406
570
  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)) { \
@@ -68,16 +73,16 @@ static void python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject
68
73
  }
69
74
 
70
75
  #define CSONPATH_APPEND_AT(array, at, el) \
71
- _Generic((at), \
72
- int: python_set_or_insert_item, \
73
- unsigned int: python_set_or_insert_item, \
74
- long: python_set_or_insert_item, \
75
- unsigned long: python_set_or_insert_item, \
76
- long long: python_set_or_insert_item, \
77
- unsigned long long: python_set_or_insert_item, \
78
- const char *: PyDict_SetItemString, \
79
- char *: PyDict_SetItemString \
80
- ) (array, at, el)
76
+ _Generic((at), \
77
+ int: python_set_or_insert_item, \
78
+ unsigned int: python_set_or_insert_item, \
79
+ long: python_set_or_insert_item, \
80
+ unsigned long: python_set_or_insert_item, \
81
+ long long: python_set_or_insert_item, \
82
+ unsigned long long: python_set_or_insert_item, \
83
+ const char *: PyDict_SetItemString, \
84
+ char *: PyDict_SetItemString \
85
+ ) (array, at, el)
81
86
 
82
87
 
83
88
  #define CSONPATH_FOREACH_EXT(obj, el, code, key_idx) \
@@ -238,10 +243,6 @@ static void PyCsonPath_dealloc(PyCsonPathObject *self) {
238
243
  }
239
244
 
240
245
 
241
- static PyObject *PyCsonPath_get_path(PyCsonPathObject *self) {
242
- return PyUnicode_FromString(self->cp->path);
243
- }
244
-
245
246
  static PyObject *PyCsonPath_set_path(PyCsonPathObject *self, PyObject* args) {
246
247
  const char *new_path;
247
248
  if (!PyArg_ParseTuple(args, "s", &new_path))
@@ -253,7 +254,6 @@ static PyObject *PyCsonPath_set_path(PyCsonPathObject *self, PyObject* args) {
253
254
  }
254
255
 
255
256
  static PyMethodDef csonpath_py_method[] = {
256
- {"get_path", (PyCFunction)PyCsonPath_get_path, METH_VARARGS, "get_path"},
257
257
  {"set_path", (PyCFunction)PyCsonPath_set_path, METH_VARARGS, "set_path"},
258
258
  {"callback", (PyCFunction)callback, METH_VARARGS, "callback"},
259
259
  {"update_or_create_callback", (PyCFunction)update_or_create_callback, METH_VARARGS, "update_or_create_callback"},
@@ -0,0 +1,44 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "csonpath"
7
+ version = "0.2.0"
8
+ readme = "README.md"
9
+
10
+ [tool.setuptools]
11
+ packages = [] # no Python packages, just an extension
12
+ ext-modules = [
13
+ {name="csonpath", sources = ["csonpath_python.c"]}
14
+ ]
15
+
16
+ [project.optional-dependencies]
17
+ dev = [
18
+ "pytest>=8.3.5"
19
+ ]
20
+
21
+ [tool.pytest.ini_options]
22
+ testpaths = ["tests/python"]
23
+
24
+ [tool.bumpversion]
25
+ current_version = "0.2.0"
26
+ parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
27
+ serialize = ["{major}.{minor}.{patch}"]
28
+ search = "{current_version}"
29
+ replace = "{new_version}"
30
+ regex = true
31
+ ignore_missing_version = false
32
+ ignore_missing_files = false
33
+ tag = true
34
+ sign_tags = false
35
+ tag_name = "v{new_version}"
36
+ tag_message = "version {new_version}"
37
+ allow_dirty = true
38
+ commit = true
39
+ message = "Bump to {new_version}"
40
+ moveable_tags = []
41
+ commit_args = ""
42
+ setup_hooks = []
43
+ pre_commit_hooks = []
44
+ post_commit_hooks = []
@@ -1,22 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools>=61.0", "wheel"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "csonpath"
7
- version = "0.0.4"
8
- readme = "README.md"
9
-
10
- [tool.setuptools]
11
- packages = [] # no Python packages, just an extension
12
- ext-modules = [
13
- {name="csonpath", sources = ["csonpath_python.c"]}
14
- ]
15
-
16
- [project.optional-dependencies]
17
- dev = [
18
- "pytest>=8.3.5"
19
- ]
20
-
21
- [tool.pytest.ini_options]
22
- testpaths = ["tests/python"]
File without changes
File without changes
File without changes