From 9ec923c67f1fb1e9689f7a419321f50950c18659 Mon Sep 17 00:00:00 2001 From: SisMaker <1713699517@qq.com> Date: Thu, 11 Feb 2021 03:07:51 +0800 Subject: [PATCH] =?UTF-8?q?ft:=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- src/eFmt.app.src | 18 +- src/eFmt.erl | 1338 ++++++++++++++++++++++---------------------- src/eFmtFormat.erl | 1124 ++++++++++++++++++------------------- 4 files changed, 1231 insertions(+), 1252 deletions(-) diff --git a/README.md b/README.md index 71f2a19..3af0650 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ eFmt ===== -An OTP library to format term, for efficient -base on otp-23.2.4 +An OTP library to format term, for efficient base on otp-23.2.4 Build diff --git a/src/eFmt.app.src b/src/eFmt.app.src index f62ebd7..6e39676 100644 --- a/src/eFmt.app.src +++ b/src/eFmt.app.src @@ -1,10 +1,10 @@ {application, eFmt, - [{description, "An OTP library"}, - {vsn, "0.1.0"}, - {registered, []}, - {applications, [kernel, stdlib]}, - {env,[]}, - {modules, []}, - {licenses, ["MIT License"]}, - {links, []} - ]}. + [{description, "An OTP library"}, + {vsn, "0.1.0"}, + {registered, []}, + {applications, [kernel, stdlib]}, + {env, []}, + {modules, []}, + {licenses, ["MIT License"]}, + {links, []} + ]}. diff --git a/src/eFmt.erl b/src/eFmt.erl index 5b16b26..d04bb73 100644 --- a/src/eFmt.erl +++ b/src/eFmt.erl @@ -1,96 +1,85 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2019. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% This module is a library of useful i/o functions. It is hoped that the -%% functions defined in it are basic enough to be used without modification -%% as components of more complex utilities. -%% -%% It is completely self-contained and uses no other modules. Its own -%% utilities are exported. -%% -%% Most of the code here is derived from the original prolog versions and -%% from similar code written by Joe Armstrong and myself. -%% -%% This module has been split into separate modules: -%% io_lib - basic write and utilities -%% io_lib_format - formatted output -%% io_lib_fread - formatted input -%% io_lib_pretty - term prettyprinter - -%% For handling ISO 8859-1 (Latin-1) we use the following type -%% information: -%% -%% 000 - 037 NUL - US control -%% 040 - 057 SPC - / punctuation -%% 060 - 071 0 - 9 digit -%% 072 - 100 : - @ punctuation -%% 101 - 132 A - Z uppercase -%% 133 - 140 [ - ` punctuation -%% 141 - 172 a - z lowercase -%% 173 - 176 { - ~ punctuation -%% 177 DEL control -%% 200 - 237 control -%% 240 - 277 NBSP - ¿ punctuation -%% 300 - 326 À - Ö uppercase -%% 327 × punctuation -%% 330 - 336 Ø - Þ uppercase -%% 337 - 366 ß - ö lowercase -%% 367 ÷ punctuation -%% 370 - 377 ø - ÿ lowercase -%% -%% Many punctuation characters region have special meaning. Must -%% watch using × \327, very close to x \170 - -module(eFmt). --export([fwrite/2,fwrite/3,fread/2,fread/3,format/2,format/3]). --export([scan_format/2,unscan_format/1,build_text/1,build_text/2]). --export([print/1,print/4,indentation/2]). - --export([write/1,write/2,write/3,nl/0,format_prompt/1,format_prompt/2]). --export([write_binary/3]). --export([write_atom/1,write_string/1,write_string/2,write_latin1_string/1, - write_latin1_string/2, write_char/1, write_latin1_char/1]). +-export([ + fwrite/2 + , fwrite/3 + , fread/2 + , fread/3 + , format/2 + , format/3 + + , scan_format/2 + , unscan_format/1 + , build_text/1 + , build_text/2 + + + , print/1 + , print/4 + , indentation/2 + + , write/1 + , write/2 + , write/3 + , nl/0 + , format_prompt/1 + , format_prompt/2 + + + , write_binary/3 + + , write_atom/1 + , write_string/1 + , write_string/2 + , write_latin1_string/1 + , write_latin1_string/2 + , write_char/1 + , write_latin1_char/1 + + , write_atom_as_latin1/1 + , write_string_as_latin1/1 + , write_string_as_latin1/2 + , write_char_as_latin1/1 + + + , quote_atom/2 + , char_list/1 + , latin1_char_list/1 + , deep_char_list/1 + , deep_latin1_char_list/1 + , printable_list/1 + , printable_latin1_list/1 + , printable_unicode_list/1 --export([write_atom_as_latin1/1, write_string_as_latin1/1, - write_string_as_latin1/2, write_char_as_latin1/1]). +%% Utilities for collecting characters. --export([quote_atom/2, char_list/1, latin1_char_list/1, - deep_char_list/1, deep_latin1_char_list/1, - printable_list/1, printable_latin1_list/1, printable_unicode_list/1]). + , collect_chars/3 + , collect_chars/4 + , collect_line/3 + , collect_line/4 + , get_until/3, get_until/4 -%% Utilities for collecting characters. --export([collect_chars/3, collect_chars/4, - collect_line/3, collect_line/4, - get_until/3, get_until/4]). %% The following functions were used by Yecc's include-file. --export([write_unicode_string/1, write_unicode_char/1, - deep_unicode_char_list/1]). --export([limit_term/2]). + , write_unicode_string/1 + , write_unicode_char/1 + , deep_unicode_char_list/1 + + , limit_term/2 --export([chars_length/1]). + , chars_length/1 +]). --export_type([chars/0, latin1_string/0, continuation/0, - fread_error/0, fread_item/0, format_spec/0, chars_limit/0]). +-export_type([ + chars/0 + , latin1_string/0 + , continuation/0 + , fread_error/0 + , fread_item/0 + , format_spec/0 + , chars_limit/0 +]). %%---------------------------------------------------------------------- @@ -98,188 +87,191 @@ -type latin1_string() :: [unicode:latin1_char()]. -type depth() :: -1 | non_neg_integer(). --opaque continuation() :: {Format :: string(), - Stack :: chars(), - Nchars :: non_neg_integer(), - Results :: [term()]}. - --type fread_error() :: 'atom' - | 'based' - | 'character' - | 'float' - | 'format' - | 'input' - | 'integer' - | 'string' - | 'unsigned'. - --type fread_item() :: string() | atom() | integer() | float(). +-opaque continuation() :: +{Format :: string(), Stack :: chars(), Nchars :: non_neg_integer(), Results :: [term()]}. + +-type fread_error() :: +'atom' +| 'based' +| 'character' +| 'float' +| 'format' +| 'input' +| 'integer' +| 'string' +| 'unsigned'. + +-type fread_item() :: +string() | +atom() | +integer() | +float(). -type format_spec() :: - #{ - control_char := char(), - args := [any()], - width := 'none' | integer(), - adjust := 'left' | 'right', - precision := 'none' | integer(), - pad_char := char(), - encoding := 'unicode' | 'latin1', - strings := boolean() - }. +#{ +control_char := char(), +args := [any()], +width := 'none' | integer(), +adjust := 'left' | 'right', +precision := 'none' | integer(), +pad_char := char(), +encoding := 'unicode' | 'latin1', +strings := boolean() +}. %%---------------------------------------------------------------------- %% Interface calls to sub-modules. -spec fwrite(Format, Data) -> chars() when - Format :: io:format(), - Data :: [term()]. + Format :: io:format(), + Data :: [term()]. fwrite(Format, Args) -> - format(Format, Args). + format(Format, Args). -type chars_limit() :: integer(). -spec fwrite(Format, Data, Options) -> chars() when - Format :: io:format(), - Data :: [term()], - Options :: [Option], - Option :: {'chars_limit', CharsLimit}, - CharsLimit :: chars_limit(). + Format :: io:format(), + Data :: [term()], + Options :: [Option], + Option :: {'chars_limit', CharsLimit}, + CharsLimit :: chars_limit(). fwrite(Format, Args, Options) -> - format(Format, Args, Options). + format(Format, Args, Options). -spec fread(Format, String) -> Result when - Format :: string(), - String :: string(), - Result :: {'ok', InputList :: [fread_item()], LeftOverChars :: string()} - | {'more', RestFormat :: string(), - Nchars :: non_neg_integer(), - InputStack :: chars()} - | {'error', {'fread', What :: fread_error()}}. + Format :: string(), + String :: string(), + Result :: {'ok', InputList :: [fread_item()], LeftOverChars :: string()} + | {'more', RestFormat :: string(), + Nchars :: non_neg_integer(), + InputStack :: chars()} + | {'error', {'fread', What :: fread_error()}}. fread(Chars, Format) -> - io_lib_fread:fread(Chars, Format). + io_lib_fread:fread(Chars, Format). -spec fread(Continuation, CharSpec, Format) -> Return when - Continuation :: continuation() | [], - CharSpec :: string() | 'eof', - Format :: string(), - Return :: {'more', Continuation1 :: continuation()} - | {'done', Result, LeftOverChars :: string()}, - Result :: {'ok', InputList :: [fread_item()]} - | 'eof' - | {'error', {'fread', What :: fread_error()}}. + Continuation :: continuation() | [], + CharSpec :: string() | 'eof', + Format :: string(), + Return :: {'more', Continuation1 :: continuation()} + | {'done', Result, LeftOverChars :: string()}, + Result :: {'ok', InputList :: [fread_item()]} + | 'eof' + | {'error', {'fread', What :: fread_error()}}. fread(Cont, Chars, Format) -> - io_lib_fread:fread(Cont, Chars, Format). + io_lib_fread:fread(Cont, Chars, Format). -spec format(Format, Data) -> chars() when - Format :: io:format(), - Data :: [term()]. + Format :: io:format(), + Data :: [term()]. format(Format, Args) -> - try io_lib_format:fwrite(Format, Args) - catch - C:R:S -> - test_modules_loaded(C, R, S), - erlang:error(badarg, [Format, Args]) - end. + try io_lib_format:fwrite(Format, Args) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [Format, Args]) + end. -spec format(Format, Data, Options) -> chars() when - Format :: io:format(), - Data :: [term()], - Options :: [Option], - Option :: {'chars_limit', CharsLimit}, - CharsLimit :: chars_limit(). + Format :: io:format(), + Data :: [term()], + Options :: [Option], + Option :: {'chars_limit', CharsLimit}, + CharsLimit :: chars_limit(). format(Format, Args, Options) -> - try io_lib_format:fwrite(Format, Args, Options) - catch - C:R:S -> - test_modules_loaded(C, R, S), - erlang:error(badarg, [Format, Args]) - end. + try io_lib_format:fwrite(Format, Args, Options) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [Format, Args]) + end. -spec scan_format(Format, Data) -> FormatList when - Format :: io:format(), - Data :: [term()], - FormatList :: [char() | format_spec()]. + Format :: io:format(), + Data :: [term()], + FormatList :: [char() | format_spec()]. scan_format(Format, Args) -> - try io_lib_format:scan(Format, Args) - catch - C:R:S -> - test_modules_loaded(C, R, S), - erlang:error(badarg, [Format, Args]) - end. + try io_lib_format:scan(Format, Args) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [Format, Args]) + end. -spec unscan_format(FormatList) -> {Format, Data} when - FormatList :: [char() | format_spec()], - Format :: io:format(), - Data :: [term()]. + FormatList :: [char() | format_spec()], + Format :: io:format(), + Data :: [term()]. unscan_format(FormatList) -> - io_lib_format:unscan(FormatList). + io_lib_format:unscan(FormatList). -spec build_text(FormatList) -> chars() when - FormatList :: [char() | format_spec()]. + FormatList :: [char() | format_spec()]. build_text(FormatList) -> - try io_lib_format:build(FormatList) - catch - C:R:S -> - test_modules_loaded(C, R, S), - erlang:error(badarg, [FormatList]) - end. + try io_lib_format:build(FormatList) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [FormatList]) + end. -spec build_text(FormatList, Options) -> chars() when - FormatList :: [char() | format_spec()], - Options :: [Option], - Option :: {'chars_limit', CharsLimit}, - CharsLimit :: chars_limit(). + FormatList :: [char() | format_spec()], + Options :: [Option], + Option :: {'chars_limit', CharsLimit}, + CharsLimit :: chars_limit(). build_text(FormatList, Options) -> - try io_lib_format:build(FormatList, Options) - catch - C:R:S -> - test_modules_loaded(C, R, S), - erlang:error(badarg, [FormatList, Options]) - end. + try io_lib_format:build(FormatList, Options) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [FormatList, Options]) + end. %% Failure to load a module must not be labeled as badarg. %% C, R, and S are included so that the original error, which could be %% a bug in io_lib_format, can be found by tracing on %% test_modules_loaded/3. test_modules_loaded(_C, _R, _S) -> - Modules = [io_lib_format, io_lib_pretty, string, unicode], - case code:ensure_modules_loaded(Modules) of - ok -> ok; - Error -> erlang:error(Error) - end. + Modules = [io_lib_format, io_lib_pretty, string, unicode], + case code:ensure_modules_loaded(Modules) of + ok -> ok; + Error -> erlang:error(Error) + end. -spec print(Term) -> chars() when - Term :: term(). + Term :: term(). print(Term) -> - io_lib_pretty:print(Term). + io_lib_pretty:print(Term). -spec print(Term, Column, LineLength, Depth) -> chars() when - Term :: term(), - Column :: non_neg_integer(), - LineLength :: non_neg_integer(), - Depth :: depth(). + Term :: term(), + Column :: non_neg_integer(), + LineLength :: non_neg_integer(), + Depth :: depth(). print(Term, Column, LineLength, Depth) -> - io_lib_pretty:print(Term, Column, LineLength, Depth). + io_lib_pretty:print(Term, Column, LineLength, Depth). -spec indentation(String, StartIndent) -> integer() when - String :: string(), - StartIndent :: integer(). + String :: string(), + StartIndent :: integer(). indentation(Chars, Current) -> - io_lib_format:indentation(Chars, Current). + io_lib_format:indentation(Chars, Current). %% Format an IO-request prompt (handles formatting errors safely). @@ -289,28 +281,28 @@ indentation(Chars, Current) -> -spec format_prompt(term()) -> chars(). format_prompt(Prompt) -> - format_prompt(Prompt, latin1). + format_prompt(Prompt, latin1). -spec format_prompt(term(), atom()) -> chars(). -format_prompt({format,Format,Args}, _Encoding) -> - do_format_prompt(Format, Args); +format_prompt({format, Format, Args}, _Encoding) -> + do_format_prompt(Format, Args); format_prompt(Prompt, Encoding) - when is_list(Prompt); is_atom(Prompt); is_binary(Prompt) -> - do_format_prompt(add_modifier(Encoding, "s"), [Prompt]); + when is_list(Prompt); is_atom(Prompt); is_binary(Prompt) -> + do_format_prompt(add_modifier(Encoding, "s"), [Prompt]); format_prompt(Prompt, Encoding) -> - do_format_prompt(add_modifier(Encoding, "p"), [Prompt]). + do_format_prompt(add_modifier(Encoding, "p"), [Prompt]). do_format_prompt(Format, Args) -> - case catch format(Format, Args) of - {'EXIT',_} -> "???"; - List -> List - end. + case catch format(Format, Args) of + {'EXIT', _} -> "???"; + List -> List + end. add_modifier(latin1, C) -> - "~"++C; + "~" ++ C; add_modifier(_, C) -> - "~t"++C. + "~t" ++ C. %% write(Term) %% write(Term, Depth) @@ -319,47 +311,47 @@ add_modifier(_, C) -> %% representation of the term. write/3 is for backward compatibility. -spec write(Term) -> chars() when - Term :: term(). + Term :: term(). write(Term) -> - write1(Term, -1, latin1). + write1(Term, -1, latin1). -spec write(term(), depth(), boolean()) -> chars(). write(Term, D, true) -> - io_lib_pretty:print(Term, 1, 80, D); + io_lib_pretty:print(Term, 1, 80, D); write(Term, D, false) -> - write(Term, D). + write(Term, D). -spec write(Term, Depth) -> chars() when - Term :: term(), - Depth :: depth(); - (Term, Options) -> chars() when - Term :: term(), - Options :: [Option], - Option :: {'chars_limit', CharsLimit} - | {'depth', Depth} - | {'encoding', 'latin1' | 'utf8' | 'unicode'}, - CharsLimit :: chars_limit(), - Depth :: depth(). + Term :: term(), + Depth :: depth(); + (Term, Options) -> chars() when + Term :: term(), + Options :: [Option], + Option :: {'chars_limit', CharsLimit} + | {'depth', Depth} + | {'encoding', 'latin1' | 'utf8' | 'unicode'}, + CharsLimit :: chars_limit(), + Depth :: depth(). write(Term, Options) when is_list(Options) -> - Depth = get_option(depth, Options, -1), - Encoding = get_option(encoding, Options, epp:default_encoding()), - CharsLimit = get_option(chars_limit, Options, -1), - if - Depth =:= 0; CharsLimit =:= 0 -> - "..."; - CharsLimit < 0 -> - write1(Term, Depth, Encoding); - CharsLimit > 0 -> - RecDefFun = fun(_, _) -> no end, - If = io_lib_pretty:intermediate - (Term, Depth, CharsLimit, RecDefFun, Encoding, _Str=false), - io_lib_pretty:write(If) - end; + Depth = get_option(depth, Options, -1), + Encoding = get_option(encoding, Options, epp:default_encoding()), + CharsLimit = get_option(chars_limit, Options, -1), + if + Depth =:= 0; CharsLimit =:= 0 -> + "..."; + CharsLimit < 0 -> + write1(Term, Depth, Encoding); + CharsLimit > 0 -> + RecDefFun = fun(_, _) -> no end, + If = io_lib_pretty:intermediate + (Term, Depth, CharsLimit, RecDefFun, Encoding, _Str = false), + io_lib_pretty:write(If) + end; write(Term, Depth) -> - write(Term, [{depth, Depth}, {encoding, latin1}]). + write(Term, [{depth, Depth}, {encoding, latin1}]). write1(_Term, 0, _E) -> "..."; write1(Term, _D, _E) when is_integer(Term) -> integer_to_list(Term); @@ -369,93 +361,93 @@ write1(Atom, _D, _E) when is_atom(Atom) -> write_atom(Atom); write1(Term, _D, _E) when is_port(Term) -> write_port(Term); write1(Term, _D, _E) when is_pid(Term) -> pid_to_list(Term); write1(Term, _D, _E) when is_reference(Term) -> write_ref(Term); -write1(<<_/bitstring>>=Term, D, _E) -> write_binary(Term, D); +write1(<<_/bitstring>> = Term, D, _E) -> write_binary(Term, D); write1([], _D, _E) -> "[]"; write1({}, _D, _E) -> "{}"; -write1([H|T], D, E) -> - if - D =:= 1 -> "[...]"; - true -> - [$[,[write1(H, D-1, E)|write_tail(T, D-1, E)],$]] - end; +write1([H | T], D, E) -> + if + D =:= 1 -> "[...]"; + true -> + [$[, [write1(H, D - 1, E) | write_tail(T, D - 1, E)], $]] + end; write1(F, _D, _E) when is_function(F) -> - erlang:fun_to_list(F); + erlang:fun_to_list(F); write1(Term, D, E) when is_map(Term) -> - write_map(Term, D, E); + write_map(Term, D, E); write1(T, D, E) when is_tuple(T) -> - if - D =:= 1 -> "{...}"; - true -> - [${, - [write1(element(1, T), D-1, E)|write_tuple(T, 2, D-1, E)], - $}] - end. + if + D =:= 1 -> "{...}"; + true -> + [${, + [write1(element(1, T), D - 1, E) | write_tuple(T, 2, D - 1, E)], + $}] + end. %% write_tail(List, Depth, Encoding) %% Test the terminating case first as this looks better with depth. write_tail([], _D, _E) -> ""; write_tail(_, 1, _E) -> [$| | "..."]; -write_tail([H|T], D, E) -> - [$,,write1(H, D-1, E)|write_tail(T, D-1, E)]; +write_tail([H | T], D, E) -> + [$,, write1(H, D - 1, E) | write_tail(T, D - 1, E)]; write_tail(Other, D, E) -> - [$|,write1(Other, D-1, E)]. + [$|, write1(Other, D - 1, E)]. write_tuple(T, I, _D, _E) when I > tuple_size(T) -> ""; write_tuple(_, _I, 1, _E) -> [$, | "..."]; write_tuple(T, I, D, E) -> - [$,,write1(element(I, T), D-1, E)|write_tuple(T, I+1, D-1, E)]. + [$,, write1(element(I, T), D - 1, E) | write_tuple(T, I + 1, D - 1, E)]. write_port(Port) -> - erlang:port_to_list(Port). + erlang:port_to_list(Port). write_ref(Ref) -> - erlang:ref_to_list(Ref). + erlang:ref_to_list(Ref). write_map(_, 1, _E) -> "#{}"; write_map(Map, D, E) when is_integer(D) -> - I = maps:iterator(Map), - case maps:next(I) of - {K, V, NextI} -> - D0 = D - 1, - W = write_map_assoc(K, V, D0, E), - [$#,${,[W | write_map_body(NextI, D0, D0, E)],$}]; - none -> "#{}" - end. + I = maps:iterator(Map), + case maps:next(I) of + {K, V, NextI} -> + D0 = D - 1, + W = write_map_assoc(K, V, D0, E), + [$#, ${, [W | write_map_body(NextI, D0, D0, E)], $}]; + none -> "#{}" + end. write_map_body(_, 1, _D0, _E) -> ",..."; write_map_body(I, D, D0, E) -> - case maps:next(I) of - {K, V, NextI} -> - W = write_map_assoc(K, V, D0, E), - [$,,W|write_map_body(NextI, D - 1, D0, E)]; - none -> "" - end. + case maps:next(I) of + {K, V, NextI} -> + W = write_map_assoc(K, V, D0, E), + [$,, W | write_map_body(NextI, D - 1, D0, E)]; + none -> "" + end. write_map_assoc(K, V, D, E) -> - [write1(K, D, E)," => ",write1(V, D, E)]. + [write1(K, D, E), " => ", write1(V, D, E)]. write_binary(B, D) when is_integer(D) -> - {S, _} = write_binary(B, D, -1), - S. + {S, _} = write_binary(B, D, -1), + S. write_binary(B, D, T) -> - {S, Rest} = write_binary_body(B, D, tsub(T, 4), []), - {[$<,$<,lists:reverse(S),$>,$>], Rest}. + {S, Rest} = write_binary_body(B, D, tsub(T, 4), []), + {[$<, $<, lists:reverse(S), $>, $>], Rest}. write_binary_body(<<>> = B, _D, _T, Acc) -> - {Acc, B}; -write_binary_body(B, D, T, Acc) when D =:= 1; T =:= 0-> - {["..."|Acc], B}; + {Acc, B}; +write_binary_body(B, D, T, Acc) when D =:= 1; T =:= 0 -> + {["..." | Acc], B}; write_binary_body(<>, _D, _T, Acc) -> - {[integer_to_list(X)|Acc], <<>>}; -write_binary_body(<>, D, T, Acc) -> - S = integer_to_list(X), - write_binary_body(Rest, D-1, tsub(T, length(S) + 1), [$,,S|Acc]); + {[integer_to_list(X) | Acc], <<>>}; +write_binary_body(<>, D, T, Acc) -> + S = integer_to_list(X), + write_binary_body(Rest, D - 1, tsub(T, length(S) + 1), [$,, S | Acc]); write_binary_body(B, _D, _T, Acc) -> - L = bit_size(B), - <> = B, - {[integer_to_list(L),$:,integer_to_list(X)|Acc], <<>>}. + L = bit_size(B), + <> = B, + {[integer_to_list(L), $:, integer_to_list(X) | Acc], <<>>}. %% Make sure T does not change sign. tsub(T, _) when T < 0 -> T; @@ -463,11 +455,11 @@ tsub(T, E) when T >= E -> T - E; tsub(_, _) -> 0. get_option(Key, TupleList, Default) -> - case lists:keyfind(Key, 1, TupleList) of - false -> Default; - {Key, Value} -> Value; - _ -> Default - end. + case lists:keyfind(Key, 1, TupleList) of + false -> Default; + {Key, Value} -> Value; + _ -> Default + end. %%% There are two functions to write Unicode atoms: %%% - they both escape control characters < 160; @@ -478,25 +470,25 @@ get_option(Key, TupleList, Default) -> %% Generate the list of characters needed to print an atom. -spec write_atom(Atom) -> chars() when - Atom :: atom(). + Atom :: atom(). write_atom(Atom) -> - write_possibly_quoted_atom(Atom, fun write_string/2). + write_possibly_quoted_atom(Atom, fun write_string/2). -spec write_atom_as_latin1(Atom) -> latin1_string() when - Atom :: atom(). + Atom :: atom(). write_atom_as_latin1(Atom) -> - write_possibly_quoted_atom(Atom, fun write_string_as_latin1/2). + write_possibly_quoted_atom(Atom, fun write_string_as_latin1/2). write_possibly_quoted_atom(Atom, PFun) -> - Chars = atom_to_list(Atom), - case quote_atom(Atom, Chars) of - true -> - PFun(Chars, $'); %' - false -> - Chars - end. + Chars = atom_to_list(Atom), + case quote_atom(Atom, Chars) of + true -> + PFun(Chars, $'); %' + false -> + Chars + end. %% quote_atom(Atom, CharList) %% Return 'true' if atom with chars in CharList needs to be quoted, else @@ -505,23 +497,23 @@ write_possibly_quoted_atom(Atom, PFun) -> -spec quote_atom(atom(), chars()) -> boolean(). quote_atom(Atom, Cs0) -> - case erl_scan:reserved_word(Atom) of - true -> true; - false -> - case Cs0 of - [C|Cs] when C >= $a, C =< $z -> - not name_chars(Cs); - [C|Cs] when C >= $ß, C =< $ÿ, C =/= $÷ -> - not name_chars(Cs); - _ -> true - end - end. - -name_chars([C|Cs]) -> - case name_char(C) of - true -> name_chars(Cs); - false -> false - end; + case erl_scan:reserved_word(Atom) of + true -> true; + false -> + case Cs0 of + [C | Cs] when C >= $a, C =< $z -> + not name_chars(Cs); + [C | Cs] when C >= $ß, C =< $ÿ, C =/= $÷ -> + not name_chars(Cs); + _ -> true + end + end. + +name_chars([C | Cs]) -> + case name_char(C) of + true -> name_chars(Cs); + false -> false + end; name_chars([]) -> true. name_char(C) when C >= $a, C =< $z -> true; @@ -542,72 +534,72 @@ name_char(_) -> false. %% Generate the list of characters needed to print a string. -spec write_string(String) -> chars() when - String :: string(). + String :: string(). write_string(S) -> - write_string(S, $"). %" + write_string(S, $"). %" -spec write_string(string(), char()) -> chars(). write_string(S, Q) -> - [Q|write_string1(unicode_as_unicode, S, Q)]. + [Q | write_string1(unicode_as_unicode, S, Q)]. %% Backwards compatibility. write_unicode_string(S) -> - write_string(S). + write_string(S). -spec write_latin1_string(Latin1String) -> latin1_string() when - Latin1String :: latin1_string(). + Latin1String :: latin1_string(). write_latin1_string(S) -> - write_latin1_string(S, $"). %" + write_latin1_string(S, $"). %" -spec write_latin1_string(latin1_string(), char()) -> latin1_string(). write_latin1_string(S, Q) -> - [Q|write_string1(latin1, S, Q)]. + [Q | write_string1(latin1, S, Q)]. -spec write_string_as_latin1(String) -> latin1_string() when - String :: string(). + String :: string(). write_string_as_latin1(S) -> - write_string_as_latin1(S, $"). %" + write_string_as_latin1(S, $"). %" -spec write_string_as_latin1(string(), char()) -> latin1_string(). write_string_as_latin1(S, Q) -> - [Q|write_string1(unicode_as_latin1, S, Q)]. - -write_string1(_,[], Q) -> - [Q]; -write_string1(Enc,[C|Cs], Q) -> - string_char(Enc,C, Q, write_string1(Enc,Cs, Q)). - -string_char(_,Q, Q, Tail) -> [$\\,Q|Tail]; %Must check these first! -string_char(_,$\\, _, Tail) -> [$\\,$\\|Tail]; -string_char(_,C, _, Tail) when C >= $\s, C =< $~ -> - [C|Tail]; -string_char(latin1,C, _, Tail) when C >= $\240, C =< $\377 -> - [C|Tail]; -string_char(unicode_as_unicode,C, _, Tail) when C >= $\240 -> - [C|Tail]; -string_char(unicode_as_latin1,C, _, Tail) when C >= $\240, C =< $\377 -> - [C|Tail]; -string_char(unicode_as_latin1,C, _, Tail) when C >= $\377 -> - "\\x{"++erlang:integer_to_list(C, 16)++"}"++Tail; -string_char(_,$\n, _, Tail) -> [$\\,$n|Tail]; %\n = LF -string_char(_,$\r, _, Tail) -> [$\\,$r|Tail]; %\r = CR -string_char(_,$\t, _, Tail) -> [$\\,$t|Tail]; %\t = TAB -string_char(_,$\v, _, Tail) -> [$\\,$v|Tail]; %\v = VT -string_char(_,$\b, _, Tail) -> [$\\,$b|Tail]; %\b = BS -string_char(_,$\f, _, Tail) -> [$\\,$f|Tail]; %\f = FF -string_char(_,$\e, _, Tail) -> [$\\,$e|Tail]; %\e = ESC -string_char(_,$\d, _, Tail) -> [$\\,$d|Tail]; %\d = DEL -string_char(_,C, _, Tail) when C < $\240-> %Other control characters. - C1 = (C bsr 6) + $0, - C2 = ((C bsr 3) band 7) + $0, - C3 = (C band 7) + $0, - [$\\,C1,C2,C3|Tail]. + [Q | write_string1(unicode_as_latin1, S, Q)]. + +write_string1(_, [], Q) -> + [Q]; +write_string1(Enc, [C | Cs], Q) -> + string_char(Enc, C, Q, write_string1(Enc, Cs, Q)). + +string_char(_, Q, Q, Tail) -> [$\\, Q | Tail]; %Must check these first! +string_char(_, $\\, _, Tail) -> [$\\, $\\ | Tail]; +string_char(_, C, _, Tail) when C >= $\s, C =< $~ -> + [C | Tail]; +string_char(latin1, C, _, Tail) when C >= $\240, C =< $\377 -> + [C | Tail]; +string_char(unicode_as_unicode, C, _, Tail) when C >= $\240 -> + [C | Tail]; +string_char(unicode_as_latin1, C, _, Tail) when C >= $\240, C =< $\377 -> + [C | Tail]; +string_char(unicode_as_latin1, C, _, Tail) when C >= $\377 -> + "\\x{" ++ erlang:integer_to_list(C, 16) ++ "}" ++ Tail; +string_char(_, $\n, _, Tail) -> [$\\, $n | Tail]; %\n = LF +string_char(_, $\r, _, Tail) -> [$\\, $r | Tail]; %\r = CR +string_char(_, $\t, _, Tail) -> [$\\, $t | Tail]; %\t = TAB +string_char(_, $\v, _, Tail) -> [$\\, $v | Tail]; %\v = VT +string_char(_, $\b, _, Tail) -> [$\\, $b | Tail]; %\b = BS +string_char(_, $\f, _, Tail) -> [$\\, $f | Tail]; %\f = FF +string_char(_, $\e, _, Tail) -> [$\\, $e | Tail]; %\e = ESC +string_char(_, $\d, _, Tail) -> [$\\, $d | Tail]; %\d = DEL +string_char(_, C, _, Tail) when C < $\240 -> %Other control characters. + C1 = (C bsr 6) + $0, + C2 = ((C bsr 3) band 7) + $0, + C3 = (C band 7) + $0, + [$\\, C1, C2, C3 | Tail]. %%% There are two functions to write a Unicode character: %%% - they both escape control characters < 160; @@ -619,27 +611,27 @@ string_char(_,C, _, Tail) when C < $\240-> %Other control characters. %% Must special case SPACE, $\s, here. -spec write_char(Char) -> chars() when - Char :: char(). + Char :: char(). -write_char($\s) -> "$\\s"; %Must special case this. +write_char($\s) -> "$\\s"; %Must special case this. write_char(C) when is_integer(C), C >= $\000 -> - [$$|string_char(unicode_as_unicode, C, -1, [])]. + [$$ | string_char(unicode_as_unicode, C, -1, [])]. %% Backwards compatibility. write_unicode_char(C) -> - write_char(C). + write_char(C). -spec write_latin1_char(Latin1Char) -> latin1_string() when - Latin1Char :: unicode:latin1_char(). + Latin1Char :: unicode:latin1_char(). -write_latin1_char(Lat1) when is_integer(Lat1), Lat1 >= $\000, Lat1 =< $\377 -> - [$$|string_char(latin1, Lat1, -1, [])]. +write_latin1_char(Lat1) when is_integer(Lat1), Lat1 >= $\000, Lat1 =< $\377 -> + [$$ | string_char(latin1, Lat1, -1, [])]. -spec write_char_as_latin1(Char) -> latin1_string() when - Char :: char(). + Char :: char(). write_char_as_latin1(Uni) when is_integer(Uni), Uni >= $\000 -> - [$$|string_char(unicode_as_latin1,Uni, -1, [])]. + [$$ | string_char(unicode_as_latin1, Uni, -1, [])]. %% latin1_char_list(CharList) %% deep_latin1_char_list(CharList) @@ -647,81 +639,81 @@ write_char_as_latin1(Uni) when is_integer(Uni), Uni >= $\000 -> %% characters, else false. -spec latin1_char_list(Term) -> boolean() when - Term :: term(). + Term :: term(). -latin1_char_list([C|Cs]) when is_integer(C), C >= $\000, C =< $\377 -> - latin1_char_list(Cs); +latin1_char_list([C | Cs]) when is_integer(C), C >= $\000, C =< $\377 -> + latin1_char_list(Cs); latin1_char_list([]) -> true; -latin1_char_list(_) -> false. %Everything else is false +latin1_char_list(_) -> false. %Everything else is false -spec char_list(Term) -> boolean() when - Term :: term(). + Term :: term(). -char_list([C|Cs]) when is_integer(C), C >= 0, C < 16#D800; - is_integer(C), C > 16#DFFF, C < 16#FFFE; - is_integer(C), C > 16#FFFF, C =< 16#10FFFF -> - char_list(Cs); +char_list([C | Cs]) when is_integer(C), C >= 0, C < 16#D800; + is_integer(C), C > 16#DFFF, C < 16#FFFE; + is_integer(C), C > 16#FFFF, C =< 16#10FFFF -> + char_list(Cs); char_list([]) -> true; -char_list(_) -> false. %Everything else is false +char_list(_) -> false. %Everything else is false -spec deep_latin1_char_list(Term) -> boolean() when - Term :: term(). + Term :: term(). deep_latin1_char_list(Cs) -> - deep_latin1_char_list(Cs, []). - -deep_latin1_char_list([C|Cs], More) when is_list(C) -> - deep_latin1_char_list(C, [Cs|More]); -deep_latin1_char_list([C|Cs], More) when is_integer(C), C >= $\000, C =< $\377 -> - deep_latin1_char_list(Cs, More); -deep_latin1_char_list([], [Cs|More]) -> - deep_latin1_char_list(Cs, More); + deep_latin1_char_list(Cs, []). + +deep_latin1_char_list([C | Cs], More) when is_list(C) -> + deep_latin1_char_list(C, [Cs | More]); +deep_latin1_char_list([C | Cs], More) when is_integer(C), C >= $\000, C =< $\377 -> + deep_latin1_char_list(Cs, More); +deep_latin1_char_list([], [Cs | More]) -> + deep_latin1_char_list(Cs, More); deep_latin1_char_list([], []) -> true; -deep_latin1_char_list(_, _More) -> %Everything else is false - false. +deep_latin1_char_list(_, _More) -> %Everything else is false + false. -spec deep_char_list(Term) -> boolean() when - Term :: term(). + Term :: term(). 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 < 16#D800; - is_integer(C), C > 16#DFFF, C < 16#FFFE; - is_integer(C), C > 16#FFFF, C =< 16#10FFFF -> - deep_char_list(Cs, More); -deep_char_list([], [Cs|More]) -> - deep_char_list(Cs, More); + 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 < 16#D800; + is_integer(C), C > 16#DFFF, C < 16#FFFE; + is_integer(C), C > 16#FFFF, C =< 16#10FFFF -> + deep_char_list(Cs, More); +deep_char_list([], [Cs | More]) -> + deep_char_list(Cs, More); deep_char_list([], []) -> true; -deep_char_list(_, _More) -> %Everything else is false - false. +deep_char_list(_, _More) -> %Everything else is false + false. deep_unicode_char_list(Term) -> - deep_char_list(Term). + deep_char_list(Term). %% printable_latin1_list([Char]) -> boolean() %% Return true if CharList is a list of printable Latin1 characters, else %% false. -spec printable_latin1_list(Term) -> boolean() when - Term :: term(). - -printable_latin1_list([C|Cs]) when is_integer(C), C >= $\040, C =< $\176 -> - printable_latin1_list(Cs); -printable_latin1_list([C|Cs]) when is_integer(C), C >= $\240, C =< $\377 -> - printable_latin1_list(Cs); -printable_latin1_list([$\n|Cs]) -> printable_latin1_list(Cs); -printable_latin1_list([$\r|Cs]) -> printable_latin1_list(Cs); -printable_latin1_list([$\t|Cs]) -> printable_latin1_list(Cs); -printable_latin1_list([$\v|Cs]) -> printable_latin1_list(Cs); -printable_latin1_list([$\b|Cs]) -> printable_latin1_list(Cs); -printable_latin1_list([$\f|Cs]) -> printable_latin1_list(Cs); -printable_latin1_list([$\e|Cs]) -> printable_latin1_list(Cs); + Term :: term(). + +printable_latin1_list([C | Cs]) when is_integer(C), C >= $\040, C =< $\176 -> + printable_latin1_list(Cs); +printable_latin1_list([C | Cs]) when is_integer(C), C >= $\240, C =< $\377 -> + printable_latin1_list(Cs); +printable_latin1_list([$\n | Cs]) -> printable_latin1_list(Cs); +printable_latin1_list([$\r | Cs]) -> printable_latin1_list(Cs); +printable_latin1_list([$\t | Cs]) -> printable_latin1_list(Cs); +printable_latin1_list([$\v | Cs]) -> printable_latin1_list(Cs); +printable_latin1_list([$\b | Cs]) -> printable_latin1_list(Cs); +printable_latin1_list([$\f | Cs]) -> printable_latin1_list(Cs); +printable_latin1_list([$\e | Cs]) -> printable_latin1_list(Cs); printable_latin1_list([]) -> true; -printable_latin1_list(_) -> false. %Everything else is false +printable_latin1_list(_) -> false. %Everything else is false %% printable_list([Char]) -> boolean() %% Return true if CharList is a list of printable characters, else @@ -735,37 +727,37 @@ printable_latin1_list(_) -> false. %Everything else is false %% character set are deemed printable. latin1 is default. -spec printable_list(Term) -> boolean() when - Term :: term(). + Term :: term(). printable_list(L) -> - %% There will be more alternatives returns from io:printable range - %% in the future. To not have a catch-all clause is deliberate. - case io:printable_range() of - latin1 -> - printable_latin1_list(L); - unicode -> - printable_unicode_list(L) - end. + %% There will be more alternatives returns from io:printable range + %% in the future. To not have a catch-all clause is deliberate. + case io:printable_range() of + latin1 -> + printable_latin1_list(L); + unicode -> + printable_unicode_list(L) + end. -spec printable_unicode_list(Term) -> boolean() when - Term :: term(). - -printable_unicode_list([C|Cs]) when is_integer(C), C >= $\040, C =< $\176 -> - printable_unicode_list(Cs); -printable_unicode_list([C|Cs]) - when is_integer(C), C >= 16#A0, C < 16#D800; - is_integer(C), C > 16#DFFF, C < 16#FFFE; - is_integer(C), C > 16#FFFF, C =< 16#10FFFF -> - printable_unicode_list(Cs); -printable_unicode_list([$\n|Cs]) -> printable_unicode_list(Cs); -printable_unicode_list([$\r|Cs]) -> printable_unicode_list(Cs); -printable_unicode_list([$\t|Cs]) -> printable_unicode_list(Cs); -printable_unicode_list([$\v|Cs]) -> printable_unicode_list(Cs); -printable_unicode_list([$\b|Cs]) -> printable_unicode_list(Cs); -printable_unicode_list([$\f|Cs]) -> printable_unicode_list(Cs); -printable_unicode_list([$\e|Cs]) -> printable_unicode_list(Cs); + Term :: term(). + +printable_unicode_list([C | Cs]) when is_integer(C), C >= $\040, C =< $\176 -> + printable_unicode_list(Cs); +printable_unicode_list([C | Cs]) + when is_integer(C), C >= 16#A0, C < 16#D800; + is_integer(C), C > 16#DFFF, C < 16#FFFE; + is_integer(C), C > 16#FFFF, C =< 16#10FFFF -> + printable_unicode_list(Cs); +printable_unicode_list([$\n | Cs]) -> printable_unicode_list(Cs); +printable_unicode_list([$\r | Cs]) -> printable_unicode_list(Cs); +printable_unicode_list([$\t | Cs]) -> printable_unicode_list(Cs); +printable_unicode_list([$\v | Cs]) -> printable_unicode_list(Cs); +printable_unicode_list([$\b | Cs]) -> printable_unicode_list(Cs); +printable_unicode_list([$\f | Cs]) -> printable_unicode_list(Cs); +printable_unicode_list([$\e | Cs]) -> printable_unicode_list(Cs); printable_unicode_list([]) -> true; -printable_unicode_list(_) -> false. %Everything else is false +printable_unicode_list(_) -> false. %Everything else is false %% List = nl() %% Return a list of characters to generate a newline. @@ -773,26 +765,26 @@ printable_unicode_list(_) -> false. %Everything else is false -spec nl() -> string(). nl() -> - "\n". + "\n". %% %% Utilities for collecting characters in input files %% -count_and_find_utf8(Bin,N) -> - cafu(Bin,N,0,0,none). - -cafu(<<>>,_N,Count,_ByteCount,SavePos) -> - {Count,SavePos}; -cafu(<<_/utf8,Rest/binary>>, 0, Count, ByteCount, _SavePos) -> - cafu(Rest,-1,Count+1,0,ByteCount); -cafu(<<_/utf8,Rest/binary>>, N, Count, _ByteCount, SavePos) when N < 0 -> - cafu(Rest,-1,Count+1,0,SavePos); -cafu(<<_/utf8,Rest/binary>> = Whole, N, Count, ByteCount, SavePos) -> - Delta = byte_size(Whole) - byte_size(Rest), - cafu(Rest,N-1,Count+1,ByteCount+Delta,SavePos); -cafu(_Other,_N,Count,_ByteCount,SavePos) -> % Non Utf8 character at end - {Count,SavePos}. +count_and_find_utf8(Bin, N) -> + cafu(Bin, N, 0, 0, none). + +cafu(<<>>, _N, Count, _ByteCount, SavePos) -> + {Count, SavePos}; +cafu(<<_/utf8, Rest/binary>>, 0, Count, ByteCount, _SavePos) -> + cafu(Rest, -1, Count + 1, 0, ByteCount); +cafu(<<_/utf8, Rest/binary>>, N, Count, _ByteCount, SavePos) when N < 0 -> + cafu(Rest, -1, Count + 1, 0, SavePos); +cafu(<<_/utf8, Rest/binary>> = Whole, N, Count, ByteCount, SavePos) -> + Delta = byte_size(Whole) - byte_size(Rest), + cafu(Rest, N - 1, Count + 1, ByteCount + Delta, SavePos); +cafu(_Other, _N, Count, _ByteCount, SavePos) -> % Non Utf8 character at end + {Count, SavePos}. %% collect_chars(State, Data, Count). New in R9C. %% Returns: @@ -800,57 +792,57 @@ cafu(_Other,_N,Count,_ByteCount,SavePos) -> % Non Utf8 character at end %% NewState %%% BC (with pre-R13). collect_chars(Tag, Data, N) -> - collect_chars(Tag, Data, latin1, N). + collect_chars(Tag, Data, latin1, N). %% Now we are aware of encoding... collect_chars(start, Data, unicode, N) when is_binary(Data) -> - {Size,Npos} = count_and_find_utf8(Data,N), - if Size > N -> - {B1,B2} = split_binary(Data, Npos), - {stop,B1,B2}; - Size < N -> - {binary,[Data],N-Size}; - true -> - {stop,Data,eof} - end; + {Size, Npos} = count_and_find_utf8(Data, N), + if Size > N -> + {B1, B2} = split_binary(Data, Npos), + {stop, B1, B2}; + Size < N -> + {binary, [Data], N - Size}; + true -> + {stop, Data, eof} + end; collect_chars(start, Data, latin1, N) when is_binary(Data) -> - Size = byte_size(Data), - if Size > N -> - {B1,B2} = split_binary(Data, N), - {stop,B1,B2}; - Size < N -> - {binary,[Data],N-Size}; - true -> - {stop,Data,eof} - end; -collect_chars(start,Data,_,N) when is_list(Data) -> - collect_chars_list([], N, Data); -collect_chars(start, eof, _,_) -> - {stop,eof,eof}; -collect_chars({binary,Stack,_N}, eof, _,_) -> - {stop,binrev(Stack),eof}; -collect_chars({binary,Stack,N}, Data,unicode, _) -> - {Size,Npos} = count_and_find_utf8(Data,N), - if Size > N -> - {B1,B2} = split_binary(Data, Npos), - {stop,binrev(Stack, [B1]),B2}; - Size < N -> - {binary,[Data|Stack],N-Size}; - true -> - {stop,binrev(Stack, [Data]),eof} - end; -collect_chars({binary,Stack,N}, Data,latin1, _) -> - Size = byte_size(Data), - if Size > N -> - {B1,B2} = split_binary(Data, N), - {stop,binrev(Stack, [B1]),B2}; - Size < N -> - {binary,[Data|Stack],N-Size}; - true -> - {stop,binrev(Stack, [Data]),eof} - end; -collect_chars({list,Stack,N}, Data, _,_) -> - collect_chars_list(Stack, N, Data); + Size = byte_size(Data), + if Size > N -> + {B1, B2} = split_binary(Data, N), + {stop, B1, B2}; + Size < N -> + {binary, [Data], N - Size}; + true -> + {stop, Data, eof} + end; +collect_chars(start, Data, _, N) when is_list(Data) -> + collect_chars_list([], N, Data); +collect_chars(start, eof, _, _) -> + {stop, eof, eof}; +collect_chars({binary, Stack, _N}, eof, _, _) -> + {stop, binrev(Stack), eof}; +collect_chars({binary, Stack, N}, Data, unicode, _) -> + {Size, Npos} = count_and_find_utf8(Data, N), + if Size > N -> + {B1, B2} = split_binary(Data, Npos), + {stop, binrev(Stack, [B1]), B2}; + Size < N -> + {binary, [Data | Stack], N - Size}; + true -> + {stop, binrev(Stack, [Data]), eof} + end; +collect_chars({binary, Stack, N}, Data, latin1, _) -> + Size = byte_size(Data), + if Size > N -> + {B1, B2} = split_binary(Data, N), + {stop, binrev(Stack, [B1]), B2}; + Size < N -> + {binary, [Data | Stack], N - Size}; + true -> + {stop, binrev(Stack, [Data]), eof} + end; +collect_chars({list, Stack, N}, Data, _, _) -> + collect_chars_list(Stack, N, Data); %% collect_chars(Continuation, MoreChars, Count) %% Returns: @@ -858,88 +850,88 @@ collect_chars({list,Stack,N}, Data, _,_) -> %% {more,Continuation} collect_chars([], Chars, _, N) -> - collect_chars1(N, Chars, []); -collect_chars({Left,Sofar}, Chars, _, _N) -> - collect_chars1(Left, Chars, Sofar). + collect_chars1(N, Chars, []); +collect_chars({Left, Sofar}, Chars, _, _N) -> + collect_chars1(Left, Chars, Sofar). collect_chars1(N, Chars, Stack) when N =< 0 -> - {done,lists:reverse(Stack, []),Chars}; -collect_chars1(N, [C|Rest], Stack) -> - collect_chars1(N-1, Rest, [C|Stack]); + {done, lists:reverse(Stack, []), Chars}; +collect_chars1(N, [C | Rest], Stack) -> + collect_chars1(N - 1, Rest, [C | Stack]); collect_chars1(_N, eof, []) -> - {done,eof,[]}; + {done, eof, []}; collect_chars1(_N, eof, Stack) -> - {done,lists:reverse(Stack, []),[]}; + {done, lists:reverse(Stack, []), []}; collect_chars1(N, [], Stack) -> - {more,{N,Stack}}. + {more, {N, Stack}}. collect_chars_list(Stack, 0, Data) -> - {stop,lists:reverse(Stack, []),Data}; + {stop, lists:reverse(Stack, []), Data}; collect_chars_list(Stack, _N, eof) -> - {stop,lists:reverse(Stack, []),eof}; + {stop, lists:reverse(Stack, []), eof}; collect_chars_list(Stack, N, []) -> - {list,Stack,N}; -collect_chars_list(Stack,N, [H|T]) -> - collect_chars_list([H|Stack], N-1, T). + {list, Stack, N}; +collect_chars_list(Stack, N, [H | T]) -> + collect_chars_list([H | Stack], N - 1, T). %% collect_line(State, Data, _). New in R9C. %% Returns: %% {stop,Result,RestData} %% NewState %%% BC (with pre-R13). -collect_line(Tag, Data, Any) -> - collect_line(Tag, Data, latin1, Any). +collect_line(Tag, Data, Any) -> + collect_line(Tag, Data, latin1, Any). %% Now we are aware of encoding... collect_line(start, Data, Encoding, _) when is_binary(Data) -> - collect_line_bin(Data, Data, [], Encoding); + collect_line_bin(Data, Data, [], Encoding); collect_line(start, Data, _, _) when is_list(Data) -> - collect_line_list(Data, []); + collect_line_list(Data, []); collect_line(start, eof, _, _) -> - {stop,eof,eof}; + {stop, eof, eof}; collect_line(Stack, Data, Encoding, _) when is_binary(Data) -> - collect_line_bin(Data, Data, Stack, Encoding); + collect_line_bin(Data, Data, Stack, Encoding); collect_line(Stack, Data, _, _) when is_list(Data) -> - collect_line_list(Data, Stack); -collect_line([B|_]=Stack, eof, _, _) when is_binary(B) -> - {stop,binrev(Stack),eof}; + collect_line_list(Data, Stack); +collect_line([B | _] = Stack, eof, _, _) when is_binary(B) -> + {stop, binrev(Stack), eof}; collect_line(Stack, eof, _, _) -> - {stop,lists:reverse(Stack, []),eof}. - - -collect_line_bin(<<$\n,T/binary>>, Data, Stack0, _) -> - N = byte_size(Data) - byte_size(T), - <> = Data, - case Stack0 of - [] -> - {stop,Line,T}; - [<<$\r>>|Stack] when N =:= 1 -> - {stop,binrev(Stack, [$\n]),T}; - _ -> - {stop,binrev(Stack0, [Line]),T} - end; -collect_line_bin(<<$\r,$\n,T/binary>>, Data, Stack, _) -> - N = byte_size(Data) - byte_size(T) - 2, - <> = Data, - {stop,binrev(Stack, [Line,$\n]),T}; + {stop, lists:reverse(Stack, []), eof}. + + +collect_line_bin(<<$\n, T/binary>>, Data, Stack0, _) -> + N = byte_size(Data) - byte_size(T), + <> = Data, + case Stack0 of + [] -> + {stop, Line, T}; + [<<$\r>> | Stack] when N =:= 1 -> + {stop, binrev(Stack, [$\n]), T}; + _ -> + {stop, binrev(Stack0, [Line]), T} + end; +collect_line_bin(<<$\r, $\n, T/binary>>, Data, Stack, _) -> + N = byte_size(Data) - byte_size(T) - 2, + <> = Data, + {stop, binrev(Stack, [Line, $\n]), T}; collect_line_bin(<<$\r>>, Data0, Stack, _) -> - N = byte_size(Data0) - 1, - <> = Data0, - [<<$\r>>,Data|Stack]; -collect_line_bin(<<_,T/binary>>, Data, Stack, Enc) -> - collect_line_bin(T, Data, Stack, Enc); + N = byte_size(Data0) - 1, + <> = Data0, + [<<$\r>>, Data | Stack]; +collect_line_bin(<<_, T/binary>>, Data, Stack, Enc) -> + collect_line_bin(T, Data, Stack, Enc); collect_line_bin(<<>>, Data, Stack, _) -> - %% Need more data here. - [Data|Stack]. - -collect_line_list([$\n|T], [$\r|Stack]) -> - {stop,lists:reverse(Stack, [$\n]),T}; -collect_line_list([$\n|T], Stack) -> - {stop,lists:reverse(Stack, [$\n]),T}; -collect_line_list([H|T], Stack) -> - collect_line_list(T, [H|Stack]); + %% Need more data here. + [Data | Stack]. + +collect_line_list([$\n | T], [$\r | Stack]) -> + {stop, lists:reverse(Stack, [$\n]), T}; +collect_line_list([$\n | T], Stack) -> + {stop, lists:reverse(Stack, [$\n]), T}; +collect_line_list([H | T], Stack) -> + collect_line_list(T, [H | Stack]); collect_line_list([], Stack) -> - Stack. + Stack. %% Translator function to emulate a new (R9C and later) %% I/O client when you have an old one. @@ -947,29 +939,29 @@ collect_line_list([], Stack) -> %% Implements a middleman that is get_until server and get_chars client. %%% BC (with pre-R13). -get_until(Any,Data,Arg) -> - get_until(Any,Data,latin1,Arg). +get_until(Any, Data, Arg) -> + get_until(Any, Data, latin1, Arg). %% Now we are aware of encoding... get_until(start, Data, Encoding, XtraArg) -> - get_until([], Data, Encoding, XtraArg); + get_until([], Data, Encoding, XtraArg); get_until(Cont, Data, Encoding, {Mod, Func, XtraArgs}) -> - Chars = if is_binary(Data), Encoding =:= unicode -> - unicode:characters_to_list(Data,utf8); - is_binary(Data) -> - binary_to_list(Data); - true -> - Data - end, - case apply(Mod, Func, [Cont,Chars|XtraArgs]) of - {done,Result,Buf} -> - {stop,if is_binary(Data), - is_list(Result), - Encoding =:= unicode -> - unicode:characters_to_binary(Result,unicode,unicode); - is_binary(Data), - is_list(Result) -> - erlang:iolist_to_binary(Result); + Chars = if is_binary(Data), Encoding =:= unicode -> + unicode:characters_to_list(Data, utf8); + is_binary(Data) -> + binary_to_list(Data); + true -> + Data + end, + case apply(Mod, Func, [Cont, Chars | XtraArgs]) of + {done, Result, Buf} -> + {stop, if is_binary(Data), + is_list(Result), + Encoding =:= unicode -> + unicode:characters_to_binary(Result, unicode, unicode); + is_binary(Data), + is_list(Result) -> + erlang:iolist_to_binary(Result); %% is_list(Data), %% is_list(Result), %% Encoding =:= latin1 -> @@ -977,19 +969,19 @@ get_until(Cont, Data, Encoding, {Mod, Func, XtraArgs}) -> %% % efficiency reasons. %% [ exit({cannot_convert, unicode, latin1}) || %% X <- List, X > 255 ]; - true -> - Result - end, - Buf}; - {more,NewCont} -> - NewCont - end. + true -> + Result + end, + Buf}; + {more, NewCont} -> + NewCont + end. binrev(L) -> - list_to_binary(lists:reverse(L, [])). + list_to_binary(lists:reverse(L, [])). binrev(L, T) -> - list_to_binary(lists:reverse(L, T)). + list_to_binary(lists:reverse(L, T)). -spec limit_term(term(), non_neg_integer()) -> term(). @@ -998,48 +990,48 @@ binrev(L, T) -> %% seen when printed with the same depth. Bitstrings are never %% truncated, which is OK as long as they are not sent to other nodes. limit_term(Term, Depth) -> - try test_limit(Term, Depth) of - ok -> Term - catch - throw:limit -> - limit(Term, Depth) - end. + try test_limit(Term, Depth) of + ok -> Term + catch + throw:limit -> + limit(Term, Depth) + end. limit(_, 0) -> '...'; -limit([H|T]=L, D) -> - if - D =:= 1 -> ['...']; - true -> - case printable_list(L) of - true -> L; - false -> - [limit(H, D-1)|limit_tail(T, D-1)] - end - end; +limit([H | T] = L, D) -> + if + D =:= 1 -> ['...']; + true -> + case printable_list(L) of + true -> L; + false -> + [limit(H, D - 1) | limit_tail(T, D - 1)] + end + end; limit(Term, D) when is_map(Term) -> - limit_map(Term, D); -limit({}=T, _D) -> T; + limit_map(Term, D); +limit({} = T, _D) -> T; limit(T, D) when is_tuple(T) -> - if - D =:= 1 -> {'...'}; - true -> - list_to_tuple([limit(element(1, T), D-1)| - limit_tuple(T, 2, D-1)]) - end; -limit(<<_/bitstring>>=Term, D) -> limit_bitstring(Term, D); + if + D =:= 1 -> {'...'}; + true -> + list_to_tuple([limit(element(1, T), D - 1) | + limit_tuple(T, 2, D - 1)]) + end; +limit(<<_/bitstring>> = Term, D) -> limit_bitstring(Term, D); limit(Term, _D) -> Term. limit_tail([], _D) -> []; limit_tail(_, 1) -> ['...']; -limit_tail([H|T], D) -> - [limit(H, D-1)|limit_tail(T, D-1)]; +limit_tail([H | T], D) -> + [limit(H, D - 1) | limit_tail(T, D - 1)]; limit_tail(Other, D) -> - limit(Other, D-1). + limit(Other, D - 1). limit_tuple(T, I, _D) when I > tuple_size(T) -> []; limit_tuple(_, _I, 1) -> ['...']; limit_tuple(T, I, D) -> - [limit(element(I, T), D-1)|limit_tuple(T, I+1, D-1)]. + [limit(element(I, T), D - 1) | limit_tuple(T, I + 1, D - 1)]. %% Cannot limit maps properly since there is no guarantee that %% maps:from_list() creates a map with the same internal ordering of @@ -1048,75 +1040,75 @@ limit_tuple(T, I, D) -> %% for tuples and lists), the same depth is applied to each and every %% (returned) association. limit_map(Map, D) -> - %% Keep one extra association to make sure the final ',...' is included. - limit_map_body(maps:iterator(Map), D + 1, D, []). + %% Keep one extra association to make sure the final ',...' is included. + limit_map_body(maps:iterator(Map), D + 1, D, []). limit_map_body(_I, 0, _D0, Acc) -> - maps:from_list(Acc); + maps:from_list(Acc); limit_map_body(I, D, D0, Acc) -> - case maps:next(I) of - {K, V, NextI} -> - limit_map_body(NextI, D-1, D0, [limit_map_assoc(K, V, D0) | Acc]); - none -> - maps:from_list(Acc) - end. + case maps:next(I) of + {K, V, NextI} -> + limit_map_body(NextI, D - 1, D0, [limit_map_assoc(K, V, D0) | Acc]); + none -> + maps:from_list(Acc) + end. limit_map_assoc(K, V, D) -> - %% Keep keys as are to avoid creating duplicated keys. - {K, limit(V, D - 1)}. + %% Keep keys as are to avoid creating duplicated keys. + {K, limit(V, D - 1)}. limit_bitstring(B, _D) -> B. % Keeps all printable binaries. test_limit(_, 0) -> throw(limit); -test_limit([H|T]=L, D) when is_integer(D) -> - if - D =:= 1 -> throw(limit); - true -> - case printable_list(L) of - true -> ok; - false -> - test_limit(H, D-1), - test_limit_tail(T, D-1) - end - end; +test_limit([H | T] = L, D) when is_integer(D) -> + if + D =:= 1 -> throw(limit); + true -> + case printable_list(L) of + true -> ok; + false -> + test_limit(H, D - 1), + test_limit_tail(T, D - 1) + end + end; test_limit(Term, D) when is_map(Term) -> - test_limit_map(Term, D); + test_limit_map(Term, D); test_limit({}, _D) -> ok; test_limit(T, D) when is_tuple(T) -> - test_limit_tuple(T, 1, tuple_size(T), D); -test_limit(<<_/bitstring>>=Term, D) -> test_limit_bitstring(Term, D); + test_limit_tuple(T, 1, tuple_size(T), D); +test_limit(<<_/bitstring>> = Term, D) -> 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) -> - test_limit(H, D-1), - test_limit_tail(T, D-1); +test_limit_tail([H | T], D) -> + test_limit(H, D - 1), + test_limit_tail(T, D - 1); test_limit_tail(Other, D) -> - test_limit(Other, D-1). + test_limit(Other, D - 1). test_limit_tuple(_T, I, Sz, _D) when I > Sz -> ok; test_limit_tuple(_, _, _, 1) -> throw(limit); test_limit_tuple(T, I, Sz, D) -> - test_limit(element(I, T), D-1), - test_limit_tuple(T, I+1, Sz, D-1). + test_limit(element(I, T), D - 1), + test_limit_tuple(T, I + 1, Sz, D - 1). test_limit_map(Map, D) -> - test_limit_map_body(maps:iterator(Map), D). + test_limit_map_body(maps:iterator(Map), D). test_limit_map_body(_I, 0) -> throw(limit); % cannot happen test_limit_map_body(I, D) -> - case maps:next(I) of - {K, V, NextI} -> - test_limit_map_assoc(K, V, D), - test_limit_map_body(NextI, D-1); - none -> - ok - end. + case maps:next(I) of + {K, V, NextI} -> + test_limit_map_assoc(K, V, D), + test_limit_map_body(NextI, D - 1); + none -> + ok + end. test_limit_map_assoc(K, V, D) -> - test_limit(K, D - 1), - test_limit(V, D - 1). + test_limit(K, D - 1), + test_limit(V, D - 1). test_limit_bitstring(_, _) -> ok. @@ -1126,10 +1118,10 @@ test_limit_bitstring(_, _) -> ok. %% by $\n if S is an iolist() (string:length() assigns such a %% sub-sequence length 1). chars_length(S) -> - try - %% true = deep_latin1_char_list(S), - iolist_size(S) - catch - _:_ -> - string:length(S) - end. + try + %% true = deep_latin1_char_list(S), + iolist_size(S) + catch + _:_ -> + string:length(S) + end. diff --git a/src/eFmtFormat.erl b/src/eFmtFormat.erl index b5c5404..bb43c98 100644 --- a/src/eFmtFormat.erl +++ b/src/eFmtFormat.erl @@ -1,28 +1,16 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2019. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% -module(eFmtFormat). %% Formatting functions of io library. - --export([fwrite/2,fwrite/3,fwrite_g/1,indentation/2,scan/2,unscan/1, - build/1, build/2]). +-export([ + fwrite/2 + , fwrite/3 + , fwrite_g/1 + , indentation/2 + , scan/2 + , unscan/1 + , build/1 + , build/2 +]). %% Format the arguments in Args after string Format. Just generate %% an error if there is an error in the arguments. @@ -39,92 +27,92 @@ %% parts. -spec fwrite(Format, Data) -> io_lib:chars() when - Format :: io:format(), - Data :: [term()]. + Format :: io:format(), + Data :: [term()]. fwrite(Format, Args) -> - build(scan(Format, Args)). + build(scan(Format, Args)). -spec fwrite(Format, Data, Options) -> io_lib:chars() when - Format :: io:format(), - Data :: [term()], - Options :: [Option], - Option :: {'chars_limit', CharsLimit}, - CharsLimit :: io_lib:chars_limit(). + Format :: io:format(), + Data :: [term()], + Options :: [Option], + Option :: {'chars_limit', CharsLimit}, + CharsLimit :: io_lib:chars_limit(). fwrite(Format, Args, Options) -> - build(scan(Format, Args), Options). + build(scan(Format, Args), Options). %% Build the output text for a pre-parsed format list. -spec build(FormatList) -> io_lib:chars() when - FormatList :: [char() | io_lib:format_spec()]. + FormatList :: [char() | io_lib:format_spec()]. build(Cs) -> - build(Cs, []). + build(Cs, []). -spec build(FormatList, Options) -> io_lib:chars() when - FormatList :: [char() | io_lib:format_spec()], - Options :: [Option], - Option :: {'chars_limit', CharsLimit}, - CharsLimit :: io_lib:chars_limit(). + FormatList :: [char() | io_lib:format_spec()], + Options :: [Option], + Option :: {'chars_limit', CharsLimit}, + CharsLimit :: io_lib:chars_limit(). build(Cs, Options) -> - CharsLimit = get_option(chars_limit, Options, -1), - Res1 = build_small(Cs), - {P, S, W, Other} = count_small(Res1), - case P + S + W of - 0 -> - Res1; - NumOfLimited -> - RemainingChars = sub(CharsLimit, Other), - build_limited(Res1, P, NumOfLimited, RemainingChars, 0) - end. + CharsLimit = get_option(chars_limit, Options, -1), + Res1 = build_small(Cs), + {P, S, W, Other} = count_small(Res1), + case P + S + W of + 0 -> + Res1; + NumOfLimited -> + RemainingChars = sub(CharsLimit, Other), + build_limited(Res1, P, NumOfLimited, RemainingChars, 0) + end. %% Parse all control sequences in the format string. -spec scan(Format, Data) -> FormatList when - Format :: io:format(), - Data :: [term()], - FormatList :: [char() | io_lib:format_spec()]. + Format :: io:format(), + Data :: [term()], + FormatList :: [char() | io_lib:format_spec()]. scan(Format, Args) when is_atom(Format) -> - scan(atom_to_list(Format), Args); + scan(atom_to_list(Format), Args); scan(Format, Args) when is_binary(Format) -> - scan(binary_to_list(Format), Args); + scan(binary_to_list(Format), Args); scan(Format, Args) -> - collect(Format, Args). + collect(Format, Args). %% Revert a pre-parsed format list to a plain character list and a %% list of arguments. -spec unscan(FormatList) -> {Format, Data} when - FormatList :: [char() | io_lib:format_spec()], - Format :: io:format(), - Data :: [term()]. + FormatList :: [char() | io_lib:format_spec()], + Format :: io:format(), + Data :: [term()]. unscan(Cs) -> - {print(Cs), args(Cs)}. + {print(Cs), args(Cs)}. args([#{args := As} | Cs]) -> - As ++ args(Cs); + As ++ args(Cs); args([_C | Cs]) -> - args(Cs); + args(Cs); args([]) -> - []. + []. print([#{control_char := C, width := F, adjust := Ad, precision := P, - pad_char := Pad, encoding := Encoding, strings := Strings} | Cs]) -> - print(C, F, Ad, P, Pad, Encoding, Strings) ++ print(Cs); + pad_char := Pad, encoding := Encoding, strings := Strings} | Cs]) -> + print(C, F, Ad, P, Pad, Encoding, Strings) ++ print(Cs); print([C | Cs]) -> - [C | print(Cs)]; + [C | print(Cs)]; print([]) -> - []. + []. print(C, F, Ad, P, Pad, Encoding, Strings) -> - [$~] ++ print_field_width(F, Ad) ++ print_precision(P, Pad) ++ - print_pad_char(Pad) ++ print_encoding(Encoding) ++ - print_strings(Strings) ++ [C]. + [$~] ++ print_field_width(F, Ad) ++ print_precision(P, Pad) ++ + print_pad_char(Pad) ++ print_encoding(Encoding) ++ + print_strings(Strings) ++ [C]. print_field_width(none, _Ad) -> ""; print_field_width(F, left) -> integer_to_list(-F); @@ -143,116 +131,116 @@ print_encoding(latin1) -> "". print_strings(false) -> "l"; print_strings(true) -> "". -collect([$~|Fmt0], Args0) -> - {C,Fmt1,Args1} = collect_cseq(Fmt0, Args0), - [C|collect(Fmt1, Args1)]; -collect([C|Fmt], Args) -> - [C|collect(Fmt, Args)]; +collect([$~ | Fmt0], Args0) -> + {C, Fmt1, Args1} = collect_cseq(Fmt0, Args0), + [C | collect(Fmt1, Args1)]; +collect([C | Fmt], Args) -> + [C | collect(Fmt, Args)]; collect([], []) -> []. collect_cseq(Fmt0, Args0) -> - {F,Ad,Fmt1,Args1} = field_width(Fmt0, Args0), - {P,Fmt2,Args2} = precision(Fmt1, Args1), - {Pad,Fmt3,Args3} = pad_char(Fmt2, Args2), - Spec0 = #{width => F, - adjust => Ad, - precision => P, - pad_char => Pad, - encoding => latin1, - strings => true}, - {Spec1,Fmt4} = modifiers(Fmt3, Spec0), - {C,As,Fmt5,Args4} = collect_cc(Fmt4, Args3), - Spec2 = Spec1#{control_char => C, args => As}, - {Spec2,Fmt5,Args4}. - -modifiers([$t|Fmt], Spec) -> - modifiers(Fmt, Spec#{encoding => unicode}); -modifiers([$l|Fmt], Spec) -> - modifiers(Fmt, Spec#{strings => false}); + {F, Ad, Fmt1, Args1} = field_width(Fmt0, Args0), + {P, Fmt2, Args2} = precision(Fmt1, Args1), + {Pad, Fmt3, Args3} = pad_char(Fmt2, Args2), + Spec0 = #{width => F, + adjust => Ad, + precision => P, + pad_char => Pad, + encoding => latin1, + strings => true}, + {Spec1, Fmt4} = modifiers(Fmt3, Spec0), + {C, As, Fmt5, Args4} = collect_cc(Fmt4, Args3), + Spec2 = Spec1#{control_char => C, args => As}, + {Spec2, Fmt5, Args4}. + +modifiers([$t | Fmt], Spec) -> + modifiers(Fmt, Spec#{encoding => unicode}); +modifiers([$l | Fmt], Spec) -> + modifiers(Fmt, Spec#{strings => false}); modifiers(Fmt, Spec) -> - {Spec, Fmt}. + {Spec, Fmt}. -field_width([$-|Fmt0], Args0) -> - {F,Fmt,Args} = field_value(Fmt0, Args0), - field_width(-F, Fmt, Args); +field_width([$- | Fmt0], Args0) -> + {F, Fmt, Args} = field_value(Fmt0, Args0), + field_width(-F, Fmt, Args); field_width(Fmt0, Args0) -> - {F,Fmt,Args} = field_value(Fmt0, Args0), - field_width(F, Fmt, Args). + {F, Fmt, Args} = field_value(Fmt0, Args0), + field_width(F, Fmt, Args). field_width(F, Fmt, Args) when F < 0 -> - {-F,left,Fmt,Args}; + {-F, left, Fmt, Args}; field_width(F, Fmt, Args) when F >= 0 -> - {F,right,Fmt,Args}. + {F, right, Fmt, Args}. -precision([$.|Fmt], Args) -> - field_value(Fmt, Args); +precision([$. | Fmt], Args) -> + field_value(Fmt, Args); precision(Fmt, Args) -> - {none,Fmt,Args}. + {none, Fmt, Args}. -field_value([$*|Fmt], [A|Args]) when is_integer(A) -> - {A,Fmt,Args}; -field_value([C|Fmt], Args) when is_integer(C), C >= $0, C =< $9 -> - field_value([C|Fmt], Args, 0); +field_value([$* | Fmt], [A | Args]) when is_integer(A) -> + {A, Fmt, Args}; +field_value([C | Fmt], Args) when is_integer(C), C >= $0, C =< $9 -> + field_value([C | Fmt], Args, 0); field_value(Fmt, Args) -> - {none,Fmt,Args}. + {none, Fmt, Args}. -field_value([C|Fmt], Args, F) when is_integer(C), C >= $0, C =< $9 -> - field_value(Fmt, Args, 10*F + (C - $0)); -field_value(Fmt, Args, F) -> %Default case - {F,Fmt,Args}. +field_value([C | Fmt], Args, F) when is_integer(C), C >= $0, C =< $9 -> + field_value(Fmt, Args, 10 * F + (C - $0)); +field_value(Fmt, Args, F) -> %Default case + {F, Fmt, Args}. -pad_char([$.,$*|Fmt], [Pad|Args]) -> {Pad,Fmt,Args}; -pad_char([$.,Pad|Fmt], Args) -> {Pad,Fmt,Args}; -pad_char(Fmt, Args) -> {$\s,Fmt,Args}. +pad_char([$., $* | Fmt], [Pad | Args]) -> {Pad, Fmt, Args}; +pad_char([$., Pad | Fmt], Args) -> {Pad, Fmt, Args}; +pad_char(Fmt, Args) -> {$\s, Fmt, Args}. %% collect_cc([FormatChar], [Argument]) -> %% {Control,[ControlArg],[FormatChar],[Arg]}. %% Here we collect the argments for each control character. %% Be explicit to cause failure early. -collect_cc([$w|Fmt], [A|Args]) -> {$w,[A],Fmt,Args}; -collect_cc([$p|Fmt], [A|Args]) -> {$p,[A],Fmt,Args}; -collect_cc([$W|Fmt], [A,Depth|Args]) -> {$W,[A,Depth],Fmt,Args}; -collect_cc([$P|Fmt], [A,Depth|Args]) -> {$P,[A,Depth],Fmt,Args}; -collect_cc([$s|Fmt], [A|Args]) -> {$s,[A],Fmt,Args}; -collect_cc([$e|Fmt], [A|Args]) -> {$e,[A],Fmt,Args}; -collect_cc([$f|Fmt], [A|Args]) -> {$f,[A],Fmt,Args}; -collect_cc([$g|Fmt], [A|Args]) -> {$g,[A],Fmt,Args}; -collect_cc([$b|Fmt], [A|Args]) -> {$b,[A],Fmt,Args}; -collect_cc([$B|Fmt], [A|Args]) -> {$B,[A],Fmt,Args}; -collect_cc([$x|Fmt], [A,Prefix|Args]) -> {$x,[A,Prefix],Fmt,Args}; -collect_cc([$X|Fmt], [A,Prefix|Args]) -> {$X,[A,Prefix],Fmt,Args}; -collect_cc([$+|Fmt], [A|Args]) -> {$+,[A],Fmt,Args}; -collect_cc([$#|Fmt], [A|Args]) -> {$#,[A],Fmt,Args}; -collect_cc([$c|Fmt], [A|Args]) -> {$c,[A],Fmt,Args}; -collect_cc([$~|Fmt], Args) when is_list(Args) -> {$~,[],Fmt,Args}; -collect_cc([$n|Fmt], Args) when is_list(Args) -> {$n,[],Fmt,Args}; -collect_cc([$i|Fmt], [A|Args]) -> {$i,[A],Fmt,Args}. +collect_cc([$w | Fmt], [A | Args]) -> {$w, [A], Fmt, Args}; +collect_cc([$p | Fmt], [A | Args]) -> {$p, [A], Fmt, Args}; +collect_cc([$W | Fmt], [A, Depth | Args]) -> {$W, [A, Depth], Fmt, Args}; +collect_cc([$P | Fmt], [A, Depth | Args]) -> {$P, [A, Depth], Fmt, Args}; +collect_cc([$s | Fmt], [A | Args]) -> {$s, [A], Fmt, Args}; +collect_cc([$e | Fmt], [A | Args]) -> {$e, [A], Fmt, Args}; +collect_cc([$f | Fmt], [A | Args]) -> {$f, [A], Fmt, Args}; +collect_cc([$g | Fmt], [A | Args]) -> {$g, [A], Fmt, Args}; +collect_cc([$b | Fmt], [A | Args]) -> {$b, [A], Fmt, Args}; +collect_cc([$B | Fmt], [A | Args]) -> {$B, [A], Fmt, Args}; +collect_cc([$x | Fmt], [A, Prefix | Args]) -> {$x, [A, Prefix], Fmt, Args}; +collect_cc([$X | Fmt], [A, Prefix | Args]) -> {$X, [A, Prefix], Fmt, Args}; +collect_cc([$+ | Fmt], [A | Args]) -> {$+, [A], Fmt, Args}; +collect_cc([$# | Fmt], [A | Args]) -> {$#, [A], Fmt, Args}; +collect_cc([$c | Fmt], [A | Args]) -> {$c, [A], Fmt, Args}; +collect_cc([$~ | Fmt], Args) when is_list(Args) -> {$~, [], Fmt, Args}; +collect_cc([$n | Fmt], Args) when is_list(Args) -> {$n, [], Fmt, Args}; +collect_cc([$i | Fmt], [A | Args]) -> {$i, [A], Fmt, Args}. %% count_small([ControlC]) -> Count. %% Count the number of big (pPwWsS) print requests and %% number of characters of other print (small) requests. count_small(Cs) -> - count_small(Cs, #{p => 0, s => 0, w => 0, other => 0}). - -count_small([#{control_char := $p}|Cs], #{p := P} = Cnts) -> - count_small(Cs, Cnts#{p := P + 1}); -count_small([#{control_char := $P}|Cs], #{p := P} = Cnts) -> - count_small(Cs, Cnts#{p := P + 1}); -count_small([#{control_char := $w}|Cs], #{w := W} = Cnts) -> - count_small(Cs, Cnts#{w := W + 1}); -count_small([#{control_char := $W}|Cs], #{w := W} = Cnts) -> - count_small(Cs, Cnts#{w := W + 1}); -count_small([#{control_char := $s}|Cs], #{w := W} = Cnts) -> - count_small(Cs, Cnts#{w := W + 1}); -count_small([S|Cs], #{other := Other} = Cnts) when is_list(S); - is_binary(S) -> - count_small(Cs, Cnts#{other := Other + io_lib:chars_length(S)}); -count_small([C|Cs], #{other := Other} = Cnts) when is_integer(C) -> - count_small(Cs, Cnts#{other := Other + 1}); + count_small(Cs, #{p => 0, s => 0, w => 0, other => 0}). + +count_small([#{control_char := $p} | Cs], #{p := P} = Cnts) -> + count_small(Cs, Cnts#{p := P + 1}); +count_small([#{control_char := $P} | Cs], #{p := P} = Cnts) -> + count_small(Cs, Cnts#{p := P + 1}); +count_small([#{control_char := $w} | Cs], #{w := W} = Cnts) -> + count_small(Cs, Cnts#{w := W + 1}); +count_small([#{control_char := $W} | Cs], #{w := W} = Cnts) -> + count_small(Cs, Cnts#{w := W + 1}); +count_small([#{control_char := $s} | Cs], #{w := W} = Cnts) -> + count_small(Cs, Cnts#{w := W + 1}); +count_small([S | Cs], #{other := Other} = Cnts) when is_list(S); + is_binary(S) -> + count_small(Cs, Cnts#{other := Other + io_lib:chars_length(S)}); +count_small([C | Cs], #{other := Other} = Cnts) when is_integer(C) -> + count_small(Cs, Cnts#{other := Other + 1}); count_small([], #{p := P, s := S, w := W, other := Other}) -> - {P, S, W, Other}. + {P, S, W, Other}. %% build_small([Control]) -> io_lib:chars(). %% Interpret the control structures, but only the small ones. @@ -264,42 +252,42 @@ count_small([], #{p := P, s := S, w := W, other := Other}) -> %% be smart when calculating indentation for characters in format. build_small([#{control_char := C, args := As, width := F, adjust := Ad, - precision := P, pad_char := Pad, encoding := Enc}=CC | Cs]) -> - case control_small(C, As, F, Ad, P, Pad, Enc) of - not_small -> [CC | build_small(Cs)]; - S -> lists:flatten(S) ++ build_small(Cs) - end; -build_small([C|Cs]) -> [C|build_small(Cs)]; + precision := P, pad_char := Pad, encoding := Enc} = CC | Cs]) -> + case control_small(C, As, F, Ad, P, Pad, Enc) of + not_small -> [CC | build_small(Cs)]; + S -> lists:flatten(S) ++ build_small(Cs) + end; +build_small([C | Cs]) -> [C | build_small(Cs)]; build_small([]) -> []. build_limited([#{control_char := C, args := As, width := F, adjust := Ad, - precision := P, pad_char := Pad, encoding := Enc, - strings := Str} | Cs], NumOfPs0, Count0, MaxLen0, I) -> - MaxChars = if - MaxLen0 < 0 -> MaxLen0; - true -> MaxLen0 div Count0 - end, - S = control_limited(C, As, F, Ad, P, Pad, Enc, Str, MaxChars, I), - NumOfPs = decr_pc(C, NumOfPs0), - Count = Count0 - 1, - MaxLen = if - MaxLen0 < 0 -> % optimization - MaxLen0; - true -> - Len = io_lib:chars_length(S), - sub(MaxLen0, Len) - end, - if - NumOfPs > 0 -> [S|build_limited(Cs, NumOfPs, Count, - MaxLen, indentation(S, I))]; - true -> [S|build_limited(Cs, NumOfPs, Count, MaxLen, I)] - end; -build_limited([$\n|Cs], NumOfPs, Count, MaxLen, _I) -> - [$\n|build_limited(Cs, NumOfPs, Count, MaxLen, 0)]; -build_limited([$\t|Cs], NumOfPs, Count, MaxLen, I) -> - [$\t|build_limited(Cs, NumOfPs, Count, MaxLen, ((I + 8) div 8) * 8)]; -build_limited([C|Cs], NumOfPs, Count, MaxLen, I) -> - [C|build_limited(Cs, NumOfPs, Count, MaxLen, I+1)]; + precision := P, pad_char := Pad, encoding := Enc, + strings := Str} | Cs], NumOfPs0, Count0, MaxLen0, I) -> + MaxChars = if + MaxLen0 < 0 -> MaxLen0; + true -> MaxLen0 div Count0 + end, + S = control_limited(C, As, F, Ad, P, Pad, Enc, Str, MaxChars, I), + NumOfPs = decr_pc(C, NumOfPs0), + Count = Count0 - 1, + MaxLen = if + MaxLen0 < 0 -> % optimization + MaxLen0; + true -> + Len = io_lib:chars_length(S), + sub(MaxLen0, Len) + end, + if + NumOfPs > 0 -> [S | build_limited(Cs, NumOfPs, Count, + MaxLen, indentation(S, I))]; + true -> [S | build_limited(Cs, NumOfPs, Count, MaxLen, I)] + end; +build_limited([$\n | Cs], NumOfPs, Count, MaxLen, _I) -> + [$\n | build_limited(Cs, NumOfPs, Count, MaxLen, 0)]; +build_limited([$\t | Cs], NumOfPs, Count, MaxLen, I) -> + [$\t | build_limited(Cs, NumOfPs, Count, MaxLen, ((I + 8) div 8) * 8)]; +build_limited([C | Cs], NumOfPs, Count, MaxLen, I) -> + [C | build_limited(Cs, NumOfPs, Count, MaxLen, I + 1)]; build_limited([], _, _, _, _) -> []. decr_pc($p, Pc) -> Pc - 1; @@ -310,15 +298,15 @@ decr_pc(_, Pc) -> Pc. %% indentation. We assume tabs at 8 cols. -spec indentation(String, StartIndent) -> integer() when - String :: io_lib:chars(), - StartIndent :: integer(). - -indentation([$\n|Cs], _I) -> indentation(Cs, 0); -indentation([$\t|Cs], I) -> indentation(Cs, ((I + 8) div 8) * 8); -indentation([C|Cs], I) when is_integer(C) -> - indentation(Cs, I+1); -indentation([C|Cs], I) -> - indentation(Cs, indentation(C, I)); + String :: io_lib:chars(), + StartIndent :: integer(). + +indentation([$\n | Cs], _I) -> indentation(Cs, 0); +indentation([$\t | Cs], I) -> indentation(Cs, ((I + 8) div 8) * 8); +indentation([C | Cs], I) when is_integer(C) -> + indentation(Cs, I + 1); +indentation([C | Cs], I) -> + indentation(Cs, indentation(C, I)); indentation([], I) -> I. %% control_small(FormatChar, [Argument], FieldWidth, Adjust, Precision, @@ -327,81 +315,81 @@ indentation([], I) -> I. %% PadChar, Encoding, StringP, ChrsLim, Indentation) -> String %% These are the dispatch functions for the various formatting controls. -control_small($s, [A], F, Adj, P, Pad, latin1=Enc) when is_atom(A) -> - L = iolist_to_chars(atom_to_list(A)), - string(L, F, Adj, P, Pad, Enc); -control_small($s, [A], F, Adj, P, Pad, unicode=Enc) when is_atom(A) -> - string(atom_to_list(A), F, Adj, P, Pad, Enc); +control_small($s, [A], F, Adj, P, Pad, latin1 = Enc) when is_atom(A) -> + L = iolist_to_chars(atom_to_list(A)), + string(L, F, Adj, P, Pad, Enc); +control_small($s, [A], F, Adj, P, Pad, unicode = Enc) when is_atom(A) -> + string(atom_to_list(A), F, Adj, P, Pad, Enc); control_small($e, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> - fwrite_e(A, F, Adj, P, Pad); + fwrite_e(A, F, Adj, P, Pad); control_small($f, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> - fwrite_f(A, F, Adj, P, Pad); + fwrite_f(A, F, Adj, P, Pad); control_small($g, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> - fwrite_g(A, F, Adj, P, Pad); + fwrite_g(A, F, Adj, P, Pad); control_small($b, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> - unprefixed_integer(A, F, Adj, base(P), Pad, true); + unprefixed_integer(A, F, Adj, base(P), Pad, true); control_small($B, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> - unprefixed_integer(A, F, Adj, base(P), Pad, false); -control_small($x, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A), - is_atom(Prefix) -> - prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), true); -control_small($x, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) -> - true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list - prefixed_integer(A, F, Adj, base(P), Pad, Prefix, true); -control_small($X, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A), - is_atom(Prefix) -> - prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), false); -control_small($X, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) -> - true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list - prefixed_integer(A, F, Adj, base(P), Pad, Prefix, false); + unprefixed_integer(A, F, Adj, base(P), Pad, false); +control_small($x, [A, Prefix], F, Adj, P, Pad, _Enc) when is_integer(A), + is_atom(Prefix) -> + prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), true); +control_small($x, [A, Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) -> + true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list + prefixed_integer(A, F, Adj, base(P), Pad, Prefix, true); +control_small($X, [A, Prefix], F, Adj, P, Pad, _Enc) when is_integer(A), + is_atom(Prefix) -> + prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), false); +control_small($X, [A, Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) -> + true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list + prefixed_integer(A, F, Adj, base(P), Pad, Prefix, false); control_small($+, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> - Base = base(P), - Prefix = [integer_to_list(Base), $#], - prefixed_integer(A, F, Adj, Base, Pad, Prefix, true); + Base = base(P), + Prefix = [integer_to_list(Base), $#], + prefixed_integer(A, F, Adj, Base, Pad, Prefix, true); control_small($#, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> - Base = base(P), - Prefix = [integer_to_list(Base), $#], - prefixed_integer(A, F, Adj, Base, Pad, Prefix, false); + Base = base(P), + Prefix = [integer_to_list(Base), $#], + prefixed_integer(A, F, Adj, Base, Pad, Prefix, false); control_small($c, [A], F, Adj, P, Pad, unicode) when is_integer(A) -> - char(A, F, Adj, P, Pad); + char(A, F, Adj, P, Pad); control_small($c, [A], F, Adj, P, Pad, _Enc) when is_integer(A) -> - char(A band 255, F, Adj, P, Pad); + char(A band 255, F, Adj, P, Pad); control_small($~, [], F, Adj, P, Pad, _Enc) -> char($~, F, Adj, P, Pad); control_small($n, [], F, Adj, P, Pad, _Enc) -> newline(F, Adj, P, Pad); control_small($i, [_A], _F, _Adj, _P, _Pad, _Enc) -> []; control_small(_C, _As, _F, _Adj, _P, _Pad, _Enc) -> not_small. -control_limited($s, [L0], F, Adj, P, Pad, latin1=Enc, _Str, CL, _I) -> - L = iolist_to_chars(L0, F, CL), - string(L, limit_field(F, CL), Adj, P, Pad, Enc); -control_limited($s, [L0], F, Adj, P, Pad, unicode=Enc, _Str, CL, _I) -> - L = cdata_to_chars(L0, F, CL), - uniconv(string(L, limit_field(F, CL), Adj, P, Pad, Enc)); +control_limited($s, [L0], F, Adj, P, Pad, latin1 = Enc, _Str, CL, _I) -> + L = iolist_to_chars(L0, F, CL), + string(L, limit_field(F, CL), Adj, P, Pad, Enc); +control_limited($s, [L0], F, Adj, P, Pad, unicode = Enc, _Str, CL, _I) -> + L = cdata_to_chars(L0, F, CL), + uniconv(string(L, limit_field(F, CL), Adj, P, Pad, Enc)); control_limited($w, [A], F, Adj, P, Pad, Enc, _Str, CL, _I) -> - Chars = io_lib:write(A, [{depth, -1}, {encoding, Enc}, {chars_limit, CL}]), - term(Chars, F, Adj, P, Pad); + Chars = io_lib:write(A, [{depth, -1}, {encoding, Enc}, {chars_limit, CL}]), + term(Chars, F, Adj, P, Pad); control_limited($p, [A], F, Adj, P, Pad, Enc, Str, CL, I) -> - print(A, -1, F, Adj, P, Pad, Enc, Str, CL, I); -control_limited($W, [A,Depth], F, Adj, P, Pad, Enc, _Str, CL, _I) - when is_integer(Depth) -> - Chars = io_lib:write(A, [{depth, Depth}, {encoding, Enc}, {chars_limit, CL}]), - term(Chars, F, Adj, P, Pad); -control_limited($P, [A,Depth], F, Adj, P, Pad, Enc, Str, CL, I) - when is_integer(Depth) -> - print(A, Depth, F, Adj, P, Pad, Enc, Str, CL, I). + print(A, -1, F, Adj, P, Pad, Enc, Str, CL, I); +control_limited($W, [A, Depth], F, Adj, P, Pad, Enc, _Str, CL, _I) + when is_integer(Depth) -> + Chars = io_lib:write(A, [{depth, Depth}, {encoding, Enc}, {chars_limit, CL}]), + term(Chars, F, Adj, P, Pad); +control_limited($P, [A, Depth], F, Adj, P, Pad, Enc, Str, CL, I) + when is_integer(Depth) -> + print(A, Depth, F, Adj, P, Pad, Enc, Str, CL, I). -ifdef(UNICODE_AS_BINARIES). uniconv(C) -> - unicode:characters_to_binary(C,unicode). + unicode:characters_to_binary(C, unicode). -else. uniconv(C) -> - C. + C. -endif. %% Default integer base base(none) -> - 10; + 10; base(B) when is_integer(B) -> - B. + B. %% term(TermList, Field, Adjust, Precision, PadChar) %% Output the characters in a term. @@ -411,14 +399,14 @@ base(B) when is_integer(B) -> term(T, none, _Adj, none, _Pad) -> T; term(T, none, Adj, P, Pad) -> term(T, P, Adj, P, Pad); term(T, F, Adj, P0, Pad) -> - L = io_lib:chars_length(T), - P = erlang:min(L, case P0 of none -> F; _ -> min(P0, F) end), - if - L > P -> - adjust(chars($*, P), chars(Pad, F-P), Adj); - F >= P -> - adjust(T, chars(Pad, F-L), Adj) - end. + L = io_lib:chars_length(T), + P = erlang:min(L, case P0 of none -> F; _ -> min(P0, F) end), + if + L > P -> + adjust(chars($*, P), chars(Pad, F - P), Adj); + F >= P -> + adjust(T, chars(Pad, F - L), Adj) + end. %% print(Term, Depth, Field, Adjust, Precision, PadChar, Encoding, %% Indentation) @@ -426,36 +414,36 @@ term(T, F, Adj, P0, Pad) -> %% initial indentation. print(T, D, none, Adj, P, Pad, E, Str, ChLim, I) -> - print(T, D, 80, Adj, P, Pad, E, Str, ChLim, I); + print(T, D, 80, Adj, P, Pad, E, Str, ChLim, I); print(T, D, F, Adj, none, Pad, E, Str, ChLim, I) -> - print(T, D, F, Adj, I+1, Pad, E, Str, ChLim, I); + print(T, D, F, Adj, I + 1, Pad, E, Str, ChLim, I); print(T, D, F, right, P, _Pad, Enc, Str, ChLim, _I) -> - Options = [{chars_limit, ChLim}, - {column, P}, - {line_length, F}, - {depth, D}, - {encoding, Enc}, - {strings, Str}], - io_lib_pretty:print(T, Options). + Options = [{chars_limit, ChLim}, + {column, P}, + {line_length, F}, + {depth, D}, + {encoding, Enc}, + {strings, Str}], + io_lib_pretty:print(T, Options). %% fwrite_e(Float, Field, Adjust, Precision, PadChar) -fwrite_e(Fl, none, Adj, none, Pad) -> %Default values - fwrite_e(Fl, none, Adj, 6, Pad); +fwrite_e(Fl, none, Adj, none, Pad) -> %Default values + fwrite_e(Fl, none, Adj, 6, Pad); fwrite_e(Fl, none, _Adj, P, _Pad) when P >= 2 -> - float_e(Fl, float_data(Fl), P); + float_e(Fl, float_data(Fl), P); fwrite_e(Fl, F, Adj, none, Pad) -> - fwrite_e(Fl, F, Adj, 6, Pad); + fwrite_e(Fl, F, Adj, 6, Pad); fwrite_e(Fl, F, Adj, P, Pad) when P >= 2 -> - term(float_e(Fl, float_data(Fl), P), F, Adj, F, Pad). + term(float_e(Fl, float_data(Fl), P), F, Adj, F, Pad). -float_e(Fl, Fd, P) when Fl < 0.0 -> %Negative numbers - [$-|float_e(-Fl, Fd, P)]; -float_e(_Fl, {Ds,E}, P) -> - case float_man(Ds, 1, P-1) of - {[$0|Fs],true} -> [[$1|Fs]|float_exp(E)]; - {Fs,false} -> [Fs|float_exp(E-1)] - end. +float_e(Fl, Fd, P) when Fl < 0.0 -> %Negative numbers + [$- | float_e(-Fl, Fd, P)]; +float_e(_Fl, {Ds, E}, P) -> + case float_man(Ds, 1, P - 1) of + {[$0 | Fs], true} -> [[$1 | Fs] | float_exp(E)]; + {Fs, false} -> [Fs | float_exp(E - 1)] + end. %% float_man([Digit], Icount, Dcount) -> {[Char],CarryFlag}. %% Generate the characters in the mantissa from the digits with Icount @@ -463,67 +451,67 @@ float_e(_Fl, {Ds,E}, P) -> %% caller decide what to do at top. float_man(Ds, 0, Dc) -> - {Cs,C} = float_man(Ds, Dc), - {[$.|Cs],C}; -float_man([D|Ds], I, Dc) -> - case float_man(Ds, I-1, Dc) of - {Cs,true} when D =:= $9 -> {[$0|Cs],true}; - {Cs,true} -> {[D+1|Cs],false}; - {Cs,false} -> {[D|Cs],false} - end; -float_man([], I, Dc) -> %Pad with 0's - {lists:duplicate(I, $0) ++ [$.|lists:duplicate(Dc, $0)],false}. - -float_man([D|_], 0) when D >= $5 -> {[],true}; -float_man([_|_], 0) -> {[],false}; -float_man([D|Ds], Dc) -> - case float_man(Ds, Dc-1) of - {Cs,true} when D =:= $9 -> {[$0|Cs],true}; - {Cs,true} -> {[D+1|Cs],false}; - {Cs,false} -> {[D|Cs],false} - end; -float_man([], Dc) -> {lists:duplicate(Dc, $0),false}. %Pad with 0's + {Cs, C} = float_man(Ds, Dc), + {[$. | Cs], C}; +float_man([D | Ds], I, Dc) -> + case float_man(Ds, I - 1, Dc) of + {Cs, true} when D =:= $9 -> {[$0 | Cs], true}; + {Cs, true} -> {[D + 1 | Cs], false}; + {Cs, false} -> {[D | Cs], false} + end; +float_man([], I, Dc) -> %Pad with 0's + {lists:duplicate(I, $0) ++ [$. | lists:duplicate(Dc, $0)], false}. + +float_man([D | _], 0) when D >= $5 -> {[], true}; +float_man([_ | _], 0) -> {[], false}; +float_man([D | Ds], Dc) -> + case float_man(Ds, Dc - 1) of + {Cs, true} when D =:= $9 -> {[$0 | Cs], true}; + {Cs, true} -> {[D + 1 | Cs], false}; + {Cs, false} -> {[D | Cs], false} + end; +float_man([], Dc) -> {lists:duplicate(Dc, $0), false}. %Pad with 0's %% float_exp(Exponent) -> [Char]. %% Generate the exponent of a floating point number. Always include sign. float_exp(E) when E >= 0 -> - [$e,$+|integer_to_list(E)]; + [$e, $+ | integer_to_list(E)]; float_exp(E) -> - [$e|integer_to_list(E)]. + [$e | integer_to_list(E)]. %% fwrite_f(FloatData, Field, Adjust, Precision, PadChar) -fwrite_f(Fl, none, Adj, none, Pad) -> %Default values - fwrite_f(Fl, none, Adj, 6, Pad); +fwrite_f(Fl, none, Adj, none, Pad) -> %Default values + fwrite_f(Fl, none, Adj, 6, Pad); fwrite_f(Fl, none, _Adj, P, _Pad) when P >= 1 -> - float_f(Fl, float_data(Fl), P); + float_f(Fl, float_data(Fl), P); fwrite_f(Fl, F, Adj, none, Pad) -> - fwrite_f(Fl, F, Adj, 6, Pad); + fwrite_f(Fl, F, Adj, 6, Pad); fwrite_f(Fl, F, Adj, P, Pad) when P >= 1 -> - term(float_f(Fl, float_data(Fl), P), F, Adj, F, Pad). + term(float_f(Fl, float_data(Fl), P), F, Adj, F, Pad). float_f(Fl, Fd, P) when Fl < 0.0 -> - [$-|float_f(-Fl, Fd, P)]; -float_f(Fl, {Ds,E}, P) when E =< 0 -> - float_f(Fl, {lists:duplicate(-E+1, $0)++Ds,1}, P); %Prepend enough 0's -float_f(_Fl, {Ds,E}, P) -> - case float_man(Ds, E, P) of - {Fs,true} -> "1" ++ Fs; %Handle carry - {Fs,false} -> Fs - end. + [$- | float_f(-Fl, Fd, P)]; +float_f(Fl, {Ds, E}, P) when E =< 0 -> + float_f(Fl, {lists:duplicate(-E + 1, $0) ++ Ds, 1}, P); %Prepend enough 0's +float_f(_Fl, {Ds, E}, P) -> + case float_man(Ds, E, P) of + {Fs, true} -> "1" ++ Fs; %Handle carry + {Fs, false} -> Fs + end. %% float_data([FloatChar]) -> {[Digit],Exponent} float_data(Fl) -> - float_data(float_to_list(Fl), []). + float_data(float_to_list(Fl), []). -float_data([$e|E], Ds) -> - {lists:reverse(Ds),list_to_integer(E)+1}; -float_data([D|Cs], Ds) when D >= $0, D =< $9 -> - float_data(Cs, [D|Ds]); -float_data([_|Cs], Ds) -> - float_data(Cs, Ds). +float_data([$e | E], Ds) -> + {lists:reverse(Ds), list_to_integer(E) + 1}; +float_data([D | Cs], Ds) when D >= $0, D =< $9 -> + float_data(Cs, [D | Ds]); +float_data([_ | Cs], Ds) -> + float_data(Cs, Ds). %% Writes the shortest, correctly rounded string that converts %% to Float when read back with list_to_float/1. @@ -535,161 +523,161 @@ float_data([_|Cs], Ds) -> -spec fwrite_g(float()) -> string(). fwrite_g(0.0) -> - "0.0"; + "0.0"; fwrite_g(Float) when is_float(Float) -> - {Frac, Exp} = mantissa_exponent(Float), - {Place, Digits} = fwrite_g_1(Float, Exp, Frac), - R = insert_decimal(Place, [$0 + D || D <- Digits]), - [$- || true <- [Float < 0.0]] ++ R. + {Frac, Exp} = mantissa_exponent(Float), + {Place, Digits} = fwrite_g_1(Float, Exp, Frac), + R = insert_decimal(Place, [$0 + D || D <- Digits]), + [$- || true <- [Float < 0.0]] ++ R. -define(BIG_POW, (1 bsl 52)). -define(MIN_EXP, (-1074)). mantissa_exponent(F) -> - case <> of - <<_S:1, 0:11, M:52>> -> % denormalized - E = log2floor(M), - {M bsl (53 - E), E - 52 - 1075}; - <<_S:1, BE:11, M:52>> when BE < 2047 -> - {M + ?BIG_POW, BE - 1075} - end. + case <> of + <<_S:1, 0:11, M:52>> -> % denormalized + E = log2floor(M), + {M bsl (53 - E), E - 52 - 1075}; + <<_S:1, BE:11, M:52>> when BE < 2047 -> + {M + ?BIG_POW, BE - 1075} + end. fwrite_g_1(Float, Exp, Frac) -> - Round = (Frac band 1) =:= 0, - if - Exp >= 0 -> - BExp = 1 bsl Exp, - if - Frac =:= ?BIG_POW -> - scale(Frac * BExp * 4, 4, BExp * 2, BExp, - Round, Round, Float); - true -> - scale(Frac * BExp * 2, 2, BExp, BExp, - Round, Round, Float) - end; - Exp < ?MIN_EXP -> - BExp = 1 bsl (?MIN_EXP - Exp), - scale(Frac * 2, 1 bsl (1 - Exp), BExp, BExp, - Round, Round, Float); - Exp > ?MIN_EXP, Frac =:= ?BIG_POW -> - scale(Frac * 4, 1 bsl (2 - Exp), 2, 1, + Round = (Frac band 1) =:= 0, + if + Exp >= 0 -> + BExp = 1 bsl Exp, + if + Frac =:= ?BIG_POW -> + scale(Frac * BExp * 4, 4, BExp * 2, BExp, Round, Round, Float); - true -> - scale(Frac * 2, 1 bsl (1 - Exp), 1, 1, + true -> + scale(Frac * BExp * 2, 2, BExp, BExp, Round, Round, Float) - end. + end; + Exp < ?MIN_EXP -> + BExp = 1 bsl (?MIN_EXP - Exp), + scale(Frac * 2, 1 bsl (1 - Exp), BExp, BExp, + Round, Round, Float); + Exp > ?MIN_EXP, Frac =:= ?BIG_POW -> + scale(Frac * 4, 1 bsl (2 - Exp), 2, 1, + Round, Round, Float); + true -> + scale(Frac * 2, 1 bsl (1 - Exp), 1, 1, + Round, Round, Float) + end. scale(R, S, MPlus, MMinus, LowOk, HighOk, Float) -> - Est = int_ceil(math:log10(abs(Float)) - 1.0e-10), - %% Note that the scheme implementation uses a 326 element look-up - %% table for int_pow(10, N) where we do not. - if - Est >= 0 -> - fixup(R, S * int_pow(10, Est), MPlus, MMinus, Est, - LowOk, HighOk); - true -> - Scale = int_pow(10, -Est), - fixup(R * Scale, S, MPlus * Scale, MMinus * Scale, Est, - LowOk, HighOk) - end. + Est = int_ceil(math:log10(abs(Float)) - 1.0e-10), + %% Note that the scheme implementation uses a 326 element look-up + %% table for int_pow(10, N) where we do not. + if + Est >= 0 -> + fixup(R, S * int_pow(10, Est), MPlus, MMinus, Est, + LowOk, HighOk); + true -> + Scale = int_pow(10, -Est), + fixup(R * Scale, S, MPlus * Scale, MMinus * Scale, Est, + LowOk, HighOk) + end. fixup(R, S, MPlus, MMinus, K, LowOk, HighOk) -> - TooLow = if - HighOk -> R + MPlus >= S; - true -> R + MPlus > S - end, - case TooLow of - true -> - {K + 1, generate(R, S, MPlus, MMinus, LowOk, HighOk)}; - false -> - {K, generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)} - end. + TooLow = if + HighOk -> R + MPlus >= S; + true -> R + MPlus > S + end, + case TooLow of + true -> + {K + 1, generate(R, S, MPlus, MMinus, LowOk, HighOk)}; + false -> + {K, generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)} + end. generate(R0, S, MPlus, MMinus, LowOk, HighOk) -> - D = R0 div S, - R = R0 rem S, - TC1 = if - LowOk -> R =< MMinus; - true -> R < MMinus - end, - TC2 = if - HighOk -> R + MPlus >= S; - true -> R + MPlus > S - end, - case {TC1, TC2} of - {false, false} -> - [D | generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)]; - {false, true} -> - [D + 1]; - {true, false} -> - [D]; - {true, true} when R * 2 < S -> - [D]; - {true, true} -> - [D + 1] - end. + D = R0 div S, + R = R0 rem S, + TC1 = if + LowOk -> R =< MMinus; + true -> R < MMinus + end, + TC2 = if + HighOk -> R + MPlus >= S; + true -> R + MPlus > S + end, + case {TC1, TC2} of + {false, false} -> + [D | generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)]; + {false, true} -> + [D + 1]; + {true, false} -> + [D]; + {true, true} when R * 2 < S -> + [D]; + {true, true} -> + [D + 1] + end. insert_decimal(0, S) -> - "0." ++ S; + "0." ++ S; insert_decimal(Place, S) -> - L = length(S), - if - Place < 0; - Place >= L -> - ExpL = integer_to_list(Place - 1), - ExpDot = if L =:= 1 -> 2; true -> 1 end, - ExpCost = length(ExpL) + 1 + ExpDot, - if - Place < 0 -> - if - 2 - Place =< ExpCost -> - "0." ++ lists:duplicate(-Place, $0) ++ S; - true -> - insert_exp(ExpL, S) - end; - true -> - if - Place - L + 2 =< ExpCost -> - S ++ lists:duplicate(Place - L, $0) ++ ".0"; - true -> - insert_exp(ExpL, S) - end - end; - true -> - {S0, S1} = lists:split(Place, S), - S0 ++ "." ++ S1 - end. + L = length(S), + if + Place < 0; + Place >= L -> + ExpL = integer_to_list(Place - 1), + ExpDot = if L =:= 1 -> 2; true -> 1 end, + ExpCost = length(ExpL) + 1 + ExpDot, + if + Place < 0 -> + if + 2 - Place =< ExpCost -> + "0." ++ lists:duplicate(-Place, $0) ++ S; + true -> + insert_exp(ExpL, S) + end; + true -> + if + Place - L + 2 =< ExpCost -> + S ++ lists:duplicate(Place - L, $0) ++ ".0"; + true -> + insert_exp(ExpL, S) + end + end; + true -> + {S0, S1} = lists:split(Place, S), + S0 ++ "." ++ S1 + end. insert_exp(ExpL, [C]) -> - [C] ++ ".0e" ++ ExpL; + [C] ++ ".0e" ++ ExpL; insert_exp(ExpL, [C | S]) -> - [C] ++ "." ++ S ++ "e" ++ ExpL. + [C] ++ "." ++ S ++ "e" ++ ExpL. int_ceil(X) when is_float(X) -> - T = trunc(X), - case (X - T) of - Neg when Neg < 0 -> T; - Pos when Pos > 0 -> T + 1; - _ -> T - end. + T = trunc(X), + case (X - T) of + Neg when Neg < 0 -> T; + Pos when Pos > 0 -> T + 1; + _ -> T + end. int_pow(X, 0) when is_integer(X) -> - 1; + 1; int_pow(X, N) when is_integer(X), is_integer(N), N > 0 -> - int_pow(X, N, 1). + int_pow(X, N, 1). int_pow(X, N, R) when N < 2 -> - R * X; + R * X; int_pow(X, N, R) -> - int_pow(X * X, N bsr 1, case N band 1 of 1 -> R * X; 0 -> R end). + int_pow(X * X, N bsr 1, case N band 1 of 1 -> R * X; 0 -> R end). log2floor(Int) when is_integer(Int), Int > 0 -> - log2floor(Int, 0). + log2floor(Int, 0). log2floor(0, N) -> - N; + N; log2floor(Int, N) -> - log2floor(Int bsr 1, 1 + N). + log2floor(Int bsr 1, 1 + N). %% fwrite_g(Float, Field, Adjust, Precision, PadChar) %% Use the f form if Float is >= 0.1 and < 1.0e4, @@ -697,161 +685,161 @@ log2floor(Int, N) -> %% Precision always means the # of significant digits. fwrite_g(Fl, F, Adj, none, Pad) -> - fwrite_g(Fl, F, Adj, 6, Pad); + fwrite_g(Fl, F, Adj, 6, Pad); fwrite_g(Fl, F, Adj, P, Pad) when P >= 1 -> - A = abs(Fl), - E = if A < 1.0e-1 -> -2; - A < 1.0e0 -> -1; - A < 1.0e1 -> 0; - A < 1.0e2 -> 1; - A < 1.0e3 -> 2; - A < 1.0e4 -> 3; - true -> fwrite_f - end, - if P =< 1, E =:= -1; - P-1 > E, E >= -1 -> - fwrite_f(Fl, F, Adj, P-1-E, Pad); - P =< 1 -> - fwrite_e(Fl, F, Adj, 2, Pad); - true -> - fwrite_e(Fl, F, Adj, P, Pad) - end. + A = abs(Fl), + E = if A < 1.0e-1 -> -2; + A < 1.0e0 -> -1; + A < 1.0e1 -> 0; + A < 1.0e2 -> 1; + A < 1.0e3 -> 2; + A < 1.0e4 -> 3; + true -> fwrite_f + end, + if P =< 1, E =:= -1; + P - 1 > E, E >= -1 -> + fwrite_f(Fl, F, Adj, P - 1 - E, Pad); + P =< 1 -> + fwrite_e(Fl, F, Adj, 2, Pad); + true -> + fwrite_e(Fl, F, Adj, P, Pad) + end. iolist_to_chars(Cs, F, CharsLimit) when CharsLimit < 0; CharsLimit >= F -> - iolist_to_chars(Cs); + iolist_to_chars(Cs); iolist_to_chars(Cs, _, CharsLimit) -> - limit_iolist_to_chars(Cs, sub(CharsLimit, 3), [], normal). % three dots + limit_iolist_to_chars(Cs, sub(CharsLimit, 3), [], normal). % three dots -iolist_to_chars([C|Cs]) when is_integer(C), C >= $\000, C =< $\377 -> - [C | iolist_to_chars(Cs)]; -iolist_to_chars([I|Cs]) -> - [iolist_to_chars(I) | iolist_to_chars(Cs)]; +iolist_to_chars([C | Cs]) when is_integer(C), C >= $\000, C =< $\377 -> + [C | iolist_to_chars(Cs)]; +iolist_to_chars([I | Cs]) -> + [iolist_to_chars(I) | iolist_to_chars(Cs)]; iolist_to_chars([]) -> - []; + []; iolist_to_chars(B) when is_binary(B) -> - binary_to_list(B). + binary_to_list(B). limit_iolist_to_chars(Cs, 0, S, normal) -> - L = limit_iolist_to_chars(Cs, 4, S, final), - case iolist_size(L) of - N when N < 4 -> L; - 4 -> "..." - end; + L = limit_iolist_to_chars(Cs, 4, S, final), + case iolist_size(L) of + N when N < 4 -> L; + 4 -> "..." + end; limit_iolist_to_chars(_Cs, 0, _S, final) -> []; -limit_iolist_to_chars([C|Cs], Limit, S, Mode) when C >= $\000, C =< $\377 -> - [C | limit_iolist_to_chars(Cs, Limit - 1, S, Mode)]; -limit_iolist_to_chars([I|Cs], Limit, S, Mode) -> - limit_iolist_to_chars(I, Limit, [Cs|S], Mode); +limit_iolist_to_chars([C | Cs], Limit, S, Mode) when C >= $\000, C =< $\377 -> + [C | limit_iolist_to_chars(Cs, Limit - 1, S, Mode)]; +limit_iolist_to_chars([I | Cs], Limit, S, Mode) -> + limit_iolist_to_chars(I, Limit, [Cs | S], Mode); limit_iolist_to_chars([], _Limit, [], _Mode) -> - []; -limit_iolist_to_chars([], Limit, [Cs|S], Mode) -> - limit_iolist_to_chars(Cs, Limit, S, Mode); + []; +limit_iolist_to_chars([], Limit, [Cs | S], Mode) -> + limit_iolist_to_chars(Cs, Limit, S, Mode); limit_iolist_to_chars(B, Limit, S, Mode) when is_binary(B) -> - case byte_size(B) of - Sz when Sz > Limit -> - {B1, B2} = split_binary(B, Limit), - [binary_to_list(B1) | limit_iolist_to_chars(B2, 0, S, Mode)]; - Sz -> - [binary_to_list(B) | limit_iolist_to_chars([], Limit-Sz, S, Mode)] - end. + case byte_size(B) of + Sz when Sz > Limit -> + {B1, B2} = split_binary(B, Limit), + [binary_to_list(B1) | limit_iolist_to_chars(B2, 0, S, Mode)]; + Sz -> + [binary_to_list(B) | limit_iolist_to_chars([], Limit - Sz, S, Mode)] + end. cdata_to_chars(Cs, F, CharsLimit) when CharsLimit < 0; CharsLimit >= F -> - cdata_to_chars(Cs); + cdata_to_chars(Cs); cdata_to_chars(Cs, _, CharsLimit) -> - limit_cdata_to_chars(Cs, sub(CharsLimit, 3), normal). % three dots + limit_cdata_to_chars(Cs, sub(CharsLimit, 3), normal). % three dots -cdata_to_chars([C|Cs]) when is_integer(C), C >= $\000 -> - [C | cdata_to_chars(Cs)]; -cdata_to_chars([I|Cs]) -> - [cdata_to_chars(I) | cdata_to_chars(Cs)]; +cdata_to_chars([C | Cs]) when is_integer(C), C >= $\000 -> + [C | cdata_to_chars(Cs)]; +cdata_to_chars([I | Cs]) -> + [cdata_to_chars(I) | cdata_to_chars(Cs)]; cdata_to_chars([]) -> - []; + []; cdata_to_chars(B) when is_binary(B) -> - case catch unicode:characters_to_list(B) of - L when is_list(L) -> L; - _ -> binary_to_list(B) - end. + case catch unicode:characters_to_list(B) of + L when is_list(L) -> L; + _ -> binary_to_list(B) + end. limit_cdata_to_chars(Cs, 0, normal) -> - L = limit_cdata_to_chars(Cs, 4, final), - case string:length(L) of - N when N < 4 -> L; - 4 -> "..." - end; + L = limit_cdata_to_chars(Cs, 4, final), + case string:length(L) of + N when N < 4 -> L; + 4 -> "..." + end; limit_cdata_to_chars(_Cs, 0, final) -> []; limit_cdata_to_chars(Cs, Limit, Mode) -> - case string:next_grapheme(Cs) of - {error, <>} -> - %% This is how ~ts handles Latin1 binaries with option - %% chars_limit. - [C | limit_cdata_to_chars(Cs1, Limit - 1, Mode)]; - {error, [C|Cs1]} -> % not all versions of module string return this - [C | limit_cdata_to_chars(Cs1, Limit - 1, Mode)]; - [] -> - []; - [GC|Cs1] -> - [GC | limit_cdata_to_chars(Cs1, Limit - 1, Mode)] - end. + case string:next_grapheme(Cs) of + {error, <>} -> + %% This is how ~ts handles Latin1 binaries with option + %% chars_limit. + [C | limit_cdata_to_chars(Cs1, Limit - 1, Mode)]; + {error, [C | Cs1]} -> % not all versions of module string return this + [C | limit_cdata_to_chars(Cs1, Limit - 1, Mode)]; + [] -> + []; + [GC | Cs1] -> + [GC | limit_cdata_to_chars(Cs1, Limit - 1, Mode)] + end. limit_field(F, CharsLimit) when CharsLimit < 0; F =:= none -> - F; + F; limit_field(F, CharsLimit) -> - max(3, min(F, CharsLimit)). + max(3, min(F, CharsLimit)). %% string(String, Field, Adjust, Precision, PadChar) string(S, none, _Adj, none, _Pad, _Enc) -> S; string(S, F, Adj, none, Pad, Enc) -> - string_field(S, F, Adj, io_lib:chars_length(S), Pad, Enc); + string_field(S, F, Adj, io_lib:chars_length(S), Pad, Enc); string(S, none, _Adj, P, Pad, Enc) -> - string_field(S, P, left, io_lib:chars_length(S), Pad, Enc); + string_field(S, P, left, io_lib:chars_length(S), Pad, Enc); string(S, F, Adj, P, Pad, Enc) when F >= P -> - N = io_lib:chars_length(S), - if F > P -> - if N > P -> - adjust(flat_trunc(S, P, Enc), chars(Pad, F-P), Adj); - N < P -> - adjust([S|chars(Pad, P-N)], chars(Pad, F-P), Adj); - true -> % N == P - adjust(S, chars(Pad, F-P), Adj) - end; - true -> % F == P - string_field(S, F, Adj, N, Pad, Enc) - end. + N = io_lib:chars_length(S), + if F > P -> + if N > P -> + adjust(flat_trunc(S, P, Enc), chars(Pad, F - P), Adj); + N < P -> + adjust([S | chars(Pad, P - N)], chars(Pad, F - P), Adj); + true -> % N == P + adjust(S, chars(Pad, F - P), Adj) + end; + true -> % F == P + string_field(S, F, Adj, N, Pad, Enc) + end. string_field(S, F, _Adj, N, _Pad, Enc) when N > F -> - flat_trunc(S, F, Enc); + flat_trunc(S, F, Enc); string_field(S, F, Adj, N, Pad, _Enc) when N < F -> - adjust(S, chars(Pad, F-N), Adj); + adjust(S, chars(Pad, F - N), Adj); string_field(S, _, _, _, _, _) -> % N == F - S. + S. %% unprefixed_integer(Int, Field, Adjust, Base, PadChar, Lowercase) %% -> [Char]. unprefixed_integer(Int, F, Adj, Base, Pad, Lowercase) - when Base >= 2, Base =< 1+$Z-$A+10 -> - if Int < 0 -> - S = cond_lowercase(erlang:integer_to_list(-Int, Base), Lowercase), - term([$-|S], F, Adj, none, Pad); - true -> - S = cond_lowercase(erlang:integer_to_list(Int, Base), Lowercase), - term(S, F, Adj, none, Pad) - end. + when Base >= 2, Base =< 1 + $Z - $A + 10 -> + if Int < 0 -> + S = cond_lowercase(erlang:integer_to_list(-Int, Base), Lowercase), + term([$- | S], F, Adj, none, Pad); + true -> + S = cond_lowercase(erlang:integer_to_list(Int, Base), Lowercase), + term(S, F, Adj, none, Pad) + end. %% prefixed_integer(Int, Field, Adjust, Base, PadChar, Prefix, Lowercase) %% -> [Char]. prefixed_integer(Int, F, Adj, Base, Pad, Prefix, Lowercase) - when Base >= 2, Base =< 1+$Z-$A+10 -> - if Int < 0 -> - S = cond_lowercase(erlang:integer_to_list(-Int, Base), Lowercase), - term([$-,Prefix|S], F, Adj, none, Pad); - true -> - S = cond_lowercase(erlang:integer_to_list(Int, Base), Lowercase), - term([Prefix|S], F, Adj, none, Pad) - end. + when Base >= 2, Base =< 1 + $Z - $A + 10 -> + if Int < 0 -> + S = cond_lowercase(erlang:integer_to_list(-Int, Base), Lowercase), + term([$-, Prefix | S], F, Adj, none, Pad); + true -> + S = cond_lowercase(erlang:integer_to_list(Int, Base), Lowercase), + term([Prefix | S], F, Adj, none, Pad) + end. %% char(Char, Field, Adjust, Precision, PadChar) -> chars(). @@ -859,7 +847,7 @@ char(C, none, _Adj, none, _Pad) -> [C]; char(C, F, _Adj, none, _Pad) -> chars(C, F); char(C, none, _Adj, P, _Pad) -> chars(C, P); char(C, F, Adj, P, Pad) when F >= P -> - adjust(chars(C, P), chars(Pad, F - P), Adj). + adjust(chars(C, P), chars(Pad, F - P), Adj). %% newline(Field, Adjust, Precision, PadChar) -> [Char]. @@ -871,33 +859,33 @@ newline(F, right, _P, _Pad) -> chars($\n, F). %% adjust(Data, [], _) -> Data; -adjust(Data, Pad, left) -> [Data|Pad]; -adjust(Data, Pad, right) -> [Pad|Data]. +adjust(Data, Pad, left) -> [Data | Pad]; +adjust(Data, Pad, right) -> [Pad | Data]. %% Flatten and truncate a deep list to at most N elements. flat_trunc(List, N, latin1) when is_integer(N), N >= 0 -> - {S, _} = lists:split(N, lists:flatten(List)), - S; + {S, _} = lists:split(N, lists:flatten(List)), + S; flat_trunc(List, N, unicode) when is_integer(N), N >= 0 -> - string:slice(List, 0, N). + string:slice(List, 0, N). %% A deep version of lists:duplicate/2 chars(_C, 0) -> - []; + []; chars(C, 1) -> - [C]; + [C]; chars(C, 2) -> - [C,C]; + [C, C]; chars(C, 3) -> - [C,C,C]; + [C, C, C]; chars(C, N) when is_integer(N), (N band 1) =:= 0 -> - S = chars(C, N bsr 1), - [S|S]; + S = chars(C, N bsr 1), + [S | S]; chars(C, N) when is_integer(N) -> - S = chars(C, N bsr 1), - [C,S|S]. + S = chars(C, N bsr 1), + [C, S | S]. %chars(C, N, Tail) -> % [chars(C, N)|Tail]. @@ -905,16 +893,16 @@ chars(C, N) when is_integer(N) -> %% Lowercase conversion cond_lowercase(String, true) -> - lowercase(String); -cond_lowercase(String,false) -> - String. - -lowercase([H|T]) when is_integer(H), H >= $A, H =< $Z -> - [(H-$A+$a)|lowercase(T)]; -lowercase([H|T]) -> - [H|lowercase(T)]; + lowercase(String); +cond_lowercase(String, false) -> + String. + +lowercase([H | T]) when is_integer(H), H >= $A, H =< $Z -> + [(H - $A + $a) | lowercase(T)]; +lowercase([H | T]) -> + [H | lowercase(T)]; lowercase([]) -> - []. + []. %% Make sure T does change sign. sub(T, _) when T < 0 -> T; @@ -922,8 +910,8 @@ sub(T, E) when T >= E -> T - E; sub(_, _) -> 0. get_option(Key, TupleList, Default) -> - case lists:keyfind(Key, 1, TupleList) of - false -> Default; - {Key, Value} -> Value; - _ -> Default - end. + case lists:keyfind(Key, 1, TupleList) of + false -> Default; + {Key, Value} -> Value; + _ -> Default + end.