extend resume api to parser
This commit is contained in:
parent
07836d5d58
commit
dd302eb7b4
2 changed files with 43 additions and 29 deletions
|
@ -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)).
|
|
@ -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),
|
|
||||||
case Config#config.incomplete_handler of
|
|
||||||
false ->
|
|
||||||
{incomplete, fun(end_stream) ->
|
{incomplete, fun(end_stream) ->
|
||||||
case State([end_json],
|
case resume([end_json], State, Handler, Stack, Config) of
|
||||||
Handler,
|
{incomplete, _} -> ?error(State, [], Handler, Stack, Config);
|
||||||
Stack,
|
Else -> Else
|
||||||
Config) of
|
end;
|
||||||
{incomplete, _} -> ?error(State, [], Handler, Stack, Config)
|
(Tokens) ->
|
||||||
; Events -> Events
|
resume(Tokens, State, Handler, Stack, Config)
|
||||||
end
|
|
||||||
; (Tokens) ->
|
|
||||||
State(Tokens, Handler, Stack, Config)
|
|
||||||
end
|
end
|
||||||
};
|
};
|
||||||
F -> F([], {parser, State, Handler, Stack}, jsx_utils:config_to_list(Config))
|
incomplete(State, Handler, Stack, Config=#config{incomplete_handler=F}) ->
|
||||||
end
|
F([], {parser, State, Handler, Stack}, jsx_utils:config_to_list(Config)).
|
||||||
).
|
|
||||||
-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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue