extend resume api to parser

This commit is contained in:
alisdair sullivan 2013-03-05 21:10:33 -08:00
parent 07836d5d58
commit dd302eb7b4
2 changed files with 43 additions and 29 deletions

View file

@ -27,11 +27,11 @@
-export([is_json/1, is_json/2, is_term/1, is_term/2]). -export([is_json/1, is_json/2, is_term/1, is_term/2]).
-export([format/1, format/2, minify/1, prettify/1]). -export([format/1, format/2, minify/1, prettify/1]).
-export([encoder/3, decoder/3, parser/3]). -export([encoder/3, decoder/3, parser/3]).
-export([resume/3]).
%% old api %% old api
-export([term_to_json/1, term_to_json/2, json_to_term/1, json_to_term/2]). -export([term_to_json/1, term_to_json/2, json_to_term/1, json_to_term/2]).
-export([to_json/1, to_json/2]). -export([to_json/1, to_json/2]).
-export([to_term/1, to_term/2]). -export([to_term/1, to_term/2]).
-export([resume/3]).
-export_type([json_term/0, json_text/0, token/0]). -export_type([json_term/0, json_text/0, token/0]).
-export_type([encoder/0, decoder/0, parser/0, internal_state/0]). -export_type([encoder/0, decoder/0, parser/0, internal_state/0]).
@ -157,7 +157,9 @@ parser(Handler, State, Config) -> jsx_parser:parser(Handler, State, Config).
-opaque internal_state() :: tuple(). -opaque internal_state() :: tuple().
-spec resume(Term::json_text(), InternalState::internal_state(), Config::list()) -> any(). -spec resume(Term::json_text() | token(), InternalState::internal_state(), Config::list()) -> any().
resume(Term, {decoder, State, Handler, Acc, Stack}, Config) -> resume(Term, {decoder, State, Handler, Acc, Stack}, Config) ->
jsx_decoder:resume(Term, State, Handler, Acc, Stack, jsx_utils:parse_config(Config)). jsx_decoder:resume(Term, State, Handler, Acc, Stack, jsx_utils:parse_config(Config));
resume(Term, {parser, State, Handler, Stack}, Config) ->
jsx_parser:resume(Term, State, Handler, Stack, jsx_utils:parse_config(Config)).

View file

@ -23,7 +23,7 @@
-module(jsx_parser). -module(jsx_parser).
-export([parser/3]). -export([parser/3, resume/5]).
-spec parser(Handler::module(), State::any(), Config::jsx:config()) -> jsx:parser(). -spec parser(Handler::module(), State::any(), Config::jsx:config()) -> jsx:parser().
@ -32,6 +32,26 @@ parser(Handler, State, Config) ->
fun(Tokens) -> value(Tokens, {Handler, Handler:init(State)}, [], jsx_utils:parse_config(Config)) end. fun(Tokens) -> value(Tokens, {Handler, Handler:init(State)}, [], jsx_utils:parse_config(Config)) end.
%% resume allows continuation from interrupted decoding without having to explicitly export
%% all states
-spec resume(
Rest::binary(),
State::atom(),
Handler::{atom(), any()},
Stack::list(atom()),
Config::jsx:config()
) -> jsx:parser().
resume(Rest, State, Handler, Stack, Config) ->
case State of
value -> value(Rest, Handler, Stack, Config);
object -> object(Rest, Handler, Stack, Config);
array -> array(Rest, Handler, Stack, Config);
maybe_done -> maybe_done(Rest, Handler, Stack, Config);
done -> done(Rest, Handler, Stack, Config)
end.
-include("jsx_config.hrl"). -include("jsx_config.hrl").
@ -47,26 +67,18 @@ parser(Handler, State, Config) ->
-endif. -endif.
-ifndef(incomplete). incomplete(State, Handler, Stack, Config=#config{incomplete_handler=false}) ->
-define(incomplete(State, Handler, Stack, Config), {incomplete, fun(end_stream) ->
case Config#config.incomplete_handler of case resume([end_json], State, Handler, Stack, Config) of
false -> {incomplete, _} -> ?error(State, [], Handler, Stack, Config);
{incomplete, fun(end_stream) -> Else -> Else
case State([end_json], end;
Handler, (Tokens) ->
Stack, resume(Tokens, State, Handler, Stack, Config)
Config) of end
{incomplete, _} -> ?error(State, [], Handler, Stack, Config) };
; Events -> Events incomplete(State, Handler, Stack, Config=#config{incomplete_handler=F}) ->
end F([], {parser, State, Handler, Stack}, jsx_utils:config_to_list(Config)).
; (Tokens) ->
State(Tokens, Handler, Stack, Config)
end
};
F -> F([], {parser, State, Handler, Stack}, jsx_utils:config_to_list(Config))
end
).
-endif.
handle_event([], Handler, _Config) -> Handler; handle_event([], Handler, _Config) -> Handler;
@ -123,7 +135,7 @@ value([{string, String}|Tokens], Handler, Stack, Config) when is_binary(String)
value([String|Tokens], Handler, Stack, Config) when is_binary(String) -> value([String|Tokens], Handler, Stack, Config) when is_binary(String) ->
value([{string, String}] ++ Tokens, Handler, Stack, Config); value([{string, String}] ++ Tokens, Handler, Stack, Config);
value([], Handler, Stack, Config) -> value([], Handler, Stack, Config) ->
?incomplete(value, Handler, Stack, Config); incomplete(value, Handler, Stack, Config);
value(BadTokens, Handler, Stack, Config) when is_list(BadTokens) -> value(BadTokens, Handler, Stack, Config) when is_list(BadTokens) ->
?error(value, BadTokens, Handler, Stack, Config); ?error(value, BadTokens, Handler, Stack, Config);
value(Token, Handler, Stack, Config) -> value(Token, Handler, Stack, Config) ->
@ -144,14 +156,14 @@ object([Key|Tokens], Handler, Stack, Config) when is_atom(Key); is_binary(Key) -
Error -> Error Error -> Error
end; end;
object([], Handler, Stack, Config) -> object([], Handler, Stack, Config) ->
?incomplete(object, Handler, Stack, Config); incomplete(object, Handler, Stack, Config);
object(Token, Handler, Stack, Config) -> object(Token, Handler, Stack, Config) ->
object([Token], Handler, Stack, Config). object([Token], Handler, Stack, Config).
array([end_array|Tokens], Handler, [array|Stack], Config) -> array([end_array|Tokens], Handler, [array|Stack], Config) ->
maybe_done(Tokens, handle_event(end_array, Handler, Config), Stack, Config); maybe_done(Tokens, handle_event(end_array, Handler, Config), Stack, Config);
array([], Handler, Stack, Config) -> array([], Handler, Stack, Config) ->
?incomplete(array, Handler, Stack, Config); incomplete(array, Handler, Stack, Config);
array(Tokens, Handler, Stack, Config) when is_list(Tokens) -> array(Tokens, Handler, Stack, Config) when is_list(Tokens) ->
value(Tokens, Handler, Stack, Config); value(Tokens, Handler, Stack, Config);
array(Token, Handler, Stack, Config) -> array(Token, Handler, Stack, Config) ->
@ -164,14 +176,14 @@ maybe_done(Tokens, Handler, [object|_] = Stack, Config) when is_list(Tokens) ->
maybe_done(Tokens, Handler, [array|_] = Stack, Config) when is_list(Tokens) -> maybe_done(Tokens, Handler, [array|_] = Stack, Config) when is_list(Tokens) ->
array(Tokens, Handler, Stack, Config); array(Tokens, Handler, Stack, Config);
maybe_done([], Handler, Stack, Config) -> maybe_done([], Handler, Stack, Config) ->
?incomplete(maybe_done, Handler, Stack, Config); incomplete(maybe_done, Handler, Stack, Config);
maybe_done(BadTokens, Handler, Stack, Config) when is_list(BadTokens) -> maybe_done(BadTokens, Handler, Stack, Config) when is_list(BadTokens) ->
?error(maybe_done, BadTokens, Handler, Stack, Config); ?error(maybe_done, BadTokens, Handler, Stack, Config);
maybe_done(Token, Handler, Stack, Config) -> maybe_done(Token, Handler, Stack, Config) ->
maybe_done([Token], Handler, Stack, Config). maybe_done([Token], Handler, Stack, Config).
done([], Handler, [], Config=#config{explicit_end=true}) -> done([], Handler, [], Config=#config{explicit_end=true}) ->
?incomplete(done, Handler, [], Config); incomplete(done, Handler, [], Config);
done(Tokens, Handler, [], Config) when Tokens == [end_json]; Tokens == [] -> done(Tokens, Handler, [], Config) when Tokens == [end_json]; Tokens == [] ->
{_, State} = handle_event(end_json, Handler, Config), {_, State} = handle_event(end_json, Handler, Config),
State; State;