diff --git a/spa/tools/spa-json-dump.c b/spa/tools/spa-json-dump.c index afd9569f6..8745cc1da 100644 --- a/spa/tools/spa-json-dump.c +++ b/spa/tools/spa-json-dump.c @@ -11,21 +11,56 @@ #include #include #include +#include #include #include #include -#define REJECT "\"\\'=:,{}[]()#" +#define DEFAULT_INDENT 2 struct data { + const char *filename; FILE *file; + + void *data; + size_t size; + int indent; bool simple_string; const char *comma; const char *key_sep; }; +#define OPTIONS "hi:s" +static const struct option long_options[] = { + { "help", no_argument, NULL, 'h'}, + + { "indent", required_argument, NULL, 'i' }, + { "spa", no_argument, NULL, 's' }, + + { NULL, 0, NULL, 0 } +}; + +static void show_usage(struct data *d, const char *name, bool is_error) +{ + FILE *fp; + + fp = is_error ? stderr : stdout; + + fprintf(fp, "%s [options] [spa-json-file]\n", name); + fprintf(fp, + " -h, --help Show this help\n" + "\n"); + fprintf(fp, + " -i --indent set indent (default %d)\n" + " -s --spa use simplified SPA JSON\n" + "\n", + DEFAULT_INDENT); +} + +#define REJECT "\"\\'=:,{}[]()#" + static bool is_simple_string(const char *val, int len) { int i; @@ -141,59 +176,46 @@ static int dump(struct data *d, int indent, struct spa_json *it, const char *val return 0; } -static int process_json(const char *filename, void *buf, size_t size) +static int process_json(struct data *d) { - struct data d; int len, res; struct spa_json it; const char *value; - spa_zero(d); - if ((len = spa_json_begin(&it, buf, size, &value)) <= 0) { - fprintf(stderr, "not a valid file '%s': %s\n", filename, spa_strerror(len)); + if ((len = spa_json_begin(&it, d->data, d->size, &value)) <= 0) { + fprintf(stderr, "not a valid file '%s': %s\n", d->filename, spa_strerror(len)); return -EINVAL; } if (!spa_json_is_container(value, len)) { - spa_json_init(&it, buf, size); + spa_json_init(&it, d->data, d->size); value = NULL; len = 0; } - d.file = stdout; -#if 1 - d.simple_string = false; - d.comma = ","; - d.key_sep = ":"; - d.indent = 2; -#else - d.simple_string = true; - d.comma = ""; - d.key_sep = " ="; - d.indent = 4; -#endif - res = dump(&d, 0, &it, value, len); + res = dump(d, 0, &it, value, len); if (spa_json_next(&it, &value) < 0) res = -EINVAL; - fprintf(d.file, "\n"); - fflush(d.file); + fprintf(d->file, "\n"); + fflush(d->file); if (res < 0) { struct spa_error_location loc; - if (spa_json_get_error(&it, buf, &loc)) + if (spa_json_get_error(&it, d->data, &loc)) spa_debug_file_error_location(stderr, &loc, "syntax error in file '%s': %s", - filename, loc.reason); + d->filename, loc.reason); else - fprintf(stderr, "error parsing file '%s': %s\n", filename, spa_strerror(res)); + fprintf(stderr, "error parsing file '%s': %s\n", + d->filename, spa_strerror(res)); return -EINVAL; } return 0; } -static int process_stdin(void) +static int process_stdin(struct data *d) { uint8_t *buf = NULL, *p; size_t alloc = 0, size = 0, read_size, res; @@ -217,8 +239,10 @@ static int process_stdin(void) fprintf(stderr, "error: %m\n"); goto error; } + d->data = buf; + d->size = size; - err = process_json("-", buf, size); + err = process_json(d); free(buf); return (err == 0) ? EXIT_SUCCESS : EXIT_FAILURE; @@ -230,38 +254,69 @@ error: int main(int argc, char *argv[]) { + int c; + int longopt_index = 0; int fd, res, exit_code = EXIT_FAILURE; - void *data; + struct data d; struct stat sbuf; - if (argc < 1) { - fprintf(stderr, "usage: %s [spa-json-file]\n", argv[0]); - goto error; - } - if (argc == 1) - return process_stdin(); - if ((fd = open(argv[1], O_CLOEXEC | O_RDONLY)) < 0) { - fprintf(stderr, "error opening file '%s': %m\n", argv[1]); - goto error; - } - if (fstat(fd, &sbuf) < 0) { - fprintf(stderr, "error statting file '%s': %m\n", argv[1]); - goto error_close; - } - if ((data = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) { - fprintf(stderr, "error mmapping file '%s': %m\n", argv[1]); - goto error_close; + spa_zero(d); + d.file = stdout; + + d.filename = "-"; + d.simple_string = false; + d.comma = ","; + d.key_sep = ":"; + d.indent = DEFAULT_INDENT; + + while ((c = getopt_long(argc, argv, OPTIONS, long_options, &longopt_index)) != -1) { + switch (c) { + case 'h' : + show_usage(&d, argv[0], false); + return 0; + case 'i': + d.indent = atoi(optarg); + break; + case 's': + d.simple_string = true; + d.comma = ""; + d.key_sep = " ="; + break; + default: + show_usage(&d, argv[0], true); + return -1; + } } - res = process_json(argv[1], data, sbuf.st_size); + if (optind < argc) + d.filename = argv[optind++]; + + if (spa_streq(d.filename, "-")) + return process_stdin(&d); + + ((fd = open(d.filename, O_CLOEXEC | O_RDONLY)) < 0) { + fprintf(stderr, "error opening file '%s': %m\n", d.filename); + goto error; + } + if (fstat(fd, &sbuf) < 0) { + fprintf(stderr, "error statting file '%s': %m\n", d.filename); + goto error_close; + } + if ((d.data = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) { + fprintf(stderr, "error mmapping file '%s': %m\n", d.filename); + goto error_close; + } + d.size = sbuf.st_size; + + res = process_json(&d); if (res < 0) exit_code = EXIT_FAILURE; else exit_code = EXIT_SUCCESS; - munmap(data, sbuf.st_size); + munmap(d.data, sbuf.st_size); error_close: - close(fd); + close(fd); error: return exit_code; }