*/
#include <stdio.h>
+#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include "matcher.h"
static struct json_object *
-parse_json(FILE *fd)
+parse_json(FILE *fd, const char **error)
{
int len;
char buf[256];
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
}
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;
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)
{
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;
}