added naked (unwrapped) values option and rewrote the handling of comments to reduce line count and be slightly clearer

This commit is contained in:
alisdair sullivan 2010-05-18 12:41:32 -07:00
parent 121fe34474
commit 5c36ec18d7
2 changed files with 45 additions and 83 deletions

View file

@ -1,6 +1,7 @@
-record(opts, { -record(opts, {
comments = false, comments = false,
escaped_unicode = ascii escaped_unicode = ascii,
naked_values = false
}). }).
%% whitespace %% whitespace

View file

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