C0 code coverage information

Generated on 2009-08-09 21:22:54 with etap 0.3.4.

Name Total lines Lines of code Total coverage Code coverage
couch_util ?? ?? ??
45% 
....1 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
....2 % use this file except in compliance with the License. You may obtain a copy of
....3 % the License at
....4 %
....5 %   http://www.apache.org/licenses/LICENSE-2.0
....6 %
....7 % Unless required by applicable law or agreed to in writing, software
....8 % distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
....9 % WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
...10 % License for the specific language governing permissions and limitations under
...11 % the License.
...12 
...13 -module(couch_util).
...14 
...15 -export([start_driver/1,terminate_linked/1]).
...16 -export([should_flush/0, should_flush/1, to_existing_atom/1]).
...17 -export([new_uuid/0, rand32/0, implode/2, collate/2, collate/3]).
...18 -export([abs_pathname/1,abs_pathname/2, trim/1, ascii_lower/1]).
...19 -export([encodeBase64/1, decodeBase64/1, encodeBase64Url/1, decodeBase64Url/1,
...20     to_hex/1,parse_term/1, dict_find/3]).
...21 -export([file_read_size/1, get_nested_json_value/2, json_user_ctx/1]).
...22 -export([to_binary/1, to_list/1, url_encode/1]).
...23 
...24 -include("couch_db.hrl").
...25 -include_lib("kernel/include/file.hrl").
...26 
...27 % arbitrarily chosen amount of memory to use before flushing to disk
...28 -define(FLUSH_MAX_MEM, 10000000).
...29 
...30 start_driver(LibDir) ->
...31     case erl_ddll:load_driver(LibDir, "couch_erl_driver") of
...32     ok ->
...33         ok;
...34     {error, already_loaded} ->
...35         ok = erl_ddll:reload_driver(LibDir, "couch_erl_driver");
...36     {error, Error} ->
...37         exit(erl_ddll:format_error(Error))
...38     end.
...39 
...40 % works like list_to_existing_atom, except can be list or binary and it
...41 % gives you the original value instead of an error if no existing atom.
...42 to_existing_atom(V) when is_list(V)->
...43     try list_to_existing_atom(V) catch _ -> V end;
...44 to_existing_atom(V) when is_binary(V)->
...45     try list_to_existing_atom(?b2l(V)) catch _ -> V end;
...46 to_existing_atom(V) when is_atom(V)->
...47     V.
...48 
...49 
...50 terminate_linked(normal) ->
...51     terminate_linked(shutdown);
...52 terminate_linked(Reason) ->
...53     {links, Links} = process_info(self(), links),
...54     [catch exit(Pid, Reason) || Pid <- Links],
...55     ok.
...56 
...57 
...58 new_uuid() ->
...59     list_to_binary(to_hex(crypto:rand_bytes(16))).
...60 
...61 to_hex([]) ->
...62     [];
...63 to_hex(Bin) when is_binary(Bin) ->
...64     to_hex(binary_to_list(Bin));
...65 to_hex([H|T]) ->
...66     [to_digit(H div 16), to_digit(H rem 16) | to_hex(T)].
...67 
...68 to_digit(N) when N < 10 -> $0 + N;
...69 to_digit(N)             -> $a + N-10.
...70 
...71 
...72 parse_term(Bin) when is_binary(Bin)->
...73     parse_term(binary_to_list(Bin));
...74 parse_term(List) ->
...75     {ok, Tokens, _} = erl_scan:string(List ++ "."),
...76     erl_parse:parse_term(Tokens).
...77 
...78 
...79 get_nested_json_value({Props}, [Key|Keys]) ->
...80     case proplists:get_value(Key, Props, nil) of
...81     nil -> throw({not_found, <<"missing json key: ", Key/binary>>});
...82     Value -> get_nested_json_value(Value, Keys)
...83     end;
...84 get_nested_json_value(Value, []) ->
...85     Value;
...86 get_nested_json_value(_NotJSONObj, _) ->
...87     throw({not_found, json_mismatch}).
...88 
...89 json_user_ctx(#db{name=DbName, user_ctx=Ctx}) ->
...90     {[{<<"db">>, DbName},
...91             {<<"name">>,Ctx#user_ctx.name},
...92             {<<"roles">>,Ctx#user_ctx.roles}]}.
...93     
...94 
...95 % returns a random integer
...96 rand32() ->
...97     crypto:rand_uniform(0, 16#100000000).
...98 
...99 % given a pathname "../foo/bar/" it gives back the fully qualified
..100 % absolute pathname.
..101 abs_pathname(" " ++ Filename) ->
..102     % strip leading whitspace
..103     abs_pathname(Filename);
..104 abs_pathname([$/ |_]=Filename) ->
..105     Filename;
..106 abs_pathname(Filename) ->
..107     {ok, Cwd} = file:get_cwd(),
..108     {Filename2, Args} = separate_cmd_args(Filename, ""),
..109     abs_pathname(Filename2, Cwd) ++ Args.
..110 
..111 abs_pathname(Filename, Dir) ->
..112     Name = filename:absname(Filename, Dir ++ "/"),
..113     OutFilename = filename:join(fix_path_list(filename:split(Name), [])),
..114     % If the filename is a dir (last char slash, put back end slash
..115     case string:right(Filename,1) of
..116     "/" ->
..117         OutFilename ++ "/";
..118     "\\" ->
..119         OutFilename ++ "/";
..120     _Else->
..121         OutFilename
..122     end.
..123 
..124 % if this as an executable with arguments, seperate out the arguments
..125 % ""./foo\ bar.sh -baz=blah" -> {"./foo\ bar.sh", " -baz=blah"}
..126 separate_cmd_args("", CmdAcc) ->
..127     {lists:reverse(CmdAcc), ""};
..128 separate_cmd_args("\\ " ++ Rest, CmdAcc) -> % handle skipped value
..129     separate_cmd_args(Rest, " \\" ++ CmdAcc);
..130 separate_cmd_args(" " ++ Rest, CmdAcc) ->
..131     {lists:reverse(CmdAcc), " " ++ Rest};
..132 separate_cmd_args([Char|Rest], CmdAcc) ->
..133     separate_cmd_args(Rest, [Char | CmdAcc]).
..134 
..135 % lowercases string bytes that are the ascii characters A-Z.
..136 % All other characters/bytes are ignored.
..137 ascii_lower(String) ->
..138     ascii_lower(String, []).
..139 
..140 ascii_lower([], Acc) ->
..141     lists:reverse(Acc);
..142 ascii_lower([Char | RestString], Acc) when Char >= $A, Char =< $B ->
..143     ascii_lower(RestString, [Char + ($a-$A) | Acc]);
..144 ascii_lower([Char | RestString], Acc)->
..145     ascii_lower(RestString, [Char | Acc]).
..146 
..147 % Is a character whitespace?
..148 is_whitespace($\s)-> true;
..149 is_whitespace($\t)-> true;
..150 is_whitespace($\n)-> true;
..151 is_whitespace($\r)-> true;
..152 is_whitespace(_Else) -> false.
..153 
..154 
..155 % removes leading and trailing whitespace from a string
..156 trim(String) ->
..157     String2 = lists:dropwhile(fun is_whitespace/1, String),
..158     lists:reverse(lists:dropwhile(fun is_whitespace/1, lists:reverse(String2))).
..159 
..160 % takes a heirarchical list of dirs and removes the dots ".", double dots
..161 % ".." and the corresponding parent dirs.
..162 fix_path_list([], Acc) ->
..163     lists:reverse(Acc);
..164 fix_path_list([".."|Rest], [_PrevAcc|RestAcc]) ->
..165     fix_path_list(Rest, RestAcc);
..166 fix_path_list(["."|Rest], Acc) ->
..167     fix_path_list(Rest, Acc);
..168 fix_path_list([Dir | Rest], Acc) ->
..169     fix_path_list(Rest, [Dir | Acc]).
..170 
..171 
..172 implode(List, Sep) ->
..173     implode(List, Sep, []).
..174 
..175 implode([], _Sep, Acc) ->
..176     lists:flatten(lists:reverse(Acc));
..177 implode([H], Sep, Acc) ->
..178     implode([], Sep, [H|Acc]);
..179 implode([H|T], Sep, Acc) ->
..180     implode(T, Sep, [Sep,H|Acc]).
..181 
..182 
..183 drv_port() ->
..184     case get(couch_drv_port) of
..185     undefined ->
..186         Port = open_port({spawn, "couch_erl_driver"}, []),
..187         put(couch_drv_port, Port),
..188         Port;
..189     Port ->
..190         Port
..191     end.
..192 
..193 collate(A, B) ->
..194     collate(A, B, []).
..195 
..196 collate(A, B, Options) when is_binary(A), is_binary(B) ->
..197     Operation =
..198     case lists:member(nocase, Options) of
..199         true -> 1; % Case insensitive
..200         false -> 0 % Case sensitive
..201     end,
..202 
..203     SizeA = size(A),
..204     SizeB = size(B),
..205     Bin = <>,
..206     [Result] = erlang:port_control(drv_port(), Operation, Bin),
..207     % Result is 0 for lt, 1 for eq and 2 for gt. Subtract 1 to return the
..208     % expected typical -1, 0, 1
..209     Result - 1.
..210 
..211 should_flush() ->
..212     should_flush(?FLUSH_MAX_MEM).
..213 
..214 should_flush(MemThreshHold) ->
..215     {memory, ProcMem} = process_info(self(), memory),
..216     BinMem = lists:foldl(fun({_Id, Size, _NRefs}, Acc) -> Size+Acc end,
..217         0, element(2,process_info(self(), binary))),
..218     if ProcMem+BinMem > 2*MemThreshHold ->
..219         garbage_collect(),
..220         {memory, ProcMem2} = process_info(self(), memory),
..221         BinMem2 = lists:foldl(fun({_Id, Size, _NRefs}, Acc) -> Size+Acc end,
..222             0, element(2,process_info(self(), binary))),
..223         if ProcMem2+BinMem2 > MemThreshHold ->
..224             true;
..225         true -> false end;
..226     true -> false end.
..227 
..228 
..229 %%% Purpose : Base 64 encoding and decoding.
..230 %%% Copied from ssl_base_64 to avoid using the
..231 %%% erlang ssl library
..232 
..233 -define(st(X,A), ((X-A+256) div 256)).
..234 
..235 %% A PEM encoding consists of characters A-Z, a-z, 0-9, +, / and
..236 %% =. Each character encodes a 6 bits value from 0 to 63 (A = 0, / =
..237 %% 63); = is a padding character.
..238 %%
..239 
..240 %%
..241 %% encode64(Bytes|Binary) -> binary
..242 %%
..243 %% Take 3 bytes a time (3 x 8 = 24 bits), and make 4 characters out of
..244 %% them (4 x 6 = 24 bits).
..245 %%
..246 encodeBase64(Bs) when is_list(Bs) ->
..247     encodeBase64(iolist_to_binary(Bs), <<>>);
..248 encodeBase64(Bs) ->
..249     encodeBase64(Bs, <<>>).
..250 
..251 encodeBase64(<>, Acc) ->
..252     <> = B,
..253     encodeBase64(Bs, <>);
..254 encodeBase64(<>, Acc) ->
..255     <> = <>,
..256     <>;
..257 encodeBase64(<>, Acc) ->
..258     <> = <>,
..259     <>;
..260 encodeBase64(<<>>, Acc) ->
..261     Acc.
..262 
..263 encodeBase64Url(Bs) when list(Bs) ->
..264     encodeBase64Url(list_to_binary(Bs), <<>>);
..265 encodeBase64Url(Bs) ->
..266     encodeBase64Url(Bs, <<>>).
..267     
..268 encodeBase64Url(<>, Acc) ->
..269     <> = B,
..270     encodeBase64Url(Bs, <>);
..271 encodeBase64Url(<>, Acc) ->
..272     <> = <>,
..273     <>;
..274 encodeBase64Url(<>, Acc) ->
..275     <> = <>,
..276     <>;
..277 encodeBase64Url(<<>>, Acc) ->
..278     Acc.
..279 
..280 %%
..281 %% decodeBase64(BinaryChars) -> Binary
..282 %%
..283 decodeBase64(Cs) when is_list(Cs)->
..284     decodeBase64(list_to_binary(Cs));
..285 decodeBase64(Cs) ->
..286     decode1(Cs, <<>>).
..287 
..288 decode1(<>, Acc) ->
..289     <> = <<(dec(C1)):6, (dec(C2)):6, 0:12>>,
..290     <>;
..291 decode1(<>, Acc) ->
..292     <> = <<(dec(C1)):6, (dec(C2)):6, (dec(C3)):6, (dec(0)):6>>,
..293     <>;
..294 decode1(<>, Acc) ->
..295     Bin = <>,
..296     decode1(Cs, Bin);
..297 decode1(<<>>, Acc) ->
..298     Acc.
..299 
..300 decodeBase64Url(Cs) when is_list(Cs)->
..301     decodeBase64Url(list_to_binary(Cs));
..302 decodeBase64Url(Cs) ->
..303     decode1Url(Cs, <<>>).
..304 
..305 decode1Url(<>, Acc) ->
..306     <> = <<(decUrl(C1)):6, (decUrl(C2)):6, 0:12>>,
..307     <>;
..308 decode1Url(<>, Acc) ->
..309     <> = <<(decUrl(C1)):6, (decUrl(C2)):6, (decUrl(C3)):6, (decUrl(0)):6>>,
..310     <>;
..311 decode1Url(<>, Acc) ->
..312     Bin = <>,
..313     decode1Url(Cs, Bin);
..314 decode1Url(<<>>, Acc) ->
..315     Acc.
..316 
..317 %% enc/1 and dec/1
..318 %%
..319 %% Mapping: 0-25 -> A-Z, 26-51 -> a-z, 52-61 -> 0-9, 62 -> +, 63 -> /
..320 %%
..321 enc(C) ->
..322     65 + C + 6*?st(C,26) - 75*?st(C,52) -15*?st(C,62) + 3*?st(C,63).
..323 
..324 dec(C) ->
..325     62*?st(C,43) + ?st(C,47) + (C-59)*?st(C,48) - 69*?st(C,65) - 6*?st(C,97).
..326 
..327 %% encUrl/1 and decUrl/1
..328 %%
..329 %% Mapping: 0-25 -> A-Z, 26-51 -> a-z, 52-61 -> 0-9, 62 -> -, 63 -> _
..330 %%
..331 encUrl(C) ->
..332     65 + C + 6*?st(C,26) - 75*?st(C,52) -13*?st(C,62) + 49*?st(C,63).
..333 
..334 decUrl(C) ->
..335     62*?st(C,45) + (C-58)*?st(C,48) - 69*?st(C,65) + 33*?st(C,95) - 39*?st(C,97).
..336 
..337 dict_find(Key, Dict, DefaultValue) ->
..338     case dict:find(Key, Dict) of
..339     {ok, Value} ->
..340         Value;
..341     error ->
..342         DefaultValue
..343     end.
..344 
..345 
..346 file_read_size(FileName) ->
..347     case file:read_file_info(FileName) of
..348         {ok, FileInfo} ->
..349             FileInfo#file_info.size;
..350         Error -> Error
..351     end.
..352 
..353 to_binary(V) when is_binary(V) ->
..354     V;
..355 to_binary(V) when is_list(V) ->
..356     try
..357         list_to_binary(V)
..358     catch
..359         _ ->
..360             list_to_binary(io_lib:format("~p", [V]))
..361     end;
..362 to_binary(V) when is_atom(V) ->
..363     list_to_binary(atom_to_list(V));
..364 to_binary(V) ->
..365     list_to_binary(io_lib:format("~p", [V])).
..366 
..367 to_list(V) when is_list(V) ->
..368     V;
..369 to_list(V) when is_binary(V) ->
..370     binary_to_list(V);
..371 to_list(V) when is_atom(V) ->
..372     atom_to_list(V);
..373 to_list(V) ->
..374     lists:flatten(io_lib:format("~p", [V])).
..375 
..376 url_encode(Bin) when is_binary(Bin) ->
..377     url_encode(binary_to_list(Bin));
..378 url_encode([H|T]) ->
..379     if
..380     H >= $a, $z >= H ->
..381         [H|url_encode(T)];
..382     H >= $A, $Z >= H ->
..383         [H|url_encode(T)];
..384     H >= $0, $9 >= H ->
..385         [H|url_encode(T)];
..386     H == $_; H == $.; H == $-; H == $: ->
..387         [H|url_encode(T)];
..388     true ->
..389         case lists:flatten(io_lib:format("~.16.0B", [H])) of
..390         [X, Y] ->
..391             [$%, X, Y | url_encode(T)];
..392         [X] ->
..393             [$%, $0, X | url_encode(T)]
..394         end
..395     end;
..396 url_encode([]) ->
..397     [].

Generated using etap 0.3.4.