unless iterate option is specified, jsx now buffers events internally before returning
This commit is contained in:
parent
986b60af37
commit
8bb0f66470
5 changed files with 143 additions and 100 deletions
47
src/jsx.erl
47
src/jsx.erl
|
@ -174,13 +174,19 @@ jsx_decoder_gen([Test|_] = Tests, [Encoding|Encodings]) ->
|
||||||
Flags = proplists:get_value(jsx_flags, Test, []),
|
Flags = proplists:get_value(jsx_flags, Test, []),
|
||||||
{generator,
|
{generator,
|
||||||
fun() ->
|
fun() ->
|
||||||
[{Name, ?_assertEqual(decode(JSON, Flags), JSX)}
|
[{Name ++ " iterative",
|
||||||
| {generator,
|
?_assertEqual(iterative_decode(JSON, Flags), JSX)}
|
||||||
|
| {generator,
|
||||||
fun() -> [{Name ++ " incremental", ?_assertEqual(
|
fun() -> [{Name ++ " incremental", ?_assertEqual(
|
||||||
incremental_decode(JSON, Flags), JSX)
|
incremental_decode(JSON, Flags), JSX)
|
||||||
} | jsx_decoder_gen(Tests, Encodings)]
|
} | {generator,
|
||||||
end
|
fun() ->
|
||||||
}
|
[{Name, ?_assertEqual(
|
||||||
|
decode(JSON, Flags), JSX)
|
||||||
|
} | jsx_decoder_gen(Tests, Encodings)]
|
||||||
|
end}
|
||||||
|
]
|
||||||
|
end}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
}.
|
}.
|
||||||
|
@ -219,20 +225,33 @@ parse_tests([], _Dir, Acc) ->
|
||||||
|
|
||||||
decode(JSON, Flags) ->
|
decode(JSON, Flags) ->
|
||||||
P = jsx:decoder(Flags),
|
P = jsx:decoder(Flags),
|
||||||
decode_loop(P(JSON), []).
|
case P(JSON) of
|
||||||
|
{error, {badjson, _}} -> {error, badjson}
|
||||||
|
; {jsx, incomplete, More} ->
|
||||||
|
case More(end_stream) of
|
||||||
|
{error, {badjson, _}} -> {error, badjson}
|
||||||
|
; {jsx, T, _} -> T
|
||||||
|
end
|
||||||
|
; {jsx, T, _} -> T
|
||||||
|
end.
|
||||||
|
|
||||||
decode_loop({jsx, end_json, _Next}, Acc) ->
|
|
||||||
|
iterative_decode(JSON, Flags) ->
|
||||||
|
P = jsx:decoder([iterate] ++ Flags),
|
||||||
|
iterative_decode_loop(P(JSON), []).
|
||||||
|
|
||||||
|
iterative_decode_loop({jsx, end_json, _Next}, Acc) ->
|
||||||
lists:reverse([end_json] ++ Acc);
|
lists:reverse([end_json] ++ Acc);
|
||||||
decode_loop({jsx, incomplete, More}, Acc) ->
|
iterative_decode_loop({jsx, incomplete, More}, Acc) ->
|
||||||
decode_loop(More(end_stream), Acc);
|
iterative_decode_loop(More(end_stream), Acc);
|
||||||
decode_loop({jsx, E, Next}, Acc) ->
|
iterative_decode_loop({jsx, E, Next}, Acc) ->
|
||||||
decode_loop(Next(), [E] ++ Acc);
|
iterative_decode_loop(Next(), [E] ++ Acc);
|
||||||
decode_loop({error, {badjson, _Error}}, _Acc) ->
|
iterative_decode_loop({error, {badjson, _Error}}, _Acc) ->
|
||||||
{error, badjson}.
|
{error, badjson}.
|
||||||
|
|
||||||
|
|
||||||
incremental_decode(<<C:1/binary, Rest/binary>>, Flags) ->
|
incremental_decode(<<C:1/binary, Rest/binary>>, Flags) ->
|
||||||
P = jsx:decoder(Flags),
|
P = jsx:decoder([iterate] ++ Flags),
|
||||||
incremental_decode_loop(P(C), Rest, []).
|
incremental_decode_loop(P(C), Rest, []).
|
||||||
|
|
||||||
incremental_decode_loop({jsx, incomplete, Next}, <<>>, Acc) ->
|
incremental_decode_loop({jsx, incomplete, Next}, <<>>, Acc) ->
|
||||||
|
@ -257,7 +276,7 @@ multi_decode_test_() ->
|
||||||
|
|
||||||
|
|
||||||
multi_decode(JSON, Flags) ->
|
multi_decode(JSON, Flags) ->
|
||||||
P = jsx:decoder(Flags ++ [multi_term]),
|
P = jsx:decoder([multi_term, iterate] ++ Flags),
|
||||||
multi_decode_loop(P(JSON), [[]]).
|
multi_decode_loop(P(JSON), [[]]).
|
||||||
|
|
||||||
multi_decode_loop({jsx, incomplete, _Next}, [[]|Acc]) ->
|
multi_decode_loop({jsx, incomplete, _Next}, [[]|Acc]) ->
|
||||||
|
|
|
@ -34,10 +34,47 @@
|
||||||
array/4,
|
array/4,
|
||||||
value/4,
|
value/4,
|
||||||
colon/4,
|
colon/4,
|
||||||
key/4
|
key/4,
|
||||||
|
string/5,
|
||||||
|
escape/5,
|
||||||
|
escaped_unicode/6,
|
||||||
|
low_surrogate/6,
|
||||||
|
low_surrogate_u/6,
|
||||||
|
low_surrogate/7,
|
||||||
|
negative/5,
|
||||||
|
zero/5,
|
||||||
|
integer/5,
|
||||||
|
initial_decimal/5,
|
||||||
|
decimal/5,
|
||||||
|
e/5,
|
||||||
|
ex/5,
|
||||||
|
exp/5,
|
||||||
|
tr/4,
|
||||||
|
tru/4,
|
||||||
|
true/4,
|
||||||
|
fa/4,
|
||||||
|
fal/4,
|
||||||
|
fals/4,
|
||||||
|
false/4,
|
||||||
|
nu/4,
|
||||||
|
nul/4,
|
||||||
|
null/4,
|
||||||
|
bad_json/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%% opts record for decoder
|
||||||
|
-record(opts, {
|
||||||
|
multi_term = false,
|
||||||
|
loose_unicode = false,
|
||||||
|
encoding = auto,
|
||||||
|
escape_forward_slash = false, %% does nothing, used by encoder
|
||||||
|
iterate = false
|
||||||
|
}).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-export([decoder/1]).
|
-export([decoder/1]).
|
||||||
-spec decoder(OptsList::jsx_opts()) -> jsx_decoder().
|
-spec decoder(OptsList::jsx_opts()) -> jsx_decoder().
|
||||||
|
|
||||||
|
@ -45,17 +82,13 @@
|
||||||
decoder(OptsList) ->
|
decoder(OptsList) ->
|
||||||
case parse_opts(OptsList) of
|
case parse_opts(OptsList) of
|
||||||
{error, badopt} -> {error, badopt}
|
{error, badopt} -> {error, badopt}
|
||||||
; Opts -> fun(JSON) -> start(JSON, iterate, [], Opts) end
|
; Opts ->
|
||||||
|
case Opts#opts.iterate of
|
||||||
|
true -> fun(JSON) -> start(JSON, iterate, [], Opts) end
|
||||||
|
; false -> fun(JSON) -> start(JSON, [], [], Opts) end
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
%% opts record for decoder
|
|
||||||
-record(opts, {
|
|
||||||
multi_term = false,
|
|
||||||
loose_unicode = false,
|
|
||||||
encoding = auto,
|
|
||||||
escape_forward_slash = false %% does nothing, used by encoder
|
|
||||||
}).
|
|
||||||
|
|
||||||
|
|
||||||
%% converts a proplist into a tuple
|
%% converts a proplist into a tuple
|
||||||
|
@ -68,6 +101,8 @@ parse_opts([multi_term|Rest], Opts) ->
|
||||||
parse_opts(Rest, Opts#opts{multi_term=true});
|
parse_opts(Rest, Opts#opts{multi_term=true});
|
||||||
parse_opts([loose_unicode|Rest], Opts) ->
|
parse_opts([loose_unicode|Rest], Opts) ->
|
||||||
parse_opts(Rest, Opts#opts{loose_unicode=true});
|
parse_opts(Rest, Opts#opts{loose_unicode=true});
|
||||||
|
parse_opts([iterate|Rest], Opts) ->
|
||||||
|
parse_opts(Rest, Opts#opts{iterate=true});
|
||||||
parse_opts([{encoding, _}|Rest], Opts) ->
|
parse_opts([{encoding, _}|Rest], Opts) ->
|
||||||
parse_opts(Rest, Opts);
|
parse_opts(Rest, Opts);
|
||||||
parse_opts(_, _) ->
|
parse_opts(_, _) ->
|
||||||
|
@ -217,35 +252,36 @@ partial_utf(_) -> false.
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
|
|
||||||
-define(incomplete(Next),
|
incomplete(State, Bin, T, Args) ->
|
||||||
case ?partial_codepoint(Bin) of
|
case ?partial_codepoint(Bin) of
|
||||||
true ->
|
true ->
|
||||||
{jsx, incomplete, fun(end_stream) ->
|
emit([incomplete], {State, Bin, T, Args})
|
||||||
{error, {badjson, Bin}}
|
|
||||||
; (Stream) ->
|
|
||||||
Next
|
|
||||||
end}
|
|
||||||
; false -> {error, {badjson, Bin}}
|
; false -> {error, {badjson, Bin}}
|
||||||
end
|
end.
|
||||||
).
|
|
||||||
|
|
||||||
%% emit takes a list of `events` to present to client code and formats them
|
%% emit takes a list of `events` to present to client code and formats them
|
||||||
%% appropriately
|
%% appropriately
|
||||||
emit([incomplete], {State, Rest, iterate, Args}) ->
|
emit([], {State, Rest, T, Args}) ->
|
||||||
|
erlang:apply(?MODULE, State, [Rest, T] ++ Args);
|
||||||
|
emit([incomplete], {State, Rest, T, Args}) ->
|
||||||
{jsx, incomplete, fun(end_stream) ->
|
{jsx, incomplete, fun(end_stream) ->
|
||||||
{error, {badjson, <<>>}}
|
{error, {badjson, <<>>}}
|
||||||
; (Stream) ->
|
; (Stream) ->
|
||||||
erlang:apply(?MODULE,
|
erlang:apply(?MODULE,
|
||||||
State,
|
State,
|
||||||
[<<Rest/binary, Stream/binary>>, iterate] ++ Args
|
[<<Rest/binary, Stream/binary>>, T] ++ Args
|
||||||
)
|
)
|
||||||
end};
|
end};
|
||||||
emit([Event], {State, Rest, iterate, Args}) ->
|
emit([Event|Events], {_State, _Rest, iterate, _Args} = Next) ->
|
||||||
{jsx, Event, fun() ->
|
{jsx, Event, fun() -> emit(Events, Next) end};
|
||||||
erlang:apply(?MODULE, State, [Rest, iterate] ++ Args)
|
emit([end_json|Events], {_State, _Rest, T, _Args} = Next) ->
|
||||||
end};
|
{jsx, lists:reverse([end_json] ++ T), fun() -> emit(Events, Next) end};
|
||||||
emit([Event|Rest], {_State, _Rest, iterate, _Args} = Next) ->
|
emit([Event|Events], {State, Rest, T, Args}) ->
|
||||||
{jsx, Event, fun() -> emit(Rest, Next) end}.
|
emit(Events, {State, Rest, [Event] ++ T, Args}).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bad_json(Stream, _) -> {error, {badjson, Stream}}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -270,7 +306,7 @@ start(<<?zero/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
start(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_nonzero(S) ->
|
start(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_nonzero(S) ->
|
||||||
integer(Rest, T, Stack, Opts, [S]);
|
integer(Rest, T, Stack, Opts, [S]);
|
||||||
start(Bin, T, Stack, Opts) ->
|
start(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(start(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(start, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
maybe_done(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
maybe_done(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
|
@ -288,7 +324,7 @@ maybe_done(Rest, T, [], #opts{multi_term=true}=Opts) ->
|
||||||
maybe_done(Rest, T, [], Opts) ->
|
maybe_done(Rest, T, [], Opts) ->
|
||||||
done(Rest, T, Opts);
|
done(Rest, T, Opts);
|
||||||
maybe_done(Bin, T, Stack, Opts) ->
|
maybe_done(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(maybe_done(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(maybe_done, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
done(<<S/?utfx, Rest/binary>>, T, Opts) when ?is_whitespace(S) ->
|
done(<<S/?utfx, Rest/binary>>, T, Opts) when ?is_whitespace(S) ->
|
||||||
|
@ -296,7 +332,7 @@ done(<<S/?utfx, Rest/binary>>, T, Opts) when ?is_whitespace(S) ->
|
||||||
done(<<>>, T, Opts) ->
|
done(<<>>, T, Opts) ->
|
||||||
emit([end_json, incomplete], {done, <<>>, T, [Opts]});
|
emit([end_json, incomplete], {done, <<>>, T, [Opts]});
|
||||||
done(Bin, T, Opts) ->
|
done(Bin, T, Opts) ->
|
||||||
?incomplete(done(<<Bin/binary, Stream/binary>>, T, Opts)).
|
incomplete(done, Bin, T, [Opts]).
|
||||||
|
|
||||||
|
|
||||||
object(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
object(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
|
@ -306,7 +342,7 @@ object(<<?quote/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
object(<<?end_object/?utfx, Rest/binary>>, T, [key|Stack], Opts) ->
|
object(<<?end_object/?utfx, Rest/binary>>, T, [key|Stack], Opts) ->
|
||||||
emit([end_object], {maybe_done, Rest, T, [Stack, Opts]});
|
emit([end_object], {maybe_done, Rest, T, [Stack, Opts]});
|
||||||
object(Bin, T, Stack, Opts) ->
|
object(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(object(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(object, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
array(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
array(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
|
@ -332,7 +368,7 @@ array(<<?start_array/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
array(<<?end_array/?utfx, Rest/binary>>, T, [array|Stack], Opts) ->
|
array(<<?end_array/?utfx, Rest/binary>>, T, [array|Stack], Opts) ->
|
||||||
emit([end_array], {maybe_done, Rest, T, [Stack, Opts]});
|
emit([end_array], {maybe_done, Rest, T, [Stack, Opts]});
|
||||||
array(Bin, T, Stack, Opts) ->
|
array(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(array(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(array, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
value(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
value(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
|
@ -356,7 +392,7 @@ value(<<?start_object/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
value(<<?start_array/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
value(<<?start_array/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
emit([start_array], {array, Rest, T, [[array|Stack], Opts]});
|
emit([start_array], {array, Rest, T, [[array|Stack], Opts]});
|
||||||
value(Bin, T, Stack, Opts) ->
|
value(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(value(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(value, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
colon(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
colon(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
|
@ -364,7 +400,7 @@ colon(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
colon(<<?colon/?utfx, Rest/binary>>, T, [key|Stack], Opts) ->
|
colon(<<?colon/?utfx, Rest/binary>>, T, [key|Stack], Opts) ->
|
||||||
value(Rest, T, [object|Stack], Opts);
|
value(Rest, T, [object|Stack], Opts);
|
||||||
colon(Bin, T, Stack, Opts) ->
|
colon(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(colon(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(colon, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
key(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
key(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
|
@ -372,7 +408,7 @@ key(<<S/?utfx, Rest/binary>>, T, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
key(<<?quote/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
key(<<?quote/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
string(Rest, T, Stack, Opts);
|
string(Rest, T, Stack, Opts);
|
||||||
key(Bin, T, Stack, Opts) ->
|
key(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(key(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(key, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
%% string has an additional parameter, an accumulator (Acc) used to hold the
|
%% string has an additional parameter, an accumulator (Acc) used to hold the
|
||||||
|
@ -423,11 +459,7 @@ string(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc)
|
||||||
string(Bin, T, Stack, Opts, Acc) ->
|
string(Bin, T, Stack, Opts, Acc) ->
|
||||||
case partial_utf(Bin) of
|
case partial_utf(Bin) of
|
||||||
true ->
|
true ->
|
||||||
{jsx, incomplete, fun(end_stream) ->
|
emit([incomplete], {string, Bin, T, [Stack, Opts, Acc]})
|
||||||
{error, {badjson, Bin}}
|
|
||||||
; (Stream) ->
|
|
||||||
string(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)
|
|
||||||
end}
|
|
||||||
; false ->
|
; false ->
|
||||||
case Opts#opts.loose_unicode of
|
case Opts#opts.loose_unicode of
|
||||||
true -> noncharacter(Bin, T, Stack, Opts, Acc)
|
true -> noncharacter(Bin, T, Stack, Opts, Acc)
|
||||||
|
@ -543,7 +575,7 @@ escape(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc)
|
||||||
when S =:= ?quote; S =:= ?solidus; S =:= ?rsolidus ->
|
when S =:= ?quote; S =:= ?solidus; S =:= ?rsolidus ->
|
||||||
string(Rest, T, Stack, Opts, [S] ++ Acc);
|
string(Rest, T, Stack, Opts, [S] ++ Acc);
|
||||||
escape(Bin, T, Stack, Opts, Acc) ->
|
escape(Bin, T, Stack, Opts, Acc) ->
|
||||||
?incomplete(escape(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)).
|
incomplete(escape, Bin, T, [Stack, Opts, Acc]).
|
||||||
|
|
||||||
|
|
||||||
%% this code is ugly and unfortunate, but so is json's handling of escaped
|
%% this code is ugly and unfortunate, but so is json's handling of escaped
|
||||||
|
@ -579,9 +611,7 @@ escaped_unicode(<<S/?utfx, Rest/binary>>, T, Stack, Opts, String, Acc)
|
||||||
when ?is_hex(S) ->
|
when ?is_hex(S) ->
|
||||||
escaped_unicode(Rest, T, Stack, Opts, String, [S] ++ Acc);
|
escaped_unicode(Rest, T, Stack, Opts, String, [S] ++ Acc);
|
||||||
escaped_unicode(Bin, T, Stack, Opts, String, Acc) ->
|
escaped_unicode(Bin, T, Stack, Opts, String, Acc) ->
|
||||||
?incomplete(
|
incomplete(escaped_unicode, Bin, T, [Stack, Opts, String, Acc]).
|
||||||
escaped_unicode(<<Bin/binary, Stream/binary>>, T, Stack, Opts, String, Acc)
|
|
||||||
).
|
|
||||||
|
|
||||||
|
|
||||||
low_surrogate(<<?rsolidus/?utfx, Rest/binary>>, T, Stack, Opts, String, High) ->
|
low_surrogate(<<?rsolidus/?utfx, Rest/binary>>, T, Stack, Opts, String, High) ->
|
||||||
|
@ -596,9 +626,7 @@ low_surrogate(<<S/?utfx, Rest/binary>> = Bin, T, Stack, Opts, String, _) ->
|
||||||
{error, {badjson, <<S/?utfx, Rest/binary>>}}
|
{error, {badjson, <<S/?utfx, Rest/binary>>}}
|
||||||
end;
|
end;
|
||||||
low_surrogate(Bin, T, Stack, Opts, String, High) ->
|
low_surrogate(Bin, T, Stack, Opts, String, High) ->
|
||||||
?incomplete(
|
incomplete(low_surrogate, Bin, T, [Stack, Opts, String, High]).
|
||||||
low_surrogate(<<Bin/binary, Stream/binary>>, T, Stack, Opts, String, High)
|
|
||||||
).
|
|
||||||
|
|
||||||
|
|
||||||
low_surrogate_u(<<$u/?utfx, Rest/binary>>, T, Stack, Opts, String, H) ->
|
low_surrogate_u(<<$u/?utfx, Rest/binary>>, T, Stack, Opts, String, H) ->
|
||||||
|
@ -618,9 +646,7 @@ low_surrogate_u(<<S/?utfx, Rest/binary>> = Bin, T, Stack, Opts, String, _) ->
|
||||||
{error, {badjson, <<S/?utfx, Rest/binary>>}}
|
{error, {badjson, <<S/?utfx, Rest/binary>>}}
|
||||||
end;
|
end;
|
||||||
low_surrogate_u(Bin, T, Stack, Opts, String, H) ->
|
low_surrogate_u(Bin, T, Stack, Opts, String, H) ->
|
||||||
?incomplete(
|
incomplete(low_surrogate_u, Bin, T, [Stack, Opts, String, H]).
|
||||||
low_surrogate_u(<<Bin/binary, Stream/binary>>, T, Stack, Opts, String, H)
|
|
||||||
).
|
|
||||||
|
|
||||||
|
|
||||||
low_surrogate(<<D/?utfx, Rest/binary>>, T, Stack, Opts, String, [C, B, A], H)
|
low_surrogate(<<D/?utfx, Rest/binary>>, T, Stack, Opts, String, [C, B, A], H)
|
||||||
|
@ -651,11 +677,7 @@ low_surrogate(<<S/?utfx, Rest/binary>>, T, Stack, Opts, String, Acc, H)
|
||||||
when ?is_hex(S) ->
|
when ?is_hex(S) ->
|
||||||
low_surrogate(Rest, T, Stack, Opts, String, [S] ++ Acc, H);
|
low_surrogate(Rest, T, Stack, Opts, String, [S] ++ Acc, H);
|
||||||
low_surrogate(Bin, T, Stack, Opts, String, Acc, H) ->
|
low_surrogate(Bin, T, Stack, Opts, String, Acc, H) ->
|
||||||
?incomplete(
|
incomplete(low_surrogate, Bin, T, [Stack, Opts, String, Acc, H]).
|
||||||
low_surrogate(
|
|
||||||
<<Bin/binary, Stream/binary>>, T, Stack, Opts, String, Acc, H
|
|
||||||
)
|
|
||||||
).
|
|
||||||
|
|
||||||
|
|
||||||
%% stole this from the unicode spec
|
%% stole this from the unicode spec
|
||||||
|
@ -670,7 +692,7 @@ negative(<<$0/?utfx, Rest/binary>>, T, Stack, Opts, Acc) ->
|
||||||
negative(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
negative(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
||||||
integer(Rest, T, Stack, Opts, [S] ++ Acc);
|
integer(Rest, T, Stack, Opts, [S] ++ Acc);
|
||||||
negative(Bin, T, Stack, Opts, Acc) ->
|
negative(Bin, T, Stack, Opts, Acc) ->
|
||||||
?incomplete(negative(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)).
|
incomplete(negative, Bin, T, [Stack, Opts, Acc]).
|
||||||
|
|
||||||
|
|
||||||
zero(<<?end_object/?utfx, Rest/binary>>, T, [object|Stack], Opts, Acc) ->
|
zero(<<?end_object/?utfx, Rest/binary>>, T, [object|Stack], Opts, Acc) ->
|
||||||
|
@ -687,12 +709,13 @@ zero(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
||||||
emit([format_number(Acc)], {maybe_done, Rest, T, [Stack, Opts]});
|
emit([format_number(Acc)], {maybe_done, Rest, T, [Stack, Opts]});
|
||||||
zero(<<>>, T, [], Opts, Acc) ->
|
zero(<<>>, T, [], Opts, Acc) ->
|
||||||
{jsx, incomplete, fun(end_stream) ->
|
{jsx, incomplete, fun(end_stream) ->
|
||||||
emit([format_number(Acc), end_json],
|
emit([format_number(Acc), end_json, incomplete],
|
||||||
{decimal, <<>>, T, [[], Opts, Acc]})
|
{bad_json, <<>>, T, []}
|
||||||
|
)
|
||||||
; (Stream) -> zero(Stream, T, [], Opts, Acc)
|
; (Stream) -> zero(Stream, T, [], Opts, Acc)
|
||||||
end};
|
end};
|
||||||
zero(Bin, T, Stack, Opts, Acc) ->
|
zero(Bin, T, Stack, Opts, Acc) ->
|
||||||
?incomplete(zero(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)).
|
incomplete(zero, Bin, T, [Stack, Opts, Acc]).
|
||||||
|
|
||||||
|
|
||||||
integer(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
integer(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
||||||
|
@ -715,21 +738,20 @@ integer(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
||||||
emit([format_number(Acc)], {maybe_done, Rest, T, [Stack, Opts]});
|
emit([format_number(Acc)], {maybe_done, Rest, T, [Stack, Opts]});
|
||||||
integer(<<>>, T, [], Opts, Acc) ->
|
integer(<<>>, T, [], Opts, Acc) ->
|
||||||
{jsx, incomplete, fun(end_stream) ->
|
{jsx, incomplete, fun(end_stream) ->
|
||||||
emit([format_number(Acc), end_json],
|
emit([format_number(Acc), end_json, incomplete],
|
||||||
{decimal, <<>>, T, [[], Opts, Acc]})
|
{bad_json, <<>>, T, []}
|
||||||
|
)
|
||||||
; (Stream) -> integer(Stream, T, [], Opts, Acc)
|
; (Stream) -> integer(Stream, T, [], Opts, Acc)
|
||||||
end};
|
end};
|
||||||
integer(Bin, T, Stack, Opts, Acc) ->
|
integer(Bin, T, Stack, Opts, Acc) ->
|
||||||
?incomplete(integer(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)).
|
incomplete(integer, Bin, T, [Stack, Opts, Acc]).
|
||||||
|
|
||||||
|
|
||||||
initial_decimal(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac})
|
initial_decimal(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac})
|
||||||
when S =:= ?zero; ?is_nonzero(S) ->
|
when S =:= ?zero; ?is_nonzero(S) ->
|
||||||
decimal(Rest, T, Stack, Opts, {Int, [S] ++ Frac});
|
decimal(Rest, T, Stack, Opts, {Int, [S] ++ Frac});
|
||||||
initial_decimal(Bin, T, Stack, Opts, Acc) ->
|
initial_decimal(Bin, T, Stack, Opts, Acc) ->
|
||||||
?incomplete(
|
incomplete(initial_decimal, Bin, T, [Stack, Opts, Acc]).
|
||||||
initial_decimal(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)
|
|
||||||
).
|
|
||||||
|
|
||||||
|
|
||||||
decimal(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac})
|
decimal(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac})
|
||||||
|
@ -750,12 +772,13 @@ decimal(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
||||||
emit([format_number(Acc)], {maybe_done, Rest, T, [Stack, Opts]});
|
emit([format_number(Acc)], {maybe_done, Rest, T, [Stack, Opts]});
|
||||||
decimal(<<>>, T, [], Opts, Acc) ->
|
decimal(<<>>, T, [], Opts, Acc) ->
|
||||||
{jsx, incomplete, fun(end_stream) ->
|
{jsx, incomplete, fun(end_stream) ->
|
||||||
emit([format_number(Acc), end_json],
|
emit([format_number(Acc), end_json, incomplete],
|
||||||
{decimal, <<>>, T, [[], Opts, Acc]})
|
{bad_json, <<>>, T, []}
|
||||||
|
)
|
||||||
; (Stream) -> decimal(Stream, T, [], Opts, Acc)
|
; (Stream) -> decimal(Stream, T, [], Opts, Acc)
|
||||||
end};
|
end};
|
||||||
decimal(Bin, T, Stack, Opts, Acc) ->
|
decimal(Bin, T, Stack, Opts, Acc) ->
|
||||||
?incomplete(decimal(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)).
|
incomplete(decimal, Bin, T, [Stack, Opts, Acc]).
|
||||||
|
|
||||||
|
|
||||||
e(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac, Exp})
|
e(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac, Exp})
|
||||||
|
@ -765,14 +788,14 @@ e(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac, Exp})
|
||||||
when S =:= ?positive; S =:= ?negative ->
|
when S =:= ?positive; S =:= ?negative ->
|
||||||
ex(Rest, T, Stack, Opts, {Int, Frac, [S] ++ Exp});
|
ex(Rest, T, Stack, Opts, {Int, Frac, [S] ++ Exp});
|
||||||
e(Bin, T, Stack, Opts, Acc) ->
|
e(Bin, T, Stack, Opts, Acc) ->
|
||||||
?incomplete(e(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)).
|
incomplete(e, Bin, T, [Stack, Opts, Acc]).
|
||||||
|
|
||||||
|
|
||||||
ex(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac, Exp})
|
ex(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac, Exp})
|
||||||
when S =:= ?zero; ?is_nonzero(S) ->
|
when S =:= ?zero; ?is_nonzero(S) ->
|
||||||
exp(Rest, T, Stack, Opts, {Int, Frac, [S] ++ Exp});
|
exp(Rest, T, Stack, Opts, {Int, Frac, [S] ++ Exp});
|
||||||
ex(Bin, T, Stack, Opts, Acc) ->
|
ex(Bin, T, Stack, Opts, Acc) ->
|
||||||
?incomplete(ex(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)).
|
incomplete(ex, Bin, T, [Stack, Opts, Acc]).
|
||||||
|
|
||||||
|
|
||||||
exp(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac, Exp})
|
exp(<<S/?utfx, Rest/binary>>, T, Stack, Opts, {Int, Frac, Exp})
|
||||||
|
@ -790,12 +813,13 @@ exp(<<S/?utfx, Rest/binary>>, T, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
||||||
emit([format_number(Acc)], {maybe_done, Rest, T, [Stack, Opts]});
|
emit([format_number(Acc)], {maybe_done, Rest, T, [Stack, Opts]});
|
||||||
exp(<<>>, T, [], Opts, Acc) ->
|
exp(<<>>, T, [], Opts, Acc) ->
|
||||||
{jsx, incomplete, fun(end_stream) ->
|
{jsx, incomplete, fun(end_stream) ->
|
||||||
emit([format_number(Acc), end_json],
|
emit([format_number(Acc), end_json, incomplete],
|
||||||
{exp, <<>>, T, [[], Opts, Acc]})
|
{bad_json, <<>>, T, []}
|
||||||
|
)
|
||||||
; (Stream) -> exp(Stream, T, [], Opts, Acc)
|
; (Stream) -> exp(Stream, T, [], Opts, Acc)
|
||||||
end};
|
end};
|
||||||
exp(Bin, T, Stack, Opts, Acc) ->
|
exp(Bin, T, Stack, Opts, Acc) ->
|
||||||
?incomplete(exp(<<Bin/binary, Stream/binary>>, T, Stack, Opts, Acc)).
|
incomplete(exp, Bin, T, [Stack, Opts, Acc]).
|
||||||
|
|
||||||
|
|
||||||
format_number(Int) when is_list(Int) ->
|
format_number(Int) when is_list(Int) ->
|
||||||
|
@ -811,61 +835,61 @@ format_number({Int, Frac, Exp}) ->
|
||||||
tr(<<$r/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
tr(<<$r/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
tru(Rest, T, Stack, Opts);
|
tru(Rest, T, Stack, Opts);
|
||||||
tr(Bin, T, Stack, Opts) ->
|
tr(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(tr(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(tr, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
tru(<<$u/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
tru(<<$u/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
true(Rest, T, Stack, Opts);
|
true(Rest, T, Stack, Opts);
|
||||||
tru(Bin, T, Stack, Opts) ->
|
tru(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(tru(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(tru, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
true(<<$e/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
true(<<$e/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
emit([{literal, true}], {maybe_done, Rest, T, [Stack, Opts]});
|
emit([{literal, true}], {maybe_done, Rest, T, [Stack, Opts]});
|
||||||
true(Bin, T, Stack, Opts) ->
|
true(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(true(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(true, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
fa(<<$a/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
fa(<<$a/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
fal(Rest, T, Stack, Opts);
|
fal(Rest, T, Stack, Opts);
|
||||||
fa(Bin, T, Stack, Opts) ->
|
fa(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(fa(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(fa, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
fal(<<$l/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
fal(<<$l/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
fals(Rest, T, Stack, Opts);
|
fals(Rest, T, Stack, Opts);
|
||||||
fal(Bin, T, Stack, Opts) ->
|
fal(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(fal(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(fal, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
fals(<<$s/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
fals(<<$s/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
false(Rest, T, Stack, Opts);
|
false(Rest, T, Stack, Opts);
|
||||||
fals(Bin, T, Stack, Opts) ->
|
fals(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(fals(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(fals, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
false(<<$e/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
false(<<$e/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
emit([{literal, false}], {maybe_done, Rest, T, [Stack, Opts]});
|
emit([{literal, false}], {maybe_done, Rest, T, [Stack, Opts]});
|
||||||
false(Bin, T, Stack, Opts) ->
|
false(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(false(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(false, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
nu(<<$u/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
nu(<<$u/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
nul(Rest, T, Stack, Opts);
|
nul(Rest, T, Stack, Opts);
|
||||||
nu(Bin, T, Stack, Opts) ->
|
nu(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(nu(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(nu, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
nul(<<$l/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
nul(<<$l/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
null(Rest, T, Stack, Opts);
|
null(Rest, T, Stack, Opts);
|
||||||
nul(Bin, T, Stack, Opts) ->
|
nul(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(nul(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(nul, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
null(<<$l/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
null(<<$l/?utfx, Rest/binary>>, T, Stack, Opts) ->
|
||||||
emit([{literal, null}], {maybe_done, Rest, T, [Stack, Opts]});
|
emit([{literal, null}], {maybe_done, Rest, T, [Stack, Opts]});
|
||||||
null(Bin, T, Stack, Opts) ->
|
null(Bin, T, Stack, Opts) ->
|
||||||
?incomplete(null(<<Bin/binary, Stream/binary>>, T, Stack, Opts)).
|
incomplete(null, Bin, T, [Stack, Opts]).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -964,7 +988,7 @@ check([H|T], Opts, Acc) ->
|
||||||
|
|
||||||
|
|
||||||
decode(JSON, Opts) ->
|
decode(JSON, Opts) ->
|
||||||
F = decoder(Opts),
|
F = decoder([iterate] ++ Opts),
|
||||||
loop(F(JSON), []).
|
loop(F(JSON), []).
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
binary() | iolist().
|
binary() | iolist().
|
||||||
|
|
||||||
format(JSON, OptsList) when is_binary(JSON) ->
|
format(JSON, OptsList) when is_binary(JSON) ->
|
||||||
P = jsx:decoder(extract_parser_opts(OptsList)),
|
P = jsx:decoder([iterate] ++ extract_parser_opts(OptsList)),
|
||||||
format(fun() -> P(JSON) end, OptsList);
|
format(fun() -> P(JSON) end, OptsList);
|
||||||
format(Terms, OptsList) when is_list(Terms); is_tuple(Terms) ->
|
format(Terms, OptsList) when is_list(Terms); is_tuple(Terms) ->
|
||||||
P = jsx:encoder(),
|
P = jsx:encoder(),
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
jsx_term() | {jsx, incomplete, fun()}.
|
jsx_term() | {jsx, incomplete, fun()}.
|
||||||
|
|
||||||
json_to_term(JSON, Opts) ->
|
json_to_term(JSON, Opts) ->
|
||||||
P = jsx:decoder(extract_parser_opts(Opts)),
|
P = jsx:decoder([iterate] ++ extract_parser_opts(Opts)),
|
||||||
case proplists:get_value(strict, Opts, false) of
|
case proplists:get_value(strict, Opts, false) of
|
||||||
true -> collect_strict(P(JSON), [[]], Opts)
|
true -> collect_strict(P(JSON), [[]], Opts)
|
||||||
; false -> collect(P(JSON), [[]], Opts)
|
; false -> collect(P(JSON), [[]], Opts)
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
; (F::jsx_iterator(), Opts::verify_opts()) -> true | false.
|
; (F::jsx_iterator(), Opts::verify_opts()) -> true | false.
|
||||||
|
|
||||||
is_json(JSON, OptsList) when is_binary(JSON) ->
|
is_json(JSON, OptsList) when is_binary(JSON) ->
|
||||||
P = jsx:decoder(extract_parser_opts(OptsList)),
|
P = jsx:decoder([iterate] ++ extract_parser_opts(OptsList)),
|
||||||
is_json(fun() -> P(JSON) end, OptsList);
|
is_json(fun() -> P(JSON) end, OptsList);
|
||||||
is_json(Terms, OptsList) when is_list(Terms) ->
|
is_json(Terms, OptsList) when is_list(Terms) ->
|
||||||
P = jsx:encoder(),
|
P = jsx:encoder(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue