X-Git-Url: https://git.librecmc.org/?p=oweals%2Fjsonpath.git;a=blobdiff_plain;f=main.c;h=ebd52c0cecf0cbb5542cb52ce20a43ec9d6bd150;hp=78fa0e4087b65fcce272020445829a4d65f74ebd;hb=f3830138661374ca10fe6a0b6f2f4b949dea3e5c;hpb=d7e77a322e98474071e850bbaaac46528abb81e8 diff --git a/main.c b/main.c index 78fa0e4..ebd52c0 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Jo-Philipp Wich + * Copyright (C) 2013-2014 Jo-Philipp Wich * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,10 +25,18 @@ #include #endif +#include + #include "lexer.h" #include "parser.h" #include "matcher.h" + +struct match_item { + struct json_object *jsobj; + struct list_head list; +}; + static struct json_object * parse_json(FILE *fd, const char *source, const char **error) { @@ -91,75 +99,113 @@ print_string(const char *s) } static void -export_value(struct json_object *jsobj, const char *prefix) +export_value(struct list_head *matches, const char *prefix) { int n, len; bool first = true; + struct match_item *item; + + if (list_empty(matches)) + return; if (prefix) { - switch (json_object_get_type(jsobj)) + printf("export %s=", prefix); + + list_for_each_entry(item, matches, list) { - case json_type_object: - printf("export %s=", prefix); - json_object_object_foreach(jsobj, key, val) + switch (json_object_get_type(item->jsobj)) { - if (!val) - continue; + case json_type_object: + ; /* a label can only be part of a statement */ + json_object_object_foreach(item->jsobj, key, val) + { + if (!val) + continue; - if (!first) - printf("\\ "); + if (!first) + printf("\\ "); - print_string(key); - first = false; - } - printf("; "); - break; + print_string(key); + first = false; + } + break; - case json_type_array: - printf("export %s=", prefix); - for (n = 0, len = json_object_array_length(jsobj); n < len; n++) - { + case json_type_array: + for (n = 0, len = json_object_array_length(item->jsobj); + n < len; n++) + { + if (!first) + printf("\\ "); + + printf("%d", n); + first = false; + } + break; + + case json_type_boolean: if (!first) printf("\\ "); + printf("%d", json_object_get_boolean(item->jsobj)); + break; - printf("%d", n); - first = false; - } - printf("; "); - break; - - case json_type_boolean: - printf("export %s=%d; ", prefix, json_object_get_boolean(jsobj)); - break; + case json_type_int: + if (!first) + printf("\\ "); + printf("%d", json_object_get_int(item->jsobj)); + break; - case json_type_int: - printf("export %s=%d; ", prefix, json_object_get_int(jsobj)); - break; + case json_type_double: + if (!first) + printf("\\ "); + printf("%f", json_object_get_double(item->jsobj)); + break; - case json_type_double: - printf("export %s=%f; ", prefix, json_object_get_double(jsobj)); - break; + case json_type_string: + if (!first) + printf("\\ "); + print_string(json_object_get_string(item->jsobj)); + break; - case json_type_string: - printf("export %s=", prefix); - print_string(json_object_get_string(jsobj)); - printf("; "); - break; + case json_type_null: + break; + } - case json_type_null: - break; + first = false; } + + printf("; "); } else { - printf("%s\n", json_object_to_json_string(jsobj)); + list_for_each_entry(item, matches, list) + { + switch (json_object_get_type(item->jsobj)) + { + case json_type_object: + case json_type_array: + case json_type_boolean: + case json_type_int: + case json_type_double: + printf("%s\n", json_object_to_json_string(item->jsobj)); + break; + + case json_type_string: + printf("%s\n", json_object_get_string(item->jsobj)); + break; + + case json_type_null: + break; + } + } } } static void -export_type(struct json_object *jsobj, const char *prefix) +export_type(struct list_head *matches, const char *prefix) { + bool first = true; + struct match_item *item; const char *types[] = { "null", "boolean", @@ -170,47 +216,79 @@ export_type(struct json_object *jsobj, const char *prefix) "string" }; + if (list_empty(matches)) + return; + + if (prefix) + printf("export %s=", prefix); + + list_for_each_entry(item, matches, list) + { + if (!first) + printf("\\ "); + + printf("%s", types[json_object_get_type(item->jsobj)]); + first = false; + } + if (prefix) - printf("export %s=%s; ", prefix, types[json_object_get_type(jsobj)]); + printf("; "); else - printf("%s\n", types[json_object_get_type(jsobj)]); + printf("\n"); +} + +static void +match_cb(struct json_object *res, void *priv) +{ + struct list_head *h = priv; + struct match_item *i = calloc(1, sizeof(*i)); + + if (i) + { + i->jsobj = res; + list_add_tail(&i->list, h); + } } static bool filter_json(int opt, struct json_object *jsobj, char *expr) { struct jp_state *state; - struct json_object *res = NULL; const char *prefix = NULL; + struct list_head matches; + struct match_item *item, *tmp; + struct json_object *res = NULL; state = jp_parse(expr); if (!state || state->error) { - fprintf(stderr, "In expression '%s': %s\n", - expr, state ? state->error : "Out of memory"); + fprintf(stderr, "Syntax error near {%s}: %s\n", + state ? expr + state->erroff : expr, + state ? state->error : "Out of memory"); goto out; } - res = jp_match(state->path, jsobj); + INIT_LIST_HEAD(&matches); - if (res) - { - prefix = (state->path->type == T_LABEL) ? state->path->str : NULL; + res = jp_match(state->path, jsobj, match_cb, &matches); + prefix = (state->path->type == T_LABEL) ? state->path->str : NULL; - switch (opt) - { - case 't': - export_type(res, prefix); - break; + switch (opt) + { + case 't': + export_type(&matches, prefix); + break; - default: - export_value(res, prefix); - break; - } + default: + export_value(&matches, prefix); + break; } + list_for_each_entry_safe(item, tmp, &matches, list) + free(item); + out: if (state) jp_free(state);