matcher.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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. #include "parser.h"
  17. #include "matcher.h"
  18. static struct json_object *
  19. jp_match_next(struct jp_opcode *ptr,
  20. struct json_object *root, struct json_object *cur,
  21. jp_match_cb_t cb, void *priv);
  22. static bool
  23. jp_json_to_op(struct json_object *obj, struct jp_opcode *op)
  24. {
  25. switch (json_object_get_type(obj))
  26. {
  27. case json_type_boolean:
  28. op->type = T_BOOL;
  29. op->num = json_object_get_boolean(obj);
  30. return true;
  31. case json_type_int:
  32. op->type = T_NUMBER;
  33. op->num = json_object_get_int(obj);
  34. return true;
  35. case json_type_string:
  36. op->type = T_STRING;
  37. op->str = (char *)json_object_get_string(obj);
  38. return true;
  39. default:
  40. return false;
  41. }
  42. }
  43. static bool
  44. jp_resolve(struct json_object *root, struct json_object *cur,
  45. struct jp_opcode *op, struct jp_opcode *res)
  46. {
  47. struct json_object *val;
  48. switch (op->type)
  49. {
  50. case T_THIS:
  51. val = jp_match(op, cur, NULL, NULL);
  52. if (val)
  53. return jp_json_to_op(val, res);
  54. return false;
  55. case T_ROOT:
  56. val = jp_match(op, root, NULL, NULL);
  57. if (val)
  58. return jp_json_to_op(val, res);
  59. return false;
  60. default:
  61. *res = *op;
  62. return true;
  63. }
  64. }
  65. static bool
  66. jp_cmp(struct jp_opcode *op, struct json_object *root, struct json_object *cur)
  67. {
  68. int delta;
  69. struct jp_opcode left, right;
  70. if (!jp_resolve(root, cur, op->down, &left) ||
  71. !jp_resolve(root, cur, op->down->sibling, &right))
  72. return false;
  73. if (left.type != right.type)
  74. return false;
  75. switch (left.type)
  76. {
  77. case T_BOOL:
  78. case T_NUMBER:
  79. delta = left.num - right.num;
  80. break;
  81. case T_STRING:
  82. delta = strcmp(left.str, right.str);
  83. break;
  84. default:
  85. return false;
  86. }
  87. switch (op->type)
  88. {
  89. case T_EQ:
  90. return (delta == 0);
  91. case T_LT:
  92. return (delta < 0);
  93. case T_LE:
  94. return (delta <= 0);
  95. case T_GT:
  96. return (delta > 0);
  97. case T_GE:
  98. return (delta >= 0);
  99. case T_NE:
  100. return (delta != 0);
  101. default:
  102. return false;
  103. }
  104. }
  105. static bool
  106. jp_regmatch(struct jp_opcode *op, struct json_object *root, struct json_object *cur)
  107. {
  108. struct jp_opcode left, right;
  109. char lbuf[22], rbuf[22], *lval, *rval;
  110. int err, rflags = REG_NOSUB | REG_NEWLINE;
  111. regex_t preg;
  112. if (!jp_resolve(root, cur, op->down, &left) ||
  113. !jp_resolve(root, cur, op->down->sibling, &right))
  114. return false;
  115. if (left.type == T_REGEXP)
  116. {
  117. switch (right.type)
  118. {
  119. case T_BOOL:
  120. lval = right.num ? "true" : "false";
  121. break;
  122. case T_NUMBER:
  123. snprintf(lbuf, sizeof(lbuf), "%d", right.num);
  124. lval = lbuf;
  125. break;
  126. case T_STRING:
  127. lval = right.str;
  128. break;
  129. default:
  130. return false;
  131. }
  132. rval = left.str;
  133. rflags = left.num;
  134. }
  135. else
  136. {
  137. switch (left.type)
  138. {
  139. case T_BOOL:
  140. lval = left.num ? "true" : "false";
  141. break;
  142. case T_NUMBER:
  143. snprintf(lbuf, sizeof(lbuf), "%d", left.num);
  144. lval = lbuf;
  145. break;
  146. case T_STRING:
  147. lval = left.str;
  148. break;
  149. default:
  150. return false;
  151. }
  152. switch (right.type)
  153. {
  154. case T_BOOL:
  155. rval = right.num ? "true" : "false";
  156. break;
  157. case T_NUMBER:
  158. snprintf(rbuf, sizeof(rbuf), "%d", right.num);
  159. rval = rbuf;
  160. break;
  161. case T_STRING:
  162. rval = right.str;
  163. break;
  164. case T_REGEXP:
  165. rval = right.str;
  166. rflags = right.num;
  167. break;
  168. default:
  169. return false;
  170. }
  171. }
  172. if (regcomp(&preg, rval, rflags))
  173. return false;
  174. err = regexec(&preg, lval, 0, NULL, 0);
  175. regfree(&preg);
  176. return err ? false : true;
  177. }
  178. static bool
  179. jp_expr(struct jp_opcode *op, struct json_object *root, struct json_object *cur,
  180. int idx, const char *key, jp_match_cb_t cb, void *priv)
  181. {
  182. struct jp_opcode *sop;
  183. switch (op->type)
  184. {
  185. case T_WILDCARD:
  186. return true;
  187. case T_EQ:
  188. case T_NE:
  189. case T_LT:
  190. case T_LE:
  191. case T_GT:
  192. case T_GE:
  193. return jp_cmp(op, root, cur);
  194. case T_MATCH:
  195. return jp_regmatch(op, root, cur);
  196. case T_ROOT:
  197. return !!jp_match(op, root, NULL, NULL);
  198. case T_THIS:
  199. return !!jp_match(op, cur, NULL, NULL);
  200. case T_NOT:
  201. return !jp_expr(op->down, root, cur, idx, key, cb, priv);
  202. case T_AND:
  203. for (sop = op->down; sop; sop = sop->sibling)
  204. if (!jp_expr(sop, root, cur, idx, key, cb, priv))
  205. return false;
  206. return true;
  207. case T_OR:
  208. case T_UNION:
  209. for (sop = op->down; sop; sop = sop->sibling)
  210. if (jp_expr(sop, root, cur, idx, key, cb, priv))
  211. return true;
  212. return false;
  213. case T_STRING:
  214. return (key && !strcmp(op->str, key));
  215. case T_NUMBER:
  216. return (idx == op->num);
  217. default:
  218. return false;
  219. }
  220. }
  221. static struct json_object *
  222. jp_match_expr(struct jp_opcode *ptr,
  223. struct json_object *root, struct json_object *cur,
  224. jp_match_cb_t cb, void *priv)
  225. {
  226. int idx, len;
  227. struct json_object *tmp, *res = NULL;
  228. switch (json_object_get_type(cur))
  229. {
  230. case json_type_object:
  231. ; /* a label can only be part of a statement and a declaration is not a statement */
  232. json_object_object_foreach(cur, key, val)
  233. {
  234. if (jp_expr(ptr, root, val, -1, key, cb, priv))
  235. {
  236. tmp = jp_match_next(ptr->sibling, root, val, cb, priv);
  237. if (tmp && !res)
  238. res = tmp;
  239. }
  240. }
  241. break;
  242. case json_type_array:
  243. len = json_object_array_length(cur);
  244. for (idx = 0; idx < len; idx++)
  245. {
  246. tmp = json_object_array_get_idx(cur, idx);
  247. if (jp_expr(ptr, root, tmp, idx, NULL, cb, priv))
  248. {
  249. tmp = jp_match_next(ptr->sibling, root, tmp, cb, priv);
  250. if (tmp && !res)
  251. res = tmp;
  252. }
  253. }
  254. break;
  255. default:
  256. break;
  257. }
  258. return res;
  259. }
  260. static struct json_object *
  261. jp_match_next(struct jp_opcode *ptr,
  262. struct json_object *root, struct json_object *cur,
  263. jp_match_cb_t cb, void *priv)
  264. {
  265. int idx;
  266. struct json_object *next = NULL;
  267. if (!ptr)
  268. {
  269. if (cb)
  270. cb(cur, priv);
  271. return cur;
  272. }
  273. switch (ptr->type)
  274. {
  275. case T_STRING:
  276. case T_LABEL:
  277. if (json_object_object_get_ex(cur, ptr->str, &next))
  278. return jp_match_next(ptr->sibling, root, next, cb, priv);
  279. break;
  280. case T_NUMBER:
  281. if (json_object_get_type(cur) == json_type_array)
  282. {
  283. idx = ptr->num;
  284. if (idx < 0)
  285. idx += json_object_array_length(cur);
  286. if (idx >= 0)
  287. next = json_object_array_get_idx(cur, idx);
  288. if (next)
  289. return jp_match_next(ptr->sibling, root, next, cb, priv);
  290. }
  291. break;
  292. default:
  293. return jp_match_expr(ptr, root, cur, cb, priv);
  294. }
  295. return NULL;
  296. }
  297. struct json_object *
  298. jp_match(struct jp_opcode *path, json_object *jsobj,
  299. jp_match_cb_t cb, void *priv)
  300. {
  301. if (path->type == T_LABEL)
  302. path = path->down;
  303. return jp_match_next(path->down, jsobj, jsobj, cb, priv);
  304. }