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 } 390
This page was automatically generated by LXR 0.3.1. • OpenWrt