From 1ba7a12c72cfb645c36187bbb95ea9160c8a3284 Mon Sep 17 00:00:00 2001 From: Christopher Lenz Date: Tue, 24 Feb 2009 22:10:04 +0000 Subject: Update MochiWeb in trunk to r97. Closes COUCHDB-255. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@747575 13f79535-47bb-0310-9956-ffa450edef68 --- src/mochiweb/mochijson2.erl | 100 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 6 deletions(-) (limited to 'src/mochiweb/mochijson2.erl') 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(<>) -> + 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 -- cgit v1.2.3