2 * Copyright (C) 2013-2014 Jo-Philipp Wich <jo@mein.io>
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.
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.
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);
27 jp_json_to_op(struct json_object *obj, struct jp_opcode *op)
29 switch (json_object_get_type(obj))
31 case json_type_boolean:
33 op->num = json_object_get_boolean(obj);
38 op->num = json_object_get_int(obj);
41 case json_type_string:
43 op->str = (char *)json_object_get_string(obj);
52 jp_resolve(struct json_object *root, struct json_object *cur,
53 struct jp_opcode *op, struct jp_opcode *res)
55 struct json_object *val;
60 val = jp_match(op, cur, NULL, NULL);
63 return jp_json_to_op(val, res);
68 val = jp_match(op, root, NULL, NULL);
71 return jp_json_to_op(val, res);
82 jp_cmp(struct jp_opcode *op, struct json_object *root, struct json_object *cur)
85 struct jp_opcode left, right;
87 if (!jp_resolve(root, cur, op->down, &left) ||
88 !jp_resolve(root, cur, op->down->sibling, &right))
91 if (left.type != right.type)
98 delta = left.num - right.num;
102 delta = strcmp(left.str, right.str);
135 jp_regmatch(struct jp_opcode *op, struct json_object *root, struct json_object *cur)
137 struct jp_opcode left, right;
138 char lbuf[22], rbuf[22], *lval, *rval;
139 int err, rflags = REG_NOSUB | REG_NEWLINE;
143 if (!jp_resolve(root, cur, op->down, &left) ||
144 !jp_resolve(root, cur, op->down->sibling, &right))
147 if (left.type == T_REGEXP)
152 lval = right.num ? "true" : "false";
156 snprintf(lbuf, sizeof(lbuf), "%d", right.num);
176 lval = left.num ? "true" : "false";
180 snprintf(lbuf, sizeof(lbuf), "%d", left.num);
195 rval = right.num ? "true" : "false";
199 snprintf(rbuf, sizeof(rbuf), "%d", right.num);
217 if (regcomp(&preg, rval, rflags))
220 err = regexec(&preg, lval, 0, NULL, 0);
224 return err ? false : true;
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)
231 struct jp_opcode *sop;
244 return jp_cmp(op, root, cur);
247 return jp_regmatch(op, root, cur);
250 return !!jp_match(op, root, NULL, NULL);
253 return !!jp_match(op, cur, NULL, NULL);
256 return !jp_expr(op->down, root, cur, idx, key, cb, priv);
259 for (sop = op->down; sop; sop = sop->sibling)
260 if (!jp_expr(sop, root, cur, idx, key, cb, priv))
266 for (sop = op->down; sop; sop = sop->sibling)
267 if (jp_expr(sop, root, cur, idx, key, cb, priv))
272 return (key && !strcmp(op->str, key));
275 return (idx == op->num);
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)
288 struct json_object *tmp, *res = NULL;
290 switch (json_object_get_type(cur))
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)
296 if (jp_expr(ptr, root, val, -1, key, cb, priv))
298 tmp = jp_match_next(ptr->sibling, root, val, cb, priv);
307 case json_type_array:
308 len = json_object_array_length(cur);
310 for (idx = 0; idx < len; idx++)
312 tmp = json_object_array_get_idx(cur, idx);
314 if (jp_expr(ptr, root, tmp, idx, NULL, cb, priv))
316 tmp = jp_match_next(ptr->sibling, root, tmp, cb, priv);
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)
338 struct json_object *next = NULL;
352 if (json_object_object_get_ex(cur, ptr->str, &next))
353 return jp_match_next(ptr->sibling, root, next, cb, priv);
358 if (json_object_get_type(cur) == json_type_array)
363 idx += json_object_array_length(cur);
366 next = json_object_array_get_idx(cur, idx);
369 return jp_match_next(ptr->sibling, root, next, cb, priv);
375 return jp_match_expr(ptr, root, cur, cb, priv);
382 jp_match(struct jp_opcode *path, json_object *jsobj,
383 jp_match_cb_t cb, void *priv)
385 if (path->type == T_LABEL)
388 return jp_match_next(path->down, jsobj, jsobj, cb, priv);