matcher.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*
  2. * Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
  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_expr(struct jp_opcode *op, struct json_object *root, struct json_object *cur,
  107. int idx, const char *key, jp_match_cb_t cb, void *priv)
  108. {
  109. struct jp_opcode *sop;
  110. switch (op->type)
  111. {
  112. case T_WILDCARD:
  113. return true;
  114. case T_EQ:
  115. case T_NE:
  116. case T_LT:
  117. case T_LE:
  118. case T_GT:
  119. case T_GE:
  120. return jp_cmp(op, root, cur);
  121. case T_ROOT:
  122. return !!jp_match(op, root, NULL, NULL);
  123. case T_THIS:
  124. return !!jp_match(op, cur, NULL, NULL);
  125. case T_NOT:
  126. return !jp_expr(op->down, root, cur, idx, key, cb, priv);
  127. case T_AND:
  128. for (sop = op->down; sop; sop = sop->sibling)
  129. if (!jp_expr(sop, root, cur, idx, key, cb, priv))
  130. return false;
  131. return true;
  132. case T_OR:
  133. case T_UNION:
  134. for (sop = op->down; sop; sop = sop->sibling)
  135. if (jp_expr(sop, root, cur, idx, key, cb, priv))
  136. return true;
  137. return false;
  138. case T_STRING:
  139. return (key && !strcmp(op->str, key));
  140. case T_NUMBER:
  141. return (idx == op->num);
  142. default:
  143. return false;
  144. }
  145. }
  146. static struct json_object *
  147. jp_match_expr(struct jp_opcode *ptr,
  148. struct json_object *root, struct json_object *cur,
  149. jp_match_cb_t cb, void *priv)
  150. {
  151. int idx, len;
  152. struct json_object *tmp, *res = NULL;
  153. switch (json_object_get_type(cur))
  154. {
  155. case json_type_object:
  156. ; /* a label can only be part of a statement and a declaration is not a statement */
  157. json_object_object_foreach(cur, key, val)
  158. {
  159. if (jp_expr(ptr, root, val, -1, key, cb, priv))
  160. {
  161. tmp = jp_match_next(ptr->sibling, root, val, cb, priv);
  162. if (tmp && !res)
  163. res = tmp;
  164. }
  165. }
  166. break;
  167. case json_type_array:
  168. len = json_object_array_length(cur);
  169. for (idx = 0; idx < len; idx++)
  170. {
  171. tmp = json_object_array_get_idx(cur, idx);
  172. if (jp_expr(ptr, root, tmp, idx, NULL, cb, priv))
  173. {
  174. tmp = jp_match_next(ptr->sibling, root, tmp, cb, priv);
  175. if (tmp && !res)
  176. res = tmp;
  177. }
  178. }
  179. break;
  180. default:
  181. break;
  182. }
  183. return res;
  184. }
  185. static struct json_object *
  186. jp_match_next(struct jp_opcode *ptr,
  187. struct json_object *root, struct json_object *cur,
  188. jp_match_cb_t cb, void *priv)
  189. {
  190. struct json_object *next;
  191. if (!ptr)
  192. {
  193. if (cb)
  194. cb(cur, priv);
  195. return cur;
  196. }
  197. switch (ptr->type)
  198. {
  199. case T_STRING:
  200. case T_LABEL:
  201. if (json_object_object_get_ex(cur, ptr->str, &next))
  202. return jp_match_next(ptr->sibling, root, next, cb, priv);
  203. break;
  204. case T_NUMBER:
  205. next = json_object_array_get_idx(cur, ptr->num);
  206. if (next)
  207. return jp_match_next(ptr->sibling, root, next, cb, priv);
  208. break;
  209. default:
  210. return jp_match_expr(ptr, root, cur, cb, priv);
  211. }
  212. return NULL;
  213. }
  214. struct json_object *
  215. jp_match(struct jp_opcode *path, json_object *jsobj,
  216. jp_match_cb_t cb, void *priv)
  217. {
  218. if (path->type == T_LABEL)
  219. path = path->down;
  220. return jp_match_next(path->down, jsobj, jsobj, cb, priv);
  221. }