|
|
@ -36,40 +36,19 @@ fwrite(Format, Args) -> |
|
|
|
fwrite(Format, Args, Options) -> |
|
|
|
build(scan(Format, Args), Options). |
|
|
|
|
|
|
|
%% Build the output text for a pre-parsed format list. |
|
|
|
|
|
|
|
-spec build(FormatList :: [char() | eFmt:format_spec()]) -> eFmt:chars(). |
|
|
|
build(Cs) -> |
|
|
|
build(Cs, []). |
|
|
|
|
|
|
|
-spec build(FormatList :: [char() | eFmt:format_spec()], Options :: [{'chars_limit', CharsLimit :: integer()}]) -> eFmt:chars(). |
|
|
|
build(Cs, Options) -> |
|
|
|
CharsLimit = getOpt(chars_limit, Options, -1), |
|
|
|
Res1 = build_small(Cs), |
|
|
|
{P, S, W, Other} = count_small(Res1, 0, 0, 0, 0), |
|
|
|
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 :: io:format(), Data :: [term()]) -> FormatList :: [char() | eFmt:fmtSpec()]. |
|
|
|
|
|
|
|
-spec scan(Format, Data) -> FormatList when |
|
|
|
Format :: io:format(), |
|
|
|
Data :: [term()], |
|
|
|
FormatList :: [char() | eFmt:format_spec()]. |
|
|
|
|
|
|
|
%% 格式 ~F.P.PadModC |
|
|
|
scan(Format, Args) -> |
|
|
|
if |
|
|
|
is_atom(Format) -> |
|
|
|
collect(atom_to_binary(Format, utf8), Args); |
|
|
|
doCollect(atom_to_binary(Format, utf8), Args, []); |
|
|
|
is_list(Format) -> |
|
|
|
collect(list_to_binary(Format), Args); |
|
|
|
doCollect(list_to_binary(Format), Args, []); |
|
|
|
true -> |
|
|
|
collect(Format, Args) |
|
|
|
doCollect(Format, Args, []) |
|
|
|
end. |
|
|
|
|
|
|
|
doCollect(FmtBinStr, Args, Acc) -> |
|
|
@ -77,109 +56,201 @@ doCollect(FmtBinStr, Args, Acc) -> |
|
|
|
[NotMatch] -> |
|
|
|
[NotMatch | Acc]; |
|
|
|
[FPart, LPart] -> |
|
|
|
doCollectList(LPart, Args,
[FPart | Acc]). |
|
|
|
end, |
|
|
|
doCollWidth(LPart, Args, 0, left, [FPart | Acc]) |
|
|
|
end. |
|
|
|
|
|
|
|
%% 格式 ~F.P.PadModC |
|
|
|
doCollectList(<<>>, _Args, Acc) -> |
|
|
|
doCollWidth(<<>>, _Args, _Width, _Adjust, Acc) -> |
|
|
|
Acc; |
|
|
|
doCollectList(LPart, Args, Acc) -> |
|
|
|
doCollWidth(LPart, Args, Width, Adjust, Acc) -> |
|
|
|
%% 匹配宽度 |
|
|
|
case LPart of |
|
|
|
<<"-", FBin/binary>> -> |
|
|
|
<<"-*", LeftLPart/binary>> -> |
|
|
|
[WidthArgs | LeftArgs] = Args, |
|
|
|
doCollPrecision(LeftLPart, LeftArgs, WidthArgs, left, Acc); |
|
|
|
<<"-", LeftLPart/binary>> -> |
|
|
|
doCollWidth(LeftLPart, Args, Width, left, Acc); |
|
|
|
<<"*", LeftLPart/binary>> -> |
|
|
|
[WidthArgs | LeftArgs] = Args, |
|
|
|
doCollPrecision(LeftLPart, LeftArgs, WidthArgs, right, Acc); |
|
|
|
<<WidthInt:8/integer, LeftLPart/binary>> -> |
|
|
|
case WidthInt >= $0 andalso WidthInt =< $9 of |
|
|
|
true -> |
|
|
|
doCollWidth(LeftLPart, Args, 10 * Width + (WidthInt - $0), Adjust, Acc); |
|
|
|
_ -> |
|
|
|
doCollPrecision(LeftLPart, Args, Width, Adjust, Acc) |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
doCollPrecision(LPart, Args, Width, Adjust, Acc) -> |
|
|
|
case LPart of |
|
|
|
<<".", LeftLPart/binary>> -> |
|
|
|
doCollPrecision(LeftLPart, Args, Width, Adjust, 0, Acc); |
|
|
|
_ -> |
|
|
|
doCollPadChar(LPart, Args, Width, Adjust, none, Acc) |
|
|
|
end. |
|
|
|
|
|
|
|
doCollPrecision(LPart, Args, Width, Adjust, Precision, Acc) -> |
|
|
|
case LPart of |
|
|
|
<<"*", LeftLPart/binary>> -> |
|
|
|
[PrecisionArgs | LeftArgs] = Args, |
|
|
|
doCollPadChar(LeftLPart, LeftArgs, Width, Adjust, PrecisionArgs, Acc); |
|
|
|
<<PrecisionInt:8/integer, LeftLPart/binary>> -> |
|
|
|
case PrecisionInt >= $0 andalso PrecisionInt =< $9 of |
|
|
|
true -> |
|
|
|
doCollPrecision(LeftLPart, Args, Width, Adjust, 10 * Precision + (PrecisionInt - $0)); |
|
|
|
_ -> |
|
|
|
case Precision == 0 of |
|
|
|
true -> |
|
|
|
doCollPadChar(LPart, Args, Width, Adjust, none, Acc); |
|
|
|
_ -> |
|
|
|
doCollPadChar(LPart, Args, Width, Adjust, Precision, Acc) |
|
|
|
end |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
doCollPadChar(LPart, Args, Width, Adjust, Precision, Acc) -> |
|
|
|
case LPart of |
|
|
|
<<".*", LeftLPart/binary>> -> |
|
|
|
[PadChar | LeftArgs] = Args, |
|
|
|
doCollEncoding(LeftLPart, LeftArgs, Width, Adjust, Precision, PadChar, Acc); |
|
|
|
<<".", PadChar:8/integer, LeftLPart/binary>> -> |
|
|
|
doCollEncoding(LeftLPart, Args, Width, Adjust, Precision, PadChar, Acc); |
|
|
|
_ -> |
|
|
|
doCollEncoding(LPart, Args, Width, Adjust, Precision, 32, Acc) |
|
|
|
end. |
|
|
|
|
|
|
|
doCollEncoding(LPart, Args, Width, Adjust, Precision, PadChar, Acc) -> |
|
|
|
case LPart of |
|
|
|
<<"t", Char:8/integer, LeftLPart/binary>> -> |
|
|
|
true = Char =/= $l, |
|
|
|
doCollStrings(LeftLPart, Args, Width, Adjust, Precision, PadChar, unicode, Acc); |
|
|
|
_ -> |
|
|
|
doCollStrings(LPart, Args, Width, Adjust, Precision, PadChar, latin1, Acc) |
|
|
|
end. |
|
|
|
|
|
|
|
doCollStrings(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, Acc) -> |
|
|
|
case LPart of |
|
|
|
<<"l", Char:8/integer, LeftLPart/binary>> -> |
|
|
|
true = Char =/= $t, |
|
|
|
doCollCA(LeftLPart, Args, Width, Adjust, Precision, PadChar, Encoding, false, Acc); |
|
|
|
_ -> |
|
|
|
doCollCA(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, true, Acc) |
|
|
|
end. |
|
|
|
|
|
|
|
doCollCA(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, Strings, Acc) -> |
|
|
|
<<Char:8/integer, LeftLPart/binary>> = LPart, |
|
|
|
[OneArgs | LeftArgs] = Args, |
|
|
|
case Char of |
|
|
|
$w -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$p -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$W -> [Depth | LastArgs] = LeftArgs, As = [OneArgs, Depth], NextArgs = LastArgs; |
|
|
|
$P -> [Depth | LastArgs] = LeftArgs, As = [OneArgs, Depth], NextArgs = LastArgs; |
|
|
|
$s -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$e -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$f -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$g -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$b -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$B -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$x -> [Prefix | LastArgs] = LeftArgs, As = [OneArgs, Prefix], NextArgs = LastArgs; |
|
|
|
$X -> [Prefix | LastArgs] = LeftArgs, As = [OneArgs, Prefix], NextArgs = LastArgs; |
|
|
|
$+ -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$# -> As = [OneArgs, NextArgs = LeftArgs; |
|
|
|
$c -> As = OneArgs, NextArgs = LeftArgs; |
|
|
|
$~ -> As = undefined, NextArgs = LeftArgs; |
|
|
|
$n -> As = undefined, NextArgs = LeftArgs; |
|
|
|
$i -> As = OneArgs, NextArgs = LeftArgs |
|
|
|
end, |
|
|
|
FmtSpec = #fmtSpec{ctlChar = Char, args = As, width = Width, adjust = Adjust, precision = Precision, padChar = PadChar, encoding = Encoding, strings = Strings}, |
|
|
|
doCollect(LeftLPart, NextArgs, [FmtSpec | Acc]). |
|
|
|
|
|
|
|
|
|
|
|
%% Build the output text for a pre-parsed format list. |
|
|
|
-spec build(FormatList :: [char() | eFmt:fmtSpec()]) -> eFmt:chars(). |
|
|
|
build(Cs) -> |
|
|
|
build(Cs, []). |
|
|
|
|
|
|
|
-spec build(FormatList :: [char() | eFmt:fmtSpec()], Options :: [{'chars_limit', CharsLimit :: integer()}]) -> eFmt:chars(). |
|
|
|
build(Cs, Options) -> |
|
|
|
CharsLimit = getOpt(chars_limit, Options, -1), |
|
|
|
Res1 = buildSmall(Cs, []), |
|
|
|
{P, S, W, Other} = count_small(Res1, 0, 0, 0, 0), |
|
|
|
case P + S + W of |
|
|
|
0 -> |
|
|
|
Res1; |
|
|
|
NumOfLimited -> |
|
|
|
RemainingChars = sub(CharsLimit, Other), |
|
|
|
build_limited(Res1, P, NumOfLimited, RemainingChars, 0) |
|
|
|
end. |
|
|
|
|
|
|
|
%% build_small([Control]) -> eFmt:chars(). |
|
|
|
%% Interpret the control structures, but only the small ones. The big ones are saved for later. |
|
|
|
%% build_limited([Control], NumberOfPps, NumberOfLimited, CharsLimit, Indentation) |
|
|
|
%% Interpret the control structures. Count the number of print |
|
|
|
%% remaining and only calculate indentation when necessary. Must also |
|
|
|
%% be smart when calculating indentation for characters in format. |
|
|
|
|
|
|
|
buildSmall([], Acc) -> Acc; |
|
|
|
buildSmall([OneCA | Cs], Acc) -> |
|
|
|
case OneCA of |
|
|
|
#fmtSpec{ctlChar = C, args = Args, width = Width, adjust = Adjust, precision = Precision, padChar = PadChar, encoding = Encoding} -> |
|
|
|
case ctlSmall(C, Args, Width, Adjust, Precision, PadChar, Encoding) of |
|
|
|
not_small -> buildSmall(Cs, [OneCA | Acc]); |
|
|
|
S -> buildSmall(Cs, [S | Acc]) |
|
|
|
end; |
|
|
|
_ -> |
|
|
|
buildSmall(Cs, [OneCA | Acc]) |
|
|
|
end. |
|
|
|
|
|
|
|
ok. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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}); |
|
|
|
modifiers(Fmt, Spec) -> |
|
|
|
{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(F, Fmt, Args) when F < 0 -> |
|
|
|
{-F, left, Fmt, Args}; |
|
|
|
field_width(F, Fmt, Args) when F >= 0 -> |
|
|
|
{F, right, Fmt, Args}. |
|
|
|
|
|
|
|
precision([$. | Fmt], Args) -> |
|
|
|
field_value(Fmt, Args); |
|
|
|
precision(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, 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}. |
|
|
|
|
|
|
|
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}. |
|
|
|
|
|
|
|
%% control_small(FormatChar, [Argument], FieldWidth, Adjust, Precision, |
|
|
|
%% PadChar, Encoding) -> String |
|
|
|
%% control_limited(FormatChar, [Argument], FieldWidth, Adjust, Precision, |
|
|
|
%% PadChar, Encoding, StringP, ChrsLim, Indentation) -> String |
|
|
|
%% These are the dispatch functions for the various formatting controls. |
|
|
|
|
|
|
|
ctlSmall($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); |
|
|
|
ctlSmall($s, A, F, Adj, P, Pad, unicode = Enc) when is_atom(A) -> |
|
|
|
string(atom_to_list(A), F, Adj, P, Pad, Enc); |
|
|
|
ctlSmall($e, A, F, Adj, P, Pad, _Enc) when is_float(A) -> |
|
|
|
fwrite_e(A, F, Adj, P, Pad); |
|
|
|
ctlSmall($f, A, F, Adj, P, Pad, _Enc) when is_float(A) -> |
|
|
|
fwrite_f(A, F, Adj, P, Pad); |
|
|
|
ctlSmall($g, A, F, Adj, P, Pad, _Enc) when is_float(A) -> |
|
|
|
fwrite_g(A, F, Adj, P, Pad); |
|
|
|
ctlSmall($b, A, F, Adj, P, Pad, _Enc) when is_integer(A) -> |
|
|
|
unprefixed_integer(A, F, Adj, base(P), Pad, true); |
|
|
|
ctlSmall($B, A, F, Adj, P, Pad, _Enc) when is_integer(A) -> |
|
|
|
unprefixed_integer(A, F, Adj, base(P), Pad, false); |
|
|
|
ctlSmall($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); |
|
|
|
ctlSmall($x, [A, Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) -> |
|
|
|
true = eFmt:deep_char_list(Prefix), %Check if Prefix a character list |
|
|
|
prefixed_integer(A, F, Adj, base(P), Pad, Prefix, true); |
|
|
|
ctlSmall($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); |
|
|
|
ctlSmall($X, [A, Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) -> |
|
|
|
true = eFmt:deep_char_list(Prefix), %Check if Prefix a character list |
|
|
|
prefixed_integer(A, F, Adj, base(P), Pad, Prefix, false); |
|
|
|
ctlSmall($+, 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); |
|
|
|
ctlSmall($#, 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); |
|
|
|
ctlSmall($c, A, F, Adj, P, Pad, unicode) when is_integer(A) -> |
|
|
|
char(A, F, Adj, P, Pad); |
|
|
|
ctlSmall($c, A, F, Adj, P, Pad, _Enc) when is_integer(A) -> |
|
|
|
char(A band 255, F, Adj, P, Pad); |
|
|
|
ctlSmall($~, _A, F, Adj, P, Pad, _Enc) -> char($~, F, Adj, P, Pad); |
|
|
|
ctlSmall($n, _A, F, Adj, P, Pad, _Enc) -> newline(F, Adj, P, Pad); |
|
|
|
ctlSmall($i, _A, _F, _Adj, _P, _Pad, _Enc) -> []; |
|
|
|
ctlSmall(_C, _A, _F, _Adj, _P, _Pad, _Enc) -> not_small. |
|
|
|
|
|
|
|
%% count_small([ControlC])->计数。计算大(pPwWsS)打印请求的数量和其他打印(小)请求的字符数。 |
|
|
|
count_small([#{control_char := $p} | Cs], P, S, W, Other) -> |
|
|
@ -199,20 +270,8 @@ count_small([C | Cs], P, S, W, Other) when is_integer(C) -> |
|
|
|
count_small([], P, S, W, Other) -> |
|
|
|
{P, S, W, Other}. |
|
|
|
|
|
|
|
%% build_small([Control]) -> eFmt:chars(). |
|
|
|
%% Interpret the control structures, but only the small ones. The big ones are saved for later. |
|
|
|
%% build_limited([Control], NumberOfPps, NumberOfLimited, CharsLimit, Indentation) |
|
|
|
%% Interpret the control structures. Count the number of print |
|
|
|
%% remaining and only calculate indentation when necessary. Must also |
|
|
|
%% 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)]; |
|
|
|
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 |
|
|
@ -261,55 +320,7 @@ indentation([C | Cs], I) -> |
|
|
|
indentation(Cs, indentation(C, I)); |
|
|
|
indentation([], I) -> I. |
|
|
|
|
|
|
|
%% control_small(FormatChar, [Argument], FieldWidth, Adjust, Precision, |
|
|
|
%% PadChar, Encoding) -> String |
|
|
|
%% control_limited(FormatChar, [Argument], FieldWidth, Adjust, Precision, |
|
|
|
%% 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($e, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> |
|
|
|
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); |
|
|
|
control_small($g, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> |
|
|
|
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); |
|
|
|
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 = eFmt: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 = eFmt: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); |
|
|
|
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); |
|
|
|
control_small($c, [A], F, Adj, P, Pad, unicode) when is_integer(A) -> |
|
|
|
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); |
|
|
|
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), |
|
|
|