From d1ac51ff397845128c0097b574456a8e355fb148 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Sun, 29 Dec 2013 21:05:44 +0000 Subject: [PATCH] cli: additional flags and cleanup * add -q flag to suppress error messages * add -t flag to test type of result * clean up exit codes to indicate success; - 0 if all -t and -e expression yielded a result - 1 if at least one -t or -e expression didn't match - 125 when failed to open input file - 126 when failed to parse json input - 127 when the farser fails due to oom --- main.c | 172 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 113 insertions(+), 59 deletions(-) diff --git a/main.c b/main.c index 05e445c..7d530fa 100644 --- a/main.c +++ b/main.c @@ -15,6 +15,7 @@ */ #include +#include #include #include @@ -29,7 +30,7 @@ #include "matcher.h" static struct json_object * -parse_json(FILE *fd) +parse_json(FILE *fd, const char **error) { int len; char buf[256]; @@ -51,7 +52,16 @@ parse_json(FILE *fd) json_tokener_free(tok); - return err ? NULL : obj; + if (err) + { + if (err == json_tokener_continue) + err = json_tokener_error_parse_eof; + + *error = json_tokener_error_desc(err); + return NULL; + } + + return obj; } static void @@ -73,37 +83,18 @@ print_string(const char *s) } static void -export_json(struct json_object *jsobj, char *expr) +export_value(struct json_object *jsobj, const char *prefix) { - bool first; - struct jp_state *state; - struct json_object *res; - const char *prefix; - - state = jp_parse(expr); - - if (!state || state->error) - { - fprintf(stderr, "In expression '%s': %s\n", - expr, state ? state->error : "Out of memory"); - - goto out; - } - - res = jp_match(state->path, jsobj); + int n, len; + bool first = true; - if (state->path->type == T_LABEL) + if (prefix) { - prefix = state->path->str; - - switch (json_object_get_type(res)) + switch (json_object_get_type(jsobj)) { case json_type_object: - printf("export %s_TYPE=object; ", prefix); - - first = true; - printf("export %s_KEYS=", prefix); - json_object_object_foreach(res, key, val) + printf("export %s=", prefix); + json_object_object_foreach(jsobj, key, val) { if (!val) continue; @@ -115,68 +106,118 @@ export_json(struct json_object *jsobj, char *expr) first = false; } printf("; "); - - //printf("export %s=", prefix); - //print_string(json_object_to_json_string(res)); - //printf("; "); - break; case json_type_array: - printf("export %s_TYPE=array; ", prefix); - printf("export %s_LENGTH=%d; ", - prefix, json_object_array_length(res)); + printf("export %s=", prefix); + for (n = 0, len = json_object_array_length(jsobj); n < len; n++) + { + if (!first) + printf("\\ "); - //printf("export %s=", prefix); - //print_string(json_object_to_json_string(res)); - //printf("; "); + printf("%d", n); + first = false; + } + printf("; "); break; case json_type_boolean: - printf("export %s_TYPE=bool; ", prefix); - printf("export %s=%d; ", prefix, json_object_get_boolean(res)); + printf("export %s=%d; ", prefix, json_object_get_boolean(jsobj)); break; case json_type_int: - printf("export %s_TYPE=int; ", prefix); - printf("export %s=%d; ", prefix, json_object_get_int(res)); + printf("export %s=%d; ", prefix, json_object_get_int(jsobj)); break; case json_type_double: - printf("export %s_TYPE=double; ", prefix); - printf("export %s=%f; ", prefix, json_object_get_double(res)); + printf("export %s=%f; ", prefix, json_object_get_double(jsobj)); break; case json_type_string: - printf("export %s_TYPE=string; ", prefix); printf("export %s=", prefix); - print_string(json_object_get_string(res)); + print_string(json_object_get_string(jsobj)); printf("; "); break; case json_type_null: - printf("unset %s %s_TYPE %s_LENGTH %s_KEYS; ", - prefix, prefix, prefix, prefix); break; } } else { - printf("%s\n", json_object_to_json_string(res)); + printf("%s\n", json_object_to_json_string(jsobj)); + } +} + +static void +export_type(struct json_object *jsobj, const char *prefix) +{ + const char *types[] = { + "null", + "boolean", + "double", + "int", + "object", + "array", + "string" + }; + + if (prefix) + printf("export %s=%s; ", prefix, types[json_object_get_type(jsobj)]); + else + printf("%s\n", types[json_object_get_type(jsobj)]); +} + +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; + + state = jp_parse(expr); + + if (!state || state->error) + { + fprintf(stderr, "In expression '%s': %s\n", + expr, state ? state->error : "Out of memory"); + + goto out; + } + + res = jp_match(state->path, jsobj); + + if (res) + { + prefix = (state->path->type == T_LABEL) ? state->path->str : NULL; + + switch (opt) + { + case 't': + export_type(res, prefix); + break; + + default: + export_value(res, prefix); + break; + } } out: if (state) jp_free(state); + + return !!res; } int main(int argc, char **argv) { - int opt; + int opt, rv = 0; FILE *input = stdin; struct json_object *jsobj = NULL; + const char *jserr = NULL; - while ((opt = getopt(argc, argv, "i:e:")) != -1) + while ((opt = getopt(argc, argv, "i:e:t:q")) != -1) { switch (opt) { @@ -188,32 +229,45 @@ int main(int argc, char **argv) fprintf(stderr, "Failed to open %s: %s\n", optarg, strerror(errno)); - exit(1); + rv = 125; + goto out; } break; + case 't': case 'e': if (!jsobj) { - jsobj = parse_json(input); + jsobj = parse_json(input, &jserr); if (!jsobj) { - fprintf(stderr, "Failed to parse json data\n"); - exit(2); + fprintf(stderr, "Failed to parse json data: %s\n", + jserr); + + rv = 126; + goto out; } } - export_json(jsobj, optarg); + if (!filter_json(opt, jsobj, optarg)) + rv = 1; + + break; + + case 'q': + fclose(stderr); break; } } +out: if (jsobj) json_object_put(jsobj); - fclose(input); + if (input != stdin) + fclose(input); - return 0; + return rv; } -- 2.25.1