From c25bb499022089fa5d37e8a933eca72bf9286eae Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Wed, 13 Aug 2014 23:00:35 -0700 Subject: [PATCH] use `end_json` to end streaming when in streaming mode in addition to `end_stream` --- CHANGES.md | 4 ++++ README.md | 6 +++--- src/jsx.erl | 31 +++++++++++++++++++++++++++++-- src/jsx_decoder.erl | 2 +- src/jsx_parser.erl | 2 +- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ca54bff..0503069 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,7 @@ +v2.1 + +* force the end of streams with `end_json` in addition to `end_stream` + v2.0.4 * more typespec adjustments diff --git a/README.md b/README.md index d497a3a..9930dc2 100644 --- a/README.md +++ b/README.md @@ -264,16 +264,16 @@ memory however, it is important to recognize that **jsx** is conservative by default. **jsx** will not consider the parsing complete even when input is exhausted and the json text is unambiguously incomplete. to end parsing call the `incomplete` function with the -argument `end_stream` like: +argument `end_stream` (or `end_json`) like: ```erlang 1> {incomplete, F} = jsx:decode(<<"[">>, [stream]). {incomplete,#Fun} -2> F(end_stream). +2> F(end_stream). % can also be `F(end_json)` ** exception error: bad argument 3> {incomplete, G} = F(<<"]">>). {incomplete,#Fun} -4> G(end_stream). +4> G(end_stream). % can also be `G(end_json)` [] ``` diff --git a/src/jsx.erl b/src/jsx.erl index 8d16abc..7c574db 100644 --- a/src/jsx.erl +++ b/src/jsx.erl @@ -107,14 +107,14 @@ is_term(Source) -> is_term(Source, []). is_term(Source, Config) -> jsx_verify:is_term(Source, Config). --type decoder() :: fun((json_text() | end_stream) -> any()). +-type decoder() :: fun((json_text() | end_stream | end_json) -> any()). -spec decoder(Handler::module(), State::any(), Config::list()) -> decoder(). decoder(Handler, State, Config) -> jsx_decoder:decoder(Handler, State, Config). --type encoder() :: fun((json_term() | end_stream) -> any()). +-type encoder() :: fun((json_term() | end_stream | end_json) -> any()). -spec encoder(Handler::module(), State::any(), Config::list()) -> encoder(). @@ -464,5 +464,32 @@ encode_test_() -> } || {Title, _, Term, Events} <- Data ]. +end_stream_test_() -> + Tokens = [start_object, end_object, end_json], + [ + {"encoder end_stream", ?_assertEqual( + Tokens, + begin + {incomplete, F} = (jsx:parser(jsx, [], [stream]))([start_object, end_object]), + F(end_stream) + end + )}, + {"encoder end_json", ?_assertEqual( + Tokens, + begin + {incomplete, F} = (jsx:parser(jsx, [], [stream]))([start_object, end_object]), + F(end_json) + end + )}, + {"decoder end_stream", ?_assertEqual( + Tokens, + begin {incomplete, F} = (jsx:decoder(jsx, [], [stream]))(<<"{}">>), F(end_stream) end + )}, + {"decoder end_json", ?_assertEqual( + Tokens, + begin {incomplete, F} = (jsx:decoder(jsx, [], [stream]))(<<"{}">>), F(end_json) end + )} + ]. + -endif. diff --git a/src/jsx_decoder.erl b/src/jsx_decoder.erl index 6848140..3f97d76 100644 --- a/src/jsx_decoder.erl +++ b/src/jsx_decoder.erl @@ -150,7 +150,7 @@ incomplete(State, Rest, Handler, Acc, Stack, Config = #config{stream=false}) -> incomplete(State, Rest, Handler, Acc, Stack, Config = #config{incomplete_handler=false}) -> {incomplete, fun(Stream) when is_binary(Stream) -> resume(<>, State, Handler, Acc, Stack, Config); - (end_stream) -> + (End) when End == end_stream; End == end_json -> case resume(<>, State, Handler, Acc, Stack, Config#config{stream=false}) of {incomplete, _} -> ?error(State, Rest, Handler, Acc, Stack, Config); Else -> Else diff --git a/src/jsx_parser.erl b/src/jsx_parser.erl index 1daa2ef..7c9af6b 100644 --- a/src/jsx_parser.erl +++ b/src/jsx_parser.erl @@ -71,7 +71,7 @@ resume(Rest, State, Handler, Stack, Config) -> incomplete(State, Handler, Stack, Config=#config{stream=false}) -> ?error(State, [], Handler, Stack, Config); incomplete(State, Handler, Stack, Config=#config{incomplete_handler=false}) -> - {incomplete, fun(end_stream) -> + {incomplete, fun(End) when End == end_stream; End == end_json -> case resume([end_json], State, Handler, Stack, Config) of {incomplete, _} -> ?error(State, [], Handler, Stack, Config); Else -> Else