Parcourir la source

ft: 修改为二进制匹配

master
SisMaker il y a 4 ans
Parent
révision
42f1afa0f1
3 fichiers modifiés avec 161 ajouts et 162 suppressions
  1. +3
    -0
      include/eFmt.hrl
  2. +3
    -3
      src/eFmt.erl
  3. +155
    -159
      src/eFmtFormat.erl

+ 3
- 0
include/eFmt.hrl Voir le fichier

@ -1,3 +1,5 @@
-define(base(Precision), case Precision of none -> 10; _ -> Precision end).
-record(fmtSpec, {
ctlChar :: char() %% $p $w
, args :: [any()] %% 使
@ -8,3 +10,4 @@
, encoding :: 'unicode' | 'latin1' %% ttrue
, strings :: boolean() %% l string设置为false
}).

+ 3
- 3
src/eFmt.erl Voir le fichier

@ -65,7 +65,7 @@
, limit_term/2
, chars_length/1
, charsLen/1
]).
-export_type([
@ -1050,12 +1050,12 @@ test_limit_map_assoc(K, V, D) ->
test_limit_bitstring(_, _) -> ok.
-spec chars_length(chars()) -> non_neg_integer().
-spec charsLen(chars()) -> non_neg_integer().
%% Optimized for deep lists S such that deep_latin1_char_list(S) is
%% true. No binaries allowed! It is assumed that $\r is never followed
%% by $\n if S is an iolist() (string:length() assigns such a
%% sub-sequence length 1).
chars_length(S) ->
charsLen(S) ->
try
%% true = deep_latin1_char_list(S),
iolist_size(S)

+ 155
- 159
src/eFmtFormat.erl Voir le fichier

@ -2,6 +2,8 @@
-include("eFmt.hrl").
-compile(export_all).
%% Formatting functions of io library.
-export([
fwrite/2
@ -77,7 +79,12 @@ doCollWidth(LPart, Args, Width, Adjust, Acc) ->
true ->
doCollWidth(LeftLPart, Args, 10 * Width + (WidthInt - $0), Adjust, Acc);
_ ->
doCollPrecision(LeftLPart, Args, Width, Adjust, Acc)
case Width == 0 of
true ->
doCollPrecision(LPart, Args, none, Adjust, Acc);
_ ->
doCollPrecision(LPart, Args, Width, Adjust, Acc)
end
end
end.
@ -139,31 +146,29 @@ doCollStrings(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, Acc) ->
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
$w -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$p ->[OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$W ->[OneArgs | LeftArgs] = Args, [Depth | LastArgs] = LeftArgs, As = [OneArgs, Depth], NextArgs = LastArgs;
$P -> [OneArgs | LeftArgs] = Args,[Depth | LastArgs] = LeftArgs, As = [OneArgs, Depth], NextArgs = LastArgs;
$s ->[OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$e ->[OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$f ->[OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$g -> [OneArgs | LeftArgs] = Args,As = OneArgs, NextArgs = LeftArgs;
$b ->[OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$B ->[OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$x ->[OneArgs | LeftArgs] = Args, [Prefix | LastArgs] = LeftArgs, As = [OneArgs, Prefix], NextArgs = LastArgs;
$X -> [OneArgs | LeftArgs] = Args,[Prefix | LastArgs] = LeftArgs, As = [OneArgs, Prefix], NextArgs = LastArgs;
$+ -> [OneArgs | LeftArgs] = Args,As = OneArgs, NextArgs = LeftArgs;
$# ->[OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$c ->[OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$~ -> As = undefined, NextArgs = Args;
$n -> As = undefined, NextArgs = Args;
$i ->[OneArgs | LeftArgs] = Args, 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) ->
@ -195,7 +200,7 @@ buildSmall([OneCA | Cs], Acc) ->
#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])
Str -> buildSmall(Cs, [Str | Acc])
end;
_ ->
buildSmall(Cs, [OneCA | Acc])
@ -208,49 +213,50 @@ buildSmall([OneCA | Cs], Acc) ->
%% 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) ->
ctlSmall($s, Args, Width, Adjust, Precision, PadChar, Encoding) when is_atom(Args) ->
case Encoding of
latin1 ->
AtomBinStr = atom_to_binary(Args, latin1);
_ ->
AtomBinStr = atom_to_binary(Args, uft8)
end,
string(AtomBinStr, Width, Adjust, Precision, PadChar, Encoding);
ctlSmall($e, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_float(Args) ->
fwriteE(Args, Width, Adjust, Precision, PadChar);
ctlSmall($f, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_float(Args) ->
fwrite_f(Args, Width, Adjust, Precision, PadChar);
ctlSmall($g, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_float(Args) ->
fwrite_g(Args, Width, Adjust, Precision, PadChar);
ctlSmall($b, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
unprefixed_integer(Args, Width, Adjust, ?base(Precision), PadChar, true);
ctlSmall($B, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
unprefixed_integer(Args, Width, Adjust, ?base(Precision), PadChar, false);
ctlSmall($x, [Args, Prefix], Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args), is_atom(Prefix) ->
prefixed_integer(Args, Width, Adjust, ?base(Precision), PadChar, atom_to_list(Prefix), true);
ctlSmall($x, [Args, Prefix], Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
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) ->
prefixed_integer(Args, Width, Adjust, ?base(Precision), PadChar, Prefix, true);
ctlSmall($X, [Args, Prefix], Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args), is_atom(Prefix) ->
prefixed_integer(Args, Width, Adjust, ?base(Precision), PadChar, atom_to_list(Prefix), false);
ctlSmall($X, [Args, Prefix], Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
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),
prefixed_integer(Args, Width, Adjust, ?base(Precision), PadChar, Prefix, false);
ctlSmall($+, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
Base = ?base(Precision),
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),
prefixed_integer(Args, Width, Adjust, Base, PadChar, Prefix, true);
ctlSmall($#, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
Base = ?base(Precision),
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.
prefixed_integer(Args, Width, Adjust, Base, PadChar, Prefix, false);
ctlSmall($c,Args, Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
char(Args, Width, Adjust, Precision, PadChar);
ctlSmall($c, Args, Width, Adjust, Precision, PadChar, _Enc) when is_integer(Args) ->
char(Args band 255, Width, Adjust, Precision, PadChar);
ctlSmall($~, _Args, Width, Adjust, Precision, PadChar, _Encoding) -> char($~, Width, Adjust, Precision, PadChar);
ctlSmall($n, _Args, Width, Adjust, Precision, PadChar, _Encoding) -> newline(Width, Adjust, Precision, PadChar);
ctlSmall($i, _Args, _Width, _Adjust, _Precision, _PadChar, _Encoding) -> [];
ctlSmall(_C, _Args, Width, _Adjust, _Precision, _PadChar, _Encoding) -> not_small.
%% count_small[ControlC]->pPwWsS
count_small([#{control_char := $p} | Cs], P, S, W, Other) ->
@ -264,7 +270,7 @@ count_small([#{control_char := $W} | Cs], P, S, W, Other) ->
count_small([#{control_char := $s} | Cs], P, S, W, Other) ->
count_small(Cs, P, S, W + 1, Other);
count_small([S | Cs], P, S, W, Other) when is_list(S);is_binary(S) ->
count_small(Cs, P, S, W, Other + eFmt:chars_length(S));
count_small(Cs, P, S, W, Other + eFmt:charsLen(S));
count_small([C | Cs], P, S, W, Other) when is_integer(C) ->
count_small(Cs, P, S, W, Other + 1);
count_small([], P, S, W, Other) ->
@ -285,7 +291,7 @@ build_limited([#{control_char := C, args := As, width := F, adjust := Ad, precis
MaxLen0 < 0 -> % optimization
MaxLen0;
true ->
Len = eFmt:chars_length(S),
Len = eFmt:charsLen(S),
sub(MaxLen0, Len)
end,
if
@ -348,11 +354,6 @@ uniconv(C) ->
uniconv(C) ->
C.
-endif.
%% Default integer base
base(none) ->
10;
base(B) when is_integer(B) ->
B.
%% term(TermList, Field, Adjust, Precision, PadChar)
%% Output the characters in a term.
@ -361,14 +362,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 = eFmt:chars_length(T),
term(T, F, Adjust, P0, Pad) ->
L = eFmt:charsLen(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);
adjust( Adjust, makePadChars($*, P, <<>>), makePadChars(Pad, F - P, <<>>));
F >= P ->
adjust(T, chars(Pad, F - L), Adj)
adjust(Adjust, T, makePadChars(Pad, F - L, <<>>))
end.
%% print(Term, Depth, Field, Adjust, Precision, PadChar, Encoding,
@ -391,18 +392,23 @@ print(T, D, F, right, P, _Pad, Enc, Str, ChLim, _I) ->
%% 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, P, _Pad) when P >= 2 ->
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, P, Pad) when P >= 2 ->
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) ->
fwriteE(Float, Width, Adjust, Precision, PadChar) ->
case Precision of
none ->
NewPrecision = 6;
_ ->
NewPrecision = Precision
end,
case Width of
none ->
floatE(Float, floatData(Float), NewPrecision);
_ ->
term(floatE(Float, floatData(Float), NewPrecision), Width, Adjust, Adjust, PadChar)
end.
floatE(Fl, Fd, P) when Fl < 0.0 -> %Negative numbers
[$- | floatE(-Fl, Fd, P)];
floatE(_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)]
@ -448,11 +454,11 @@ float_exp(E) ->
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, floatData(Fl), P);
fwrite_f(Fl, F, Adj, none, 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, floatData(Fl), P), F, Adj, F, Pad).
float_f(Fl, Fd, P) when Fl < 0.0 ->
[$- | float_f(-Fl, Fd, P)];
@ -465,16 +471,14 @@ float_f(_Fl, {Ds, E}, P) ->
end.
%% float_data([FloatChar]) -> {[Digit],Exponent}
float_data(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).
floatData(Float) ->
FloatBin = float_to_binary(Float),
case binary:split(FloatBin, <<"e">>) of
[DigitBin, ExponentBin] ->
{DigitBin, binary_to_integer(ExponentBin) + 1};
_ ->
{FloatBin, 0}
end.
%% Writes the shortest, correctly rounded string that converts
%% to Float when read back with list_to_float/1.
@ -663,9 +667,9 @@ fwrite_g(Fl, F, Adj, P, Pad) when P >= 1 ->
P - 1 > E, E >= -1 ->
fwrite_f(Fl, F, Adj, P - 1 - E, Pad);
P =< 1 ->
fwrite_e(Fl, F, Adj, 2, Pad);
fwriteE(Fl, F, Adj, 2, Pad);
true ->
fwrite_e(Fl, F, Adj, P, Pad)
fwriteE(Fl, F, Adj, P, Pad)
end.
@ -750,33 +754,55 @@ limit_field(F, CharsLimit) when CharsLimit < 0; F =:= none ->
limit_field(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, eFmt:chars_length(S), Pad, Enc);
string(S, none, _Adj, P, Pad, Enc) ->
string_field(S, P, left, eFmt:chars_length(S), Pad, Enc);
string(S, F, Adj, P, Pad, Enc) when F >= P ->
N = eFmt: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);
string_field(S, F, Adj, N, Pad, _Enc) when N < F ->
adjust(S, chars(Pad, F - N), Adj);
string_field(S, _, _, _, _, _) -> % N == F
S.
string(Str, Width, Adjust, Precision, PadChar, Encoding) ->
if
Width == none andalso Precision == none ->
Str;
Precision == none ->
strField(Str, Width, Adjust, eFmt:charsLen(Str), PadChar, Encoding);
Width == none ->
strField(Str, Precision, left, eFmt:charsLen(Str), PadChar, Encoding);
true ->
StrLen = eFmt:charsLen(Str),
if
Width > Precision ->
if StrLen > Precision ->
adjust(Adjust, flatTrunc(Str, Precision, Encoding), makePadChars(PadChar, Width - Precision, <<>>));
StrLen < Precision ->
adjust(Adjust, [Str | makePadChars(PadChar, Precision - StrLen, <<>>)], makePadChars(PadChar, Width - Precision, <<>>));
true -> % N == P
adjust(Adjust, Str, makePadChars(PadChar, Width - Precision, <<>>))
end;
true -> % F == P
strField(Str, Width, Adjust, StrLen, PadChar, Encoding)
end
end.
strField(Str, Width, Adjust, StrLen, PadChar, Encoding) when StrLen > Width ->
if
StrLen > Width ->
flatTrunc(Str, Width, Encoding);
StrLen < Width ->
adjust(Adjust, Str, makePadChars(PadChar, Width - StrLen, <<>>));
true ->
Str
end.
flatTrunc(List, Width, _Encoding) ->
binary:part(iolist_to_binary(List), 0, Width).
makePadChars(Char, Cnt, BinStr) ->
case Cnt > 0 of
true ->
makePadChars(Cnt - 1, Char, <<BinStr/binary, Char>>);
_ ->
BinStr
end.
adjust(left, Data, Pad) -> [Data | Pad];
adjust(right, Data, Pad) -> [Pad | Data].
%% unprefixed_integer(Int, Field, Adjust, Base, PadChar, Lowercase)
%% -> [Char].
@ -807,48 +833,18 @@ prefixed_integer(Int, F, Adj, Base, Pad, Prefix, Lowercase)
%% char(Char, Field, Adjust, Precision, PadChar) -> chars().
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, none, _Pad) -> makePadChars(C, F, <<>>);
char(C, none, _Adj, P, _Pad) -> makePadChars(C, P, <<>>);
char(C, F, Adj, P, Pad) when F >= P ->
adjust(chars(C, P), chars(Pad, F - P), Adj).
adjust( Adj, makePadChars(C, P, <<>>), makePadChars(Pad, F - P, <<>>)).
%% newline(Field, Adjust, Precision, PadChar) -> [Char].
newline(none, _Adj, _P, _Pad) -> "\n";
newline(F, right, _P, _Pad) -> chars($\n, F).
%%
%% Utilities
%%
adjust(Data, [], _) -> Data;
adjust(Data, Pad, left) -> [Data | Pad];
adjust(Data, Pad, right) -> [Pad | Data].
newline(F, right, _P, _Pad) -> makePadChars($\n, F, <<>>).
%% 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;
flat_trunc(List, N, unicode) when is_integer(N), N >= 0 ->
string:slice(List, 0, N).
%% A deep version of lists:duplicate/2
chars(_C, 0) ->
[];
chars(C, 1) ->
[C];
chars(C, 2) ->
[C, C];
chars(C, 3) ->
[C, C, C];
chars(C, N) when is_integer(N), (N band 1) =:= 0 ->
S = chars(C, N bsr 1),
[S | S];
chars(C, N) when is_integer(N) ->
S = chars(C, N bsr 1),
[C, S | S].
%chars(C, N, Tail) ->
% [chars(C, N)|Tail].

Chargement…
Annuler
Enregistrer