diff options
author | Hans Bolinder <[email protected]> | 2019-02-26 10:11:59 +0100 |
---|---|---|
committer | Hans Bolinder <[email protected]> | 2019-03-05 12:02:25 +0100 |
commit | cd5dbd5204a783743c72116d81e993ec041b7396 (patch) | |
tree | 16673271f8c9e97b2aafd41f2c6287358f56f9a1 /lib/stdlib/src | |
parent | 23c33d5b8d5234a159b0dc39e2fe6aa99dadaed2 (diff) | |
download | otp-cd5dbd5204a783743c72116d81e993ec041b7396.tar.gz otp-cd5dbd5204a783743c72116d81e993ec041b7396.tar.bz2 otp-cd5dbd5204a783743c72116d81e993ec041b7396.zip |
stdlib: Correct and optimize pretty printing of strings
Avoid traversing all of the list/string when only part of it will be
used. An explicit check that the list is flat is needed since
string:slice() accepts deep lists and more.
Diffstat (limited to 'lib/stdlib/src')
-rw-r--r-- | lib/stdlib/src/io_lib_pretty.erl | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl index 5483ea87b5..8f2fd7ea8f 100644 --- a/lib/stdlib/src/io_lib_pretty.erl +++ b/lib/stdlib/src/io_lib_pretty.erl @@ -721,7 +721,7 @@ printable_list(_L, 1, _T, _Enc) -> printable_list(L, _D, T, latin1) when T < 0 -> io_lib:printable_latin1_list(L); printable_list(L, _D, T, Enc) when T >= 0 -> - case slice(L, tsub(T, 2)) of + case slice(L, tsub(T, 2), Enc) of false -> false; {prefix, Prefix} when Enc =:= latin1 -> @@ -737,20 +737,46 @@ printable_list(L, _D, T, Enc) when T >= 0 -> printable_list(L, _D, T, _Uni) when T < 0-> io_lib:printable_list(L). -slice(L, N) -> - try io_lib:chars_length(L) =< N of - true -> +slice(L, N, latin1) -> + try lists:split(N, L) of + {_, []} -> all; - false -> - case string:slice(L, 0, N) of - "" -> - false; - Prefix -> - {prefix, Prefix} + {[], _} -> + false; + {L1, _} -> + {prefix, L1} + catch + _:_ -> + all + end; +slice(L, N, _Uni) -> + %% Be careful not to traverse more of L than necessary. + try string:slice(L, 0, N) of + "" -> + false; + Prefix -> + %% Assume no binaries are introduced by string:slice(). + case is_flat(L, lists:flatlength(Prefix)) of + true -> + case string:equal(Prefix, L) of + true -> + all; + false -> + {prefix, Prefix} + end; + false -> + false end catch _:_ -> false end. +is_flat(_L, 0) -> + true; +is_flat([C|Cs], N) when is_integer(C) -> + is_flat(Cs, N - 1); +is_flat(_, _N) -> + false. + printable_bin0(Bin, D, T, Enc) -> Len = case D >= 0 of true -> |