2 * Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
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.
25 #include <json-c/json.h>
28 #include <libubox/list.h>
36 struct json_object *jsobj;
37 struct list_head list;
40 static struct json_object *
41 parse_json(FILE *fd, const char *source, const char **error)
45 struct json_object *obj = NULL;
46 struct json_tokener *tok = json_tokener_new();
47 enum json_tokener_error err = json_tokener_continue;
54 obj = json_tokener_parse_ex(tok, source, strlen(source));
55 err = json_tokener_get_error(tok);
59 while ((len = fread(buf, 1, sizeof(buf), fd)) > 0)
61 obj = json_tokener_parse_ex(tok, buf, len);
62 err = json_tokener_get_error(tok);
64 if (!err || err != json_tokener_continue)
69 json_tokener_free(tok);
73 if (err == json_tokener_continue)
74 err = json_tokener_error_parse_eof;
76 *error = json_tokener_error_desc(err);
84 print_string(const char *s)
102 print_separator(const char *sep, int *sc, int sl)
106 switch (sep[(*sc - 1) % sl])
121 printf("%c", sep[(*sc - 1) % sl]);
129 export_value(struct list_head *matches, const char *prefix, const char *sep)
132 int sc = 0, sl = strlen(sep);
133 struct match_item *item;
135 if (list_empty(matches))
140 printf("export %s=", prefix);
142 list_for_each_entry(item, matches, list)
144 switch (json_object_get_type(item->jsobj))
146 case json_type_object:
147 ; /* a label can only be part of a statement */
148 json_object_object_foreach(item->jsobj, key, val)
153 print_separator(sep, &sc, sl);
158 case json_type_array:
159 for (n = 0, len = json_object_array_length(item->jsobj);
162 print_separator(sep, &sc, sl);
167 case json_type_boolean:
168 print_separator(sep, &sc, sl);
169 printf("%d", json_object_get_boolean(item->jsobj));
173 print_separator(sep, &sc, sl);
174 printf("%d", json_object_get_int(item->jsobj));
177 case json_type_double:
178 print_separator(sep, &sc, sl);
179 printf("%f", json_object_get_double(item->jsobj));
182 case json_type_string:
183 print_separator(sep, &sc, sl);
184 print_string(json_object_get_string(item->jsobj));
196 list_for_each_entry(item, matches, list)
198 switch (json_object_get_type(item->jsobj))
200 case json_type_object:
201 case json_type_array:
202 case json_type_boolean:
204 case json_type_double:
205 printf("%s\n", json_object_to_json_string(item->jsobj));
208 case json_type_string:
209 printf("%s\n", json_object_get_string(item->jsobj));
220 export_type(struct list_head *matches, const char *prefix)
223 struct match_item *item;
224 const char *types[] = {
234 if (list_empty(matches))
238 printf("export %s=", prefix);
240 list_for_each_entry(item, matches, list)
245 printf("%s", types[json_object_get_type(item->jsobj)]);
256 match_cb(struct json_object *res, void *priv)
258 struct list_head *h = priv;
259 struct match_item *i = calloc(1, sizeof(*i));
264 list_add_tail(&i->list, h);
269 print_error(struct jp_state *state, char *expr)
274 fprintf(stderr, "Syntax error: ");
276 switch (state->error_code)
279 fprintf(stderr, "Unexpected character\n");
283 fprintf(stderr, "String or label literal too long\n");
287 fprintf(stderr, "Invalid escape sequence\n");
291 fprintf(stderr, "Unterminated string\n");
295 for (i = 0; i < sizeof(state->error_code) * 8; i++)
297 if (state->error_code & (1 << i))
300 first ? "Expecting %s" : " or %s", tokennames[i]);
306 fprintf(stderr, "\n");
310 fprintf(stderr, "In expression %s\n", expr);
311 fprintf(stderr, "Near here ----");
313 for (i = 0; i < state->error_pos; i++)
314 fprintf(stderr, "-");
316 fprintf(stderr, "^\n");
320 filter_json(int opt, struct json_object *jsobj, char *expr, const char *sep)
322 struct jp_state *state;
323 const char *prefix = NULL;
324 struct list_head matches;
325 struct match_item *item, *tmp;
326 struct json_object *res = NULL;
328 state = jp_parse(expr);
332 fprintf(stderr, "Out of memory\n");
335 else if (state->error_code)
337 print_error(state, expr);
341 INIT_LIST_HEAD(&matches);
343 res = jp_match(state->path, jsobj, match_cb, &matches);
344 prefix = (state->path->type == T_LABEL) ? state->path->str : NULL;
349 export_type(&matches, prefix);
353 export_value(&matches, prefix, sep);
357 list_for_each_entry_safe(item, tmp, &matches, list)
367 int main(int argc, char **argv)
371 struct json_object *jsobj = NULL;
372 const char *jserr = NULL, *source = NULL, *separator = " ";
374 while ((opt = getopt(argc, argv, "i:s:e:t:F:q")) != -1)
379 input = fopen(optarg, "r");
383 fprintf(stderr, "Failed to open %s: %s\n",
384 optarg, strerror(errno));
397 if (optarg && *optarg)
405 jsobj = parse_json(input, source, &jserr);
409 fprintf(stderr, "Failed to parse json data: %s\n",
417 if (!filter_json(opt, jsobj, optarg, separator))
430 json_object_put(jsobj);