main: fix spurious premature parse aborts in array mode
[project/jsonpath.git] / matcher.c
1 /*
2 * Copyright (C) 2013-2014 Jo-Philipp Wich <jo@mein.io>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include "parser.h"
18 #include "matcher.h"
19
20
21 static struct json_object *
22 jp_match_next(struct jp_opcode *ptr,
23 struct json_object *root, struct json_object *cur,
24 jp_match_cb_t cb, void *priv);
25
26 static bool
27 jp_json_to_op(struct json_object *obj, struct jp_opcode *op)
28 {
29 switch (json_object_get_type(obj))
30 {
31 case json_type_boolean:
32 op->type = T_BOOL;
33 op->num = json_object_get_boolean(obj);
34 return true;
35
36 case json_type_int:
37 op->type = T_NUMBER;
38 op->num = json_object_get_int(obj);
39 return true;
40
41 case json_type_string:
42 op->type = T_STRING;
43 op->str = (char *)json_object_get_string(obj);
44 return true;
45
46 default:
47 return false;
48 }
49 }
50
51 static bool
52 jp_resolve(struct json_object *root, struct json_object *cur,
53 struct jp_opcode *op, struct jp_opcode *res)
54 {
55 struct json_object *val;
56
57 switch (op->type)
58 {
59 case T_THIS:
60 val = jp_match(op, cur, NULL, NULL);
61
62 if (val)
63 return jp_json_to_op(val, res);
64
65 return false;
66
67 case T_ROOT:
68 val = jp_match(op, root, NULL, NULL);
69
70 if (val)
71 return jp_json_to_op(val, res);
72
73 return false;
74
75 default:
76 *res = *op;
77 return true;
78 }
79 }
80
81 static bool
82 jp_cmp(struct jp_opcode *op, struct json_object *root, struct json_object *cur)
83 {
84 int delta;
85 struct jp_opcode left, right;
86
87 if (!jp_resolve(root, cur, op->down, &left) ||
88 !jp_resolve(root, cur, op->down->sibling, &right))
89 return false;
90
91 if (left.type != right.type)
92 return false;
93
94 switch (left.type)
95 {
96 case T_BOOL:
97 case T_NUMBER:
98 delta = left.num - right.num;
99 break;
100
101 case T_STRING:
102 delta = strcmp(left.str, right.str);
103 break;
104
105 default:
106 return false;
107 }
108
109 switch (op->type)
110 {
111 case T_EQ:
112 return (delta == 0);
113
114 case T_LT:
115 return (delta < 0);
116
117 case T_LE:
118 return (delta <= 0);
119
120 case T_GT:
121 return (delta > 0);
122
123 case T_GE:
124 return (delta >= 0);
125
126 case T_NE:
127 return (delta != 0);
128
129 default:
130 return false;
131 }
132 }
133
134 static bool
135 jp_regmatch(struct jp_opcode *op, struct json_object *root, struct json_object *cur)
136 {
137 struct jp_opcode left, right;
138 char lbuf[22], rbuf[22], *lval, *rval;
139 int err, rflags = REG_NOSUB | REG_NEWLINE;
140 regex_t preg;
141
142
143 if (!jp_resolve(root, cur, op->down, &left) ||
144 !jp_resolve(root, cur, op->down->sibling, &right))
145 return false;
146
147 if (left.type == T_REGEXP)
148 {
149 switch (right.type)
150 {
151 case T_BOOL:
152 lval = right.num ? "true" : "false";
153 break;
154
155 case T_NUMBER:
156 snprintf(lbuf, sizeof(lbuf), "%d", right.num);
157 lval = lbuf;
158 break;
159
160 case T_STRING:
161 lval = right.str;
162 break;
163
164 default:
165 return false;
166 }
167
168 rval = left.str;
169 rflags = left.num;
170 }
171 else
172 {
173 switch (left.type)
174 {
175 case T_BOOL:
176 lval = left.num ? "true" : "false";
177 break;
178
179 case T_NUMBER:
180 snprintf(lbuf, sizeof(lbuf), "%d", left.num);
181 lval = lbuf;
182 break;
183
184 case T_STRING:
185 lval = left.str;
186 break;
187
188 default:
189 return false;
190 }
191
192 switch (right.type)
193 {
194 case T_BOOL:
195 rval = right.num ? "true" : "false";
196 break;
197
198 case T_NUMBER:
199 snprintf(rbuf, sizeof(rbuf), "%d", right.num);
200 rval = rbuf;
201 break;
202
203 case T_STRING:
204 rval = right.str;
205 break;
206
207 case T_REGEXP:
208 rval = right.str;
209 rflags = right.num;
210 break;
211
212 default:
213 return false;
214 }
215 }
216
217 if (regcomp(&preg, rval, rflags))
218 return false;
219
220 err = regexec(&preg, lval, 0, NULL, 0);
221
222 regfree(&preg);
223
224 return err ? false : true;
225 }
226
227 static bool
228 jp_expr(struct jp_opcode *op, struct json_object *root, struct json_object *cur,
229 int idx, const char *key, jp_match_cb_t cb, void *priv)
230 {
231 struct jp_opcode *sop;
232
233 switch (op->type)
234 {
235 case T_WILDCARD:
236 return true;
237
238 case T_EQ:
239 case T_NE:
240 case T_LT:
241 case T_LE:
242 case T_GT:
243 case T_GE:
244 return jp_cmp(op, root, cur);
245
246 case T_MATCH:
247 return jp_regmatch(op, root, cur);
248
249 case T_ROOT:
250 return !!jp_match(op, root, NULL, NULL);
251
252 case T_THIS:
253 return !!jp_match(op, cur, NULL, NULL);
254
255 case T_NOT:
256 return !jp_expr(op->down, root, cur, idx, key, cb, priv);
257
258 case T_AND:
259 for (sop = op->down; sop; sop = sop->sibling)
260 if (!jp_expr(sop, root, cur, idx, key, cb, priv))
261 return false;
262 return true;
263
264 case T_OR:
265 case T_UNION:
266 for (sop = op->down; sop; sop = sop->sibling)
267 if (jp_expr(sop, root, cur, idx, key, cb, priv))
268 return true;
269 return false;
270
271 case T_STRING:
272 return (key && !strcmp(op->str, key));
273
274 case T_NUMBER:
275 return (idx == op->num);
276
277 default:
278 return false;
279 }
280 }
281
282 static struct json_object *
283 jp_match_expr(struct jp_opcode *ptr,
284 struct json_object *root, struct json_object *cur,
285 jp_match_cb_t cb, void *priv)
286 {
287 int idx, len;
288 struct json_object *tmp, *res = NULL;
289
290 switch (json_object_get_type(cur))
291 {
292 case json_type_object:
293 ; /* a label can only be part of a statement and a declaration is not a statement */
294 json_object_object_foreach(cur, key, val)
295 {
296 if (jp_expr(ptr, root, val, -1, key, cb, priv))
297 {
298 tmp = jp_match_next(ptr->sibling, root, val, cb, priv);
299
300 if (tmp && !res)
301 res = tmp;
302 }
303 }
304
305 break;
306
307 case json_type_array:
308 len = json_object_array_length(cur);
309
310 for (idx = 0; idx < len; idx++)
311 {
312 tmp = json_object_array_get_idx(cur, idx);
313
314 if (jp_expr(ptr, root, tmp, idx, NULL, cb, priv))
315 {
316 tmp = jp_match_next(ptr->sibling, root, tmp, cb, priv);
317
318 if (tmp && !res)
319 res = tmp;
320 }
321 }
322
323 break;
324
325 default:
326 break;
327 }
328
329 return res;
330 }
331
332 static struct json_object *
333 jp_match_next(struct jp_opcode *ptr,
334 struct json_object *root, struct json_object *cur,
335 jp_match_cb_t cb, void *priv)
336 {
337 int idx;
338 struct json_object *next = NULL;
339
340 if (!ptr)
341 {
342 if (cb)
343 cb(cur, priv);
344
345 return cur;
346 }
347
348 switch (ptr->type)
349 {
350 case T_STRING:
351 case T_LABEL:
352 if (json_object_object_get_ex(cur, ptr->str, &next))
353 return jp_match_next(ptr->sibling, root, next, cb, priv);
354
355 break;
356
357 case T_NUMBER:
358 if (json_object_get_type(cur) == json_type_array)
359 {
360 idx = ptr->num;
361
362 if (idx < 0)
363 idx += json_object_array_length(cur);
364
365 if (idx >= 0)
366 next = json_object_array_get_idx(cur, idx);
367
368 if (next)
369 return jp_match_next(ptr->sibling, root, next, cb, priv);
370 }
371
372 break;
373
374 default:
375 return jp_match_expr(ptr, root, cur, cb, priv);
376 }
377
378 return NULL;
379 }
380
381 struct json_object *
382 jp_match(struct jp_opcode *path, json_object *jsobj,
383 jp_match_cb_t cb, void *priv)
384 {
385 if (path->type == T_LABEL)
386 path = path->down;
387
388 return jp_match_next(path->down, jsobj, jsobj, cb, priv);
389 }