summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2013-12-29 21:05:44 +0000
committerJo-Philipp Wich <jow@openwrt.org>2013-12-29 21:05:44 +0000
commitd1ac51ff397845128c0097b574456a8e355fb148 (patch)
tree701b45339e75e483533bb1c36cf6418dd7d31a5a
parentd0975f0ae61979633f4ef6537a8baa3e4c9c1fc3 (diff)
downloadjsonpath-d1ac51ff397845128c0097b574456a8e355fb148.tar.gz
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
-rw-r--r--main.c172
1 files 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 <stdio.h>
+#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
@@ -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;
}