Packages
otpbp
4.76.2
7.18.0
7.16.1
7.15.0
7.14.0
7.13.0
7.12.0
7.11.0
7.10.2
7.9.3
7.9.2
7.9.1
7.8.7
7.8.6
7.8.5
7.8.4
7.7.1
7.7.0
7.6.3
7.6.2
7.6.1
7.6.0
7.5.1
7.5.0
7.4.0
7.3.4
7.3.3
7.3.2
7.3.1
7.3.0
7.2.0
7.1.1
7.1.0
7.0.4
7.0.3
7.0.2
7.0.1
6.26.0
6.25.0
6.24.0
6.23.0
6.22.2
6.21.3
6.21.2
6.21.1
6.20.2
6.19.1
6.19.0
6.18.3
6.18.2
6.18.1
6.18.0
6.17.1
6.17.0
6.16.0
6.15.4
6.15.3
6.15.2
6.15.1
6.15.0
6.14.0
6.13.5
6.13.4
6.13.3
6.13.2
6.13.1
6.13.0
6.12.0
6.11.2
6.11.1
6.10.0
6.9.2
6.9.1
6.9.0
6.8.0
6.7.1
6.7.0
6.6.4
6.6.3
6.6.2
6.6.1
6.6.0
6.5.0
6.4.0
6.3.3
6.3.2
6.3.1
6.3.0
6.2.1
6.2.0
6.1.0
6.0.0
5.39.0
5.38.0
5.37.0
5.36.0
5.35.2
5.34.3
5.34.2
5.34.1
5.33.1
5.32.1
5.32.0
5.31.3
5.31.2
5.31.1
5.31.0
5.30.1
5.30.0
5.29.0
5.28.4
5.28.3
5.28.2
5.28.1
5.28.0
5.27.0
5.26.5
5.26.4
5.26.3
5.26.2
5.26.1
5.26.0
5.25.0
5.24.2
5.24.1
5.23.0
5.22.2
5.22.1
5.22.0
5.21.0
5.20.1
5.20.0
5.19.4
5.19.3
5.19.2
5.19.1
5.19.0
5.18.0
5.17.0
5.16.3
5.16.1
5.16.0
5.15.1
5.15.0
5.14.0
5.13.1
5.13.0
5.12.1
5.12.0
5.11.2
5.11.1
5.10.1
5.10.0
5.9.0
5.8.0
5.7.0
5.6.1
5.6.0
5.5.0
5.4.2
5.4.1
5.4.0
5.3.0
5.2.2
5.2.1
5.2.0
5.1.2
5.1.1
4.79.0
4.78.0
4.77.0
4.76.2
4.75.3
4.75.2
4.75.1
4.74.0
4.73.1
4.73.0
4.72.3
4.72.2
4.72.1
4.72.0
4.71.1
4.71.0
4.70.0
4.69.4
4.69.3
4.69.2
4.69.1
4.69.0
4.68.0
4.67.5
4.67.4
4.67.3
4.67.2
4.67.0
4.66.0
4.65.2
4.65.1
4.64.0
4.63.2
4.63.1
4.63.0
4.62.0
4.61.1
4.61.0
4.60.4
4.60.3
4.60.2
4.60.1
4.60.0
4.59.0
4.58.0
4.57.2
4.57.1
4.57.0
4.56.2
4.56.1
4.56.0
4.55.0
4.54.0
4.53.0
4.52.1
4.52.0
4.51.3
4.51.2
4.51.0
4.50.0
4.49.3
4.49.2
OTP backports
Current section
Files
Jump to
Current section
Files
src/otpbp_io_lib.erl
-module(otpbp_io_lib).
-ifndef(HAVE_io_lib__limit_term_2).
% OTP 20.0
-export([limit_term/2]).
-endif.
-ifndef(HAVE_io_lib__write_atom_as_latin1_1).
% OTP 20.0
-export([write_atom_as_latin1/1]).
-endif.
-ifndef(HAVE_io_lib__format_3).
% OTP 21.0
-export([format/3]).
-endif.
-ifndef(HAVE_io_lib__fwrite_3).
% OTP 21.0
-export([fwrite/3]).
-endif.
-ifndef(HAVE_io_lib__bformat_2).
% OTP 28.0
-export([bformat/2]).
-endif.
-ifndef(HAVE_io_lib__bformat_3).
% OTP 28.0
-export([bformat/3]).
-endif.
-ifndef(HAVE_io_lib__bwrite_1).
-export([bwrite/1]).
-endif.
-ifndef(HAVE_io_lib__bwrite_2).
% OTP 28.0
-export([bwrite/2]).
-endif.
-ifndef(HAVE_io_lib__bwrite_string_2).
-export([bwrite_string/2]).
-endif.
-ifndef(HAVE_io_lib__bwrite_string_3).
% OTP 28.0
-export([bwrite_string/3]).
-endif.
-ifndef(HAVE_io_lib__write_5).
% OTP 28.0
-export([write/5]).
-endif.
-ifndef(HAVE_io_lib__write_bin_5).
% OTP 28.0
-export([write_bin/5]).
-endif.
-ifndef(HAVE_io_lib__write_string_bin_3).
% OTP 28.0
-export([write_string_bin/3]).
-endif.
-ifndef(HAVE_io_lib__bformat_3).
-ifndef(NEED_IMPORT_io_lib__format_3).
-define(NEED_IMPORT_io_lib__format_3, true).
-endif.
-endif.
-ifndef(HAVE_io_lib__fwrite_3).
-ifndef(NEED_IMPORT_io_lib__format_3).
-define(NEED_IMPORT_io_lib__format_3, true).
-endif.
-endif.
-ifndef(HAVE_io_lib__write_bin_5).
-ifdef(HAVE_io_lib__write_5).
-import(io_lib, [write/5]).
-endif.
-endif.
-ifndef(HAVE_io_lib__bwrite_string_2).
-ifndef(NEED_IMPORT_io_lib__bwrite_string_3).
-define(NEED_IMPORT_io_lib__bwrite_string_3, true).
-endif.
-endif.
-ifndef(HAVE_io_lib__write_string_bin_3).
-ifndef(NEED_IMPORT_io_lib__bwrite_string_3).
-define(NEED_IMPORT_io_lib__bwrite_string_3, true).
-endif.
-endif.
-ifdef(NEED_IMPORT_io_lib__format_3).
-ifdef(HAVE_io_lib__format_3).
-import(io_lib, [format/3]).
-endif.
-endif.
-ifdef(NEED_IMPORT_io_lib__bwrite_string_3).
-ifdef(HAVE_io_lib__bwrite_string_3).
-import(io_lib, [bwrite_string/3]).
-endif.
-endif.
-ifndef(HAVE_io_lib__limit_term_2).
%% The intention is to mimic the depth limitation of io_lib:write()
%% and io_lib_pretty:print(). The leaves ('...') should never be
%% seen when printed with the same depth. Bitstrings are never
%% truncated, which is OK as long as they are not sent to other nodes.
-spec limit_term(term(), non_neg_integer()) -> term().
limit_term(Term, Depth) ->
try test_limit(Term, Depth) of
ok -> Term
catch
throw:limit -> limit(Term, Depth)
end.
limit(_, 0) -> '...';
limit([_|_], 1) -> '...';
limit([H|T] = L, D) ->
case io_lib:printable_list(L) of
true -> L;
false ->
D1 = D - 1,
[limit(H, D1)|limit_tail(T, D1)]
end;
limit({}, _D) -> {};
limit(T, D) when is_tuple(T) -> limit_tuple(T, D);
limit(Term, D) when is_map(Term) -> limit_map(Term, D);
limit(Term, D) when is_bitstring(Term) -> limit_bitstring(Term, D);
limit(Term, _D) -> Term.
limit_tail([], _D) -> [];
limit_tail(_, 1) -> ['...'];
limit_tail([H|T], D) ->
D1 = D - 1,
[limit(H, D1)|limit_tail(T, D1)];
limit_tail(Other, D) -> limit(Other, D - 1).
limit_tuple(T, 1) when is_tuple(T) -> '...';
limit_tuple(T, D) when is_tuple(T) ->
D1 = D - 1,
[H|R] = tuple_to_list(T),
list_to_tuple([limit(H, D1)|limit_tail(R, D1)]).
limit_map(Map, D) when map_size(Map) =< D -> Map;
limit_map(Map, D) -> limit_map(maps:to_list(Map), D, #{}).
limit_map(_, 0, A) -> A;
limit_map([{K, V}|T], D, A) -> limit_map(T, D - 1, A#{K => V}).
%% limit_map_body(_, 0) -> [{'...', '...'}];
%% limit_map_body([], _) -> [];
%% limit_map_body([{K,V}], D) -> [limit_map_assoc(K, V, D)];
%% limit_map_body([{K,V}|KVs], D) ->
%% [limit_map_assoc(K, V, D) | limit_map_body(KVs, D-1)].
%% limit_map_assoc(K, V, D) ->
%% {limit(K, D-1), limit(V, D-1)}.
-compile({inline, limit_tuple/2}).
limit_bitstring(B, _D) -> B. %% Keeps all printable binaries.
test_limit(_, 0) -> throw(limit);
test_limit([_|_], 1) -> throw(limit);
test_limit([H|T] = L, D) when is_integer(D) ->
case io_lib:printable_list(L) of
true -> ok;
false ->
D1 = D - 1,
test_limit(H, D1),
test_limit_tail(T, D1)
end;
test_limit({}, _D) -> ok;
test_limit(T, D) when is_tuple(T) -> test_limit_tuple(T, D);
test_limit(Term, D) when is_map(Term) -> test_limit_map(Term, D);
test_limit(Term, D) when is_bitstring(Term) -> test_limit_bitstring(Term, D);
test_limit(_Term, _D) -> ok.
test_limit_tail([], _D) -> ok;
test_limit_tail(_, 1) -> throw(limit);
test_limit_tail([H|T], D) ->
D1 = D - 1,
test_limit(H, D1),
test_limit_tail(T, D1);
test_limit_tail(Other, D) -> test_limit(Other, D - 1).
test_limit_tuple(T, D) when is_tuple(T) -> test_limit_tuple(T, 1, tuple_size(T), D).
test_limit_tuple(_T, I, Sz, _D) when I > Sz -> ok;
test_limit_tuple(_, _, _, 1) -> throw(limit);
test_limit_tuple(T, I, Sz, D) ->
D1 = D - 1,
test_limit(element(I, T), D1),
test_limit_tuple(T, I + 1, Sz, D1).
test_limit_map(_Map, _D) -> ok.
%% test_limit_map_body(erts_internal:maps_to_list(Map, D), D).
%% test_limit_map_body(_, 0) -> throw(limit);
%% test_limit_map_body([], _) -> ok;
%% test_limit_map_body([{K,V}], D) -> test_limit_map_assoc(K, V, D);
%% test_limit_map_body([{K,V}|KVs], D) ->
%% test_limit_map_assoc(K, V, D),
%% test_limit_map_body(KVs, D-1).
%% test_limit_map_assoc(K, V, D) ->
%% test_limit(K, D-1),
%% test_limit(V, D-1).
-compile({inline, test_limit_tuple/2}).
test_limit_bitstring(_, _) -> ok.
-endif.
-ifndef(HAVE_io_lib__format_3).
format(Format, Data, []) -> io_lib:format(Format, Data);
format(Format, Data, [{chars_limit, L}]) when is_integer(L) -> io_lib:format(Format, Data).
-endif.
-ifndef(HAVE_io_lib__fwrite_3).
fwrite(Format, Data, Opts) -> format(Format, Data, Opts).
-endif.
-ifndef(HAVE_io_lib__write_atom_as_latin1_1).
write_atom_as_latin1(Atom) ->
Chars = atom_to_list(Atom),
case quote_atom(Atom, Chars) of
true -> io_lib:write_string_as_latin1(Chars, $');
false -> Chars
end.
-compile({inline, quote_atom/2}).
quote_atom(_Atom, []) -> true;
quote_atom(Atom, [C|Cs]) when is_integer(C) ->
if
C >= $a, C =< $z; C >= $ß, C =< $ÿ, C =/= $÷ -> not name_chars(Cs) orelse erl_scan:reserved_word(Atom);
true -> true
end.
name_chars([C|Cs]) when is_integer(C) -> name_char(C) andalso name_chars(Cs);
name_chars([]) -> true.
-compile({inline, name_char/1}).
name_char(C) ->
C >= $0 andalso C =< $9 orelse
C >= $a andalso C =< $z orelse
C >= $A andalso C =< $Z orelse
C >= $ß andalso C =< $ÿ andalso C =/= $÷ orelse
C >= $À andalso C =< $Þ andalso C =/= $× orelse
C =:= $_ orelse
C =:= $@.
-endif.
-ifndef(HAVE_io_lib__bformat_2).
bformat(Format, Data) -> unicode:characters_to_binary(io_lib:format(Format, Data)).
-endif.
-ifndef(HAVE_io_lib__bformat_3).
bformat(Format, Data, Options) -> unicode:characters_to_binary(format(Format, Data, Options)).
-endif.
-ifndef(HAVE_io_lib__bwrite_1).
bwrite(Term) -> unicode:characters_to_binary(io_lib:write(Term, [{encoding, utf8}])).
-endif.
-ifndef(HAVE_io_lib__bwrite_2).
bwrite(Term, Options) -> unicode:characters_to_binary(io_lib:write(Term, Options, [{encoding, utf8}])).
-endif.
-ifndef(HAVE_io_lib__bwrite_string_2).
bwrite_string(String, Qoute) -> bwrite_string(String, Qoute, unicode).
-endif.
-ifndef(HAVE_io_lib__bwrite_string_3).
bwrite_string(String, Qoute, latin1) when is_binary(String) ->
unicode:characters_to_binary(io_lib:write_string(String, Qoute), latin1, utf8);
bwrite_string(String, Qoute, InEnc) when is_list(String); is_binary(String), InEnc =:= unicode ->
unicode:characters_to_binary(io_lib:write_string(String, Qoute)).
-endif.
-ifndef(HAVE_io_lib__write_5).
write(Term, Depth, Encoding, MapsOrder, CharsLimit) ->
io_lib:write(Term, [{depth, Depth}, {encoding, Encoding}, {maps_order, MapsOrder}, {chars_limit, CharsLimit}]).
-endif.
-ifndef(HAVE_io_lib__write_bin_5).
write_bin(Term, Depth, Encoding, MapsOrder, CharsLimit) ->
unicode:characters_to_binary(write(Term, Depth, Encoding, MapsOrder, CharsLimit)).
-endif.
-ifndef(HAVE_io_lib__write_string_bin_3).
write_string_bin(String, Qoute, InEnc) ->
B = bwrite_string(String, Qoute, InEnc),
{B, string:length(B)}.
-endif.