moved option parsing into the decoder module,trying to get as much implementation outside the interface module as possible
This commit is contained in:
parent
00baba4dc7
commit
1f1cb04cfd
3 changed files with 73 additions and 74 deletions
72
src/jsx.erl
72
src/jsx.erl
|
@ -161,17 +161,13 @@ parser() ->
|
|||
%% @end
|
||||
|
||||
parser(OptsList) ->
|
||||
F = case proplists:get_value(encoding, OptsList, auto) of
|
||||
utf8 -> fun jsx_utf8:parse/2
|
||||
; utf16 -> fun jsx_utf16:parse/2
|
||||
; utf32 -> fun jsx_utf32:parse/2
|
||||
; {utf16, little} -> fun jsx_utf16le:parse/2
|
||||
; {utf32, little} -> fun jsx_utf32le:parse/2
|
||||
; auto -> fun detect_encoding/2
|
||||
end,
|
||||
case parse_opts(OptsList) of
|
||||
{error, badopt} -> {error, badopt}
|
||||
; Opts -> fun(Stream) -> F(Stream, Opts) end
|
||||
case proplists:get_value(encoding, OptsList, auto) of
|
||||
utf8 -> jsx_utf8:parser(OptsList)
|
||||
; utf16 -> jsx_utf16:parser(OptsList)
|
||||
; utf32 -> jsx_utf32:parser(OptsList)
|
||||
; {utf16, little} -> jsx_utf16le:parser(OptsList)
|
||||
; {utf32, little} -> jsx_utf32le:parser(OptsList)
|
||||
; auto -> detect_encoding(OptsList)
|
||||
end.
|
||||
|
||||
|
||||
|
@ -352,64 +348,44 @@ eventify([Next|Rest]) ->
|
|||
fun() -> {event, Next, eventify(Rest)} end.
|
||||
|
||||
|
||||
%% ----------------------------------------------------------------------------
|
||||
|
||||
%% internal functions
|
||||
%% ----------------------------------------------------------------------------
|
||||
|
||||
%% option parsing
|
||||
|
||||
%% converts a proplist into a tuple
|
||||
parse_opts(Opts) ->
|
||||
parse_opts(Opts, #opts{}).
|
||||
|
||||
parse_opts([], Opts) ->
|
||||
Opts;
|
||||
parse_opts([{comments, Value}|Rest], Opts) ->
|
||||
true = lists:member(Value, [true, false]),
|
||||
parse_opts(Rest, Opts#opts{comments = Value});
|
||||
parse_opts([{escaped_unicode, Value}|Rest], Opts) ->
|
||||
true = lists:member(Value, [ascii, codepoint, none]),
|
||||
parse_opts(Rest, Opts#opts{escaped_unicode = Value});
|
||||
parse_opts([{multi_term, Value}|Rest], Opts) ->
|
||||
true = lists:member(Value, [true, false]),
|
||||
parse_opts(Rest, Opts#opts{multi_term = Value});
|
||||
parse_opts([{encoding, _}|Rest], Opts) ->
|
||||
parse_opts(Rest, Opts);
|
||||
parse_opts(_, _) ->
|
||||
{error, badopt}.
|
||||
|
||||
|
||||
%% encoding detection
|
||||
%% 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
|
||||
%% which may delay failure later than if an encoding is explicitly provided
|
||||
|
||||
detect_encoding(OptsList) ->
|
||||
fun(Stream) -> detect_encoding(Stream, OptsList) end.
|
||||
|
||||
%% utf8 bom detection
|
||||
detect_encoding(<<16#ef, 16#bb, 16#bf, Rest/binary>>, Opts) -> jsx_utf8:parse(Rest, Opts);
|
||||
detect_encoding(<<16#ef, 16#bb, 16#bf, Rest/binary>>, Opts) -> (jsx_utf8:parser(Opts))(Rest);
|
||||
%% utf32-little bom detection (this has to come before utf16-little or it'll match that)
|
||||
detect_encoding(<<16#ff, 16#fe, 0, 0, Rest/binary>>, Opts) -> jsx_utf32le:parse(Rest, Opts);
|
||||
detect_encoding(<<16#ff, 16#fe, 0, 0, Rest/binary>>, Opts) -> (jsx_utf32le:parser(Opts))(Rest);
|
||||
%% utf16-big bom detection
|
||||
detect_encoding(<<16#fe, 16#ff, Rest/binary>>, Opts) -> jsx_utf16:parse(Rest, Opts);
|
||||
detect_encoding(<<16#fe, 16#ff, Rest/binary>>, Opts) -> (jsx_utf16:parser(Opts))(Rest);
|
||||
%% utf16-little bom detection
|
||||
detect_encoding(<<16#ff, 16#fe, Rest/binary>>, Opts) -> jsx_utf16le:parse(Rest, Opts);
|
||||
detect_encoding(<<16#ff, 16#fe, Rest/binary>>, Opts) -> (jsx_utf16le:parser(Opts))(Rest);
|
||||
%% utf32-big bom detection
|
||||
detect_encoding(<<0, 0, 16#fe, 16#ff, Rest/binary>>, Opts) -> jsx_utf32:parse(Rest, Opts);
|
||||
detect_encoding(<<0, 0, 16#fe, 16#ff, Rest/binary>>, Opts) -> (jsx_utf32:parser(Opts))(Rest);
|
||||
|
||||
%% utf32-little null order detection
|
||||
detect_encoding(<<X, 0, 0, 0, _Rest/binary>> = JSON, Opts) when X =/= 0 ->
|
||||
jsx_utf32le:parse(JSON, Opts);
|
||||
(jsx_utf32le:parser(Opts))(JSON);
|
||||
%% utf16-big null order detection
|
||||
detect_encoding(<<0, X, 0, Y, _Rest/binary>> = JSON, Opts) when X =/= 0, Y =/= 0 ->
|
||||
jsx_utf16:parse(JSON, Opts);
|
||||
(jsx_utf16:parser(Opts))(JSON);
|
||||
%% utf16-little null order detection
|
||||
detect_encoding(<<X, 0, Y, 0, _Rest/binary>> = JSON, Opts) when X =/= 0, Y =/= 0 ->
|
||||
jsx_utf16le:parse(JSON, Opts);
|
||||
(jsx_utf16le:parser(Opts))(JSON);
|
||||
%% utf32-big null order detection
|
||||
detect_encoding(<<0, 0, 0, X, _Rest/binary>> = JSON, Opts) when X =/= 0 ->
|
||||
jsx_utf32:parse(JSON, Opts);
|
||||
(jsx_utf32:parser(Opts))(JSON);
|
||||
%% utf8 null order detection
|
||||
detect_encoding(<<X, Y, _Rest/binary>> = JSON, Opts) when X =/= 0, Y =/= 0 ->
|
||||
jsx_utf8:parse(JSON, Opts);
|
||||
(jsx_utf8:parser(Opts))(JSON);
|
||||
|
||||
%% 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
|
||||
|
@ -418,7 +394,7 @@ detect_encoding(<<X>>, Opts) when X =/= 0 ->
|
|||
{incomplete,
|
||||
fun(end_stream) ->
|
||||
try
|
||||
{incomplete, Next} = jsx_utf8:parse(<<X>>, Opts),
|
||||
{incomplete, Next} = (jsx_utf8:parser(Opts))(<<X>>),
|
||||
Next(end_stream)
|
||||
catch error:function_clause -> {error, badjson}
|
||||
end
|
||||
|
@ -429,7 +405,7 @@ detect_encoding(<<0, X>>, Opts) when X =/= 0 ->
|
|||
{incomplete,
|
||||
fun(end_stream) ->
|
||||
try
|
||||
{incomplete, Next} = jsx_utf16:parse(<<0, X>>, Opts),
|
||||
{incomplete, Next} = (jsx_utf16:parser(Opts))(<<0, X>>),
|
||||
Next(end_stream)
|
||||
catch error:function_clause -> {error, badjson}
|
||||
end
|
||||
|
@ -440,7 +416,7 @@ detect_encoding(<<X, 0>>, Opts) when X =/= 0 ->
|
|||
{incomplete,
|
||||
fun(end_stream) ->
|
||||
try
|
||||
{incomplete, Next} = jsx_utf16le:parse(<<X, 0>>, Opts),
|
||||
{incomplete, Next} = (jsx_utf16le:parser(Opts))(<<X, 0>>),
|
||||
Next(end_stream)
|
||||
catch error:function_clause -> {error, badjson}
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue