%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1998-2010. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %%%********************************************************************* %%% %%% Description: This file contains io functions adapted to the %%% TV requirements. %%% %%%********************************************************************* -module(tv_io_lib). -export([format/2]). -export([write/1,write/2]). -export([write_atom/1,write_string/2]). -export([char_list/1,deep_char_list/1,printable_list/1]). %% Interface calls to sub-modules. format(Format, Args) -> tv_io_lib_format:fwrite(Format, Args). %% write(Term) %% write(Term, Depth) %% write(Term, Depth, Pretty) %% Return a (non-flattened) list of characters giving a printed %% representation of the term. write(Term) -> write(Term, -1). write(_Term, 0) -> "..."; write(Term, _D) when is_integer(Term) -> integer_to_list(Term); write(Term, _D) when is_float(Term) -> tv_io_lib_format:fwrite_g(Term); write(Atom, _D) when is_atom(Atom) -> write_atom(Atom); write(Term, _D) when is_port(Term) -> lists:flatten(io_lib:write(Term)); write(Term, _D) when is_pid(Term) -> pid_to_list(Term); write(Term, _D) when is_reference(Term) -> io_lib:write(Term); write(Term, _D) when is_binary(Term), byte_size(Term) > 100 -> "#Bin"; write(Term, _D) when is_binary(Term) -> "<<\"" ++ binary_to_list(Term) ++ "\">>"; write(Term, _D) when is_bitstring(Term) -> "#Bitstr"; write([], _D) -> "[]"; write({}, _D) -> "{}"; write([H|T], D) -> if D =:= 1 -> "[...]"; true -> [$[,[write(H, D-1)|write_tail(T, D-1)],$]] end; write(F, _D) when is_function(F) -> {module,M} = erlang:fun_info(F, module), ["#Fun<",atom_to_list(M),">"]; write(T, D) when is_tuple(T) -> if D =:= 1 -> "{...}"; true -> [${, [write(element(1, T), D-1)|write_tail(tl(tuple_to_list(T)), D-1)], $}] end. %% write_tail(List, Depth) %% Test the terminating case first as this looks better with depth. write_tail([], _D) -> ""; write_tail(_List, 1) -> "|..."; write_tail([H|T], D) -> [$,,write(H, D-1)|write_tail(T, D-1)]; write_tail(Other, D) -> [$|,write(Other, D-1)]. %% write_atom(Atom) -> [Char] %% Generate the list of characters needed to print an atom. write_atom(Atom) -> Chars = atom_to_list(Atom), case quote_atom(Atom, Chars) of true -> write_string(Chars, $'); false -> Chars end. write_string(S, Q) -> [Q|write_string1(S, Q)]. write_string1([], Q) -> [Q]; write_string1([C|Cs], Q) -> write_char(C, Q, write_string1(Cs, Q)). write_char(Q, Q, Tail) -> %Must check this first [$\\,Q|Tail]; write_char($\\, _, Tail) -> %In printable character range [$\\,$\\|Tail]; write_char(C, _, Tail) when C >= $ , C =< $~ -> [C|Tail]; write_char(C, _, Tail) when C >= 128+$ , C =< 255 -> [C|Tail]; write_char($\n, _Q, Tail) -> %\n = LF [$\\,$n|Tail]; write_char($\r, _, Tail) -> %\r = CR [$\\,$r|Tail]; write_char($\t, _, Tail) -> %\t = TAB [$\\,$t|Tail]; write_char($\v, _, Tail) -> %\v = VT [$\\,$v|Tail]; write_char($\b, _, Tail) -> %\b = BS [$\\,$b|Tail]; write_char($\f, _, Tail) -> %\f = FF [$\\,$f|Tail]; write_char($\e, _, Tail) -> %\e = ESC [$\\,$e|Tail]; write_char($\d, _, Tail) -> %\d = DEL [$\\,$d|Tail]; write_char(C, _, Tail) when C < $ -> C1 = (C bsr 3) + $0, C2 = (C band 7) + $0, [$\\,$0,C1,C2|Tail]; write_char(C, _, Tail) when C > $~ -> C1 = (C bsr 6) + $0, C2 = ((C bsr 3) band 7) + $0, C3 = (C band 7) + $0, [$\\,C1,C2,C3|Tail]. %% quote_atom(Atom, CharList) %% Return 'true' if atom with chars in CharList needs to be quoted, else %% return 'false'. quote_atom(Atom, Cs0) -> case erl_scan:reserved_word(Atom) of true -> true; false -> case Cs0 of [C|Cs] when C >= $a, C =< $z -> quote_atom(Cs); _ -> true end end. quote_atom([C|Cs]) when C >= $a, C =< $z -> quote_atom(Cs); quote_atom([C|Cs]) when C >= $A, C =< $Z -> quote_atom(Cs); quote_atom([C|Cs]) when C >= $0, C =< $9 -> quote_atom(Cs); quote_atom([$_|Cs]) -> quote_atom(Cs); quote_atom([$@|Cs]) -> quote_atom(Cs); quote_atom([_|_]) -> true; quote_atom([]) -> false. %% char_list(CharList) %% deep_char_list(CharList) %% Return true if CharList is a (possibly deep) list of characters, else %% false. char_list([C|Cs]) when is_integer(C), C >= 0, C =< 255 -> char_list(Cs); char_list([]) -> true; char_list(_Other) -> false. %Everything else is false deep_char_list(Cs) -> deep_char_list(Cs, []). deep_char_list([C|Cs], More) when is_list(C) -> deep_char_list(C, [Cs|More]); deep_char_list([C|Cs], More) when is_integer(C), C >= 0, C =< 255 -> deep_char_list(Cs, More); deep_char_list([], [Cs|More]) -> deep_char_list(Cs, More); deep_char_list([], []) -> true; deep_char_list(_Other, _More) -> %Everything else is false false. %% printable_list([Char]) -> bool() %% Return true if CharList is a list of printable characters, else %% false. printable_list([C|Cs]) when is_integer(C), C >= $ , C =< 255 -> printable_list(Cs); printable_list([$\n|Cs]) -> printable_list(Cs); printable_list([$\r|Cs]) -> printable_list(Cs); printable_list([$\t|Cs]) -> printable_list(Cs); printable_list([$\v|Cs]) -> printable_list(Cs); printable_list([$\b|Cs]) -> printable_list(Cs); printable_list([$\f|Cs]) -> printable_list(Cs); printable_list([$\e|Cs]) -> printable_list(Cs); printable_list([]) -> true; printable_list(_Other) -> false. %Everything else is false