From 8e2d7a02539150f019d03ddb184ff813d8457de5 Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Sun, 7 Dec 2014 16:31:29 -0800 Subject: [PATCH] decoder clause reordering and unrolling to reduce `when` clauses --- src/jsx_decoder.erl | 102 ++++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 27 deletions(-) diff --git a/src/jsx_decoder.erl b/src/jsx_decoder.erl index 0f4f3f2..1ba5c07 100644 --- a/src/jsx_decoder.erl +++ b/src/jsx_decoder.erl @@ -119,10 +119,6 @@ resume(Rest, State, Handler, Acc, Stack, Config) -> Symbol >= $1 andalso Symbol =< $9 ). --define(is_whitespace(Symbol), - Symbol =:= ?space; Symbol =:= ?tab; Symbol =:= ?cr; Symbol =:= ?newline -). - %% error is a macro so the stack trace shows the error site when possible -ifndef(error). @@ -177,8 +173,12 @@ start(Bin, Handler, Stack, Config) -> value(<>, Handler, Stack, Config) -> string(Rest, Handler, Stack, Config); -value(<>, Handler, Stack, Config=#config{strict_single_quotes=false}) -> - string(Rest, Handler, [singlequote|Stack], Config); +value(<>, Handler, Stack, Config) -> + value(Rest, Handler, Stack, Config); +value(<>, Handler, Stack, Config) -> + object(Rest, handle_event(start_object, Handler, Config), [key|Stack], Config); +value(<>, Handler, Stack, Config) -> + array(Rest, handle_event(start_array, Handler, Config), [array|Stack], Config); value(<<$t, Rest/binary>>, Handler, Stack, Config) -> true(Rest, Handler, Stack, Config); value(<<$f, Rest/binary>>, Handler, Stack, Config) -> @@ -189,14 +189,16 @@ value(<>, Handler, Stack, Config) -> negative(Rest, Handler, [$-], Stack, Config); value(<>, Handler, Stack, Config) -> zero(Rest, Handler, [$0], Stack, Config); +value(<>, Handler, Stack, Config) -> + value(Rest, Handler, Stack, Config); +value(<>, Handler, Stack, Config) -> + value(Rest, Handler, Stack, Config); +value(<>, Handler, Stack, Config) -> + value(Rest, Handler, Stack, Config); +value(<>, Handler, Stack, Config=#config{strict_single_quotes=false}) -> + string(Rest, Handler, [singlequote|Stack], Config); value(<>, Handler, Stack, Config) when ?is_nonzero(S) -> integer(Rest, Handler, [S], Stack, Config); -value(<>, Handler, Stack, Config) -> - object(Rest, handle_event(start_object, Handler, Config), [key|Stack], Config); -value(<>, Handler, Stack, Config) -> - array(Rest, handle_event(start_array, Handler, Config), [array|Stack], Config); -value(<>, Handler, Stack, Config) when ?is_whitespace(S) -> - value(Rest, Handler, Stack, Config); value(<> = Rest, Handler, Stack, Config=#config{strict_commas=false}) -> maybe_done(Rest, Handler, Stack, Config); value(<>, Handler, Stack, Config=#config{strict_comments=true}) -> @@ -215,12 +217,18 @@ value(Bin, Handler, Stack, Config) -> object(<>, Handler, Stack, Config) -> string(Rest, Handler, Stack, Config); -object(<>, Handler, Stack, Config=#config{strict_single_quotes=false}) -> - string(Rest, Handler, [singlequote|Stack], Config); +object(<>, Handler, Stack, Config) -> + object(Rest, Handler, Stack, Config); object(<>, Handler, [key|Stack], Config) -> maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config); -object(<>, Handler, Stack, Config) when ?is_whitespace(S) -> +object(<>, Handler, Stack, Config) -> object(Rest, Handler, Stack, Config); +object(<>, Handler, Stack, Config) -> + object(Rest, Handler, Stack, Config); +object(<>, Handler, Stack, Config) -> + object(Rest, Handler, Stack, Config); +object(<>, Handler, Stack, Config=#config{strict_single_quotes=false}) -> + string(Rest, Handler, [singlequote|Stack], Config); object(<>, Handler, Stack, Config=#config{strict_comments=true}) -> ?error(object, <>, Handler, Stack, Config); object(<>, Handler, Stack, Config) -> @@ -237,7 +245,13 @@ object(Bin, Handler, Stack, Config) -> array(<>, Handler, [array|Stack], Config) -> maybe_done(Rest, handle_event(end_array, Handler, Config), Stack, Config); -array(<>, Handler, Stack, Config) when ?is_whitespace(S) -> +array(<>, Handler, Stack, Config) -> + array(Rest, Handler, Stack, Config); +array(<>, Handler, Stack, Config) -> + array(Rest, Handler, Stack, Config); +array(<>, Handler, Stack, Config) -> + array(Rest, Handler, Stack, Config); +array(<>, Handler, Stack, Config) -> array(Rest, Handler, Stack, Config); array(<>, Handler, Stack, Config=#config{strict_comments=true}) -> value(<>, Handler, Stack, Config); @@ -255,7 +269,13 @@ array(Bin, Handler, Stack, Config) -> colon(<>, Handler, [key|Stack], Config) -> value(Rest, Handler, [object|Stack], Config); -colon(<>, Handler, Stack, Config) when ?is_whitespace(S) -> +colon(<>, Handler, Stack, Config) -> + colon(Rest, Handler, Stack, Config); +colon(<>, Handler, Stack, Config) -> + colon(Rest, Handler, Stack, Config); +colon(<>, Handler, Stack, Config) -> + colon(Rest, Handler, Stack, Config); +colon(<>, Handler, Stack, Config) -> colon(Rest, Handler, Stack, Config); colon(<>, Handler, Stack, Config=#config{strict_comments=true}) -> ?error(colon, <>, Handler, Stack, Config); @@ -273,12 +293,18 @@ colon(Bin, Handler, Stack, Config) -> key(<>, Handler, Stack, Config) -> string(Rest, Handler, Stack, Config); -key(<>, Handler, Stack, Config=#config{strict_single_quotes=false}) -> - string(Rest, Handler, [singlequote|Stack], Config); -key(<>, Handler, Stack, Config) when ?is_whitespace(S) -> +key(<>, Handler, Stack, Config) -> key(Rest, Handler, Stack, Config); key(<>, Handler, [key|Stack], Config=#config{strict_commas=false}) -> maybe_done(<>, Handler, [object|Stack], Config); +key(<>, Handler, Stack, Config) -> + key(Rest, Handler, Stack, Config); +key(<>, Handler, Stack, Config) -> + key(Rest, Handler, Stack, Config); +key(<>, Handler, Stack, Config) -> + key(Rest, Handler, Stack, Config); +key(<>, Handler, Stack, Config=#config{strict_single_quotes=false}) -> + string(Rest, Handler, [singlequote|Stack], Config); key(<>, Handler, Stack, Config=#config{strict_comments=true}) -> ?error(key, <>, Handler, Stack, Config); key(<>, Handler, Stack, Config) -> @@ -310,10 +336,17 @@ string(<>, Handler, Acc, Stack, Config) -> string(Rest, Handler, [Acc, maybe_replace(?solidus, Config)], Stack, Config); string(<>, Handler, Acc, Stack, Config) -> unescape(Rest, Handler, Acc, Stack, Config); -string(<>, Handler, Acc, Stack, Config=#config{uescape=true}) when X >= 16#80 -> - string(Rest, Handler, [Acc, json_escape_sequence(X)], Stack, Config); -string(<>, Handler, Acc, Stack, Config) when X == 16#2028; X == 16#2029 -> - string(Rest, Handler, [Acc, maybe_replace(X, Config)], Stack, Config); +string(<>, Handler, Acc, Stack, Config=#config{uescape=true}) -> + case X of + X when X < 16#80 -> string(Rest, Handler, [Acc, X], Stack, Config); + X -> string(Rest, Handler, [Acc, json_escape_sequence(X)], Stack, Config) + end; +%% u+2028 +string(<<226, 128, 168, Rest/binary>>, Handler, Acc, Stack, Config) -> + string(Rest, Handler, [Acc, maybe_replace(16#2028, Config)], Stack, Config); +%% u+2029 +string(<<226, 128, 169, Rest/binary>>, Handler, Acc, Stack, Config) -> + string(Rest, Handler, [Acc, maybe_replace(16#2029, Config)], Stack, Config); string(<<_/utf8, _/binary>> = Bin, Handler, Acc, Stack, Config) -> Size = count(Bin, 0, Config), <> = Bin, @@ -616,7 +649,10 @@ count(<<_, Rest/binary>>, N, Config=#config{dirty_strings=true}) -> count(<<_/utf8, _/binary>>, N, #config{uescape=true}) -> N; count(<>, N, Config) when X < 16#800 -> count(Rest, N + 2, Config); -count(<>, N, _) when X == 16#2028; X == 16#2029 -> N; +%% u+2028 +count(<<226, 128, 168, _/binary>>, N, _) -> N; +%% u+2029 +count(<<226, 128, 169, _/binary>>, N, _) -> N; count(<>, N, Config) when X < 16#10000 -> count(Rest, N + 3, Config); count(<<_/utf8, Rest/binary>>, N, Config) -> @@ -944,6 +980,8 @@ comment(Bin, Handler, Resume, Stack, Config) -> maybe_done(<>, Handler, [], Config) -> done(Rest, handle_event(end_json, Handler, Config), [], Config); +maybe_done(<>, Handler, Stack, Config) -> + maybe_done(Rest, Handler, Stack, Config); maybe_done(<>, Handler, [object|Stack], Config) -> maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config); maybe_done(<>, Handler, [array|Stack], Config) -> @@ -952,7 +990,11 @@ maybe_done(<>, Handler, [object|Stack], Config) -> key(Rest, Handler, [key|Stack], Config); maybe_done(<>, Handler, [array|_] = Stack, Config) -> value(Rest, Handler, Stack, Config); -maybe_done(<>, Handler, Stack, Config) when ?is_whitespace(S) -> +maybe_done(<>, Handler, Stack, Config) -> + maybe_done(Rest, Handler, Stack, Config); +maybe_done(<>, Handler, Stack, Config) -> + maybe_done(Rest, Handler, Stack, Config); +maybe_done(<>, Handler, Stack, Config) -> maybe_done(Rest, Handler, Stack, Config); maybe_done(<>, Handler, Stack, Config=#config{strict_comments=true}) -> ?error(maybe_done, <>, Handler, Stack, Config); @@ -968,7 +1010,13 @@ maybe_done(Bin, Handler, Stack, Config) -> ?error(maybe_done, Bin, Handler, Stack, Config). -done(<>, Handler, [], Config) when ?is_whitespace(S) -> +done(<>, Handler, [], Config) -> + done(Rest, Handler, [], Config); +done(<>, Handler, [], Config) -> + done(Rest, Handler, [], Config); +done(<>, Handler, [], Config) -> + done(Rest, Handler, [], Config); +done(<>, Handler, [], Config) -> done(Rest, Handler, [], Config); done(<>, Handler, Stack, Config=#config{strict_comments=true}) -> ?error(done, <>, Handler, Stack, Config);