-module(bucs). -include_lib("eunit/include/eunit.hrl"). -include("../include/bucs.hrl"). -export([ to_atom/1, to_list/1, to_string/1, to_binary/1, to_integer/1, to_float/1, to_float/2, to_term/1, module_exist/1, module_exists/1, function_exist/3, function_exists/3, apply/4, apply/3, apply/2, is_string/1, is_kw_list/1, compare_as_list/2, compare_as_string/2, compare_as_atom/2, compare_as_integer/2, compare_as_binary/2, pipecall/1, match/2, call/3, blank/1, present/1, default_to/2, eval/1, eval/2 ]). % @doc % Convert the given term to atom % % Example: %
% atom = bucs:to_atom(atom).
% atom = bucs:to_atom(<<"atom">>).
% atom = bucs:to_atom("atom").
% 
% @end to_atom(X) when is_atom(X) -> X; to_atom(X) when is_binary(X); is_bitstring(X) -> binary_to_atom(X, utf8); to_atom(X) when is_list(X) -> list_to_atom(X); to_atom(X) -> to_atom(to_list(X)). % @doc % Convert the given term to list % % Example: %
% "list" = bucs:to_list(list).
% "list" = bucs:to_list("list").
% "list" = bucs:to_list(<<"list">>).
% "123" = bucs:to_list(123).
% "1.20000000000000000000e+01" = bucs:to_list(12.0).
% "true" = bucs:to_list(true).
% "false" = bucs:to_list(false).
% 
% @end to_list(true) -> "true"; to_list(false) -> "false"; to_list(V) when is_atom(V) -> atom_to_list(V); to_list(V) when is_list(V) -> V; to_list(V) when is_integer(V) -> integer_to_list(V); to_list(V) when is_float(V) -> float_to_list(V); to_list(V) when is_binary(V); is_bitstring(V) -> binary_to_list(V); to_list(V) when is_tuple(V) -> [element(I, V) || I <- lists:seq(1, tuple_size(V))]; to_list(V) when is_pid(V) -> pid_to_list(V); to_list(V) when is_reference(V) -> erlang:ref_to_list(V). % @doc % Convert the given term to string % @end to_string(V) when is_binary(V); is_bitstring(V); is_atom(V); is_pid(V); is_reference(V)-> lists:flatten(to_list(V)); to_string(V) -> case is_string(V) of true -> V; false -> lists:flatten(io_lib:format("~p", [V])) end. % @doc % Convert the given term to binary % % Example: %
% <<"list">> = bucs:to_binary(list).
% <<"list">> = bucs:to_binary("list").
% <<"list">> = bucs:to_binary(<<"list">>).
% <<"123">> = bucs:to_binary(123).
% <<"1.20000000000000000000e+01">> = bucs:to_binary(12.0).
% <<"true">> = bucs:to_binary(true).
% <<"false">> = bucs:to_binary(false).
% 
% @end to_binary(V) when is_binary(V); is_bitstring(V) -> V; to_binary(V) when is_float(V) -> iolist_to_binary(to_string(V)); to_binary(V) -> iolist_to_binary(to_list(V)). % @doc % Convert the given term to integer % % Example %
% 123 = bucs:to_integer(123).
% 123 = bucs:to_integer("123").
% 123 = bucs:to_integer(<<"123">>).
% 123 = bucs:to_integer('123').
% 123 = bucs:to_integer(123.456).
% 
% @end to_integer(I) when is_integer(I) -> I; to_integer(I) when is_list(I) -> try list_to_integer(I) catch _:_ -> to_integer(to_float(I)) end; to_integer(I) when is_binary(I); is_bitstring(I) -> try binary_to_integer(I) catch _:_ -> to_integer(to_float(I)) end; to_integer(I) when is_atom(I) -> to_integer(atom_to_list(I)); to_integer(I) when is_float(I) -> to_integer(float_to_list(I, [{decimals, 0}])). % @doc % Convert the given term to float % % Example %
% 123.45 = bucs:to_float(123.45).
% 123.45 = bucs:to_float("123.45").
% 123.45 = bucs:to_float(<<"123.45">>).
% 123.45 = bucs:to_float('123.45').
% 123.0 = bucs:to_float(123).
% 
% @end to_float(Value) when is_integer(Value) -> float(Value); to_float(Value) when is_float(Value) -> Value; to_float(Value) when is_list(Value) -> case string:to_float(Value) of {error, no_float} -> float(list_to_integer(Value)); {F, _} -> F end; to_float(Value) when is_binary(Value) -> to_float(binary_to_list(Value)); to_float(Value) when is_atom(Value) -> to_float(atom_to_list(Value)). % @doc % Convert the given term to float, with the given precision % % Example %
% 123.457 = bucs:to_float(123.45678i, 3).
% 123.457 = bucs:to_float("123.45678", 3).
% 123.457 = bucs:to_float(<<"123.45678">>, 3).
% 123.457 = bucs:to_float('123.45678', 3).
% 123.0 = bucs:to_float(123, 3).
% 
% @end to_float(Value, Precision) -> to_float(float_to_list(to_float(Value), [{decimals, Precision}])). % @doc % Convert the given value to term % % Example %
%
% 
% @end to_term(Value) -> try Value0 = to_string(Value), Value1 = case lists:reverse(Value0) of [$.|_] -> Value0; _ -> Value0 ++ "." end, {ok, Tokens, _} = erl_scan:string(Value1), case erl_parse:parse_term(Tokens) of {ok, Term} -> {ok, Term}; {error, {_, _, Reason}} -> {error, Reason} end catch _:Error -> {error, Error} end. % @deprecated module_exist(Module) -> module_exists(Module). % @doc % Check if the given module exist % @end module_exists(Module) -> case is_atom(Module) of true -> try Module:module_info() of _InfoList -> true catch _:_ -> false end; false -> false end. % @deprecated function_exist(Module, Function, Arity) -> function_exists(Module, Function, Arity). % @doc % Check if the given function exist % @end function_exists(Module, Function, Arity) -> case code:ensure_loaded(Module) of {module, Module} -> erlang:function_exported(Module, Function, Arity); _ -> false end. % @doc % @end apply(Module, Function, Args, Default) -> case function_exists(Module, Function, length(Args)) of true -> erlang:apply(Module, Function, Args); false -> Default end. % @doc % @end apply(Fun, Args, Default) when is_function(Fun), is_list(Args) -> case bucs:apply(Fun, Args) of {ok, Result} -> Result; error -> Default end; apply(Module, Function, Args) when is_atom(Module), is_atom(Function), is_list(Args) -> try {ok, erlang:apply(Module, Function, Args)} catch _:_ -> error end. apply(Fun, Args) -> try {ok, erlang:apply(Fun, Args)} catch _:_ -> error end. % @doc % Check if the given value is a string % @end is_string(V) when is_list(V) -> io_lib:printable_list(V) orelse io_lib:printable_latin1_list(V) orelse io_lib:printable_unicode_list(V); is_string(_) -> false. % @doc % Wheck is the given value is a keyword list % @end is_kw_list(V) when is_list(V) -> lists:all(fun ({_, _}) -> true; (_) -> false end, V); is_kw_list(_) -> false. % @doc % Return true if A match B. false otherwise. % @end match(A, B) -> case A of B -> true; _ -> false end. compare_as_list(V1, V2) -> compare_as(fun to_list/1, V1, V2). compare_as_string(V1, V2) -> compare_as(fun to_string/1, V1, V2). compare_as_atom(V1, V2) -> compare_as(fun to_atom/1, V1, V2). compare_as_integer(V1, V2) -> compare_as(fun to_integer/1, V1, V2). compare_as_binary(V1, V2) -> compare_as(fun to_binary/1, V1, V2). compare_as(Fun, V1, V2) -> V11 = Fun(V1), V21 = Fun(V2), if V11 < V21 -> -1; V11 =:= V21 -> 0; true -> 1 end. % @doc % Pipe fun call % % Example: %
% Add = math:pow(7, 3),
% Log = math:log(Add),
% Mul = multiplication(Log, 7),
% Res = addition(Mul, 7).
%
% % With bucs:pipecall/1 :
% Res = bucs:pipecall([
%                      {fun math:pow/2, [7, 3]},
%                      fun math:log/1,
%                      {fun multiplication/2, [7]},
%                      {fun addition/2, [7]}
%                     ]).
% 
% @end pipecall([{Call, Args}|Rest]) -> pipecall(Rest, erlang:apply(Call, Args)); pipecall([Call|Rest]) -> pipecall(Rest, erlang:apply(Call, [])). pipecall([], Out) -> Out; pipecall([{Call, Args}|Rest], Out) -> pipecall(Rest, erlang:apply(Call, [Out|Args])); pipecall([Call|Rest], Out) -> pipecall([{Call, []}|Rest], Out). % @doc % Returns the result of applying Function in Module to Args. The applied % function must be exported from Module. The arity of the function is the length of Args. % % Return {error, undefined_function} if the applied function is not exported. % @end -spec call(Module :: module(), Function :: atom(), Args :: [term()]) -> term() | {error, undefined_function}. call(Module, Function, Args) -> case erlang:function_exposted(Module, Function, length(Args)) of true -> erlang:apply(Module, Function, Args); false -> {error, undefined_function} end. % @doc % @end blank([]) -> true; blank({}) -> true; blank(<<>>) -> true; blank(M) when is_map(M) -> maps:size(M) == 0; blank(nil) -> true; blank(undefined) -> true; blank(false) -> true; blank(X) -> try binary:replace(bucs:to_binary(X), [<<" ">>, <<"\r">>, <<"\n">>, <<"\t">>], <<>>, [global]) == <<>> catch _:_ -> false end. % @doc % @end present(X) -> not blank(X). % @doc % @end default_to(X, Default) -> case blank(X) of true -> Default; _ -> X end. eval(Value) -> eval(Value, []). eval(Value, Environ) -> Value0 = to_string(Value), Value1 = case lists:reverse(Value0) of [$.|_] -> Value0; _ -> Value0 ++ "." end, case erl_scan:string(Value1) of {ok, Scanned, _} -> case erl_parse:parse_exprs(Scanned) of {ok, Parsed} -> erl_eval:exprs(Parsed, Environ); Error -> Error end; Error -> Error end.