new interruptable api, examples broken for the hojillionth time
This commit is contained in:
parent
e690d7723a
commit
4286892861
3 changed files with 186 additions and 199 deletions
125
src/jsx.erl
125
src/jsx.erl
|
@ -21,15 +21,17 @@
|
||||||
%% THE SOFTWARE.
|
%% THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-module(jsx).
|
-module(jsx).
|
||||||
-author("alisdairsullivan@yahoo.ca").
|
-author("alisdairsullivan@yahoo.ca").
|
||||||
|
|
||||||
-export([decode/1, decode/2, parser/0, parser/1, parser/2]).
|
-export([decode/1, decode/2, parser/0, parser/1]).
|
||||||
|
|
||||||
-include("jsx_types.hrl").
|
-include("jsx_types.hrl").
|
||||||
|
|
||||||
|
|
||||||
|
%% decode takes a json binary (and optionally, a proplist of options) and returns a list
|
||||||
|
%% of events corresponding to the json structure/contents. it converts incompletes into
|
||||||
|
%% errors
|
||||||
|
|
||||||
-spec decode(JSON::json()) -> {ok, [jsx_event(),...]} | {error, badjson}.
|
-spec decode(JSON::json()) -> {ok, [jsx_event(),...]} | {error, badjson}.
|
||||||
-spec decode(JSON::json(), Opts::jsx_opts()) -> {ok, [jsx_event(),...]} | {error, badjson}.
|
-spec decode(JSON::json(), Opts::jsx_opts()) -> {ok, [jsx_event(),...]} | {error, badjson}.
|
||||||
|
@ -39,47 +41,39 @@ decode(JSON) ->
|
||||||
|
|
||||||
decode(JSON, Opts) ->
|
decode(JSON, Opts) ->
|
||||||
F = parser(Opts),
|
F = parser(Opts),
|
||||||
case F(JSON) of
|
decode_loop(F(JSON), []).
|
||||||
{incomplete, _} -> {error, badjson}
|
|
||||||
; {error, badjson} -> {error, badjson}
|
|
||||||
; {Result, _} -> {ok, Result}
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
decode_loop({incomplete, _}, _) -> {error, badjson};
|
||||||
|
decode_loop({error, badjson}, _) -> {error, badjson};
|
||||||
|
decode_loop({end_json, _}, State) -> {ok, lists:reverse(State)};
|
||||||
|
decode_loop({Event, F}, State) -> decode_loop(F(), [Event] ++ State).
|
||||||
|
|
||||||
|
|
||||||
|
%% parser returns an anonymous function of arity 1 that takes a json binary as it's
|
||||||
|
%% argument and returns a tuple containing an error, incomplete and a new parser that
|
||||||
|
%% can be handed more input to resume parsing or a single event and a function that
|
||||||
|
%% can be called to get the next result
|
||||||
|
|
||||||
-spec parser() -> jsx_parser().
|
-spec parser() -> jsx_parser().
|
||||||
-spec parser(Opts::jsx_opts()) -> jsx_parser().
|
-spec parser(Opts::jsx_opts()) -> jsx_parser().
|
||||||
-spec parser(Callbacks::{fun((jsx_event(), any()) -> any())}, Opts::jsx_opts()) -> jsx_parser()
|
|
||||||
; (Callbacks::{atom(), atom(), any()}, Opts::jsx_opts()) -> jsx_parser().
|
|
||||||
|
|
||||||
parser() ->
|
parser() ->
|
||||||
parser([]).
|
parser([]).
|
||||||
|
|
||||||
parser(Opts) ->
|
parser(OptsList) ->
|
||||||
F = fun(end_json, State) -> lists:reverse(State)
|
|
||||||
; (Event, State) -> [Event] ++ State
|
|
||||||
end,
|
|
||||||
parser({F, []}, Opts).
|
|
||||||
|
|
||||||
parser({F, S} = Callback, OptsList) when is_list(OptsList), is_function(F) ->
|
|
||||||
start(Callback, OptsList);
|
|
||||||
parser({Mod, Fun, State}, OptsList) when is_list(OptsList), is_atom(Mod), is_atom(Fun) ->
|
|
||||||
start({fun(E, S) -> Mod:Fun(E, S) end, State}, OptsList).
|
|
||||||
|
|
||||||
|
|
||||||
start(Callback, OptsList) ->
|
|
||||||
F = case proplists:get_value(encoding, OptsList, auto) of
|
F = case proplists:get_value(encoding, OptsList, auto) of
|
||||||
utf8 -> fun jsx_utf8:parse/3
|
utf8 -> fun jsx_utf8:parse/2
|
||||||
; utf16 -> fun jsx_utf16:parse/3
|
; utf16 -> fun jsx_utf16:parse/2
|
||||||
; utf32 -> fun jsx_utf32:parse/3
|
; utf32 -> fun jsx_utf32:parse/2
|
||||||
; {utf16, little} -> fun jsx_utf16le:parse/3
|
; {utf16, little} -> fun jsx_utf16le:parse/2
|
||||||
; {utf32, little} -> fun jsx_utf32le:parse/3
|
; {utf32, little} -> fun jsx_utf32le:parse/2
|
||||||
; auto -> fun detect_encoding/3
|
; auto -> fun detect_encoding/2
|
||||||
end,
|
end,
|
||||||
start(F, Callback, OptsList).
|
start(F, OptsList).
|
||||||
|
|
||||||
start(F, Callback, OptsList) ->
|
start(F, OptsList) ->
|
||||||
Opts = parse_opts(OptsList),
|
Opts = parse_opts(OptsList),
|
||||||
fun(Stream) -> F(Stream, Callback, Opts) end.
|
fun(Stream) -> F(Stream, Opts) end.
|
||||||
|
|
||||||
|
|
||||||
parse_opts(Opts) ->
|
parse_opts(Opts) ->
|
||||||
|
@ -95,84 +89,87 @@ parse_opts([{escaped_unicode, Value}|Rest], {Comments, _EscapedUnicode, Stream})
|
||||||
parse_opts(Rest, {Comments, Value, Stream});
|
parse_opts(Rest, {Comments, Value, Stream});
|
||||||
parse_opts([{stream_mode, Value}|Rest], {Comments, EscapedUnicode, _Stream}) ->
|
parse_opts([{stream_mode, Value}|Rest], {Comments, EscapedUnicode, _Stream}) ->
|
||||||
true = lists:member(Value, [true, false]),
|
true = lists:member(Value, [true, false]),
|
||||||
parse_opts(Rest, {Comments, EscapedUnicode, Value}).
|
parse_opts(Rest, {Comments, EscapedUnicode, Value});
|
||||||
|
parse_opts([{encoding, _}|Rest], Opts) ->
|
||||||
|
parse_opts(Rest, Opts).
|
||||||
|
|
||||||
|
|
||||||
%% first check to see if there's a bom, if not, use the rfc4627 method for determining
|
%% first check to see if there's a bom, if not, use the rfc4627 method for determining
|
||||||
%% encoding. this function makes some assumptions about the validity of the stream
|
%% encoding. this function makes some assumptions about the validity of the stream
|
||||||
%% which may delay failure later than if an encoding is explicitly provided.
|
%% which may delay failure later than if an encoding is explicitly provided
|
||||||
|
|
||||||
%% utf8 bom detection
|
%% utf8 bom detection
|
||||||
detect_encoding(<<16#ef, 16#bb, 16#bf, Rest/binary>>, Callback, Opts) ->
|
detect_encoding(<<16#ef, 16#bb, 16#bf, Rest/binary>>, Opts) ->
|
||||||
jsx_utf8:parse(Rest, Callback, Opts);
|
jsx_utf8:parse(Rest, Opts);
|
||||||
|
|
||||||
%% utf32-little bom detection (this has to come before utf16-little)
|
%% utf32-little bom detection (this has to come before utf16-little)
|
||||||
detect_encoding(<<16#ff, 16#fe, 0, 0, Rest/binary>>, Callback, Opts) ->
|
detect_encoding(<<16#ff, 16#fe, 0, 0, Rest/binary>>, Opts) ->
|
||||||
jsx_utf32le:parse(Rest, Callback, Opts);
|
jsx_utf32le:parse(Rest, Opts);
|
||||||
|
|
||||||
%% utf16-big bom detection
|
%% utf16-big bom detection
|
||||||
detect_encoding(<<16#fe, 16#ff, Rest/binary>>, Callback, Opts) ->
|
detect_encoding(<<16#fe, 16#ff, Rest/binary>>, Opts) ->
|
||||||
jsx_utf16:parse(Rest, Callback, Opts);
|
jsx_utf16:parse(Rest, Opts);
|
||||||
|
|
||||||
%% utf16-little bom detection
|
%% utf16-little bom detection
|
||||||
detect_encoding(<<16#ff, 16#fe, Rest/binary>>, Callback, Opts) ->
|
detect_encoding(<<16#ff, 16#fe, Rest/binary>>, Opts) ->
|
||||||
jsx_utf16le:parse(Rest, Callback, Opts);
|
jsx_utf16le:parse(Rest, Opts);
|
||||||
|
|
||||||
%% utf32-big bom detection
|
%% utf32-big bom detection
|
||||||
detect_encoding(<<0, 0, 16#fe, 16#ff, Rest/binary>>, Callback, Opts) ->
|
detect_encoding(<<0, 0, 16#fe, 16#ff, Rest/binary>>, Opts) ->
|
||||||
jsx_utf32:parse(Rest, Callback, Opts);
|
jsx_utf32:parse(Rest, Opts);
|
||||||
|
|
||||||
|
|
||||||
%% utf32-little null order detection
|
%% utf32-little null order detection
|
||||||
detect_encoding(<<X, 0, 0, 0, _Rest/binary>> = JSON, Callback, Opts) when X =/= 0 ->
|
detect_encoding(<<X, 0, 0, 0, _Rest/binary>> = JSON, Opts) when X =/= 0 ->
|
||||||
jsx_utf32le:parse(JSON, Callback, Opts);
|
jsx_utf32le:parse(JSON, Opts);
|
||||||
|
|
||||||
%% utf16-big null order detection
|
%% utf16-big null order detection
|
||||||
detect_encoding(<<0, X, 0, Y, _Rest/binary>> = JSON, Callback, Opts) when X =/= 0, Y =/= 0 ->
|
detect_encoding(<<0, X, 0, Y, _Rest/binary>> = JSON, Opts) when X =/= 0, Y =/= 0 ->
|
||||||
jsx_utf16:parse(JSON, Callback, Opts);
|
jsx_utf16:parse(JSON, Opts);
|
||||||
|
|
||||||
%% utf16-little null order detection
|
%% utf16-little null order detection
|
||||||
detect_encoding(<<X, 0, Y, 0, _Rest/binary>> = JSON, Callback, Opts) when X =/= 0, Y =/= 0 ->
|
detect_encoding(<<X, 0, Y, 0, _Rest/binary>> = JSON, Opts) when X =/= 0, Y =/= 0 ->
|
||||||
jsx_utf16le:parse(JSON, Callback, Opts);
|
jsx_utf16le:parse(JSON, Opts);
|
||||||
|
|
||||||
%% utf32-big null order detection
|
%% utf32-big null order detection
|
||||||
detect_encoding(<<0, 0, 0, X, _Rest/binary>> = JSON, Callback, Opts) when X =/= 0 ->
|
detect_encoding(<<0, 0, 0, X, _Rest/binary>> = JSON, Opts) when X =/= 0 ->
|
||||||
jsx_utf32:parse(JSON, Callback, Opts);
|
jsx_utf32:parse(JSON, Opts);
|
||||||
|
|
||||||
%% utf8 null order detection
|
%% utf8 null order detection
|
||||||
detect_encoding(<<X, Y, _Rest/binary>> = JSON, Callback, Opts) when X =/= 0, Y =/= 0 ->
|
detect_encoding(<<X, Y, _Rest/binary>> = JSON, Opts) when X =/= 0, Y =/= 0 ->
|
||||||
jsx_utf8:parse(JSON, Callback, Opts);
|
jsx_utf8:parse(JSON, Opts);
|
||||||
|
|
||||||
%% a problem, to autodetect naked single digits' encoding, there is not enough data
|
%% a problem, to autodetect naked single digits' encoding, there is not enough data
|
||||||
%% to conclusively determine the encoding correctly. below is an attempt to solve
|
%% to conclusively determine the encoding correctly. below is an attempt to solve
|
||||||
%% the problem
|
%% the problem
|
||||||
|
|
||||||
detect_encoding(<<X>>, Callback, Opts) when X =/= 0 ->
|
detect_encoding(<<X>>, Opts) when X =/= 0 ->
|
||||||
{try {Result, _} = jsx_utf8:parse(<<X>>, Callback, Opts), Result
|
{try {Result, _} = jsx_utf8:parse(<<X>>, Opts), Result
|
||||||
catch error:function_clause -> incomplete end,
|
catch error:function_clause -> incomplete end,
|
||||||
fun(Stream) ->
|
fun(Stream) ->
|
||||||
detect_encoding(<<X, Stream/binary>>, Callback, Opts)
|
detect_encoding(<<X, Stream/binary>>, Opts)
|
||||||
end
|
end
|
||||||
};
|
};
|
||||||
detect_encoding(<<0, X>>, Callback, Opts) when X =/= 0 ->
|
detect_encoding(<<0, X>>, Opts) when X =/= 0 ->
|
||||||
{try {Result, _} = jsx_utf16:parse(<<0, X>>, Callback, Opts), Result
|
{try {Result, _} = jsx_utf16:parse(<<0, X>>, Opts), Result
|
||||||
catch error:function_clause -> incomplete end,
|
catch error:function_clause -> incomplete end,
|
||||||
fun(Stream) ->
|
fun(Stream) ->
|
||||||
detect_encoding(<<0, X, Stream/binary>>, Callback, Opts)
|
detect_encoding(<<0, X, Stream/binary>>, Opts)
|
||||||
end
|
end
|
||||||
};
|
};
|
||||||
detect_encoding(<<X, 0>>, Callback, Opts) when X =/= 0 ->
|
detect_encoding(<<X, 0>>, Opts) when X =/= 0 ->
|
||||||
{try {Result, _} = jsx_utf16le:parse(<<X, 0>>, Callback, Opts), Result
|
{try {Result, _} = jsx_utf16le:parse(<<X, 0>>, Opts), Result
|
||||||
catch error:function_clause -> incomplete end,
|
catch error:function_clause -> incomplete end,
|
||||||
fun(Stream) ->
|
fun(Stream) ->
|
||||||
detect_encoding(<<X, 0, Stream/binary>>, Callback, Opts)
|
detect_encoding(<<X, 0, Stream/binary>>, Opts)
|
||||||
end
|
end
|
||||||
};
|
};
|
||||||
|
|
||||||
%% not enough input, request more
|
%% not enough input, request more
|
||||||
detect_encoding(Bin, Callback, Opts) ->
|
|
||||||
|
detect_encoding(Bin, Opts) ->
|
||||||
{incomplete,
|
{incomplete,
|
||||||
fun(Stream) ->
|
fun(Stream) ->
|
||||||
detect_encoding(<<Bin/binary, Stream/binary>>, Callback, Opts)
|
detect_encoding(<<Bin/binary, Stream/binary>>, Opts)
|
||||||
end
|
end
|
||||||
}.
|
}.
|
|
@ -27,30 +27,16 @@
|
||||||
-module(?name).
|
-module(?name).
|
||||||
-author("alisdairsullivan@yahoo.ca").
|
-author("alisdairsullivan@yahoo.ca").
|
||||||
|
|
||||||
|
-export([parse/2]).
|
||||||
|
|
||||||
-include("jsx_decoder.hrl").
|
-include("jsx_decoder.hrl").
|
||||||
|
-include("jsx_types.hrl").
|
||||||
-export([parse/3]).
|
|
||||||
-compile(inline).
|
|
||||||
|
|
||||||
|
|
||||||
parse(JSON, {Callback, State}, Opts) ->
|
-spec parse(JSON::json(), Opts::jsx_opts()) -> parser_result().
|
||||||
parse(Callback, State, fun() -> start(JSON, [], Opts) end, Opts).
|
|
||||||
|
|
||||||
parse(Callback, State, F, Opts) ->
|
parse(JSON, Opts) ->
|
||||||
case F() of
|
start(JSON, [], Opts).
|
||||||
{incomplete, Next} -> {incomplete, Next}
|
|
||||||
; {end_json, Next} -> {Callback(end_json, State), Next}
|
|
||||||
; {error, badjson} -> {error, badjson}
|
|
||||||
; {Event, Next} -> parse(Callback, Callback(Event, State), Next, Opts)
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
emit(incomplete, F) ->
|
|
||||||
{incomplete, F};
|
|
||||||
emit(end_json, F) ->
|
|
||||||
{end_json, F};
|
|
||||||
emit(Event, F) ->
|
|
||||||
{Event, F}.
|
|
||||||
|
|
||||||
|
|
||||||
%% this code is mostly autogenerated and mostly ugly. apologies. for more insight on
|
%% this code is mostly autogenerated and mostly ugly. apologies. for more insight on
|
||||||
|
@ -64,9 +50,9 @@ emit(Event, F) ->
|
||||||
start(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_whitespace(S) ->
|
start(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
start(Rest, Stack, Opts);
|
start(Rest, Stack, Opts);
|
||||||
start(<<?start_object/?encoding, Rest/binary>>, Stack, Opts) ->
|
start(<<?start_object/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
emit(start_object, fun() -> object(Rest, [key|Stack], Opts) end);
|
{start_object, fun() -> object(Rest, [key|Stack], Opts) end};
|
||||||
start(<<?start_array/?encoding, Rest/binary>>, Stack, Opts) ->
|
start(<<?start_array/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
emit(start_array, fun() -> array(Rest, [array|Stack], Opts) end);
|
{start_array, fun() -> array(Rest, [array|Stack], Opts) end};
|
||||||
start(<<?quote/?encoding, Rest/binary>>, Stack, Opts) ->
|
start(<<?quote/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
string(Rest, Stack, Opts, []);
|
string(Rest, Stack, Opts, []);
|
||||||
start(<<$t/?encoding, Rest/binary>>, Stack, Opts) ->
|
start(<<$t/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
|
@ -86,16 +72,16 @@ start(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
||||||
start(Bin, Stack, Opts) ->
|
start(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> start(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> start(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
maybe_done(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_whitespace(S) ->
|
maybe_done(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
maybe_done(Rest, Stack, Opts);
|
maybe_done(Rest, Stack, Opts);
|
||||||
maybe_done(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts) ->
|
maybe_done(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts) ->
|
||||||
emit(end_object, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{end_object, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
maybe_done(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts) ->
|
maybe_done(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts) ->
|
||||||
emit(end_array, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{end_array, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
maybe_done(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts) ->
|
maybe_done(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts) ->
|
||||||
key(Rest, [key|Stack], Opts);
|
key(Rest, [key|Stack], Opts);
|
||||||
maybe_done(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts) ->
|
maybe_done(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts) ->
|
||||||
|
@ -103,13 +89,13 @@ maybe_done(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts) ->
|
||||||
maybe_done(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
maybe_done(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
||||||
maybe_comment(Rest, fun(Resume) -> maybe_done(Resume, Stack, Opts) end);
|
maybe_comment(Rest, fun(Resume) -> maybe_done(Resume, Stack, Opts) end);
|
||||||
maybe_done(Bin, [], ?stream_mode(Opts)) ->
|
maybe_done(Bin, [], ?stream_mode(Opts)) ->
|
||||||
emit(end_json, fun() -> start(Bin, [], Opts) end);
|
{end_json, fun() -> start(Bin, [], Opts) end};
|
||||||
maybe_done(<<>>, [], Opts) ->
|
maybe_done(<<>>, [], Opts) ->
|
||||||
emit(end_json, fun() -> emit(incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end) end);
|
{end_json, fun() -> {incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end} end};
|
||||||
maybe_done(Bin, Stack, Opts) ->
|
maybe_done(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> maybe_done(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> maybe_done(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,13 +104,13 @@ object(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_whitespace(S) ->
|
||||||
object(<<?quote/?encoding, Rest/binary>>, Stack, Opts) ->
|
object(<<?quote/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
string(Rest, Stack, Opts, []);
|
string(Rest, Stack, Opts, []);
|
||||||
object(<<?end_object/?encoding, Rest/binary>>, [key|Stack], Opts) ->
|
object(<<?end_object/?encoding, Rest/binary>>, [key|Stack], Opts) ->
|
||||||
emit(end_object, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{end_object, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
object(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
object(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
||||||
maybe_comment(Rest, fun(Resume) -> object(Resume, Stack, Opts) end);
|
maybe_comment(Rest, fun(Resume) -> object(Resume, Stack, Opts) end);
|
||||||
object(Bin, Stack, Opts) ->
|
object(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> object(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> object(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,17 +131,17 @@ array(<<?zero/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
array(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_nonzero(S) ->
|
array(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_nonzero(S) ->
|
||||||
integer(Rest, Stack, Opts, [S]);
|
integer(Rest, Stack, Opts, [S]);
|
||||||
array(<<?start_object/?encoding, Rest/binary>>, Stack, Opts) ->
|
array(<<?start_object/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
emit(start_object, fun() -> object(Rest, [key|Stack], Opts) end);
|
{start_object, fun() -> object(Rest, [key|Stack], Opts) end};
|
||||||
array(<<?start_array/?encoding, Rest/binary>>, Stack, Opts) ->
|
array(<<?start_array/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
emit(start_array, fun() -> array(Rest, [array|Stack], Opts) end);
|
{start_array, fun() -> array(Rest, [array|Stack], Opts) end};
|
||||||
array(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts) ->
|
array(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts) ->
|
||||||
emit(end_array, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{end_array, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
array(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
array(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
||||||
maybe_comment(Rest, fun(Resume) -> array(Resume, Stack, Opts) end);
|
maybe_comment(Rest, fun(Resume) -> array(Resume, Stack, Opts) end);
|
||||||
array(Bin, Stack, Opts) ->
|
array(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> array(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> array(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,15 +162,15 @@ value(<<?zero/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
value(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_nonzero(S) ->
|
value(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_nonzero(S) ->
|
||||||
integer(Rest, Stack, Opts, [S]);
|
integer(Rest, Stack, Opts, [S]);
|
||||||
value(<<?start_object/?encoding, Rest/binary>>, Stack, Opts) ->
|
value(<<?start_object/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
emit(start_object, fun() -> object(Rest, [key|Stack], Opts) end);
|
{start_object, fun() -> object(Rest, [key|Stack], Opts) end};
|
||||||
value(<<?start_array/?encoding, Rest/binary>>, Stack, Opts) ->
|
value(<<?start_array/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
emit(start_array, fun() -> array(Rest, [array|Stack], Opts) end);
|
{start_array, fun() -> array(Rest, [array|Stack], Opts) end};
|
||||||
value(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
value(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
||||||
maybe_comment(Rest, fun(Resume) -> value(Resume, Stack, Opts) end);
|
maybe_comment(Rest, fun(Resume) -> value(Resume, Stack, Opts) end);
|
||||||
value(Bin, Stack, Opts) ->
|
value(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> value(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> value(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,7 +183,7 @@ colon(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
||||||
colon(Bin, Stack, Opts) ->
|
colon(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> colon(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> colon(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,7 +196,7 @@ key(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts)) ->
|
||||||
key(Bin, Stack, Opts) ->
|
key(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> key(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> key(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -220,9 +206,9 @@ key(Bin, Stack, Opts) ->
|
||||||
%% converted back to lists by the user anyways.
|
%% converted back to lists by the user anyways.
|
||||||
|
|
||||||
string(<<?quote/?encoding, Rest/binary>>, [key|_] = Stack, Opts, Acc) ->
|
string(<<?quote/?encoding, Rest/binary>>, [key|_] = Stack, Opts, Acc) ->
|
||||||
emit({key, lists:reverse(Acc)}, fun() -> colon(Rest, Stack, Opts) end);
|
{{key, lists:reverse(Acc)}, fun() -> colon(Rest, Stack, Opts) end};
|
||||||
string(<<?quote/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
string(<<?quote/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
emit({string, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{{string, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
string(<<?rsolidus/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
string(<<?rsolidus/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
escape(Rest, Stack, Opts, Acc);
|
escape(Rest, Stack, Opts, Acc);
|
||||||
string(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_noncontrol(S) ->
|
string(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_noncontrol(S) ->
|
||||||
|
@ -230,7 +216,7 @@ string(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_noncontrol(S) ->
|
||||||
string(Bin, Stack, Opts, Acc) ->
|
string(Bin, Stack, Opts, Acc) ->
|
||||||
case partial_utf(Bin) of
|
case partial_utf(Bin) of
|
||||||
false -> {error, badjson}
|
false -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> string(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> string(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -304,7 +290,7 @@ escape(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc)
|
||||||
escape(Bin, Stack, Opts, Acc) ->
|
escape(Bin, Stack, Opts, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> escape(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> escape(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -354,9 +340,9 @@ escaped_unicode(<<S/?encoding, Rest/binary>>, Stack, Opts, String, Acc) when ?is
|
||||||
escaped_unicode(Bin, Stack, Opts, String, Acc) ->
|
escaped_unicode(Bin, Stack, Opts, String, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) ->
|
; _ -> {incomplete, fun(Stream) ->
|
||||||
escaped_unicode(<<Bin/binary, Stream/binary>>, Stack, Opts, String, Acc)
|
escaped_unicode(<<Bin/binary, Stream/binary>>, Stack, Opts, String, Acc)
|
||||||
end)
|
end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% upon encountering a low pair json/hex encoded value, check to see if there's a high
|
%% upon encountering a low pair json/hex encoded value, check to see if there's a high
|
||||||
|
@ -389,58 +375,58 @@ negative(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
||||||
negative(Bin, Stack, Opts, Acc) ->
|
negative(Bin, Stack, Opts, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> negative(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> negative(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
zero(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
zero(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() ->
|
{{integer, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_object, fun() -> maybe_done(Rest, Stack, Opts) end)
|
{end_object, fun() -> maybe_done(Rest, Stack, Opts) end}
|
||||||
end);
|
end};
|
||||||
zero(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts, Acc) ->
|
zero(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() ->
|
{{integer, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_array, fun() -> maybe_done(Rest, Stack, Opts) end)
|
{end_array, fun() -> maybe_done(Rest, Stack, Opts) end}
|
||||||
end);
|
end};
|
||||||
zero(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
zero(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() -> key(Rest, [key|Stack], Opts) end);
|
{{integer, lists:reverse(Acc)}, fun() -> key(Rest, [key|Stack], Opts) end};
|
||||||
zero(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
zero(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() -> value(Rest, Stack, Opts) end);
|
{{integer, lists:reverse(Acc)}, fun() -> value(Rest, Stack, Opts) end};
|
||||||
zero(<<?decimalpoint/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
zero(<<?decimalpoint/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
initial_decimal(Rest, Stack, Opts, [?decimalpoint] ++ Acc);
|
initial_decimal(Rest, Stack, Opts, [?decimalpoint] ++ Acc);
|
||||||
zero(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
zero(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{{integer, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
zero(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts), Acc) ->
|
zero(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts), Acc) ->
|
||||||
maybe_comment(Rest, fun(Resume) -> zero(Resume, Stack, Opts, Acc) end);
|
maybe_comment(Rest, fun(Resume) -> zero(Resume, Stack, Opts, Acc) end);
|
||||||
zero(Bin, [], ?stream_mode(Opts), Acc) ->
|
zero(Bin, [], ?stream_mode(Opts), Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() ->
|
{{integer, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_json, fun() -> start(Bin, [], Opts) end)
|
{end_json, fun() -> start(Bin, [], Opts) end}
|
||||||
end);
|
end};
|
||||||
zero(<<>>, [], Opts, Acc) ->
|
zero(<<>>, [], Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() ->
|
{{integer, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_json, fun() -> emit(incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end)
|
{end_json, fun() -> {incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end}
|
||||||
end)
|
end}
|
||||||
end);
|
end};
|
||||||
zero(Bin, Stack, Opts, Acc) ->
|
zero(Bin, Stack, Opts, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> zero(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> zero(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
integer(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
integer(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
||||||
integer(Rest, Stack, Opts, [S] ++ Acc);
|
integer(Rest, Stack, Opts, [S] ++ Acc);
|
||||||
integer(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
integer(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() ->
|
{{integer, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_object, fun() -> maybe_done(Rest, Stack, Opts) end)
|
{end_object, fun() -> maybe_done(Rest, Stack, Opts) end}
|
||||||
end);
|
end};
|
||||||
integer(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts, Acc) ->
|
integer(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() ->
|
{{integer, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_array, fun() -> maybe_done(Rest, Stack, Opts) end)
|
{end_array, fun() -> maybe_done(Rest, Stack, Opts) end}
|
||||||
end);
|
end};
|
||||||
integer(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
integer(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() -> key(Rest, [key|Stack], Opts) end);
|
{{integer, lists:reverse(Acc)}, fun() -> key(Rest, [key|Stack], Opts) end};
|
||||||
integer(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
integer(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() -> value(Rest, Stack, Opts) end);
|
{{integer, lists:reverse(Acc)}, fun() -> value(Rest, Stack, Opts) end};
|
||||||
integer(<<?decimalpoint/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
integer(<<?decimalpoint/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
initial_decimal(Rest, Stack, Opts, [?decimalpoint] ++ Acc);
|
initial_decimal(Rest, Stack, Opts, [?decimalpoint] ++ Acc);
|
||||||
integer(<<?zero/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
integer(<<?zero/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
|
@ -450,22 +436,22 @@ integer(<<$e/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
integer(<<$E/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
integer(<<$E/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
e(Rest, Stack, Opts, "e0." ++ Acc);
|
e(Rest, Stack, Opts, "e0." ++ Acc);
|
||||||
integer(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
integer(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{{integer, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
integer(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts), Acc) ->
|
integer(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts), Acc) ->
|
||||||
maybe_comment(Rest, fun(Resume) -> integer(Resume, Stack, Opts, Acc) end);
|
maybe_comment(Rest, fun(Resume) -> integer(Resume, Stack, Opts, Acc) end);
|
||||||
integer(Bin, [], ?stream_mode(Opts), Acc) ->
|
integer(Bin, [], ?stream_mode(Opts), Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() ->
|
{{integer, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_json, fun() -> start(Bin, [], Opts) end)
|
{end_json, fun() -> start(Bin, [], Opts) end}
|
||||||
end);
|
end};
|
||||||
integer(<<>>, [], Opts, Acc) ->
|
integer(<<>>, [], Opts, Acc) ->
|
||||||
emit({integer, lists:reverse(Acc)}, fun() ->
|
{{integer, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_json, fun() -> emit(incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end)
|
{end_json, fun() -> {incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end}
|
||||||
end)
|
end}
|
||||||
end);
|
end};
|
||||||
integer(Bin, Stack, Opts, Acc) ->
|
integer(Bin, Stack, Opts, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> integer(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> integer(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -476,24 +462,24 @@ initial_decimal(<<?zero/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
initial_decimal(Bin, Stack, Opts, Acc) ->
|
initial_decimal(Bin, Stack, Opts, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> initial_decimal(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> initial_decimal(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
decimal(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
decimal(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
||||||
decimal(Rest, Stack, Opts, [S] ++ Acc);
|
decimal(Rest, Stack, Opts, [S] ++ Acc);
|
||||||
decimal(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
decimal(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() ->
|
{{float, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_object, fun() -> maybe_done(Rest, Stack, Opts) end)
|
{end_object, fun() -> maybe_done(Rest, Stack, Opts) end}
|
||||||
end);
|
end};
|
||||||
decimal(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts, Acc) ->
|
decimal(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() ->
|
{{float, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_array, fun() -> maybe_done(Rest, Stack, Opts) end)
|
{end_array, fun() -> maybe_done(Rest, Stack, Opts) end}
|
||||||
end);
|
end};
|
||||||
decimal(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
decimal(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() -> key(Rest, [key|Stack], Opts) end);
|
{{float, lists:reverse(Acc)}, fun() -> key(Rest, [key|Stack], Opts) end};
|
||||||
decimal(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
decimal(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() -> value(Rest, Stack, Opts) end);
|
{{float, lists:reverse(Acc)}, fun() -> value(Rest, Stack, Opts) end};
|
||||||
decimal(<<?zero/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
decimal(<<?zero/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
decimal(Rest, Stack, Opts, [?zero] ++ Acc);
|
decimal(Rest, Stack, Opts, [?zero] ++ Acc);
|
||||||
decimal(<<$e/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
decimal(<<$e/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
|
@ -501,22 +487,22 @@ decimal(<<$e/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
decimal(<<$E/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
decimal(<<$E/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
e(Rest, Stack, Opts, "e" ++ Acc);
|
e(Rest, Stack, Opts, "e" ++ Acc);
|
||||||
decimal(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
decimal(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{{float, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
decimal(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts), Acc) ->
|
decimal(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts), Acc) ->
|
||||||
maybe_comment(Rest, fun(Resume) -> decimal(Resume, Stack, Opts, Acc) end);
|
maybe_comment(Rest, fun(Resume) -> decimal(Resume, Stack, Opts, Acc) end);
|
||||||
decimal(Bin, [], ?stream_mode(Opts), Acc) ->
|
decimal(Bin, [], ?stream_mode(Opts), Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() ->
|
{{float, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_json, fun() -> start(Bin, [], Opts) end)
|
{end_json, fun() -> start(Bin, [], Opts) end}
|
||||||
end);
|
end};
|
||||||
decimal(<<>>, [], Opts, Acc) ->
|
decimal(<<>>, [], Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() ->
|
{{float, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_json, fun() -> emit(incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end)
|
{end_json, fun() -> {incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end}
|
||||||
end)
|
end}
|
||||||
end);
|
end};
|
||||||
decimal(Bin, Stack, Opts, Acc) ->
|
decimal(Bin, Stack, Opts, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> decimal(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> decimal(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -527,7 +513,7 @@ e(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when S =:= ?positive; S =:= ?n
|
||||||
e(Bin, Stack, Opts, Acc) ->
|
e(Bin, Stack, Opts, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> e(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> e(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -536,43 +522,43 @@ ex(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when S =:= ?zero; ?is_nonzero
|
||||||
ex(Bin, Stack, Opts, Acc) ->
|
ex(Bin, Stack, Opts, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> ex(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> ex(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
exp(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
exp(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_nonzero(S) ->
|
||||||
exp(Rest, Stack, Opts, [S] ++ Acc);
|
exp(Rest, Stack, Opts, [S] ++ Acc);
|
||||||
exp(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
exp(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() ->
|
{{float, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_object, fun() -> maybe_done(Rest, Stack, Opts) end)
|
{end_object, fun() -> maybe_done(Rest, Stack, Opts) end}
|
||||||
end);
|
end};
|
||||||
exp(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts, Acc) ->
|
exp(<<?end_array/?encoding, Rest/binary>>, [array|Stack], Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() ->
|
{{float, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_array, fun() -> maybe_done(Rest, Stack, Opts) end)
|
{end_array, fun() -> maybe_done(Rest, Stack, Opts) end}
|
||||||
end);
|
end};
|
||||||
exp(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
exp(<<?comma/?encoding, Rest/binary>>, [object|Stack], Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() -> key(Rest, [key|Stack], Opts) end);
|
{{float, lists:reverse(Acc)}, fun() -> key(Rest, [key|Stack], Opts) end};
|
||||||
exp(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
exp(<<?comma/?encoding, Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() -> value(Rest, Stack, Opts) end);
|
{{float, lists:reverse(Acc)}, fun() -> value(Rest, Stack, Opts) end};
|
||||||
exp(<<?zero/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
exp(<<?zero/?encoding, Rest/binary>>, Stack, Opts, Acc) ->
|
||||||
exp(Rest, Stack, Opts, [?zero] ++ Acc);
|
exp(Rest, Stack, Opts, [?zero] ++ Acc);
|
||||||
exp(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
exp(<<S/?encoding, Rest/binary>>, Stack, Opts, Acc) when ?is_whitespace(S) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{{float, lists:reverse(Acc)}, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
exp(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts), Acc) ->
|
exp(<<?solidus/?encoding, Rest/binary>>, Stack, ?comments_enabled(Opts), Acc) ->
|
||||||
maybe_comment(Rest, fun(Resume) -> exp(Resume, Stack, Opts, Acc) end);
|
maybe_comment(Rest, fun(Resume) -> exp(Resume, Stack, Opts, Acc) end);
|
||||||
exp(Bin, [], ?stream_mode(Opts), Acc) ->
|
exp(Bin, [], ?stream_mode(Opts), Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() ->
|
{{float, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_json, fun() -> start(Bin, [], Opts) end)
|
{end_json, fun() -> start(Bin, [], Opts) end}
|
||||||
end);
|
end};
|
||||||
exp(<<>>, [], Opts, Acc) ->
|
exp(<<>>, [], Opts, Acc) ->
|
||||||
emit({float, lists:reverse(Acc)}, fun() ->
|
{{float, lists:reverse(Acc)}, fun() ->
|
||||||
emit(end_json, fun() -> emit(incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end)
|
{end_json, fun() -> {incomplete, fun(Stream) -> maybe_done(Stream, [], Opts) end}
|
||||||
end)
|
end}
|
||||||
end);
|
end};
|
||||||
exp(Bin, Stack, Opts, Acc) ->
|
exp(Bin, Stack, Opts, Acc) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> exp(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end)
|
; _ -> {incomplete, fun(Stream) -> exp(<<Bin/binary, Stream/binary>>, Stack, Opts, Acc) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -581,7 +567,7 @@ tr(<<$r/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
tr(Bin, Stack, Opts) ->
|
tr(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> tr(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> tr(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -590,16 +576,16 @@ tru(<<$u/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
tru(Bin, Stack, Opts) ->
|
tru(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> tru(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> tru(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
true(<<$e/?encoding, Rest/binary>>, Stack, Opts) ->
|
true(<<$e/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
emit({literal, true}, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{{literal, true}, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
true(Bin, Stack, Opts) ->
|
true(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> true(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> true(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -608,7 +594,7 @@ fa(<<$a/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
fa(Bin, Stack, Opts) ->
|
fa(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> fa(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> fa(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -617,7 +603,7 @@ fal(<<$l/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
fal(Bin, Stack, Opts) ->
|
fal(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> fal(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> fal(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -626,16 +612,16 @@ fals(<<$s/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
fals(Bin, Stack, Opts) ->
|
fals(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> fals(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> fals(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
false(<<$e/?encoding, Rest/binary>>, Stack, Opts) ->
|
false(<<$e/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
emit({literal, false}, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{{literal, false}, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
false(Bin, Stack, Opts) ->
|
false(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> false(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> false(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -644,7 +630,7 @@ nu(<<$u/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
nu(Bin, Stack, Opts) ->
|
nu(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> nu(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> nu(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -653,16 +639,16 @@ nul(<<$l/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
nul(Bin, Stack, Opts) ->
|
nul(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> nul(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> nul(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
null(<<$l/?encoding, Rest/binary>>, Stack, Opts) ->
|
null(<<$l/?encoding, Rest/binary>>, Stack, Opts) ->
|
||||||
emit({literal, null}, fun() -> maybe_done(Rest, Stack, Opts) end);
|
{{literal, null}, fun() -> maybe_done(Rest, Stack, Opts) end};
|
||||||
null(Bin, Stack, Opts) ->
|
null(Bin, Stack, Opts) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> null(<<Bin/binary, Stream/binary>>, Stack, Opts) end)
|
; _ -> {incomplete, fun(Stream) -> null(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -677,7 +663,7 @@ maybe_comment(<<?star/?encoding, Rest/binary>>, Resume) ->
|
||||||
maybe_comment(Bin, Resume) ->
|
maybe_comment(Bin, Resume) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> maybe_comment(<<Bin/binary, Stream/binary>>, Resume) end)
|
; _ -> {incomplete, fun(Stream) -> maybe_comment(<<Bin/binary, Stream/binary>>, Resume) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -688,7 +674,7 @@ comment(<<_/?encoding, Rest/binary>>, Resume) ->
|
||||||
comment(Bin, Resume) ->
|
comment(Bin, Resume) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> comment(<<Bin/binary, Stream/binary>>, Resume) end)
|
; _ -> {incomplete, fun(Stream) -> comment(<<Bin/binary, Stream/binary>>, Resume) end}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -699,5 +685,5 @@ maybe_comment_done(<<_/?encoding, Rest/binary>>, Resume) ->
|
||||||
maybe_comment_done(Bin, Resume) ->
|
maybe_comment_done(Bin, Resume) ->
|
||||||
case byte_size(Bin) >= ?symbol_size of
|
case byte_size(Bin) >= ?symbol_size of
|
||||||
true -> {error, badjson}
|
true -> {error, badjson}
|
||||||
; _ -> emit(incomplete, fun(Stream) -> maybe_comment_done(<<Bin/binary, Stream/binary>>, Resume) end)
|
; _ -> {incomplete, fun(Stream) -> maybe_comment_done(<<Bin/binary, Stream/binary>>, Resume) end}
|
||||||
end.
|
end.
|
|
@ -44,7 +44,6 @@
|
||||||
| start_array
|
| start_array
|
||||||
| end_array
|
| end_array
|
||||||
| end_json
|
| end_json
|
||||||
| reset
|
|
||||||
| {key, unicode_string()}
|
| {key, unicode_string()}
|
||||||
| {string, unicode_string()}
|
| {string, unicode_string()}
|
||||||
| {integer, unicode_string()}
|
| {integer, unicode_string()}
|
||||||
|
@ -60,3 +59,8 @@
|
||||||
| {incomplete, jsx_parser()}
|
| {incomplete, jsx_parser()}
|
||||||
| {error, badjson}
|
| {error, badjson}
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
|
-type parser_result() :: {jsx_event(), fun(() -> parser_result())}
|
||||||
|
| {incomplete, jsx_parser()}
|
||||||
|
| {error, badjson}.
|
Loading…
Add table
Add a link
Reference in a new issue