couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cml...@apache.org
Subject svn commit: r659234 - in /incubator/couchdb/vendor/mochiweb/current/src: mochifmt.erl mochifmt_records.erl mochifmt_std.erl mochiweb.erl mochiweb_html.erl mochiweb_multipart.erl mochiweb_request.erl mochiweb_socket_server.erl
Date Thu, 22 May 2008 20:09:18 GMT
Author: cmlenz
Date: Thu May 22 13:09:17 2008
New Revision: 659234

URL: http://svn.apache.org/viewvc?rev=659234&view=rev
Log:
Updated MochiWeb vendor branch to r73 from <http://mochiweb.googlecode.com/svn/trunk/>.

Added:
    incubator/couchdb/vendor/mochiweb/current/src/mochifmt.erl
    incubator/couchdb/vendor/mochiweb/current/src/mochifmt_records.erl
    incubator/couchdb/vendor/mochiweb/current/src/mochifmt_std.erl
Modified:
    incubator/couchdb/vendor/mochiweb/current/src/mochiweb.erl
    incubator/couchdb/vendor/mochiweb/current/src/mochiweb_html.erl
    incubator/couchdb/vendor/mochiweb/current/src/mochiweb_multipart.erl
    incubator/couchdb/vendor/mochiweb/current/src/mochiweb_request.erl
    incubator/couchdb/vendor/mochiweb/current/src/mochiweb_socket_server.erl

Added: incubator/couchdb/vendor/mochiweb/current/src/mochifmt.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochifmt.erl?rev=659234&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochifmt.erl (added)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochifmt.erl Thu May 22 13:09:17 2008
@@ -0,0 +1,426 @@
+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2008 Mochi Media, Inc.
+
+%% @doc String Formatting for Erlang, inspired by Python 2.6
+%%      (<a href="http://www.python.org/dev/peps/pep-3101/">PEP 3101</a>).
+%%
+-module(mochifmt).
+-author('bob@mochimedia.com').
+-export([format/2, format_field/2, convert_field/2, get_value/2, get_field/2]).
+-export([tokenize/1, format/3, get_field/3, format_field/3]).
+-export([bformat/2, bformat/3]).
+-export([f/2, f/3]).
+-export([test/0]).
+
+-record(conversion, {length, precision, ctype, align, fill_char, sign}).
+
+%% @spec tokenize(S::string()) -> tokens()
+%% @doc Tokenize a format string into mochifmt's internal format.
+tokenize(S) ->
+    {?MODULE, tokenize(S, "", [])}.
+
+%% @spec convert_field(Arg, Conversion::conversion()) -> term()
+%% @doc Process Arg according to the given explicit conversion specifier.
+convert_field(Arg, "") ->
+    Arg;
+convert_field(Arg, "r") ->
+    repr(Arg);
+convert_field(Arg, "s") ->
+    str(Arg).
+
+%% @spec get_value(Key::string(), Args::args()) -> term()
+%% @doc Get the Key from Args. If Args is a tuple then convert Key to
+%%      an integer and get element(1 + Key, Args). If Args is a list and Key
+%%      can be parsed as an integer then use lists:nth(1 + Key, Args),
+%%      otherwise try and look for Key in Args as a proplist, converting
+%%      Key to an atom or binary if necessary.
+get_value(Key, Args) when is_tuple(Args) ->
+    element(1 + list_to_integer(Key), Args);
+get_value(Key, Args) when is_list(Args) ->
+    try lists:nth(1 + list_to_integer(Key), Args)
+    catch error:_ ->
+            {_K, V} = proplist_lookup(Key, Args),
+            V
+    end.
+
+%% @spec get_field(Key::string(), Args) -> term()
+%% @doc Consecutively call get_value/2 on parts of Key delimited by ".",
+%%      replacing Args with the result of the previous get_value. This
+%%      is used to implement formats such as {0.0}.
+get_field(Key, Args) ->
+    get_field(Key, Args, ?MODULE).
+
+%% @spec get_field(Key::string(), Args, Module) -> term()
+%% @doc Consecutively call Module:get_value/2 on parts of Key delimited by ".",
+%%      replacing Args with the result of the previous get_value. This
+%%      is used to implement formats such as {0.0}.
+get_field(Key, Args, Module) ->
+    {Name, Next} = lists:splitwith(fun (C) -> C =/= $. end, Key),
+    Res = try Module:get_value(Name, Args)
+          catch error:undef -> get_value(Name, Args) end,
+    case Next of
+        "" ->
+            Res;
+        "." ++ S1 ->
+            get_field(S1, Res, Module)
+    end.
+
+%% @spec format(Format::string(), Args) -> iolist()
+%% @doc Format Args with Format.
+format(Format, Args) ->
+    format(Format, Args, ?MODULE).
+
+%% @spec format(Format::string(), Args, Module) -> iolist()
+%% @doc Format Args with Format using Module.
+format({?MODULE, Parts}, Args, Module) ->
+    format2(Parts, Args, Module, []);
+format(S, Args, Module) ->
+    format(tokenize(S), Args, Module).
+
+%% @spec format_field(Arg, Format) -> iolist()
+%% @doc Format Arg with Format.
+format_field(Arg, Format) ->
+    format_field(Arg, Format, ?MODULE).
+
+%% @spec format_field(Arg, Format, _Module) -> iolist()
+%% @doc Format Arg with Format.
+format_field(Arg, Format, _Module) ->
+    F = default_ctype(Arg, parse_std_conversion(Format)),
+    fix_padding(fix_sign(convert2(Arg, F), F), F).
+
+%% @spec f(Format::string(), Args) -> string()
+%% @doc Format Args with Format and return a string().
+f(Format, Args) ->
+    f(Format, Args, ?MODULE).
+
+%% @spec f(Format::string(), Args, Module) -> string()
+%% @doc Format Args with Format using Module and return a string().
+f(Format, Args, Module) ->
+    case lists:member(${, Format) of
+        true ->
+            binary_to_list(bformat(Format, Args, Module));
+        false ->
+            Format
+    end.
+
+%% @spec bformat(Format::string(), Args) -> binary()
+%% @doc Format Args with Format and return a binary().
+bformat(Format, Args) ->
+    iolist_to_binary(format(Format, Args)).
+
+%% @spec bformat(Format::string(), Args, Module) -> binary()
+%% @doc Format Args with Format using Module and return a binary().
+bformat(Format, Args, Module) ->
+    iolist_to_binary(format(Format, Args, Module)).
+
+%% @spec test() -> ok
+%% @doc Run tests.
+test() ->
+    ok = test_tokenize(),
+    ok = test_format(),
+    ok = test_std(),
+    ok = test_records(),
+    ok.
+
+%% Internal API
+
+add_raw("", Acc) ->
+    Acc;
+add_raw(S, Acc) ->
+    [{raw, lists:reverse(S)} | Acc].
+
+tokenize([], S, Acc) ->
+    lists:reverse(add_raw(S, Acc));
+tokenize("{{" ++ Rest, S, Acc) ->
+    tokenize(Rest, "{" ++ S, Acc);
+tokenize("{" ++ Rest, S, Acc) ->
+    {Format, Rest1} = tokenize_format(Rest),
+    tokenize(Rest1, "", [{format, make_format(Format)} | add_raw(S, Acc)]);
+tokenize("}}" ++ Rest, S, Acc) ->
+    tokenize(Rest, "}" ++ S, Acc);
+tokenize([C | Rest], S, Acc) ->
+    tokenize(Rest, [C | S], Acc).
+
+tokenize_format(S) ->
+    tokenize_format(S, 1, []).
+
+tokenize_format("}" ++ Rest, 1, Acc) ->
+    {lists:reverse(Acc), Rest};
+tokenize_format("}" ++ Rest, N, Acc) ->
+    tokenize_format(Rest, N - 1, "}" ++ Acc);
+tokenize_format("{" ++ Rest, N, Acc) ->
+    tokenize_format(Rest, 1 + N, "{" ++ Acc);
+tokenize_format([C | Rest], N, Acc) ->
+    tokenize_format(Rest, N, [C | Acc]).
+
+make_format(S) ->
+    {Name0, Spec} = case lists:splitwith(fun (C) -> C =/= $: end, S) of
+                        {_, ""} ->
+                            {S, ""};
+                        {SN, ":" ++ SS} ->
+                            {SN, SS}
+                    end,
+    {Name, Transform} = case lists:splitwith(fun (C) -> C =/= $! end, Name0) of
+                            {_, ""} ->
+                                {Name0, ""};
+                            {TN, "!" ++ TT} ->
+                                {TN, TT}
+                        end,
+    {Name, Transform, Spec}.
+
+proplist_lookup(S, P) ->
+    A = try list_to_existing_atom(S)
+        catch error:_ -> make_ref() end,
+    B = try list_to_binary(S)
+        catch error:_ -> make_ref() end,
+    proplist_lookup2({S, A, B}, P).
+
+proplist_lookup2({KS, KA, KB}, [{K, V} | _])
+  when KS =:= K orelse KA =:= K orelse KB =:= K ->
+    {K, V};
+proplist_lookup2(Keys, [_ | Rest]) ->
+    proplist_lookup2(Keys, Rest).
+
+format2([], _Args, _Module, Acc) ->
+    lists:reverse(Acc);
+format2([{raw, S} | Rest], Args, Module, Acc) ->
+    format2(Rest, Args, Module, [S | Acc]);
+format2([{format, {Key, Convert, Format0}} | Rest], Args, Module, Acc) ->
+    Format = f(Format0, Args, Module),
+    V = case Module of
+            ?MODULE ->
+                V0 = get_field(Key, Args),
+                V1 = convert_field(V0, Convert),
+                format_field(V1, Format);
+            _ ->
+                V0 = try Module:get_field(Key, Args)
+                     catch error:undef -> get_field(Key, Args, Module) end,
+                V1 = try Module:convert_field(V0, Convert)
+                     catch error:undef -> convert_field(V0, Convert) end,
+                try Module:format_field(V1, Format)
+                catch error:undef -> format_field(V1, Format, Module) end
+        end,
+    format2(Rest, Args, Module, [V | Acc]).
+
+default_ctype(_Arg, C=#conversion{ctype=N}) when N =/= undefined ->
+    C;
+default_ctype(Arg, C) when is_integer(Arg) ->
+    C#conversion{ctype=decimal};
+default_ctype(Arg, C) when is_float(Arg) ->
+    C#conversion{ctype=general};
+default_ctype(_Arg, C) ->
+    C#conversion{ctype=string}.
+
+fix_padding(Arg, #conversion{length=undefined}) ->
+    Arg;
+fix_padding(Arg, F=#conversion{length=Length, fill_char=Fill0, align=Align0,
+                               ctype=Type}) ->
+    Padding = Length - iolist_size(Arg),
+    Fill = case Fill0 of
+               undefined ->
+                   $\s;
+               _ ->
+                   Fill0
+           end,
+    Align = case Align0 of
+                undefined ->
+                    case Type of
+                        string ->
+                            left;
+                        _ ->
+                            right
+                    end;
+                _ ->
+                    Align0
+            end,
+    case Padding > 0 of
+        true ->
+            do_padding(Arg, Padding, Fill, Align, F);
+        false ->
+            Arg
+    end.
+
+do_padding(Arg, Padding, Fill, right, _F) ->
+    [lists:duplicate(Padding, Fill), Arg];
+do_padding(Arg, Padding, Fill, center, _F) ->
+    LPadding = lists:duplicate(Padding div 2, Fill),
+    RPadding = case Padding band 1 of
+                   1 ->
+                       [Fill | LPadding];
+                   _ ->
+                       LPadding
+               end,
+    [LPadding, Arg, RPadding];
+do_padding([$- | Arg], Padding, Fill, sign_right, _F) ->
+    [[$- | lists:duplicate(Padding, Fill)], Arg];
+do_padding(Arg, Padding, Fill, sign_right, #conversion{sign=$-}) ->
+    [lists:duplicate(Padding, Fill), Arg];
+do_padding([S | Arg], Padding, Fill, sign_right, #conversion{sign=S}) ->
+    [[S | lists:duplicate(Padding, Fill)], Arg];
+do_padding(Arg, Padding, Fill, sign_right, #conversion{sign=undefined}) ->
+    [lists:duplicate(Padding, Fill), Arg];
+do_padding(Arg, Padding, Fill, left, _F) ->
+    [Arg | lists:duplicate(Padding, Fill)].
+
+fix_sign(Arg, #conversion{sign=$+}) when Arg >= 0 ->
+    [$+, Arg];
+fix_sign(Arg, #conversion{sign=$\s}) when Arg >= 0 ->
+    [$\s, Arg];
+fix_sign(Arg, _F) ->
+    Arg.
+
+ctype($\%) -> percent;
+ctype($s) -> string;
+ctype($b) -> bin;
+ctype($o) -> oct;
+ctype($X) -> upper_hex;
+ctype($x) -> hex;
+ctype($c) -> char;
+ctype($d) -> decimal;
+ctype($g) -> general;
+ctype($f) -> fixed;
+ctype($e) -> exp.
+
+align($<) -> left;
+align($>) -> right;
+align($^) -> center;
+align($=) -> sign_right.
+
+convert2(Arg, F=#conversion{ctype=percent}) ->
+    [convert2(100.0 * Arg, F#conversion{ctype=fixed}), $\%];
+convert2(Arg, #conversion{ctype=string}) ->
+    str(Arg);
+convert2(Arg, #conversion{ctype=bin}) ->
+    erlang:integer_to_list(Arg, 2);
+convert2(Arg, #conversion{ctype=oct}) ->
+    erlang:integer_to_list(Arg, 8);
+convert2(Arg, #conversion{ctype=upper_hex}) ->
+    erlang:integer_to_list(Arg, 16);
+convert2(Arg, #conversion{ctype=hex}) ->
+    string:to_lower(erlang:integer_to_list(Arg, 16));
+convert2(Arg, #conversion{ctype=char}) when Arg < 16#80 ->
+    [Arg];
+convert2(Arg, #conversion{ctype=char}) ->
+    xmerl_ucs:to_utf8(Arg);
+convert2(Arg, #conversion{ctype=decimal}) ->
+    integer_to_list(Arg);
+convert2(Arg, #conversion{ctype=general, precision=undefined}) ->
+    try mochinum:digits(Arg)
+    catch error:undef -> io_lib:format("~g", [Arg]) end;
+convert2(Arg, #conversion{ctype=fixed, precision=undefined}) ->
+    io_lib:format("~f", [Arg]);
+convert2(Arg, #conversion{ctype=exp, precision=undefined}) ->
+    io_lib:format("~e", [Arg]);
+convert2(Arg, #conversion{ctype=general, precision=P}) ->
+    io_lib:format("~." ++ integer_to_list(P) ++ "g", [Arg]);
+convert2(Arg, #conversion{ctype=fixed, precision=P}) ->
+    io_lib:format("~." ++ integer_to_list(P) ++ "f", [Arg]);
+convert2(Arg, #conversion{ctype=exp, precision=P}) ->
+    io_lib:format("~." ++ integer_to_list(P) ++ "e", [Arg]).
+
+str(A) when is_atom(A) ->
+    atom_to_list(A);
+str(I) when is_integer(I) ->
+    integer_to_list(I);
+str(F) when is_float(F) ->
+    try mochinum:digits(F)
+    catch error:undef -> io_lib:format("~g", [F]) end;
+str(L) when is_list(L) ->
+    L;
+str(B) when is_binary(B) ->
+    B;
+str(P) ->
+    repr(P).
+
+repr(P) when is_float(P) ->
+    try mochinum:digits(P)
+    catch error:undef -> float_to_list(P) end;
+repr(P) ->
+    io_lib:format("~p", [P]).
+
+parse_std_conversion(S) ->
+    parse_std_conversion(S, #conversion{}).
+
+parse_std_conversion("", Acc) ->
+    Acc;
+parse_std_conversion([Fill, Align | Spec], Acc)
+  when Align =:= $< orelse Align =:= $> orelse Align =:= $= orelse Align =:= $^ ->
+    parse_std_conversion(Spec, Acc#conversion{fill_char=Fill,
+                                              align=align(Align)});
+parse_std_conversion([Align | Spec], Acc)
+  when Align =:= $< orelse Align =:= $> orelse Align =:= $= orelse Align =:= $^ ->
+    parse_std_conversion(Spec, Acc#conversion{align=align(Align)});
+parse_std_conversion([Sign | Spec], Acc)
+  when Sign =:= $+ orelse Sign =:= $- orelse Sign =:= $\s ->
+    parse_std_conversion(Spec, Acc#conversion{sign=Sign});
+parse_std_conversion("0" ++ Spec, Acc) ->
+    Align = case Acc#conversion.align of
+                undefined ->
+                    sign_right;
+                A ->
+                    A
+            end,
+    parse_std_conversion(Spec, Acc#conversion{fill_char=$0, align=Align});
+parse_std_conversion(Spec=[D|_], Acc) when D >= $0 andalso D =< $9 ->
+    {W, Spec1} = lists:splitwith(fun (C) -> C >= $0 andalso C =< $9 end, Spec),
+    parse_std_conversion(Spec1, Acc#conversion{length=list_to_integer(W)});
+parse_std_conversion([$. | Spec], Acc) ->
+    case lists:splitwith(fun (C) -> C >= $0 andalso C =< $9 end, Spec) of
+        {"", Spec1} ->
+            parse_std_conversion(Spec1, Acc);
+        {P, Spec1} ->
+            parse_std_conversion(Spec1,
+                                 Acc#conversion{precision=list_to_integer(P)})
+    end;
+parse_std_conversion([Type], Acc) ->
+    parse_std_conversion("", Acc#conversion{ctype=ctype(Type)}).
+
+test_tokenize() ->
+    {?MODULE, [{raw, "ABC"}]} = tokenize("ABC"),
+    {?MODULE, [{format, {"0", "", ""}}]} = tokenize("{0}"),
+    {?MODULE, [{raw, "ABC"}, {format, {"1", "", ""}}, {raw, "DEF"}]} =
+        tokenize("ABC{1}DEF"),
+    ok.
+
+test_format() ->
+    <<"  -4">> = bformat("{0:4}", [-4]),
+    <<"   4">> = bformat("{0:4}", [4]),
+    <<"   4">> = bformat("{0:{0}}", [4]),
+    <<"4   ">> = bformat("{0:4}", ["4"]),
+    <<"4   ">> = bformat("{0:{0}}", ["4"]),
+    <<"1.2yoDEF">> = bformat("{2}{0}{1}{3}", {yo, "DE", 1.2, <<"F">>}),
+    <<"cafebabe">> = bformat("{0:x}", {16#cafebabe}),
+    <<"CAFEBABE">> = bformat("{0:X}", {16#cafebabe}),
+    <<"CAFEBABE">> = bformat("{0:X}", {16#cafebabe}),
+    <<"755">> = bformat("{0:o}", {8#755}),
+    <<"a">> = bformat("{0:c}", {97}),
+    %% Horizontal ellipsis
+    <<226, 128, 166>> = bformat("{0:c}", {16#2026}),
+    <<"11">> = bformat("{0:b}", {3}),
+    <<"11">> = bformat("{0:b}", [3]),
+    <<"11">> = bformat("{three:b}", [{three, 3}]),
+    <<"11">> = bformat("{three:b}", [{"three", 3}]),
+    <<"11">> = bformat("{three:b}", [{<<"three">>, 3}]),
+    <<"\"foo\"">> = bformat("{0!r}", {"foo"}),
+    <<"2008-5-4">> = bformat("{0.0}-{0.1}-{0.2}", {{2008,5,4}}),
+    <<"2008-05-04">> = bformat("{0.0:04}-{0.1:02}-{0.2:02}", {{2008,5,4}}),
+    <<"foo6bar-6">> = bformat("foo{1}{0}-{1}", {bar, 6}),
+    <<"-'atom test'-">> = bformat("-{arg!r}-", [{arg, 'atom test'}]),
+    <<"2008-05-04">> = bformat("{0.0:0{1.0}}-{0.1:0{1.1}}-{0.2:0{1.2}}",
+                               {{2008,5,4}, {4, 2, 2}}),
+    ok.
+
+test_std() ->
+    M = mochifmt_std:new(),
+    <<"01">> = bformat("{0}{1}", [0, 1], M),
+    ok.
+
+test_records() ->
+    M = mochifmt_records:new([{conversion, record_info(fields, conversion)}]),
+    R = #conversion{length=long, precision=hard, sign=peace},
+    long = M:get_value("length", R),
+    hard = M:get_value("precision", R),
+    peace = M:get_value("sign", R),
+    <<"long hard">> = bformat("{length} {precision}", R, M),
+    <<"long hard">> = bformat("{0.length} {0.precision}", [R], M),
+    ok.

Added: incubator/couchdb/vendor/mochiweb/current/src/mochifmt_records.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochifmt_records.erl?rev=659234&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochifmt_records.erl (added)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochifmt_records.erl Thu May 22 13:09:17
2008
@@ -0,0 +1,30 @@
+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2008 Mochi Media, Inc.
+
+%% @doc Formatter that understands records.
+%%
+%% Usage:
+%%
+%%    1> M = mochifmt_records:new([{rec, record_info(fields, rec)}]),
+%%    M:format("{0.bar}", [#rec{bar=foo}]).
+%%    foo
+
+-module(mochifmt_records, [Recs]).
+-author('bob@mochimedia.com').
+-export([get_value/2]).
+
+get_value(Key, Rec) when is_tuple(Rec) and is_atom(element(1, Rec)) ->
+    try begin
+            Atom = list_to_existing_atom(Key),
+            {_, Fields} = proplists:lookup(element(1, Rec), Recs),
+            element(get_rec_index(Atom, Fields, 2), Rec)
+        end
+    catch error:_ -> mochifmt:get_value(Key, Rec)
+    end;
+get_value(Key, Args) ->
+    mochifmt:get_value(Key, Args).
+
+get_rec_index(Atom, [Atom | _], Index) ->
+    Index;
+get_rec_index(Atom, [_ | Rest], Index) ->
+    get_rec_index(Atom, Rest, 1 + Index).

Added: incubator/couchdb/vendor/mochiweb/current/src/mochifmt_std.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochifmt_std.erl?rev=659234&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochifmt_std.erl (added)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochifmt_std.erl Thu May 22 13:09:17 2008
@@ -0,0 +1,23 @@
+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2008 Mochi Media, Inc.
+
+%% @doc Template module for a mochifmt formatter.
+
+-module(mochifmt_std, []).
+-author('bob@mochimedia.com').
+-export([format/2, get_value/2, format_field/2, get_field/2, convert_field/2]).
+
+format(Format, Args) ->
+    mochifmt:format(Format, Args, THIS).
+
+get_field(Key, Args) ->
+    mochifmt:get_field(Key, Args, THIS).
+
+convert_field(Key, Args) ->
+    mochifmt:convert_field(Key, Args).
+
+get_value(Key, Args) ->
+    mochifmt:get_value(Key, Args).
+
+format_field(Arg, Format) ->
+    mochifmt:format_field(Arg, Format, THIS).

Modified: incubator/couchdb/vendor/mochiweb/current/src/mochiweb.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb.erl?rev=659234&r1=659233&r2=659234&view=diff
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb.erl (original)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb.erl Thu May 22 13:09:17 2008
@@ -35,6 +35,7 @@
     mochijson:test(),
     mochiweb_charref:test(),
     mochiweb_html:test(),
+    mochifmt:test(),
     test_request(),
     ok.
 

Modified: incubator/couchdb/vendor/mochiweb/current/src/mochiweb_html.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb_html.erl?rev=659234&r1=659233&r2=659234&view=diff
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb_html.erl (original)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb_html.erl Thu May 22 13:09:17 2008
@@ -35,7 +35,7 @@
 -define(IS_LITERAL_SAFE(C),
         ((C >= $A andalso C =< $Z) orelse (C >= $a andalso C =< $z)
          orelse (C >= $0 andalso C =< $9))).
-                                
+
 -record(decoder, {line=1,
                   column=1,
                   offset=0}).
@@ -202,7 +202,7 @@
     attrs_to_html(Rest,
                   [[<<" ">>, escape(K), <<"=\"">>,
                     escape_attr(V), <<"\"">>] | Acc]).
-    
+
 test_escape() ->
     <<"&amp;quot;\"word &lt;&lt;up!&amp;quot;">> =
         escape(<<"&quot;\"word <<up!&quot;">>),
@@ -299,6 +299,14 @@
         tokens(<<"<foo bar=baz wibble='wibble' alice=bob/>">>),
     [{comment, <<"[if lt IE 7]>\n<style type=\"text/css\">\n.no_ie { display:
none; }\n</style>\n<![endif]">>}] =
         tokens(<<"<!--[if lt IE 7]>\n<style type=\"text/css\">\n.no_ie
{ display: none; }\n</style>\n<![endif]-->">>),
+    [{start_tag, <<"script">>, [{<<"type">>, <<"text/javascript">>}],
false},
+     {data, <<" A= B <= C ">>, false},
+     {end_tag, <<"script">>}] =
+        tokens(<<"<script type=\"text/javascript\"> A= B <= C </script>">>),
+    [{start_tag, <<"textarea">>, [], false},
+     {data, <<"<html></body>">>, false},
+     {end_tag, <<"textarea">>}] =
+        tokens(<<"<textarea><html></body></textarea>">>),
     ok.
 
 tokens(B, S=#decoder{offset=O}, Acc) ->
@@ -307,8 +315,29 @@
             lists:reverse(Acc);
         _ ->
             {Tag, S1} = tokenize(B, S),
-            tokens(B, S1, [Tag | Acc])
-    end.
+            case parse_flag(Tag) of
+                script ->
+                    {Tag2, S2} = tokenize_script(B, S1),
+                    tokens(B, S2, [Tag2, Tag | Acc]);
+                textarea ->
+                    {Tag2, S2} = tokenize_textarea(B, S1),
+                    tokens(B, S2, [Tag2, Tag | Acc]);
+                none ->
+                    tokens(B, S1, [Tag | Acc])
+            end
+    end.
+
+parse_flag({start_tag, B, _, false}) ->
+    case string:to_lower(binary_to_list(B)) of
+        "script" ->
+            script;
+        "textarea" ->
+            textarea;
+        _ ->
+            none
+    end;
+parse_flag(_) ->
+    none.
 
 tokenize(B, S=#decoder{offset=O}) ->
     case B of
@@ -330,7 +359,7 @@
             {S2, _} = find_gt(B, S1),
             {{end_tag, Tag}, S2};
         <<_:O/binary, "<", C, _/binary>> when ?IS_WHITESPACE(C) ->
-            %% This isn't really strict HTML but we want this for markdown
+            %% This isn't really strict HTML
             tokenize_data(B, ?INC_COL(S));
         <<_:O/binary, "<", _/binary>> ->
             {Tag, S1} = tokenize_literal(B, ?INC_COL(S)),
@@ -524,7 +553,7 @@
 
 destack(TagName, Stack) when is_list(Stack) ->
     F = fun (X) ->
-                case X of 
+                case X of
                     {TagName, _, _} ->
                         false;
                     _ ->
@@ -542,7 +571,7 @@
             %% Unfurl up to the tag, then accumulate it
             [{T0, A0, [destack(Pre ++ [T]) | Acc0]} | Post]
     end.
-    
+
 destack([{Tag, Attrs, Acc}]) ->
     {Tag, Attrs, lists:reverse(Acc)};
 destack([{T1, A1, Acc1}, {T0, A0, Acc0} | Rest]) ->
@@ -655,7 +684,7 @@
 
 tokenize_charref(Bin, S=#decoder{offset=O}) ->
     tokenize_charref(Bin, S, O).
-    
+
 tokenize_charref(Bin, S=#decoder{offset=O}, Start) ->
     case Bin of
         <<_:O/binary>> ->
@@ -758,3 +787,49 @@
         <<_:Start/binary, Raw/binary>> ->
             {{comment, Raw}, S}
     end.
+
+tokenize_script(Bin, S=#decoder{offset=O}) ->
+    tokenize_script(Bin, S, O).
+
+tokenize_script(Bin, S=#decoder{offset=O}, Start) ->
+    case Bin of
+        %% Just a look-ahead, we want the end_tag separately
+        <<_:O/binary, $<, $/, SS, CC, RR, II, PP, TT, _/binary>>
+        when (SS =:= $s orelse SS =:= $S) andalso
+             (CC =:= $c orelse CC =:= $C) andalso
+             (RR =:= $r orelse RR =:= $R) andalso
+             (II =:= $i orelse II =:= $I) andalso
+             (PP =:= $p orelse PP =:= $P) andalso
+             (TT=:= $t orelse TT =:= $T) ->
+            Len = O - Start,
+            <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin,
+            {{data, Raw, false}, S};
+        <<_:O/binary, C, _/binary>> ->
+            tokenize_script(Bin, ?INC_CHAR(S, C), Start);
+        <<_:Start/binary, Raw/binary>> ->
+            {{data, Raw, false}, S}
+    end.
+
+tokenize_textarea(Bin, S=#decoder{offset=O}) ->
+    tokenize_textarea(Bin, S, O).
+
+tokenize_textarea(Bin, S=#decoder{offset=O}, Start) ->
+    case Bin of
+        %% Just a look-ahead, we want the end_tag separately
+        <<_:O/binary, $<, $/, TT, EE, XX, TT2, AA, RR, EE2, AA2, _/binary>>
+        when (TT =:= $t orelse TT =:= $T) andalso
+             (EE =:= $e orelse EE =:= $E) andalso
+             (XX =:= $x orelse XX =:= $X) andalso
+             (TT2 =:= $t orelse TT2 =:= $T) andalso
+             (AA =:= $a orelse AA =:= $A) andalso
+             (RR =:= $r orelse RR =:= $R) andalso
+             (EE2 =:= $e orelse EE2 =:= $E) andalso
+             (AA2 =:= $a orelse AA2 =:= $A) ->
+            Len = O - Start,
+            <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin,
+            {{data, Raw, false}, S};
+        <<_:O/binary, C, _/binary>> ->
+            tokenize_textarea(Bin, ?INC_CHAR(S, C), Start);
+        <<_:Start/binary, Raw/binary>> ->
+            {{data, Raw, false}, S}
+    end.

Modified: incubator/couchdb/vendor/mochiweb/current/src/mochiweb_multipart.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb_multipart.erl?rev=659234&r1=659233&r2=659234&view=diff
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb_multipart.erl (original)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb_multipart.erl Thu May 22 13:09:17
2008
@@ -6,7 +6,7 @@
 -module(mochiweb_multipart).
 -author('bob@mochimedia.com').
 
--export([parse_form/2]).
+-export([parse_form/1, parse_form/2]).
 -export([parse_multipart_request/2]).
 -export([test/0]).
 
@@ -16,6 +16,9 @@
 
 %% TODO: DOCUMENT THIS MODULE.
 
+parse_form(Req) ->
+    parse_form(Req, fun default_file_handler/2).
+
 parse_form(Req, FileHandler) ->
     Callback = fun (Next) -> parse_form_outer(Next, FileHandler, []) end,
     {_, _, Res} = parse_multipart_request(Req, Callback),
@@ -56,6 +59,17 @@
     H1 = Handler(Data),
     fun (Next) -> parse_form_file(Next, {Name, H1}, FileHandler, State) end.
 
+default_file_handler(Filename, ContentType) ->
+    default_file_handler_1(Filename, ContentType, []).
+
+default_file_handler_1(Filename, ContentType, Acc) ->
+    fun(eof) ->
+            Value = iolist_to_binary(lists:reverse(Acc)),
+            {Filename, ContentType, Value};
+       (Next) ->
+            default_file_handler_1(Filename, ContentType, [Next | Acc])
+    end.
+
 parse_multipart_request(Req, Callback) ->
     %% TODO: Support chunked?
     Length = list_to_integer(Req:get_header_value("content-length")),
@@ -295,19 +309,6 @@
     ok = with_socket_server(ServerFun, ClientFun),
     ok.
 
-handler_test(Filename, ContentType) ->
-    fun (Next) ->
-            handler_test_read(Next, {Filename, ContentType}, [])
-    end.
-
-handler_test_read(eof, {Filename, ContentType}, Acc) ->
-    Value = iolist_to_binary(lists:reverse(Acc)),
-    {Filename, ContentType, Value};
-handler_test_read(Data, H, Acc) ->
-    Acc1 = [Data | Acc],
-    fun (Next) -> handler_test_read(Next, H, Acc1) end.
-
-
 test_parse_form() ->
     ContentType = "multipart/form-data; boundary=AaB03x",
     "AaB03x" = get_boundary(ContentType),
@@ -334,7 +335,7 @@
     ClientFun = fun (Socket) ->
                         Req = fake_request(Socket, ContentType,
                                            size(BinContent)),
-                        Res = parse_form(Req, fun handler_test/2),
+                        Res = parse_form(Req),
                         [{"submit-name", "Larry"},
                          {"files", {"file1.txt", {"text/plain",[]},
                                     <<"... contents of file1.txt ...">>}

Modified: incubator/couchdb/vendor/mochiweb/current/src/mochiweb_request.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb_request.erl?rev=659234&r1=659233&r2=659234&view=diff
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb_request.erl (original)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb_request.erl Thu May 22 13:09:17
2008
@@ -386,7 +386,7 @@
                              [];
                          Binary ->
                              case get_primary_header_value("content-type") of
-                                 "application/x-www-form-urlencoded" ->
+                                 "application/x-www-form-urlencoded" ++ _ ->
                                      mochiweb_util:parse_qs(Binary);
                                  _ ->
                                      []

Modified: incubator/couchdb/vendor/mochiweb/current/src/mochiweb_socket_server.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb_socket_server.erl?rev=659234&r1=659233&r2=659234&view=diff
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb_socket_server.erl (original)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb_socket_server.erl Thu May 22 13:09:17
2008
@@ -103,7 +103,8 @@
                 {packet, 0},
                 {backlog, Backlog},
                 {recbuf, 8192},
-                {active, false}],
+                {active, false},
+                {nodelay, true}],
     Opts = case Ip of
                any ->
                    BaseOpts;



Mime
View raw message