diff --git a/src/jsx.erl b/src/jsx.erl index 9f11ea8..25d8930 100644 --- a/src/jsx.erl +++ b/src/jsx.erl @@ -27,6 +27,38 @@ -export([decoder/0, decoder/1, decoder/2]). +decoder() -> + decoder([]). + +decoder(Opts) -> + F = fun(end_of_stream, State) -> lists:reverse(State) ;(Event, State) -> [Event] ++ State end, + decoder({F, []}, Opts). + +decoder({F, _} = Callbacks, OptsList) when is_list(OptsList), is_function(F) -> + Opts = parse_opts(OptsList), + decoder(Callbacks, Opts); +decoder({{Mod, Fun}, State}, OptsList) when is_list(OptsList), is_atom(Mod), is_atom(Fun) -> + Opts = parse_opts(OptsList), + decoder({fun(E, S) -> Mod:Fun(E, S) end, State}, Opts); +decoder(Callbacks, Opts) -> + fun(Stream) -> try start(Stream, [], Callbacks, Opts) catch error:function_clause -> {error, badjson} ;error:badjson -> {error, badjson} end end. + + +parse_opts(Opts) -> + parse_opts(Opts, {false, codepoint}). + +parse_opts([], Opts) -> + Opts; +parse_opts([{comments, Value}|Rest], {_Comments, EscapedUnicode}) -> + true = lists:member(Value, [true, false]), + parse_opts(Rest, {Value, EscapedUnicode}); +parse_opts([{escaped_unicode, Value}|Rest], {Comments, _EscapedUnicode}) -> + true = lists:member(Value, [ascii, codepoint, none]), + parse_opts(Rest, {Comments, Value}); +parse_opts([_UnknownOpt|Rest], Opts) -> + parse_opts(Rest, Opts). + + %% option flags -define(comments_true(X), {true, _} = X). @@ -85,38 +117,6 @@ -define(is_whitespace(Symbol), Symbol =:= ?space; Symbol =:= ?tab; Symbol =:= ?cr; Symbol =:= ?newline ). - - -decoder() -> - decoder([]). - -decoder(Opts) -> - F = fun(end_of_stream, State) -> lists:reverse(State) ;(Event, State) -> [Event] ++ State end, - decoder({F, []}, Opts). - -decoder({F, _} = Callbacks, OptsList) when is_list(OptsList), is_function(F) -> - Opts = parse_opts(OptsList), - decoder(Callbacks, Opts); -decoder({{Mod, Fun}, State}, OptsList) when is_list(OptsList), is_atom(Mod), is_atom(Fun) -> - Opts = parse_opts(OptsList), - decoder({fun(E, S) -> Mod:Fun(E, S) end, State}, Opts); -decoder(Callbacks, Opts) -> - fun(Stream) -> try start(Stream, [], Callbacks, Opts) catch error:function_clause -> {error, badjson} ;error:badjson -> {error, badjson} end end. - - -parse_opts(Opts) -> - parse_opts(Opts, {false, codepoint}). - -parse_opts([], Opts) -> - Opts; -parse_opts([{comments, Value}|Rest], {_Comments, EscapedUnicode}) -> - true = lists:member(Value, [true, false]), - parse_opts(Rest, {Value, EscapedUnicode}); -parse_opts([{escaped_unicode, Value}|Rest], {Comments, _EscapedUnicode}) -> - true = lists:member(Value, [ascii, codepoint, none]), - parse_opts(Rest, {Comments, Value}); -parse_opts([_UnknownOpt|Rest], Opts) -> - parse_opts(Rest, Opts). %% this code is mostly autogenerated and mostly ugly. apologies. for more insight on @@ -274,9 +274,7 @@ string(<>, Stack, Callbacks, Opts, Acc) -> string(<>, Stack, Callbacks, Opts, Acc) when ?is_noncontrol(S) -> string(Rest, Stack, Callbacks, Opts, [S] ++ Acc); string(Bin, Stack, Callbacks, Opts, Acc) -> - {incomplete, fun(Stream) -> string(<>, Stack, Callbacks, Opts, Acc) end}; -string(<<>>, Stack, Callbacks, Opts, Acc) -> - {incomplete, fun(Stream) -> string(Stream, Stack, Callbacks, Opts, Acc) end}. + {incomplete, fun(Stream) -> string(<>, Stack, Callbacks, Opts, Acc) end}. %% only thing to note here is the additional accumulator passed to escaped_unicode used