summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Williams <nico@cryptonector.com>2013-05-06 17:25:19 -0500
committerNicolas Williams <nico@cryptonector.com>2013-05-23 13:52:06 -0500
commit03598bb5d687e3e21dd65cd49386645d9c3a5807 (patch)
treee5cc6c4e13c819a96cea19b094da0b3ab52a6431
parent0535e724a274818f0ef7fab74d5a59a32fd78ac9 (diff)
Add --argfile variant of --arg (issue #117)
This is useful when one has a database (in JSON form) to query using jq input data. % echo '{"a":1, "c":5}' > db.json % echo '"c"'|./jq --argfile f /tmp/a '$f[.]' 5 % echo '"a"'|./jq --argfile f /tmp/a '$f[.]' 1 % echo '"b"'|./jq --argfile f /tmp/a '$f[.]' null %
-rw-r--r--docs/content/3.manual/manual.yml8
-rw-r--r--main.c42
2 files changed, 46 insertions, 4 deletions
diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml
index 9b8a7b4a..df3c177e 100644
--- a/docs/content/3.manual/manual.yml
+++ b/docs/content/3.manual/manual.yml
@@ -127,6 +127,14 @@ sections:
variable. If you run jq with `--arg foo bar`, then `$foo` is
available in the program and has the value `"bar"`.
+ * `--argfile name filename`:
+
+ This option passes the first value from the named file as a
+ value to the jq program as a predefined variable. If you run jq
+ with `--argfile foo bar`, then `$foo` is available in the
+ program and has the value resulting from parsing the content of
+ the file named `bar`.
+
- title: Basic filters
entries:
- title: "`.`"
diff --git a/main.c b/main.c
index 73359ffe..42e309a9 100644
--- a/main.c
+++ b/main.c
@@ -92,18 +92,32 @@ static void process(jv value, int flags) {
jq_teardown(&jq);
}
-static jv slurp_file(const char* filename) {
+static jv slurp_file(const char* filename, int raw) {
FILE* file = fopen(filename, "r");
+ struct jv_parser parser;
+ jv data;
if (!file) {
return jv_invalid_with_msg(jv_string_fmt("Could not open %s: %s",
filename,
strerror(errno)));
}
- jv data = jv_string("");
+ if (raw) {
+ data = jv_string("");
+ } else {
+ data = jv_array();
+ jv_parser_init(&parser);
+ }
while (!feof(file) && !ferror(file)) {
char buf[4096];
size_t n = fread(buf, 1, sizeof(buf), file);
- data = jv_string_concat(data, jv_string_sized(buf, (int)n));
+ if (raw) {
+ data = jv_string_concat(data, jv_string_sized(buf, (int)n));
+ } else {
+ jv_parser_set_buf(&parser, buf, strlen(buf), !feof(file));
+ jv value;
+ while (jv_is_valid((value = jv_parser_next(&parser))))
+ data = jv_array_append(data, value);
+ }
}
int badread = ferror(file);
fclose(file);
@@ -197,6 +211,26 @@ int main(int argc, char* argv[]) {
arg = jv_object_set(arg, jv_string("value"), jv_string(argv[i+2]));
program_arguments = jv_array_append(program_arguments, arg);
i += 2; // skip the next two arguments
+ } else if (isoption(argv[i], 0, "argfile")) {
+ if (i >= argc - 2) {
+ fprintf(stderr, "%s: --argfile takes two parameters (e.g. -a varname filename)\n", progname);
+ die();
+ }
+ jv arg = jv_object();
+ arg = jv_object_set(arg, jv_string("name"), jv_string(argv[i+1]));
+ jv data = slurp_file(argv[i+2], 0);
+ if (!jv_is_valid(data)) {
+ data = jv_invalid_get_msg(data);
+ fprintf(stderr, "%s: Bad JSON in --argfile %s %s: %s\n", progname,
+ argv[i+1], argv[i+2], jv_string_value(data));
+ jv_free(data);
+ return 1;
+ }
+ if (jv_array_length(data) == 1)
+ data = jv_array_get(data, 0);
+ arg = jv_object_set(arg, jv_string("value"), data);
+ program_arguments = jv_array_append(program_arguments, arg);
+ i += 2; // skip the next two arguments
} else if (isoption(argv[i], 0, "debug-dump-disasm")) {
options |= DUMP_DISASM;
} else if (isoption(argv[i], 0, "debug-trace")) {
@@ -220,7 +254,7 @@ int main(int argc, char* argv[]) {
}
if (options & FROM_FILE) {
- jv data = slurp_file(program);
+ jv data = slurp_file(program, 1);
if (!jv_is_valid(data)) {
data = jv_invalid_get_msg(data);
fprintf(stderr, "%s: %s\n", progname, jv_string_value(data));