summaryrefslogtreecommitdiff
path: root/src/mochiweb/mochijson2.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mochiweb/mochijson2.erl')
-rw-r--r--src/mochiweb/mochijson2.erl100
1 files changed, 94 insertions, 6 deletions
diff --git a/src/mochiweb/mochijson2.erl b/src/mochiweb/mochijson2.erl
index 9b59c7df..8bfd23c8 100644
--- a/src/mochiweb/mochijson2.erl
+++ b/src/mochiweb/mochijson2.erl
@@ -132,13 +132,81 @@ json_encode_proplist(Props, State) ->
lists:reverse([$\} | Acc1]).
json_encode_string(A, _State) when is_atom(A) ->
- json_encode_string_unicode(xmerl_ucs:from_utf8(atom_to_list(A)), [?Q]);
+ L = atom_to_list(A),
+ case json_string_is_safe(L) of
+ true ->
+ [?Q, L, ?Q];
+ false ->
+ json_encode_string_unicode(xmerl_ucs:from_utf8(L), [?Q])
+ end;
json_encode_string(B, _State) when is_binary(B) ->
- json_encode_string_unicode(xmerl_ucs:from_utf8(B), [?Q]);
+ case json_bin_is_safe(B) of
+ true ->
+ [?Q, B, ?Q];
+ false ->
+ json_encode_string_unicode(xmerl_ucs:from_utf8(B), [?Q])
+ end;
json_encode_string(I, _State) when is_integer(I) ->
- json_encode_string_unicode(integer_to_list(I), [?Q]);
+ [?Q, integer_to_list(I), ?Q];
json_encode_string(L, _State) when is_list(L) ->
- json_encode_string_unicode(L, [?Q]).
+ case json_string_is_safe(L) of
+ true ->
+ [?Q, L, ?Q];
+ false ->
+ json_encode_string_unicode(L, [?Q])
+ end.
+
+json_string_is_safe([]) ->
+ true;
+json_string_is_safe([C | Rest]) ->
+ case C of
+ ?Q ->
+ false;
+ $\\ ->
+ false;
+ $\b ->
+ false;
+ $\f ->
+ false;
+ $\n ->
+ false;
+ $\r ->
+ false;
+ $\t ->
+ false;
+ C when C >= 0, C < $\s; C >= 16#7f, C =< 16#10FFFF ->
+ false;
+ C when C < 16#7f ->
+ json_string_is_safe(Rest);
+ _ ->
+ false
+ end.
+
+json_bin_is_safe(<<>>) ->
+ true;
+json_bin_is_safe(<<C, Rest/binary>>) ->
+ case C of
+ ?Q ->
+ false;
+ $\\ ->
+ false;
+ $\b ->
+ false;
+ $\f ->
+ false;
+ $\n ->
+ false;
+ $\r ->
+ false;
+ $\t ->
+ false;
+ C when C >= 0, C < $\s; C >= 16#7f, C =< 16#10FFFF ->
+ false;
+ C when C < 16#7f ->
+ json_bin_is_safe(Rest);
+ _ ->
+ false
+ end.
json_encode_string_unicode([], Acc) ->
lists:reverse([$\" | Acc]);
@@ -260,8 +328,28 @@ decode_array(B, S=#decoder{state=comma}, Acc) ->
decode_array(B, S1#decoder{state=any}, Acc)
end.
-tokenize_string(B, S) ->
- tokenize_string(B, S, []).
+tokenize_string(B, S=#decoder{offset=O}) ->
+ case tokenize_string_fast(B, O) of
+ {escape, O1} ->
+ Length = O1 - O,
+ S1 = ?ADV_COL(S, Length),
+ <<_:O/binary, Head:Length/binary, _/binary>> = B,
+ tokenize_string(B, S1, lists:reverse(binary_to_list(Head)));
+ O1 ->
+ Length = O1 - O,
+ <<_:O/binary, String:Length/binary, ?Q, _/binary>> = B,
+ {{const, String}, ?ADV_COL(S, Length + 1)}
+ end.
+
+tokenize_string_fast(B, O) ->
+ case B of
+ <<_:O/binary, ?Q, _/binary>> ->
+ O;
+ <<_:O/binary, C, _/binary>> when C =/= $\\ ->
+ tokenize_string_fast(B, 1 + O);
+ _ ->
+ {escape, O}
+ end.
tokenize_string(B, S=#decoder{offset=O}, Acc) ->
case B of