|
@@ -16,16 +16,40 @@
|
|
|
-module(cowboy_bstr).
|
|
|
|
|
|
%% Binary strings.
|
|
|
+-export([capitalize_token/1]).
|
|
|
-export([to_lower/1]).
|
|
|
|
|
|
%% Characters.
|
|
|
-export([char_to_lower/1]).
|
|
|
-export([char_to_upper/1]).
|
|
|
|
|
|
+-ifdef(TEST).
|
|
|
+-include_lib("eunit/include/eunit.hrl").
|
|
|
+-endif.
|
|
|
+
|
|
|
+%% @doc Capitalize a token.
|
|
|
+%%
|
|
|
+%% The first letter and all letters after a dash are capitalized.
|
|
|
+%% This is the form seen for header names in the HTTP/1.1 RFC and
|
|
|
+%% others. Note that using this form isn't required, as header name
|
|
|
+%% are case insensitive, and it is only provided for use with eventual
|
|
|
+%% badly implemented clients.
|
|
|
+-spec capitalize_token(B) -> B when B::binary().
|
|
|
+capitalize_token(B) ->
|
|
|
+ capitalize_token(B, true, <<>>).
|
|
|
+capitalize_token(<<>>, _, Acc) ->
|
|
|
+ Acc;
|
|
|
+capitalize_token(<< $-, Rest/bits >>, _, Acc) ->
|
|
|
+ capitalize_token(Rest, true, << Acc/binary, $- >>);
|
|
|
+capitalize_token(<< C, Rest/bits >>, true, Acc) ->
|
|
|
+ capitalize_token(Rest, false, << Acc/binary, (char_to_upper(C)) >>);
|
|
|
+capitalize_token(<< C, Rest/bits >>, false, Acc) ->
|
|
|
+ capitalize_token(Rest, false, << Acc/binary, (char_to_lower(C)) >>).
|
|
|
+
|
|
|
%% @doc Convert a binary string to lowercase.
|
|
|
--spec to_lower(binary()) -> binary().
|
|
|
-to_lower(L) ->
|
|
|
- << << (char_to_lower(C)) >> || << C >> <= L >>.
|
|
|
+-spec to_lower(B) -> B when B::binary().
|
|
|
+to_lower(B) ->
|
|
|
+ << << (char_to_lower(C)) >> || << C >> <= B >>.
|
|
|
|
|
|
%% @doc Convert [A-Z] characters to lowercase.
|
|
|
%% @end
|
|
@@ -88,3 +112,22 @@ char_to_upper($x) -> $X;
|
|
|
char_to_upper($y) -> $Y;
|
|
|
char_to_upper($z) -> $Z;
|
|
|
char_to_upper(Ch) -> Ch.
|
|
|
+
|
|
|
+%% Tests.
|
|
|
+
|
|
|
+-ifdef(TEST).
|
|
|
+
|
|
|
+capitalize_token_test_() ->
|
|
|
+ %% {Header, Result}
|
|
|
+ Tests = [
|
|
|
+ {<<"heLLo-woRld">>, <<"Hello-World">>},
|
|
|
+ {<<"Sec-Websocket-Version">>, <<"Sec-Websocket-Version">>},
|
|
|
+ {<<"Sec-WebSocket-Version">>, <<"Sec-Websocket-Version">>},
|
|
|
+ {<<"sec-websocket-version">>, <<"Sec-Websocket-Version">>},
|
|
|
+ {<<"SEC-WEBSOCKET-VERSION">>, <<"Sec-Websocket-Version">>},
|
|
|
+ {<<"Sec-WebSocket--Version">>, <<"Sec-Websocket--Version">>},
|
|
|
+ {<<"Sec-WebSocket---Version">>, <<"Sec-Websocket---Version">>}
|
|
|
+ ],
|
|
|
+ [{H, fun() -> R = capitalize_token(H) end} || {H, R} <- Tests].
|
|
|
+
|
|
|
+-endif.
|