diff options
author | Christopher Lenz <cmlenz@apache.org> | 2009-02-24 22:10:04 +0000 |
---|---|---|
committer | Christopher Lenz <cmlenz@apache.org> | 2009-02-24 22:10:04 +0000 |
commit | 1ba7a12c72cfb645c36187bbb95ea9160c8a3284 (patch) | |
tree | 1b8ca4890d737ce9ceb9c0927b11659666193d33 /src/mochiweb/mochijson2.erl | |
parent | 47895d920228edfb195e62ff04d5aa8ef667ed5b (diff) |
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
Diffstat (limited to 'src/mochiweb/mochijson2.erl')
-rw-r--r-- | src/mochiweb/mochijson2.erl | 100 |
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 |