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
);