1
0
mirror of https://github.com/stedolan/jq.git synced 2024-05-11 05:55:39 +00:00

Add Streaming parser (--stream)

Streaming means that outputs are produced as soon as possible.  With the
`foreach` syntax one can write programs which reduce portions of the
streaming parse of a large input (reduce into proper JSON values, for
example), and discard the rest, processing incrementally.

This:

    $ jq -c --stream .

should produce the same output as this:

    $ jq -c '. as $dot | path(..) as $p | $dot | getpath($p) | [$p,.]'

The output of `jq --stream .` should be a sequence of`[[<path>],<leaf>]`
and `[[<path>]]` values.  The latter indicate that the array/object at
that path ended.

Scalars and empty arrays and objects are leaf values for this purpose.

For example, a truncated input produces a path as soon as possible, then
later the error:

    $ printf '[0,\n'|./jq -c --stream .
    [[0],0]
    parse error: Unfinished JSON term at EOF at line 3, column 0
    $
This commit is contained in:
Nicolas Williams
2014-12-22 23:06:27 -06:00
parent 906d2537b9
commit 5bfb9781f7
10 changed files with 480 additions and 80 deletions

View File

@@ -862,6 +862,18 @@ static jv f_modulemeta(jq_state *jq, jv a) {
return load_module_meta(jq, a);
}
static jv f_input(jq_state *jq, jv input) {
jv_free(input);
jq_input_cb cb;
void *data;
jq_get_input_cb(jq, &cb, &data);
jv v = cb(jq, data);
if (jv_is_valid(v) || jv_invalid_has_msg(jv_copy(v)))
return v;
return jv_invalid_with_msg(jv_string("break"));
}
#define LIBM_DD(name) \
{(cfunction_ptr)f_ ## name, "_" #name, 1},
@@ -912,6 +924,7 @@ static const struct cfunction function_list[] = {
{(cfunction_ptr)f_env, "env", 1},
{(cfunction_ptr)f_match, "_match_impl", 4},
{(cfunction_ptr)f_modulemeta, "modulemeta", 1},
{(cfunction_ptr)f_input, "_input", 1},
};
#undef LIBM_DD
@@ -1014,6 +1027,7 @@ static const char* const jq_builtins[] = {
"def nulls: select(type == \"null\");",
"def values: select(. != null);",
"def scalars: select(. == null or . == true or . == false or type == \"number\" or type == \"string\");",
"def scalars_or_empty: select(. == null or . == true or . == false or type == \"number\" or type == \"string\" or ((type==\"array\" or type==\"object\") and length==0));",
"def leaf_paths: paths(scalars);",
"def join($x): reduce .[] as $i (\"\"; . + (if . == \"\" then $i else $x + $i end));",
"def flatten: reduce .[] as $i ([]; if $i | type == \"array\" then . + ($i | flatten) else . + [$i] end);",