diff --git a/src/jsx_common.hrl b/src/jsx_common.hrl index 65decf6..cd4b981 100644 --- a/src/jsx_common.hrl +++ b/src/jsx_common.hrl @@ -1,6 +1,7 @@ -record(opts, { comments = false, - escaped_unicode = ascii + escaped_unicode = ascii, + naked_values = false }). %% whitespace diff --git a/src/jsx_utf8.erl b/src/jsx_utf8.erl index 6580807..130db5e 100644 --- a/src/jsx_utf8.erl +++ b/src/jsx_utf8.erl @@ -12,23 +12,32 @@ callback(Event, Callbacks) -> %% this code is mostly autogenerated and mostly ugly. apologies. for more insight on %% Callbacks or Opts, see the comments accompanying callback/2 (in this file) and -%% parse_opts/1 (in jsx.erl). Stack is a stack of flags used to track depth. all -%% pops, peeks and pushes are inlined. comments are handled in function to get around -%% a limitation of erlang's binary matching optimizations, and a function_clause -%% error is raised if comments are disallowed to maintain consistency with behaviour -%% of other invalid input +%% parse_opts/1 (in jsx.erl). Stack is a stack of flags used to track depth and to +%% keep track of whether we are returning from a value or a key inside objects. all +%% pops, peeks and pushes are inlined. the code that handles naked values and comments +%% is not optimized by the compiler for efficient matching, but you shouldn't be using +%% naked values or comments anyways, they are horrible and contrary to the spec. start(<>, Stack, Callbacks, Opts) -> object(Rest, [key|Stack], callback(start_object, Callbacks), Opts); start(<>, Stack, Callbacks, Opts) -> array(Rest, [array|Stack], callback(start_array, Callbacks), Opts); -start(<>, Stack, Callbacks, Opts) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> start(Resume, Stack, Callbacks, Opts) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +start(<>, Stack, Callbacks, Opts) when Opts#opts.naked_values == true -> + string(Rest, Stack, Callbacks, Opts, []); +start(<<$t/utf8, Rest/binary>>, Stack, Callbacks, Opts) when Opts#opts.naked_values == true -> + tr(Rest, Stack, Callbacks, Opts); +start(<<$f/utf8, Rest/binary>>, Stack, Callbacks, Opts) when Opts#opts.naked_values == true -> + fa(Rest, Stack, Callbacks, Opts); +start(<<$n/utf8, Rest/binary>>, Stack, Callbacks, Opts) when Opts#opts.naked_values == true -> + nu(Rest, Stack, Callbacks, Opts); +start(<>, Stack, Callbacks, Opts) when Opts#opts.naked_values == true -> + negative(Rest, Stack, Callbacks, Opts, "-"); +start(<>, Stack, Callbacks, Opts) when Opts#opts.naked_values == true -> + zero(Rest, Stack, Callbacks, Opts, "0"); +start(<>, Stack, Callbacks, Opts) when ?is_nonzero(S), Opts#opts.naked_values == true -> + integer(Rest, Stack, Callbacks, Opts, [S]); +start(<>, Stack, Callbacks, Opts) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> start(Resume, Stack, Callbacks, Opts) end); start(<>, Stack, Callbacks, Opts) when ?is_whitespace(S) -> start(Rest, Stack, Callbacks, Opts); start(<<>>, Stack, Callbacks, Opts) -> @@ -43,13 +52,8 @@ maybe_done(<>, [object|Stack], Callbacks, Opts) -> key(Rest, [key|Stack], Callbacks, Opts); maybe_done(<>, [array|_] = Stack, Callbacks, Opts) -> value(Rest, Stack, Callbacks, Opts); -maybe_done(<>, Stack, Callbacks, Opts) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> maybe_done(Resume, Stack, Callbacks, Opts) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +maybe_done(<>, Stack, Callbacks, Opts) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> maybe_done(Resume, Stack, Callbacks, Opts) end); maybe_done(<>, Stack, Callbacks, Opts) when ?is_whitespace(S) -> maybe_done(Rest, Stack, Callbacks, Opts); maybe_done(<<>>, [], Callbacks, _Opts) -> @@ -62,13 +66,8 @@ object(<>, [key|Stack], Callbacks, Opts) -> maybe_done(Rest, Stack, callback(end_object, Callbacks), Opts); object(<>, Stack, Callbacks, Opts) -> string(Rest, Stack, Callbacks, Opts, []); -object(<>, Stack, Callbacks, Opts) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> object(Resume, Stack, Callbacks, Opts) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +object(<>, Stack, Callbacks, Opts) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> object(Resume, Stack, Callbacks, Opts) end); object(<>, Stack, Callbacks, Opts) when ?is_whitespace(S) -> object(Rest, Stack, Callbacks, Opts); object(<<>>, Stack, Callbacks, Opts) -> @@ -95,13 +94,8 @@ array(<>, Stack, Callbacks, Opts) -> zero(Rest, Stack, Callbacks, Opts, "0"); array(<>, Stack, Callbacks, Opts) when ?is_nonzero(S) -> integer(Rest, Stack, Callbacks, Opts, [S]); -array(<>, Stack, Callbacks, Opts) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> array(Resume, Stack, Callbacks, Opts) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +array(<>, Stack, Callbacks, Opts) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> array(Resume, Stack, Callbacks, Opts) end); array(<>, Stack, Callbacks, Opts) when ?is_whitespace(S) -> array(Rest, Stack, Callbacks, Opts); array(<<>>, Stack, Callbacks, Opts) -> @@ -126,13 +120,8 @@ value(<>, Stack, Callbacks, Opts) -> zero(Rest, Stack, Callbacks, Opts, "0"); value(<>, Stack, Callbacks, Opts) when ?is_nonzero(S) -> integer(Rest, Stack, Callbacks, Opts, [S]); -value(<>, Stack, Callbacks, Opts) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> value(Resume, Stack, Callbacks, Opts) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +value(<>, Stack, Callbacks, Opts) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> value(Resume, Stack, Callbacks, Opts) end); value(<>, Stack, Callbacks, Opts) when ?is_whitespace(S) -> value(Rest, Stack, Callbacks, Opts); value(<<>>, Stack, Callbacks, Opts) -> @@ -141,13 +130,8 @@ value(<<>>, Stack, Callbacks, Opts) -> colon(<>, [key|Stack], Callbacks, Opts) -> value(Rest, [object|Stack], Callbacks, Opts); -colon(<>, Stack, Callbacks, Opts) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> colon(Resume, Stack, Callbacks, Opts) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +colon(<>, Stack, Callbacks, Opts) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> colon(Resume, Stack, Callbacks, Opts) end); colon(<>, Stack, Callbacks, Opts) when ?is_whitespace(S) -> colon(Rest, Stack, Callbacks, Opts); colon(<<>>, Stack, Callbacks, Opts) -> @@ -156,13 +140,8 @@ colon(<<>>, Stack, Callbacks, Opts) -> key(<>, Stack, Callbacks, Opts) -> string(Rest, Stack, Callbacks, Opts, []); -key(<>, Stack, Callbacks, Opts) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> key(Resume, Stack, Callbacks, Opts) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +key(<>, Stack, Callbacks, Opts) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> key(Resume, Stack, Callbacks, Opts) end); key(<>, Stack, Callbacks, Opts) when ?is_whitespace(S) -> key(Rest, Stack, Callbacks, Opts); key(<<>>, Stack, Callbacks, Opts) -> @@ -237,6 +216,8 @@ escaped_unicode(<<>>, Stack, Callbacks, Opts, String, Acc) -> %% being emitted to the callback handler. no processing of numbers is done in %% process, it's left for the user, though there are convenience functions to %% convert them into erlang floats/integers in jsx_utils.erl. + +%% TODO: actually write that jsx_utils.erl module mentioned above... negative(<<"0"/utf8, Rest/binary>>, Stack, Callbacks, Opts, Acc) -> zero(Rest, Stack, Callbacks, Opts, "0" ++ Acc); @@ -258,13 +239,8 @@ zero(<>, Stack, Callbacks, Opts, Acc) -> fraction(Rest, Stack, Callbacks, Opts, [?decimalpoint] ++ Acc); zero(<>, Stack, Callbacks, Opts, Acc) when ?is_whitespace(S) -> maybe_done(Rest, Stack, callback({number, lists:reverse(Acc)}, Callbacks), Opts); -zero(<>, Stack, Callbacks, Opts, Acc) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> zero(Resume, Stack, Callbacks, Opts, Acc) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +zero(<>, Stack, Callbacks, Opts, Acc) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> zero(Resume, Stack, Callbacks, Opts, Acc) end); zero(<<>>, Stack, Callbacks, Opts, Acc) -> fun(Stream) -> zero(Stream, Stack, Callbacks, Opts, Acc) end. @@ -289,13 +265,8 @@ integer(<>, Stack, Callbacks, Opts, Acc) when ?is_nonzero(S integer(Rest, Stack, Callbacks, Opts, [S] ++ Acc); integer(<>, Stack, Callbacks, Opts, Acc) when ?is_whitespace(S) -> maybe_done(Rest, Stack, callback({number, lists:reverse(Acc)}, Callbacks), Opts); -integer(<>, Stack, Callbacks, Opts, Acc) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> integer(Resume, Stack, Callbacks, Opts, Acc) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +integer(<>, Stack, Callbacks, Opts, Acc) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> integer(Resume, Stack, Callbacks, Opts, Acc) end); integer(<<>>, Stack, Callbacks, Opts, Acc) -> fun(Stream) -> integer(Stream, Stack, Callbacks, Opts, Acc) end. @@ -318,13 +289,8 @@ fraction(<>, Stack, Callbacks, Opts, Acc) when ?is_nonzero( fraction(Rest, Stack, Callbacks, Opts, [S] ++ Acc); fraction(<>, Stack, Callbacks, Opts, Acc) when ?is_whitespace(S) -> maybe_done(Rest, Stack, callback({number, lists:reverse(Acc)}, Callbacks), Opts); -fraction(<>, Stack, Callbacks, Opts, Acc) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> fraction(Resume, Stack, Callbacks, Opts, Acc) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +fraction(<>, Stack, Callbacks, Opts, Acc) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> fraction(Resume, Stack, Callbacks, Opts, Acc) end); fraction(<<>>, Stack, Callbacks, Opts, Acc) -> fun(Stream) -> fraction(Stream, Stack, Callbacks, Opts, Acc) end. @@ -357,13 +323,8 @@ exp(<>, Stack, Callbacks, Opts, Acc) when ?is_nonzero(S) -> exp(Rest, Stack, Callbacks, Opts, [S] ++ Acc); exp(<>, Stack, Callbacks, Opts, Acc) when ?is_whitespace(S) -> maybe_done(Rest, Stack, callback({number, lists:reverse(Acc)}, Callbacks), Opts); -exp(<>, Stack, Callbacks, Opts, Acc) -> - case Opts#opts.comments of - true -> - maybe_comment(Rest, fun(Resume) -> exp(Resume, Stack, Callbacks, Opts, Acc) end) - ; false -> - erlang:error(function_clause, [<>, Stack, Callbacks, Opts]) - end; +exp(<>, Stack, Callbacks, Opts, Acc) when Opts#opts.comments == true -> + maybe_comment(Rest, fun(Resume) -> exp(Resume, Stack, Callbacks, Opts, Acc) end); exp(<<>>, Stack, Callbacks, Opts, Acc) -> fun(Stream) -> exp(Stream, Stack, Callbacks, Opts, Acc) end.