1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-2019. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(io_lib_format). 21 22%% Formatting functions of io library. 23 24-export([fwrite/2,fwrite/3,fwrite_g/1,indentation/2,scan/2,unscan/1, 25 build/1, build/2]). 26 27%% Format the arguments in Args after string Format. Just generate 28%% an error if there is an error in the arguments. 29%% 30%% To do the printing command correctly we need to calculate the 31%% current indentation for everything before it. This may be very 32%% expensive, especially when it is not needed, so we first determine 33%% if, and for how long, we need to calculate the indentations. We do 34%% this by first collecting all the control sequences and 35%% corresponding arguments, then counting the print sequences and 36%% then building the output. This method has some drawbacks, it does 37%% two passes over the format string and creates more temporary data, 38%% and it also splits the handling of the control characters into two 39%% parts. 40 41-spec fwrite(Format, Data) -> io_lib:chars() when 42 Format :: io:format(), 43 Data :: [term()]. 44 45fwrite(Format, Args) -> 46 build(scan(Format, Args)). 47 48-spec fwrite(Format, Data, Options) -> io_lib:chars() when 49 Format :: io:format(), 50 Data :: [term()], 51 Options :: [Option], 52 Option :: {'chars_limit', CharsLimit}, 53 CharsLimit :: io_lib:chars_limit(). 54 55fwrite(Format, Args, Options) -> 56 build(scan(Format, Args), Options). 57 58%% Build the output text for a pre-parsed format list. 59 60-spec build(FormatList) -> io_lib:chars() when 61 FormatList :: [char() | io_lib:format_spec()]. 62 63build(Cs) -> 64 build(Cs, []). 65 66-spec build(FormatList, Options) -> io_lib:chars() when 67 FormatList :: [char() | io_lib:format_spec()], 68 Options :: [Option], 69 Option :: {'chars_limit', CharsLimit}, 70 CharsLimit :: io_lib:chars_limit(). 71 72build(Cs, Options) -> 73 CharsLimit = get_option(chars_limit, Options, -1), 74 Res1 = build_small(Cs), 75 {P, S, W, Other} = count_small(Res1), 76 case P + S + W of 77 0 -> 78 Res1; 79 NumOfLimited -> 80 RemainingChars = sub(CharsLimit, Other), 81 build_limited(Res1, P, NumOfLimited, RemainingChars, 0) 82 end. 83 84%% Parse all control sequences in the format string. 85 86-spec scan(Format, Data) -> FormatList when 87 Format :: io:format(), 88 Data :: [term()], 89 FormatList :: [char() | io_lib:format_spec()]. 90 91scan(Format, Args) when is_atom(Format) -> 92 scan(atom_to_list(Format), Args); 93scan(Format, Args) when is_binary(Format) -> 94 scan(binary_to_list(Format), Args); 95scan(Format, Args) -> 96 collect(Format, Args). 97 98%% Revert a pre-parsed format list to a plain character list and a 99%% list of arguments. 100 101-spec unscan(FormatList) -> {Format, Data} when 102 FormatList :: [char() | io_lib:format_spec()], 103 Format :: io:format(), 104 Data :: [term()]. 105 106unscan(Cs) -> 107 {print(Cs), args(Cs)}. 108 109args([#{args := As} | Cs]) -> 110 As ++ args(Cs); 111args([_C | Cs]) -> 112 args(Cs); 113args([]) -> 114 []. 115 116print([#{control_char := C, width := F, adjust := Ad, precision := P, 117 pad_char := Pad, encoding := Encoding, strings := Strings} | Cs]) -> 118 print(C, F, Ad, P, Pad, Encoding, Strings) ++ print(Cs); 119print([C | Cs]) -> 120 [C | print(Cs)]; 121print([]) -> 122 []. 123 124print(C, F, Ad, P, Pad, Encoding, Strings) -> 125 [$~] ++ print_field_width(F, Ad) ++ print_precision(P, Pad) ++ 126 print_pad_char(Pad) ++ print_encoding(Encoding) ++ 127 print_strings(Strings) ++ [C]. 128 129print_field_width(none, _Ad) -> ""; 130print_field_width(F, left) -> integer_to_list(-F); 131print_field_width(F, right) -> integer_to_list(F). 132 133print_precision(none, $\s) -> ""; 134print_precision(none, _Pad) -> "."; % pad must be second dot 135print_precision(P, _Pad) -> [$. | integer_to_list(P)]. 136 137print_pad_char($\s) -> ""; % default, no need to make explicit 138print_pad_char(Pad) -> [$., Pad]. 139 140print_encoding(unicode) -> "t"; 141print_encoding(latin1) -> "". 142 143print_strings(false) -> "l"; 144print_strings(true) -> "". 145 146collect([$~|Fmt0], Args0) -> 147 {C,Fmt1,Args1} = collect_cseq(Fmt0, Args0), 148 [C|collect(Fmt1, Args1)]; 149collect([C|Fmt], Args) -> 150 [C|collect(Fmt, Args)]; 151collect([], []) -> []. 152 153collect_cseq(Fmt0, Args0) -> 154 {F,Ad,Fmt1,Args1} = field_width(Fmt0, Args0), 155 {P,Fmt2,Args2} = precision(Fmt1, Args1), 156 {Pad,Fmt3,Args3} = pad_char(Fmt2, Args2), 157 Spec0 = #{width => F, 158 adjust => Ad, 159 precision => P, 160 pad_char => Pad, 161 encoding => latin1, 162 strings => true}, 163 {Spec1,Fmt4} = modifiers(Fmt3, Spec0), 164 {C,As,Fmt5,Args4} = collect_cc(Fmt4, Args3), 165 Spec2 = Spec1#{control_char => C, args => As}, 166 {Spec2,Fmt5,Args4}. 167 168modifiers([$t|Fmt], Spec) -> 169 modifiers(Fmt, Spec#{encoding => unicode}); 170modifiers([$l|Fmt], Spec) -> 171 modifiers(Fmt, Spec#{strings => false}); 172modifiers(Fmt, Spec) -> 173 {Spec, Fmt}. 174 175field_width([$-|Fmt0], Args0) -> 176 {F,Fmt,Args} = field_value(Fmt0, Args0), 177 field_width(-F, Fmt, Args); 178field_width(Fmt0, Args0) -> 179 {F,Fmt,Args} = field_value(Fmt0, Args0), 180 field_width(F, Fmt, Args). 181 182field_width(F, Fmt, Args) when F < 0 -> 183 {-F,left,Fmt,Args}; 184field_width(F, Fmt, Args) when F >= 0 -> 185 {F,right,Fmt,Args}. 186 187precision([$.|Fmt], Args) -> 188 field_value(Fmt, Args); 189precision(Fmt, Args) -> 190 {none,Fmt,Args}. 191 192field_value([$*|Fmt], [A|Args]) when is_integer(A) -> 193 {A,Fmt,Args}; 194field_value([C|Fmt], Args) when is_integer(C), C >= $0, C =< $9 -> 195 field_value([C|Fmt], Args, 0); 196field_value(Fmt, Args) -> 197 {none,Fmt,Args}. 198 199field_value([C|Fmt], Args, F) when is_integer(C), C >= $0, C =< $9 -> 200 field_value(Fmt, Args, 10*F + (C - $0)); 201field_value(Fmt, Args, F) -> %Default case 202 {F,Fmt,Args}. 203 204pad_char([$.,$*|Fmt], [Pad|Args]) -> {Pad,Fmt,Args}; 205pad_char([$.,Pad|Fmt], Args) -> {Pad,Fmt,Args}; 206pad_char(Fmt, Args) -> {$\s,Fmt,Args}. 207 208%% collect_cc([FormatChar], [Argument]) -> 209%% {Control,[ControlArg],[FormatChar],[Arg]}. 210%% Here we collect the argments for each control character. 211%% Be explicit to cause failure early. 212 213collect_cc([$w|Fmt], [A|Args]) -> {$w,[A],Fmt,Args}; 214collect_cc([$p|Fmt], [A|Args]) -> {$p,[A],Fmt,Args}; 215collect_cc([$W|Fmt], [A,Depth|Args]) -> {$W,[A,Depth],Fmt,Args}; 216collect_cc([$P|Fmt], [A,Depth|Args]) -> {$P,[A,Depth],Fmt,Args}; 217collect_cc([$s|Fmt], [A|Args]) -> {$s,[A],Fmt,Args}; 218collect_cc([$e|Fmt], [A|Args]) -> {$e,[A],Fmt,Args}; 219collect_cc([$f|Fmt], [A|Args]) -> {$f,[A],Fmt,Args}; 220collect_cc([$g|Fmt], [A|Args]) -> {$g,[A],Fmt,Args}; 221collect_cc([$b|Fmt], [A|Args]) -> {$b,[A],Fmt,Args}; 222collect_cc([$B|Fmt], [A|Args]) -> {$B,[A],Fmt,Args}; 223collect_cc([$x|Fmt], [A,Prefix|Args]) -> {$x,[A,Prefix],Fmt,Args}; 224collect_cc([$X|Fmt], [A,Prefix|Args]) -> {$X,[A,Prefix],Fmt,Args}; 225collect_cc([$+|Fmt], [A|Args]) -> {$+,[A],Fmt,Args}; 226collect_cc([$#|Fmt], [A|Args]) -> {$#,[A],Fmt,Args}; 227collect_cc([$c|Fmt], [A|Args]) -> {$c,[A],Fmt,Args}; 228collect_cc([$~|Fmt], Args) when is_list(Args) -> {$~,[],Fmt,Args}; 229collect_cc([$n|Fmt], Args) when is_list(Args) -> {$n,[],Fmt,Args}; 230collect_cc([$i|Fmt], [A|Args]) -> {$i,[A],Fmt,Args}. 231 232%% count_small([ControlC]) -> Count. 233%% Count the number of big (pPwWsS) print requests and 234%% number of characters of other print (small) requests. 235 236count_small(Cs) -> 237 count_small(Cs, #{p => 0, s => 0, w => 0, other => 0}). 238 239count_small([#{control_char := $p}|Cs], #{p := P} = Cnts) -> 240 count_small(Cs, Cnts#{p := P + 1}); 241count_small([#{control_char := $P}|Cs], #{p := P} = Cnts) -> 242 count_small(Cs, Cnts#{p := P + 1}); 243count_small([#{control_char := $w}|Cs], #{w := W} = Cnts) -> 244 count_small(Cs, Cnts#{w := W + 1}); 245count_small([#{control_char := $W}|Cs], #{w := W} = Cnts) -> 246 count_small(Cs, Cnts#{w := W + 1}); 247count_small([#{control_char := $s}|Cs], #{w := W} = Cnts) -> 248 count_small(Cs, Cnts#{w := W + 1}); 249count_small([S|Cs], #{other := Other} = Cnts) when is_list(S); 250 is_binary(S) -> 251 count_small(Cs, Cnts#{other := Other + io_lib:chars_length(S)}); 252count_small([C|Cs], #{other := Other} = Cnts) when is_integer(C) -> 253 count_small(Cs, Cnts#{other := Other + 1}); 254count_small([], #{p := P, s := S, w := W, other := Other}) -> 255 {P, S, W, Other}. 256 257%% build_small([Control]) -> io_lib:chars(). 258%% Interpret the control structures, but only the small ones. 259%% The big ones are saved for later. 260%% build_limited([Control], NumberOfPps, NumberOfLimited, 261%% CharsLimit, Indentation) 262%% Interpret the control structures. Count the number of print 263%% remaining and only calculate indentation when necessary. Must also 264%% be smart when calculating indentation for characters in format. 265 266build_small([#{control_char := C, args := As, width := F, adjust := Ad, 267 precision := P, pad_char := Pad, encoding := Enc}=CC | Cs]) -> 268 case control_small(C, As, F, Ad, P, Pad, Enc) of 269 not_small -> [CC | build_small(Cs)]; 270 S -> lists:flatten(S) ++ build_small(Cs) 271 end; 272build_small([C|Cs]) -> [C|build_small(Cs)]; 273build_small([]) -> []. 274 275build_limited([#{control_char := C, args := As, width := F, adjust := Ad, 276 precision := P, pad_char := Pad, encoding := Enc, 277 strings := Str} | Cs], NumOfPs0, Count0, MaxLen0, I) -> 278 MaxChars = if 279 MaxLen0 < 0 -> MaxLen0; 280 true -> MaxLen0 div Count0 281 end, 282 S = control_limited(C, As, F, Ad, P, Pad, Enc, Str, MaxChars, I), 283 NumOfPs = decr_pc(C, NumOfPs0), 284 Count = Count0 - 1, 285 MaxLen = if 286 MaxLen0 < 0 -> % optimization 287 MaxLen0; 288 true -> 289 Len = io_lib:chars_length(S), 290 sub(MaxLen0, Len) 291 end, 292 if 293 NumOfPs > 0 -> [S|build_limited(Cs, NumOfPs, Count, 294 MaxLen, indentation(S, I))]; 295 true -> [S|build_limited(Cs, NumOfPs, Count, MaxLen, I)] 296 end; 297build_limited([$\n|Cs], NumOfPs, Count, MaxLen, _I) -> 298 [$\n|build_limited(Cs, NumOfPs, Count, MaxLen, 0)]; 299build_limited([$\t|Cs], NumOfPs, Count, MaxLen, I) -> 300 [$\t|build_limited(Cs, NumOfPs, Count, MaxLen, ((I + 8) div 8) * 8)]; 301build_limited([C|Cs], NumOfPs, Count, MaxLen, I) -> 302 [C|build_limited(Cs, NumOfPs, Count, MaxLen, I+1)]; 303build_limited([], _, _, _, _) -> []. 304 305decr_pc($p, Pc) -> Pc - 1; 306decr_pc($P, Pc) -> Pc - 1; 307decr_pc(_, Pc) -> Pc. 308 309%% Calculate the indentation of the end of a string given its start 310%% indentation. We assume tabs at 8 cols. 311 312-spec indentation(String, StartIndent) -> integer() when 313 String :: io_lib:chars(), 314 StartIndent :: integer(). 315 316indentation([$\n|Cs], _I) -> indentation(Cs, 0); 317indentation([$\t|Cs], I) -> indentation(Cs, ((I + 8) div 8) * 8); 318indentation([C|Cs], I) when is_integer(C) -> 319 indentation(Cs, I+1); 320indentation([C|Cs], I) -> 321 indentation(Cs, indentation(C, I)); 322indentation([], I) -> I. 323 324%% control_small(FormatChar, [Argument], FieldWidth, Adjust, Precision, 325%% PadChar, Encoding) -> String 326%% control_limited(FormatChar, [Argument], FieldWidth, Adjust, Precision, 327%% PadChar, Encoding, StringP, ChrsLim, Indentation) -> String 328%% These are the dispatch functions for the various formatting controls. 329 330control_small($s, [A], F, Adj, P, Pad, latin1=Enc) when is_atom(A) -> 331 L = iolist_to_chars(atom_to_list(A)), 332 string(L, F, Adj, P, Pad, Enc); 333control_small($s, [A], F, Adj, P, Pad, unicode=Enc) when is_atom(A) -> 334 string(atom_to_list(A), F, Adj, P, Pad, Enc); 335control_small($e, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> 336 fwrite_e(A, F, Adj, P, Pad); 337control_small($f, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> 338 fwrite_f(A, F, Adj, P, Pad); 339control_small($g, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> 340 fwrite_g(A, F, Adj, P, Pad); 341control_small($b, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> 342 unprefixed_integer(A, F, Adj, base(P), Pad, true); 343control_small($B, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> 344 unprefixed_integer(A, F, Adj, base(P), Pad, false); 345control_small($x, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A), 346 is_atom(Prefix) -> 347 prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), true); 348control_small($x, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) -> 349 true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list 350 prefixed_integer(A, F, Adj, base(P), Pad, Prefix, true); 351control_small($X, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A), 352 is_atom(Prefix) -> 353 prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), false); 354control_small($X, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) -> 355 true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list 356 prefixed_integer(A, F, Adj, base(P), Pad, Prefix, false); 357control_small($+, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> 358 Base = base(P), 359 Prefix = [integer_to_list(Base), $#], 360 prefixed_integer(A, F, Adj, Base, Pad, Prefix, true); 361control_small($#, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> 362 Base = base(P), 363 Prefix = [integer_to_list(Base), $#], 364 prefixed_integer(A, F, Adj, Base, Pad, Prefix, false); 365control_small($c, [A], F, Adj, P, Pad, unicode) when is_integer(A) -> 366 char(A, F, Adj, P, Pad); 367control_small($c, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> 368 char(A band 255, F, Adj, P, Pad); 369control_small($~, [], F, Adj, P, Pad, _Enc) -> char($~, F, Adj, P, Pad); 370control_small($n, [], F, Adj, P, Pad, _Enc) -> newline(F, Adj, P, Pad); 371control_small($i, [_A], _F, _Adj, _P, _Pad, _Enc) -> []; 372control_small(_C, _As, _F, _Adj, _P, _Pad, _Enc) -> not_small. 373 374control_limited($s, [L0], F, Adj, P, Pad, latin1=Enc, _Str, CL, _I) -> 375 L = iolist_to_chars(L0, F, CL), 376 string(L, limit_field(F, CL), Adj, P, Pad, Enc); 377control_limited($s, [L0], F, Adj, P, Pad, unicode=Enc, _Str, CL, _I) -> 378 L = cdata_to_chars(L0, F, CL), 379 uniconv(string(L, limit_field(F, CL), Adj, P, Pad, Enc)); 380control_limited($w, [A], F, Adj, P, Pad, Enc, _Str, CL, _I) -> 381 Chars = io_lib:write(A, [{depth, -1}, {encoding, Enc}, {chars_limit, CL}]), 382 term(Chars, F, Adj, P, Pad); 383control_limited($p, [A], F, Adj, P, Pad, Enc, Str, CL, I) -> 384 print(A, -1, F, Adj, P, Pad, Enc, Str, CL, I); 385control_limited($W, [A,Depth], F, Adj, P, Pad, Enc, _Str, CL, _I) 386 when is_integer(Depth) -> 387 Chars = io_lib:write(A, [{depth, Depth}, {encoding, Enc}, {chars_limit, CL}]), 388 term(Chars, F, Adj, P, Pad); 389control_limited($P, [A,Depth], F, Adj, P, Pad, Enc, Str, CL, I) 390 when is_integer(Depth) -> 391 print(A, Depth, F, Adj, P, Pad, Enc, Str, CL, I). 392 393-ifdef(UNICODE_AS_BINARIES). 394uniconv(C) -> 395 unicode:characters_to_binary(C,unicode). 396-else. 397uniconv(C) -> 398 C. 399-endif. 400%% Default integer base 401base(none) -> 402 10; 403base(B) when is_integer(B) -> 404 B. 405 406%% term(TermList, Field, Adjust, Precision, PadChar) 407%% Output the characters in a term. 408%% Adjust the characters within the field if length less than Max padding 409%% with PadChar. 410 411term(T, none, _Adj, none, _Pad) -> T; 412term(T, none, Adj, P, Pad) -> term(T, P, Adj, P, Pad); 413term(T, F, Adj, P0, Pad) -> 414 L = io_lib:chars_length(T), 415 P = erlang:min(L, case P0 of none -> F; _ -> min(P0, F) end), 416 if 417 L > P -> 418 adjust(chars($*, P), chars(Pad, F-P), Adj); 419 F >= P -> 420 adjust(T, chars(Pad, F-L), Adj) 421 end. 422 423%% print(Term, Depth, Field, Adjust, Precision, PadChar, Encoding, 424%% Indentation) 425%% Print a term. Field width sets maximum line length, Precision sets 426%% initial indentation. 427 428print(T, D, none, Adj, P, Pad, E, Str, ChLim, I) -> 429 print(T, D, 80, Adj, P, Pad, E, Str, ChLim, I); 430print(T, D, F, Adj, none, Pad, E, Str, ChLim, I) -> 431 print(T, D, F, Adj, I+1, Pad, E, Str, ChLim, I); 432print(T, D, F, right, P, _Pad, Enc, Str, ChLim, _I) -> 433 Options = [{chars_limit, ChLim}, 434 {column, P}, 435 {line_length, F}, 436 {depth, D}, 437 {encoding, Enc}, 438 {strings, Str}], 439 io_lib_pretty:print(T, Options). 440 441%% fwrite_e(Float, Field, Adjust, Precision, PadChar) 442 443fwrite_e(Fl, none, Adj, none, Pad) -> %Default values 444 fwrite_e(Fl, none, Adj, 6, Pad); 445fwrite_e(Fl, none, _Adj, P, _Pad) when P >= 2 -> 446 float_e(Fl, float_data(Fl), P); 447fwrite_e(Fl, F, Adj, none, Pad) -> 448 fwrite_e(Fl, F, Adj, 6, Pad); 449fwrite_e(Fl, F, Adj, P, Pad) when P >= 2 -> 450 term(float_e(Fl, float_data(Fl), P), F, Adj, F, Pad). 451 452float_e(Fl, Fd, P) when Fl < 0.0 -> %Negative numbers 453 [$-|float_e(-Fl, Fd, P)]; 454float_e(_Fl, {Ds,E}, P) -> 455 case float_man(Ds, 1, P-1) of 456 {[$0|Fs],true} -> [[$1|Fs]|float_exp(E)]; 457 {Fs,false} -> [Fs|float_exp(E-1)] 458 end. 459 460%% float_man([Digit], Icount, Dcount) -> {[Char],CarryFlag}. 461%% Generate the characters in the mantissa from the digits with Icount 462%% characters before the '.' and Dcount decimals. Handle carry and let 463%% caller decide what to do at top. 464 465float_man(Ds, 0, Dc) -> 466 {Cs,C} = float_man(Ds, Dc), 467 {[$.|Cs],C}; 468float_man([D|Ds], I, Dc) -> 469 case float_man(Ds, I-1, Dc) of 470 {Cs,true} when D =:= $9 -> {[$0|Cs],true}; 471 {Cs,true} -> {[D+1|Cs],false}; 472 {Cs,false} -> {[D|Cs],false} 473 end; 474float_man([], I, Dc) -> %Pad with 0's 475 {lists:duplicate(I, $0) ++ [$.|lists:duplicate(Dc, $0)],false}. 476 477float_man([D|_], 0) when D >= $5 -> {[],true}; 478float_man([_|_], 0) -> {[],false}; 479float_man([D|Ds], Dc) -> 480 case float_man(Ds, Dc-1) of 481 {Cs,true} when D =:= $9 -> {[$0|Cs],true}; 482 {Cs,true} -> {[D+1|Cs],false}; 483 {Cs,false} -> {[D|Cs],false} 484 end; 485float_man([], Dc) -> {lists:duplicate(Dc, $0),false}. %Pad with 0's 486 487%% float_exp(Exponent) -> [Char]. 488%% Generate the exponent of a floating point number. Always include sign. 489 490float_exp(E) when E >= 0 -> 491 [$e,$+|integer_to_list(E)]; 492float_exp(E) -> 493 [$e|integer_to_list(E)]. 494 495%% fwrite_f(FloatData, Field, Adjust, Precision, PadChar) 496 497fwrite_f(Fl, none, Adj, none, Pad) -> %Default values 498 fwrite_f(Fl, none, Adj, 6, Pad); 499fwrite_f(Fl, none, _Adj, P, _Pad) when P >= 1 -> 500 float_f(Fl, float_data(Fl), P); 501fwrite_f(Fl, F, Adj, none, Pad) -> 502 fwrite_f(Fl, F, Adj, 6, Pad); 503fwrite_f(Fl, F, Adj, P, Pad) when P >= 1 -> 504 term(float_f(Fl, float_data(Fl), P), F, Adj, F, Pad). 505 506float_f(Fl, Fd, P) when Fl < 0.0 -> 507 [$-|float_f(-Fl, Fd, P)]; 508float_f(Fl, {Ds,E}, P) when E =< 0 -> 509 float_f(Fl, {lists:duplicate(-E+1, $0)++Ds,1}, P); %Prepend enough 0's 510float_f(_Fl, {Ds,E}, P) -> 511 case float_man(Ds, E, P) of 512 {Fs,true} -> "1" ++ Fs; %Handle carry 513 {Fs,false} -> Fs 514 end. 515 516%% float_data([FloatChar]) -> {[Digit],Exponent} 517 518float_data(Fl) -> 519 float_data(float_to_list(Fl), []). 520 521float_data([$e|E], Ds) -> 522 {lists:reverse(Ds),list_to_integer(E)+1}; 523float_data([D|Cs], Ds) when D >= $0, D =< $9 -> 524 float_data(Cs, [D|Ds]); 525float_data([_|Cs], Ds) -> 526 float_data(Cs, Ds). 527 528%% Writes the shortest, correctly rounded string that converts 529%% to Float when read back with list_to_float/1. 530%% 531%% See also "Printing Floating-Point Numbers Quickly and Accurately" 532%% in Proceedings of the SIGPLAN '96 Conference on Programming 533%% Language Design and Implementation. 534 535-spec fwrite_g(float()) -> string(). 536 537fwrite_g(0.0) -> 538 "0.0"; 539fwrite_g(Float) when is_float(Float) -> 540 {Frac, Exp} = mantissa_exponent(Float), 541 {Place, Digits} = fwrite_g_1(Float, Exp, Frac), 542 R = insert_decimal(Place, [$0 + D || D <- Digits]), 543 [$- || true <- [Float < 0.0]] ++ R. 544 545-define(BIG_POW, (1 bsl 52)). 546-define(MIN_EXP, (-1074)). 547 548mantissa_exponent(F) -> 549 case <<F:64/float>> of 550 <<_S:1, 0:11, M:52>> -> % denormalized 551 E = log2floor(M), 552 {M bsl (53 - E), E - 52 - 1075}; 553 <<_S:1, BE:11, M:52>> when BE < 2047 -> 554 {M + ?BIG_POW, BE - 1075} 555 end. 556 557fwrite_g_1(Float, Exp, Frac) -> 558 Round = (Frac band 1) =:= 0, 559 if 560 Exp >= 0 -> 561 BExp = 1 bsl Exp, 562 if 563 Frac =:= ?BIG_POW -> 564 scale(Frac * BExp * 4, 4, BExp * 2, BExp, 565 Round, Round, Float); 566 true -> 567 scale(Frac * BExp * 2, 2, BExp, BExp, 568 Round, Round, Float) 569 end; 570 Exp < ?MIN_EXP -> 571 BExp = 1 bsl (?MIN_EXP - Exp), 572 scale(Frac * 2, 1 bsl (1 - Exp), BExp, BExp, 573 Round, Round, Float); 574 Exp > ?MIN_EXP, Frac =:= ?BIG_POW -> 575 scale(Frac * 4, 1 bsl (2 - Exp), 2, 1, 576 Round, Round, Float); 577 true -> 578 scale(Frac * 2, 1 bsl (1 - Exp), 1, 1, 579 Round, Round, Float) 580 end. 581 582scale(R, S, MPlus, MMinus, LowOk, HighOk, Float) -> 583 Est = int_ceil(math:log10(abs(Float)) - 1.0e-10), 584 %% Note that the scheme implementation uses a 326 element look-up 585 %% table for int_pow(10, N) where we do not. 586 if 587 Est >= 0 -> 588 fixup(R, S * int_pow(10, Est), MPlus, MMinus, Est, 589 LowOk, HighOk); 590 true -> 591 Scale = int_pow(10, -Est), 592 fixup(R * Scale, S, MPlus * Scale, MMinus * Scale, Est, 593 LowOk, HighOk) 594 end. 595 596fixup(R, S, MPlus, MMinus, K, LowOk, HighOk) -> 597 TooLow = if 598 HighOk -> R + MPlus >= S; 599 true -> R + MPlus > S 600 end, 601 case TooLow of 602 true -> 603 {K + 1, generate(R, S, MPlus, MMinus, LowOk, HighOk)}; 604 false -> 605 {K, generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)} 606 end. 607 608generate(R0, S, MPlus, MMinus, LowOk, HighOk) -> 609 D = R0 div S, 610 R = R0 rem S, 611 TC1 = if 612 LowOk -> R =< MMinus; 613 true -> R < MMinus 614 end, 615 TC2 = if 616 HighOk -> R + MPlus >= S; 617 true -> R + MPlus > S 618 end, 619 case {TC1, TC2} of 620 {false, false} -> 621 [D | generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)]; 622 {false, true} -> 623 [D + 1]; 624 {true, false} -> 625 [D]; 626 {true, true} when R * 2 < S -> 627 [D]; 628 {true, true} -> 629 [D + 1] 630 end. 631 632insert_decimal(0, S) -> 633 "0." ++ S; 634insert_decimal(Place, S) -> 635 L = length(S), 636 if 637 Place < 0; 638 Place >= L -> 639 ExpL = integer_to_list(Place - 1), 640 ExpDot = if L =:= 1 -> 2; true -> 1 end, 641 ExpCost = length(ExpL) + 1 + ExpDot, 642 if 643 Place < 0 -> 644 if 645 2 - Place =< ExpCost -> 646 "0." ++ lists:duplicate(-Place, $0) ++ S; 647 true -> 648 insert_exp(ExpL, S) 649 end; 650 true -> 651 if 652 Place - L + 2 =< ExpCost -> 653 S ++ lists:duplicate(Place - L, $0) ++ ".0"; 654 true -> 655 insert_exp(ExpL, S) 656 end 657 end; 658 true -> 659 {S0, S1} = lists:split(Place, S), 660 S0 ++ "." ++ S1 661 end. 662 663insert_exp(ExpL, [C]) -> 664 [C] ++ ".0e" ++ ExpL; 665insert_exp(ExpL, [C | S]) -> 666 [C] ++ "." ++ S ++ "e" ++ ExpL. 667 668int_ceil(X) when is_float(X) -> 669 T = trunc(X), 670 case (X - T) of 671 Neg when Neg < 0 -> T; 672 Pos when Pos > 0 -> T + 1; 673 _ -> T 674 end. 675 676int_pow(X, 0) when is_integer(X) -> 677 1; 678int_pow(X, N) when is_integer(X), is_integer(N), N > 0 -> 679 int_pow(X, N, 1). 680 681int_pow(X, N, R) when N < 2 -> 682 R * X; 683int_pow(X, N, R) -> 684 int_pow(X * X, N bsr 1, case N band 1 of 1 -> R * X; 0 -> R end). 685 686log2floor(Int) when is_integer(Int), Int > 0 -> 687 log2floor(Int, 0). 688 689log2floor(0, N) -> 690 N; 691log2floor(Int, N) -> 692 log2floor(Int bsr 1, 1 + N). 693 694%% fwrite_g(Float, Field, Adjust, Precision, PadChar) 695%% Use the f form if Float is >= 0.1 and < 1.0e4, 696%% and the prints correctly in the f form, else the e form. 697%% Precision always means the # of significant digits. 698 699fwrite_g(Fl, F, Adj, none, Pad) -> 700 fwrite_g(Fl, F, Adj, 6, Pad); 701fwrite_g(Fl, F, Adj, P, Pad) when P >= 1 -> 702 A = abs(Fl), 703 E = if A < 1.0e-1 -> -2; 704 A < 1.0e0 -> -1; 705 A < 1.0e1 -> 0; 706 A < 1.0e2 -> 1; 707 A < 1.0e3 -> 2; 708 A < 1.0e4 -> 3; 709 true -> fwrite_f 710 end, 711 if P =< 1, E =:= -1; 712 P-1 > E, E >= -1 -> 713 fwrite_f(Fl, F, Adj, P-1-E, Pad); 714 P =< 1 -> 715 fwrite_e(Fl, F, Adj, 2, Pad); 716 true -> 717 fwrite_e(Fl, F, Adj, P, Pad) 718 end. 719 720 721iolist_to_chars(Cs, F, CharsLimit) when CharsLimit < 0; CharsLimit >= F -> 722 iolist_to_chars(Cs); 723iolist_to_chars(Cs, _, CharsLimit) -> 724 limit_iolist_to_chars(Cs, sub(CharsLimit, 3), [], normal). % three dots 725 726iolist_to_chars([C|Cs]) when is_integer(C), C >= $\000, C =< $\377 -> 727 [C | iolist_to_chars(Cs)]; 728iolist_to_chars([I|Cs]) -> 729 [iolist_to_chars(I) | iolist_to_chars(Cs)]; 730iolist_to_chars([]) -> 731 []; 732iolist_to_chars(B) when is_binary(B) -> 733 binary_to_list(B). 734 735limit_iolist_to_chars(Cs, 0, S, normal) -> 736 L = limit_iolist_to_chars(Cs, 4, S, final), 737 case iolist_size(L) of 738 N when N < 4 -> L; 739 4 -> "..." 740 end; 741limit_iolist_to_chars(_Cs, 0, _S, final) -> []; 742limit_iolist_to_chars([C|Cs], Limit, S, Mode) when C >= $\000, C =< $\377 -> 743 [C | limit_iolist_to_chars(Cs, Limit - 1, S, Mode)]; 744limit_iolist_to_chars([I|Cs], Limit, S, Mode) -> 745 limit_iolist_to_chars(I, Limit, [Cs|S], Mode); 746limit_iolist_to_chars([], _Limit, [], _Mode) -> 747 []; 748limit_iolist_to_chars([], Limit, [Cs|S], Mode) -> 749 limit_iolist_to_chars(Cs, Limit, S, Mode); 750limit_iolist_to_chars(B, Limit, S, Mode) when is_binary(B) -> 751 case byte_size(B) of 752 Sz when Sz > Limit -> 753 {B1, B2} = split_binary(B, Limit), 754 [binary_to_list(B1) | limit_iolist_to_chars(B2, 0, S, Mode)]; 755 Sz -> 756 [binary_to_list(B) | limit_iolist_to_chars([], Limit-Sz, S, Mode)] 757 end. 758 759cdata_to_chars(Cs, F, CharsLimit) when CharsLimit < 0; CharsLimit >= F -> 760 cdata_to_chars(Cs); 761cdata_to_chars(Cs, _, CharsLimit) -> 762 limit_cdata_to_chars(Cs, sub(CharsLimit, 3), normal). % three dots 763 764cdata_to_chars([C|Cs]) when is_integer(C), C >= $\000 -> 765 [C | cdata_to_chars(Cs)]; 766cdata_to_chars([I|Cs]) -> 767 [cdata_to_chars(I) | cdata_to_chars(Cs)]; 768cdata_to_chars([]) -> 769 []; 770cdata_to_chars(B) when is_binary(B) -> 771 case catch unicode:characters_to_list(B) of 772 L when is_list(L) -> L; 773 _ -> binary_to_list(B) 774 end. 775 776limit_cdata_to_chars(Cs, 0, normal) -> 777 L = limit_cdata_to_chars(Cs, 4, final), 778 case string:length(L) of 779 N when N < 4 -> L; 780 4 -> "..." 781 end; 782limit_cdata_to_chars(_Cs, 0, final) -> []; 783limit_cdata_to_chars(Cs, Limit, Mode) -> 784 case string:next_grapheme(Cs) of 785 {error, <<C,Cs1/binary>>} -> 786 %% This is how ~ts handles Latin1 binaries with option 787 %% chars_limit. 788 [C | limit_cdata_to_chars(Cs1, Limit - 1, Mode)]; 789 {error, [C|Cs1]} -> % not all versions of module string return this 790 [C | limit_cdata_to_chars(Cs1, Limit - 1, Mode)]; 791 [] -> 792 []; 793 [GC|Cs1] -> 794 [GC | limit_cdata_to_chars(Cs1, Limit - 1, Mode)] 795 end. 796 797limit_field(F, CharsLimit) when CharsLimit < 0; F =:= none -> 798 F; 799limit_field(F, CharsLimit) -> 800 max(3, min(F, CharsLimit)). 801 802%% string(String, Field, Adjust, Precision, PadChar) 803 804string(S, none, _Adj, none, _Pad, _Enc) -> S; 805string(S, F, Adj, none, Pad, Enc) -> 806 string_field(S, F, Adj, io_lib:chars_length(S), Pad, Enc); 807string(S, none, _Adj, P, Pad, Enc) -> 808 string_field(S, P, left, io_lib:chars_length(S), Pad, Enc); 809string(S, F, Adj, P, Pad, Enc) when F >= P -> 810 N = io_lib:chars_length(S), 811 if F > P -> 812 if N > P -> 813 adjust(flat_trunc(S, P, Enc), chars(Pad, F-P), Adj); 814 N < P -> 815 adjust([S|chars(Pad, P-N)], chars(Pad, F-P), Adj); 816 true -> % N == P 817 adjust(S, chars(Pad, F-P), Adj) 818 end; 819 true -> % F == P 820 string_field(S, F, Adj, N, Pad, Enc) 821 end. 822 823string_field(S, F, _Adj, N, _Pad, Enc) when N > F -> 824 flat_trunc(S, F, Enc); 825string_field(S, F, Adj, N, Pad, _Enc) when N < F -> 826 adjust(S, chars(Pad, F-N), Adj); 827string_field(S, _, _, _, _, _) -> % N == F 828 S. 829 830%% unprefixed_integer(Int, Field, Adjust, Base, PadChar, Lowercase) 831%% -> [Char]. 832 833unprefixed_integer(Int, F, Adj, Base, Pad, Lowercase) 834 when Base >= 2, Base =< 1+$Z-$A+10 -> 835 if Int < 0 -> 836 S = cond_lowercase(erlang:integer_to_list(-Int, Base), Lowercase), 837 term([$-|S], F, Adj, none, Pad); 838 true -> 839 S = cond_lowercase(erlang:integer_to_list(Int, Base), Lowercase), 840 term(S, F, Adj, none, Pad) 841 end. 842 843%% prefixed_integer(Int, Field, Adjust, Base, PadChar, Prefix, Lowercase) 844%% -> [Char]. 845 846prefixed_integer(Int, F, Adj, Base, Pad, Prefix, Lowercase) 847 when Base >= 2, Base =< 1+$Z-$A+10 -> 848 if Int < 0 -> 849 S = cond_lowercase(erlang:integer_to_list(-Int, Base), Lowercase), 850 term([$-,Prefix|S], F, Adj, none, Pad); 851 true -> 852 S = cond_lowercase(erlang:integer_to_list(Int, Base), Lowercase), 853 term([Prefix|S], F, Adj, none, Pad) 854 end. 855 856%% char(Char, Field, Adjust, Precision, PadChar) -> chars(). 857 858char(C, none, _Adj, none, _Pad) -> [C]; 859char(C, F, _Adj, none, _Pad) -> chars(C, F); 860char(C, none, _Adj, P, _Pad) -> chars(C, P); 861char(C, F, Adj, P, Pad) when F >= P -> 862 adjust(chars(C, P), chars(Pad, F - P), Adj). 863 864%% newline(Field, Adjust, Precision, PadChar) -> [Char]. 865 866newline(none, _Adj, _P, _Pad) -> "\n"; 867newline(F, right, _P, _Pad) -> chars($\n, F). 868 869%% 870%% Utilities 871%% 872 873adjust(Data, [], _) -> Data; 874adjust(Data, Pad, left) -> [Data|Pad]; 875adjust(Data, Pad, right) -> [Pad|Data]. 876 877%% Flatten and truncate a deep list to at most N elements. 878 879flat_trunc(List, N, latin1) when is_integer(N), N >= 0 -> 880 {S, _} = lists:split(N, lists:flatten(List)), 881 S; 882flat_trunc(List, N, unicode) when is_integer(N), N >= 0 -> 883 string:slice(List, 0, N). 884 885%% A deep version of lists:duplicate/2 886 887chars(_C, 0) -> 888 []; 889chars(C, 1) -> 890 [C]; 891chars(C, 2) -> 892 [C,C]; 893chars(C, 3) -> 894 [C,C,C]; 895chars(C, N) when is_integer(N), (N band 1) =:= 0 -> 896 S = chars(C, N bsr 1), 897 [S|S]; 898chars(C, N) when is_integer(N) -> 899 S = chars(C, N bsr 1), 900 [C,S|S]. 901 902%chars(C, N, Tail) -> 903% [chars(C, N)|Tail]. 904 905%% Lowercase conversion 906 907cond_lowercase(String, true) -> 908 lowercase(String); 909cond_lowercase(String,false) -> 910 String. 911 912lowercase([H|T]) when is_integer(H), H >= $A, H =< $Z -> 913 [(H-$A+$a)|lowercase(T)]; 914lowercase([H|T]) -> 915 [H|lowercase(T)]; 916lowercase([]) -> 917 []. 918 919%% Make sure T does change sign. 920sub(T, _) when T < 0 -> T; 921sub(T, E) when T >= E -> T - E; 922sub(_, _) -> 0. 923 924get_option(Key, TupleList, Default) -> 925 case lists:keyfind(Key, 1, TupleList) of 926 false -> Default; 927 {Key, Value} -> Value; 928 _ -> Default 929 end. 930