25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

1061 satır
40 KiB

4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
  1. -module(eFmt).
  2. -import(binary, [split/2, part/3]).
  3. -compile(inline).
  4. -compile({inline_size, 128}).
  5. -include("eFmt.hrl").
  6. -export([
  7. %% eFmt
  8. format/2
  9. , format/3
  10. , formatBin/2
  11. , formatBin/3
  12. , scan/2
  13. , build/1
  14. , build/2
  15. , write/1
  16. , write/2
  17. , write/3
  18. , write/4
  19. , write/6
  20. %% eFmtformat
  21. , fWrite/2
  22. , fWrite/3
  23. , fScan/2
  24. , fBuild/1
  25. , fBuild/2
  26. %% utils
  27. , toLowerStr/1
  28. , toUpperStr/1
  29. , toBinary/1
  30. , charsLen/1
  31. , getOpt/3
  32. , visualList/2
  33. , visualBin/2
  34. , writeTerm/3
  35. , writeTerm/5
  36. ]).
  37. %% ********************************************** eFmt start ***********************************************************
  38. -type chars() :: [char() | chars() | binary()].
  39. -type depth() :: -1 | non_neg_integer().
  40. -type encoding() :: epp:source_encoding() | 'unicode'.
  41. -type charsLimit() :: integer().
  42. -type fmtSpec() :: #fmtSpec{}.
  43. -type format() :: atom() | string() | binary().
  44. -spec format(Format :: format(), Data :: [term()]) -> chars().
  45. format(Format, Args) ->
  46. try fWrite(Format, Args)
  47. catch
  48. _C:_R ->
  49. erlang:error(badarg, [Format, Args, _C, _R])
  50. end.
  51. -spec format(Format :: format(), Data :: [term()], Options :: [{charsLimit, CharsLimit :: charsLimit()}]) -> chars().
  52. format(Format, Args, Options) ->
  53. try fWrite(Format, Args, Options)
  54. catch
  55. _C:_R ->
  56. erlang:error(badarg, [Format, Args])
  57. end.
  58. -spec formatBin(Format :: format(), Data :: [term()]) -> chars().
  59. formatBin(Format, Args) ->
  60. try iolist_to_binary(fWrite(Format, Args))
  61. catch
  62. _C:_R ->
  63. erlang:error(badarg, [Format, Args, _C, _R])
  64. end.
  65. -spec formatBin(Format :: format(), Data :: [term()], Options :: [{charsLimit, CharsLimit :: charsLimit()}]) -> chars().
  66. formatBin(Format, Args, Options) ->
  67. try iolist_to_binary(fWrite(Format, Args, Options))
  68. catch
  69. _C:_R ->
  70. erlang:error(badarg, [Format, Args])
  71. end.
  72. -spec scan(Format :: format(), Data :: [term()]) -> FormatList :: [char() | fmtSpec()].
  73. scan(Format, Args) ->
  74. try fScan(Format, Args)
  75. catch
  76. _C:_R ->
  77. erlang:error(badarg, [Format, Args])
  78. end.
  79. -spec build(FormatList :: [char() | fmtSpec()]) -> chars().
  80. build(FormatList) ->
  81. try fBuild(FormatList)
  82. catch
  83. _C:_R ->
  84. erlang:error(badarg, [FormatList])
  85. end.
  86. -spec build(FormatList :: [char() | fmtSpec()], Options :: [{charsLimit, CharsLimit :: charsLimit()}]) -> chars().
  87. build(FormatList, Options) ->
  88. try fBuild(FormatList, Options)
  89. catch
  90. _C:_R ->
  91. erlang:error(badarg, [FormatList, Options])
  92. end.
  93. -spec write(Term :: term()) -> chars().
  94. write(Term) ->
  95. writeTerm(Term, -1, latin1).
  96. -spec write(Term :: term(), Depth :: depth()) -> chars().
  97. write(Term, Depth) ->
  98. writeTerm(Term, Depth, latin1).
  99. -spec write(Term :: term(), Depth :: depth(), IsPretty :: boolean()) -> chars().
  100. write(Term, Depth, IsPretty) ->
  101. case IsPretty of
  102. true ->
  103. writeTerm(Term, Depth, ?LineCCnt, latin1, true);
  104. _ ->
  105. writeTerm(Term, Depth, latin1)
  106. end.
  107. -spec write(Term :: term(), Depth :: depth(), Encoding :: encoding(), CharsLimit :: charsLimit()) -> chars().
  108. write(Term, Depth, Encoding, CharsLimit) ->
  109. if
  110. Depth =:= 0 orelse CharsLimit =:= 0 ->
  111. <<"...">>;
  112. CharsLimit < 0 ->
  113. writeTerm(Term, Depth, Encoding);
  114. true ->
  115. BinTerm = writeTerm(Term, Depth, ?LineCCnt, Encoding, false),
  116. BinTermSize = byte_size(BinTerm),
  117. if
  118. CharsLimit < 0 ->
  119. BinTerm;
  120. BinTermSize > CharsLimit ->
  121. <<(part(BinTerm, 0, CharsLimit))/binary, "...">>;
  122. true ->
  123. BinTerm
  124. end
  125. end.
  126. write(Term, Depth, Width, CharsLimit, Encoding, Strings) ->
  127. if
  128. Depth =:= 0 orelse CharsLimit =:= 0 ->
  129. <<"...">>;
  130. true ->
  131. BinTerm = writeTerm(Term, Depth, Width, Encoding, Strings),
  132. BinTermSize = byte_size(BinTerm),
  133. if
  134. CharsLimit < 0 ->
  135. BinTerm;
  136. BinTermSize > CharsLimit ->
  137. <<(part(BinTerm, 0, CharsLimit))/binary, "...">>;
  138. true ->
  139. BinTerm
  140. end
  141. end.
  142. -define(writeInt(Int), integer_to_binary(Term)).
  143. -define(writeFloat(Float), floatG(Term)).
  144. -define(writePort(Port), list_to_binary(port_to_list(Port))).
  145. -define(writeRef(Ref), list_to_binary(ref_to_list(Ref))).
  146. -define(writePid(Ref), list_to_binary(pid_to_list(Ref))).
  147. -define(writeFun(Fun), list_to_binary(erlang:fun_to_list(Fun))).
  148. writeAtom(Atom, Encoding) ->
  149. AtomBin = atom_to_binary(Atom, Encoding),
  150. case isQuoteAtom(Atom, AtomBin) of
  151. true ->
  152. <<"'", (atom_to_binary(Atom, Encoding))/binary, "'">>;
  153. _ ->
  154. AtomBin
  155. end.
  156. isQuoteAtom(Atom, AtomBin) ->
  157. case erl_scan:reserved_word(Atom) of
  158. true -> true;
  159. _ ->
  160. visualAtomBin(AtomBin)
  161. end.
  162. visualAtomBin(<<>>) -> false;
  163. visualAtomBin(<<C/utf8, Left/binary>>) -> ?IIF(visualAtomChar(C), visualAtomBin(Left), true);
  164. visualAtomBin(_) -> true.
  165. visualAtomChar(C) when C >= $a, C =< $z -> true;
  166. visualAtomChar(C) when C >= , C =< $ÿ, C =/= -> true;
  167. visualAtomChar(C) when C >= $A, C =< $Z -> true;
  168. visualAtomChar(C) when C >= , C =< , C =/= -> true;
  169. visualAtomChar(C) when C >= $0, C =< $9 -> true;
  170. visualAtomChar($_) -> true;
  171. visualAtomChar($@) -> true;
  172. visualAtomChar(_) -> false.
  173. %% **************************************************** ~w start *******************************************************
  174. writeList([], _D, _E, BinAcc) ->
  175. <<BinAcc/binary, "]">>;
  176. writeList([One], D, E, BinAcc) ->
  177. <<BinAcc/binary, (writeTerm(One, D, E))/binary, "]">>;
  178. writeList([One | List], D, E, BinAcc) ->
  179. if
  180. D =:= 1 -> <<BinAcc, "|...]">>;
  181. true ->
  182. writeList(List, D - 1, E, <<BinAcc/binary, (writeTerm(One, D, E))/binary, ",">>)
  183. end;
  184. writeList(Other, D, E, BinAcc) ->
  185. NewBinAcc = part(BinAcc, 0, byte_size(BinAcc) - 1),
  186. <<NewBinAcc/binary, "|", (writeTerm(Other, D, E))/binary, "]">>.
  187. writeTuple(Tuple, D, E, Index, TupleSize, BinAcc) ->
  188. if
  189. D =:= 1 -> <<BinAcc/binary, "...}">>;
  190. true ->
  191. if
  192. Index < TupleSize ->
  193. writeTuple(Tuple, D - 1, E, Index + 1, TupleSize, <<BinAcc/binary, (writeTerm(element(Index, Tuple), D - 1, E))/binary, ",">>);
  194. Index == TupleSize ->
  195. <<BinAcc/binary, (writeTerm(element(Index, Tuple), D - 1, E))/binary, "}">>;
  196. true ->
  197. <<BinAcc/binary, "}">>
  198. end
  199. end.
  200. writeMap(Map, D, E, BinAcc) ->
  201. if
  202. D =:= 1 ->
  203. <<BinAcc/binary, "...}">>;
  204. true ->
  205. writeMapBody(maps:iterator(Map), D, E, BinAcc)
  206. end.
  207. writeMapBody(I, D, E, BinAcc) ->
  208. if
  209. D =:= 1 ->
  210. <<BinAcc/binary, " ...}">>;
  211. true ->
  212. case maps:next(I) of
  213. {K, V, none} ->
  214. <<BinAcc/binary, (writeTerm(K, -1, E))/binary, " => ", (writeTerm(V, D, E))/binary, "}">>;
  215. {K, V, NextI} ->
  216. writeMapBody(NextI, D - 1, E, <<BinAcc/binary, (writeTerm(K, -1, E))/binary, " => ", (writeTerm(V, D, E))/binary, ",">>);
  217. _ ->
  218. <<BinAcc/binary, "}">>
  219. end
  220. end.
  221. writeBinary(Bin, D, BinAcc) ->
  222. if
  223. D == 1 ->
  224. <<BinAcc/binary, "...>>">>;
  225. true ->
  226. case Bin of
  227. <<>> ->
  228. <<BinAcc/binary, ">>">>;
  229. <<Int:8>> ->
  230. <<BinAcc/binary, (integer_to_binary(Int))/binary, ">>">>;
  231. <<Int:8, LeftBin/bitstring>> ->
  232. writeBinary(LeftBin, D - 1, <<BinAcc/binary, (integer_to_binary(Int))/binary, ",">>);
  233. _ ->
  234. L = bit_size(Bin),
  235. <<X:L>> = Bin,
  236. <<BinAcc/binary, (integer_to_binary(X))/binary, ":", (integer_to_binary(L))/binary, ">>">>
  237. end
  238. end.
  239. %% **************************************************** ~w end *******************************************************
  240. %% **************************************************** ~p start *******************************************************
  241. writeList([], _Depth, _Width, _Encoding, _Strings) ->
  242. <<"[]">>;
  243. writeList(List, Depth, Width, Encoding, Strings) ->
  244. case Strings andalso visualList(List, Encoding) of
  245. true ->
  246. <<"\"", (unicode:characters_to_binary(List))/binary, "\"">>;
  247. _ ->
  248. writeList(List, Depth, Width, Encoding, Strings, 0, <<"[">>)
  249. end.
  250. writeList([], _Depth, _Width, _Encoding, _Strings, _SumLC, BinAcc) ->
  251. <<BinAcc/binary, "]">>;
  252. writeList([One], Depth, Width, Encoding, Strings, SumLC, BinAcc) ->
  253. TermBin = writeTerm(One, Depth, Width, Encoding, Strings),
  254. TermBinBinSize = byte_size(TermBin),
  255. NewSumLC = SumLC + TermBinBinSize,
  256. case NewSumLC >= Width of
  257. true ->
  258. <<BinAcc/binary, TermBin/binary, "]\n">>;
  259. _ ->
  260. <<BinAcc/binary, TermBin/binary, "]">>
  261. end;
  262. writeList([One | List], Depth, Width, Encoding, Strings, SumLC, BinAcc) ->
  263. if
  264. Depth =:= 1 -> <<BinAcc, "|...]">>;
  265. true ->
  266. TermBin = writeTerm(One, Depth, Width, Encoding, Strings),
  267. TermBinBinSize = byte_size(TermBin),
  268. NewSumLC = SumLC + TermBinBinSize,
  269. case NewSumLC >= Width of
  270. true ->
  271. writeList(List, Depth - 1, Width, Encoding, Strings, 0, <<BinAcc/binary, TermBin/binary, ",\n">>);
  272. _ ->
  273. writeList(List, Depth - 1, Width, Encoding, Strings, NewSumLC, <<BinAcc/binary, TermBin/binary, ",">>)
  274. end
  275. end;
  276. writeList(Other, Depth, Width, Encoding, Strings, SumLC, BinAcc) ->
  277. TermBin = writeTerm(Other, Depth, Width, Encoding, Strings),
  278. TermBinBinSize = byte_size(TermBin),
  279. NewSumLC = SumLC + TermBinBinSize,
  280. NewBinAcc = part(BinAcc, 0, byte_size(BinAcc) - 1),
  281. case NewSumLC >= Width of
  282. true ->
  283. <<NewBinAcc/binary, "|", TermBin/binary, "]\n">>;
  284. _ ->
  285. <<NewBinAcc/binary, "|", TermBin/binary, "]">>
  286. end.
  287. writeTuple(Tuple, Depth, Width, Encoding, Strings, Index, TupleSize, SumLC, BinAcc) ->
  288. if
  289. Depth =:= 1 -> <<BinAcc/binary, "...}">>;
  290. true ->
  291. if
  292. Index < TupleSize ->
  293. TermBin = writeTerm(element(Index, Tuple), Depth, Width, Encoding, Strings),
  294. TermBinBinSize = byte_size(TermBin),
  295. NewSumLC = SumLC + TermBinBinSize,
  296. case NewSumLC >= Width of
  297. true ->
  298. writeTuple(Tuple, Depth - 1, Width, Encoding, Strings, Index + 1, TupleSize, 0, <<BinAcc/binary, TermBin/binary, ",\n">>);
  299. _ ->
  300. writeTuple(Tuple, Depth - 1, Width, Encoding, Strings, Index + 1, TupleSize, NewSumLC, <<BinAcc/binary, TermBin/binary, ",">>)
  301. end;
  302. Index == TupleSize ->
  303. TermBin = writeTerm(element(Index, Tuple), Depth, Width, Encoding, Strings),
  304. TermBinBinSize = byte_size(TermBin),
  305. NewSumLC = SumLC + TermBinBinSize,
  306. case NewSumLC >= Width of
  307. true ->
  308. <<BinAcc/binary, TermBin/binary, "}\n">>;
  309. _ ->
  310. <<BinAcc/binary, TermBin/binary, "}">>
  311. end;
  312. true ->
  313. <<BinAcc/binary, "}">>
  314. end
  315. end.
  316. writeMap(Map, Depth, Width, Encoding, Strings, SumLC, BinAcc) ->
  317. if
  318. Depth =:= 1 ->
  319. <<BinAcc/binary, "...}">>;
  320. true ->
  321. writeMapBody(maps:iterator(Map), Depth, Width, Encoding, Strings, SumLC, BinAcc)
  322. end.
  323. writeMapBody(I, Depth, Width, Encoding, Strings, SumLC, BinAcc) ->
  324. if
  325. Depth =:= 1 ->
  326. <<BinAcc/binary, " ...}">>;
  327. true ->
  328. case maps:next(I) of
  329. {K, V, none} ->
  330. KeyTermBin = writeTerm(K, -1, Width, Encoding, Strings),
  331. ValueTermBin = writeTerm(V, -1, Width, Encoding, Strings),
  332. TermBinBinSize = byte_size(KeyTermBin) + byte_size(ValueTermBin),
  333. NewSumLC = SumLC + TermBinBinSize,
  334. case NewSumLC >= Width of
  335. true ->
  336. <<BinAcc/binary, KeyTermBin/binary, " => ", ValueTermBin/binary, "}\n">>;
  337. _ ->
  338. <<BinAcc/binary, KeyTermBin/binary, " => ", ValueTermBin/binary, "}">>
  339. end;
  340. {K, V, NextI} ->
  341. KeyTermBin = writeTerm(K, -1, Width, Encoding, Strings),
  342. ValueTermBin = writeTerm(V, -1, Width, Encoding, Strings),
  343. TermBinBinSize = byte_size(KeyTermBin) + byte_size(ValueTermBin),
  344. NewSumLC = SumLC + TermBinBinSize,
  345. case NewSumLC >= Width of
  346. true ->
  347. writeMapBody(NextI, Depth - 1, Width, Encoding, Strings, 0, <<BinAcc/binary, KeyTermBin/binary, " => ", ValueTermBin/binary, ",\n">>);
  348. _ ->
  349. writeMapBody(NextI, Depth - 1, Width, Encoding, Strings, NewSumLC, <<BinAcc/binary, KeyTermBin/binary, " => ", ValueTermBin/binary, ",">>)
  350. end;
  351. _ ->
  352. <<BinAcc/binary, "}">>
  353. end
  354. end.
  355. writeBinary(<<>>, _Depth, _Width, _Encoding, _Strings) ->
  356. <<"<<>>">>;
  357. writeBinary(Bin, Depth, Width, Encoding, Strings) ->
  358. case Strings andalso visualBin(Bin, Encoding) of
  359. true ->
  360. <<"<<\"", Bin/binary, "\">>">>;
  361. _ ->
  362. writeBinary(Bin, Depth, Width, Encoding, Strings, 0, <<"<<">>)
  363. end.
  364. writeBinary(Bin, Depth, Width, Encoding, Strings, SumLC, BinAcc) ->
  365. if
  366. Depth == 1 ->
  367. <<BinAcc/binary, "...>>">>;
  368. true ->
  369. case Bin of
  370. <<>> ->
  371. <<BinAcc/binary, ">>">>;
  372. <<Int:8>> ->
  373. <<BinAcc/binary, (integer_to_binary(Int))/binary, ">>">>;
  374. <<Int:8, LeftBin/bitstring>> ->
  375. TermBin = integer_to_binary(Int),
  376. TermBinBinSize = byte_size(TermBin),
  377. NewSumLC = SumLC + TermBinBinSize,
  378. case NewSumLC >= Width of
  379. true ->
  380. writeBinary(LeftBin, Depth - 1, Width, Encoding, Strings, 0, <<BinAcc/binary, TermBin/binary, ",\n">>);
  381. _ ->
  382. writeBinary(LeftBin, Depth - 1, Width, Encoding, Strings, NewSumLC, <<BinAcc/binary, TermBin/binary, ",">>)
  383. end;
  384. _ ->
  385. L = bit_size(Bin),
  386. <<X:L>> = Bin,
  387. <<BinAcc/binary, (integer_to_binary(X))/binary, ":", (integer_to_binary(L))/binary, ">>">>
  388. end
  389. end.
  390. %% **************************************************** ~p end *******************************************************
  391. %% ~w
  392. writeTerm(_Term, Depth, _E) when Depth == 0 -> <<"...">>;
  393. writeTerm(Term, _Depth, _E) when is_integer(Term) -> ?writeInt(Term);
  394. writeTerm(Term, _Depth, E) when is_atom(Term) -> writeAtom(Term, E);
  395. writeTerm(Term, Depth, E) when is_list(Term) -> writeList(Term, Depth, E, <<"[">>);
  396. writeTerm(Term, Depth, E) when is_map(Term) -> writeMap(Term, Depth, E, <<"#{">>);
  397. writeTerm(Term, Depth, E) when is_tuple(Term) -> writeTuple(Term, Depth, E, 1, tuple_size(Term), <<"{">>);
  398. writeTerm(Term, Depth, _E) when is_bitstring(Term) -> writeBinary(Term, Depth, <<"<<">>);
  399. writeTerm(Term, _Depth, _E) when is_pid(Term) -> ?writePid(Term);
  400. writeTerm(Term, _Depth, _E) when is_float(Term) -> ?writeFloat(Term);
  401. writeTerm(Term, _Depth, _E) when is_port(Term) -> ?writePort(Term);
  402. writeTerm(Term, _Depth, _E) when is_reference(Term) -> ?writeRef(Term);
  403. writeTerm(Term, _Depth, _E) when is_function(Term) -> ?writeFun(Term).
  404. %% ~p
  405. writeTerm(_Term, Depth, _Width, _Encoding, _Strings) when Depth == 0 -> <<"...">>;
  406. writeTerm(Term, _Depth, _Width, _Encoding, _Strings) when is_integer(Term) -> ?writeInt(Term);
  407. writeTerm(Term, _Depth, _Width, Encoding, _Strings) when is_atom(Term) -> writeAtom(Term, Encoding);
  408. writeTerm(Term, Depth, Width, Encoding, Strings) when is_list(Term) -> writeList(Term, Depth, Width, Encoding, Strings);
  409. writeTerm(Term, Depth, Width, Encoding, Strings) when is_map(Term) ->
  410. writeMap(Term, Depth, Width, Encoding, Strings, 0, <<"#{">>);
  411. writeTerm(Term, Depth, Width, Encoding, Strings) when is_tuple(Term) ->
  412. writeTuple(Term, Depth, Width, Encoding, Strings, 1, tuple_size(Term), 0, <<"{">>);
  413. writeTerm(Term, Depth, Width, Encoding, Strings) when is_bitstring(Term) ->
  414. writeBinary(Term, Depth, Width, Encoding, Strings);
  415. writeTerm(Term, _Depth, _Width, _Encoding, _Strings) when is_pid(Term) -> ?writePid(Term);
  416. writeTerm(Term, _Depth, _Width, _Encoding, _Strings) when is_float(Term) -> ?writeFloat(Term);
  417. writeTerm(Term, _Depth, _Width, _Encoding, _Strings) when is_port(Term) -> ?writePort(Term);
  418. writeTerm(Term, _Depth, _Width, _Encoding, _Strings) when is_reference(Term) -> ?writeRef(Term);
  419. writeTerm(Term, _Depth, _Width, _Encoding, _Strings) when is_function(Term) -> ?writeFun(Term).
  420. %% ********************************************** eFmt end *************************************************************
  421. %% ********************************************** eFmtFormat start *****************************************************
  422. -spec fWrite(Format :: format(), Data :: [term()]) -> chars().
  423. fWrite(Format, Args) ->
  424. fBuild(fScan(Format, Args), []).
  425. -spec fWrite(Format :: format(), Data :: [term()], Options :: [{'chars_limit', CharsLimit :: integer()}]) -> chars().
  426. fWrite(Format, Args, Options) ->
  427. fBuild(fScan(Format, Args), Options).
  428. %% 格式 ~F.P.PadModC
  429. %% Parse all control sequences in the format string.
  430. -spec fScan(Format :: format(), Data :: [term()]) -> FormatList :: [char() | fmtSpec()].
  431. fScan(Format, Args) ->
  432. if
  433. is_binary(Format) ->
  434. doCollect(Format, Args, []);
  435. is_list(Format) ->
  436. doCollect(list_to_binary(Format), Args, []);
  437. is_atom(Format) ->
  438. doCollect(atom_to_binary(Format, utf8), Args, []);
  439. true ->
  440. throw(bad_format)
  441. end.
  442. doCollect(FmtBinStr, Args, Acc) ->
  443. case split(FmtBinStr, <<"~">>) of
  444. [NotMatch] ->
  445. true = [] == Args,
  446. ?IIF(NotMatch == <<>>, Acc, [NotMatch | Acc]);
  447. [FPart, LPart] ->
  448. doCollWidth(LPart, Args, 0, right, ?IIF(FPart == <<>>, Acc, [FPart | Acc]))
  449. end.
  450. doCollWidth(<<>>, _Args, _Width, _Adjust, Acc) ->
  451. Acc;
  452. doCollWidth(LPart, Args, Width, Adjust, Acc) ->
  453. case LPart of
  454. <<"-*", LeftLPart/binary>> ->
  455. [WidthArgs | LeftArgs] = Args,
  456. doCollPrecision(LeftLPart, LeftArgs, WidthArgs, left, Acc);
  457. <<"-", LeftLPart/binary>> ->
  458. doCollWidth(LeftLPart, Args, Width, left, Acc);
  459. <<"*", LeftLPart/binary>> ->
  460. [WidthArgs | LeftArgs] = Args,
  461. doCollPrecision(LeftLPart, LeftArgs, WidthArgs, right, Acc);
  462. <<WidthInt:8/integer, LeftLPart/binary>> ->
  463. case WidthInt >= $0 andalso WidthInt =< $9 of
  464. true ->
  465. doCollWidth(LeftLPart, Args, 10 * Width + (WidthInt - $0), Adjust, Acc);
  466. _ ->
  467. case Width == 0 of
  468. true ->
  469. doCollPrecision(LPart, Args, none, left, Acc);
  470. _ ->
  471. doCollPrecision(LPart, Args, Width, Adjust, Acc)
  472. end
  473. end
  474. end.
  475. doCollPrecision(LPart, Args, Width, Adjust, Acc) ->
  476. case LPart of
  477. <<".", LeftLPart/binary>> ->
  478. doCollPrecision(LeftLPart, Args, Width, Adjust, 0, Acc);
  479. _ ->
  480. doCollPadChar(LPart, Args, Width, Adjust, none, Acc)
  481. end.
  482. doCollPrecision(LPart, Args, Width, Adjust, Precision, Acc) ->
  483. case LPart of
  484. <<"*", LeftLPart/binary>> ->
  485. [PrecisionArgs | LeftArgs] = Args,
  486. doCollPadChar(LeftLPart, LeftArgs, Width, Adjust, PrecisionArgs, Acc);
  487. <<PrecisionInt:8/integer, LeftLPart/binary>> ->
  488. case PrecisionInt >= $0 andalso PrecisionInt =< $9 of
  489. true ->
  490. doCollPrecision(LeftLPart, Args, Width, Adjust, 10 * Precision + (PrecisionInt - $0), Acc);
  491. _ ->
  492. case Precision == 0 of
  493. true ->
  494. doCollPadChar(LPart, Args, Width, Adjust, none, Acc);
  495. _ ->
  496. doCollPadChar(LPart, Args, Width, Adjust, Precision, Acc)
  497. end
  498. end
  499. end.
  500. doCollPadChar(LPart, Args, Width, Adjust, Precision, Acc) ->
  501. case LPart of
  502. <<".*", LeftLPart/binary>> ->
  503. [PadChar | LeftArgs] = Args,
  504. doCollEncoding(LeftLPart, LeftArgs, Width, Adjust, Precision, PadChar, Acc);
  505. <<".", PadChar:8/integer, LeftLPart/binary>> ->
  506. doCollEncoding(LeftLPart, Args, Width, Adjust, Precision, PadChar, Acc);
  507. _ ->
  508. doCollEncoding(LPart, Args, Width, Adjust, Precision, 32, Acc)
  509. end.
  510. doCollEncoding(LPart, Args, Width, Adjust, Precision, PadChar, Acc) ->
  511. case LPart of
  512. <<"t", LeftLPart/binary>> ->
  513. %true = Char =/= $l,
  514. doCollStrings(LeftLPart, Args, Width, Adjust, Precision, PadChar, unicode, Acc);
  515. _ ->
  516. doCollStrings(LPart, Args, Width, Adjust, Precision, PadChar, latin1, Acc)
  517. end.
  518. doCollStrings(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, Acc) ->
  519. case LPart of
  520. <<"l", LeftLPart/binary>> ->
  521. %true = Char =/= $t,
  522. doCollCA(LeftLPart, Args, Width, Adjust, Precision, PadChar, Encoding, false, Acc);
  523. _ ->
  524. doCollCA(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, true, Acc)
  525. end.
  526. doCollCA(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, Strings, Acc) ->
  527. <<CtlChar:8/integer, LeftLPart/binary>> = LPart,
  528. case CtlChar of
  529. $w -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  530. $p -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  531. $W -> [OneArgs | LeftArgs] = Args, [Depth | LastArgs] = LeftArgs, As = {OneArgs, Depth}, NextArgs = LastArgs;
  532. $P -> [OneArgs | LeftArgs] = Args, [Depth | LastArgs] = LeftArgs, As = {OneArgs, Depth}, NextArgs = LastArgs;
  533. $s -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  534. $e -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  535. $f -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  536. $g -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  537. $b -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  538. $B -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  539. $x -> [OneArgs | LeftArgs] = Args, [Prefix | LastArgs] = LeftArgs, As = {OneArgs, Prefix}, NextArgs = LastArgs;
  540. $X -> [OneArgs | LeftArgs] = Args, [Prefix | LastArgs] = LeftArgs, As = {OneArgs, Prefix}, NextArgs = LastArgs;
  541. $+ -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  542. $# -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  543. $c -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
  544. $~ -> As = undefined, NextArgs = Args;
  545. $n -> As = undefined, NextArgs = Args;
  546. $i -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs
  547. end,
  548. FmtSpec = #fmtSpec{ctlChar = CtlChar, args = As, width = Width, adjust = Adjust, precision = Precision, padChar = PadChar, encoding = Encoding, strings = Strings},
  549. doCollect(LeftLPart, NextArgs, [FmtSpec | Acc]).
  550. %% Build the output text for a pre-parsed format list.
  551. -spec fBuild(FormatList :: [char() | fmtSpec()]) -> chars().
  552. fBuild(Cs) ->
  553. fBuild(Cs, []).
  554. -spec fBuild(FormatList :: [char() | fmtSpec()], Options :: [{'chars_limit', CharsLimit :: integer()}]) -> chars().
  555. fBuild(Cs, Options) ->
  556. CharsLimit = getOpt(chars_limit, Options, -1),
  557. buildSmall(Cs, CharsLimit, 0, 0, 0, 0, []).
  558. buildSmall([], CharsLimit, P, S, W, Other, Acc) ->
  559. NumOfLimited = P + S + W,
  560. case NumOfLimited of
  561. 0 ->
  562. Acc;
  563. _ ->
  564. RemainChars = remainChars(CharsLimit, Other),
  565. case buildLimited(Acc, P, NumOfLimited, RemainChars, 0, []) of
  566. [] ->
  567. [];
  568. [_One] = Ret ->
  569. Ret;
  570. [One, Two] ->
  571. [Two, One];
  572. [One, Two, Three] ->
  573. [Three, Two, One];
  574. Ret ->
  575. lists:reverse(Ret, [])
  576. end
  577. end;
  578. buildSmall([OneCA | Cs], CharsLimit, P, S, W, Other, Acc) ->
  579. case OneCA of
  580. #fmtSpec{ctlChar = CtlChar, args = Args, width = Width, adjust = Adjust, precision = Precision, padChar = PadChar, encoding = Encoding} ->
  581. case ctlSmall(CtlChar, Args, Width, Adjust, Precision, PadChar, Encoding) of
  582. not_small ->
  583. case CtlChar of
  584. $p ->
  585. buildSmall(Cs, CharsLimit, P + 1, S, W, Other, [OneCA | Acc]);
  586. $P ->
  587. buildSmall(Cs, CharsLimit, P + 1, S, W, Other, [OneCA | Acc]);
  588. $w ->
  589. buildSmall(Cs, CharsLimit, P, S, W + 1, Other, [OneCA | Acc]);
  590. $W ->
  591. buildSmall(Cs, CharsLimit, P, S, W + 1, Other, [OneCA | Acc]);
  592. $s ->
  593. buildSmall(Cs, CharsLimit, P, S, W + 1, Other, [OneCA | Acc]);
  594. _ ->
  595. buildSmall(Cs, CharsLimit, P, S, W, Other, [OneCA | Acc])
  596. end;
  597. ignore ->
  598. buildSmall(Cs, CharsLimit, P, S, W, Other, Acc);
  599. Str ->
  600. if
  601. is_binary(Str) orelse is_list(Str) ->
  602. buildSmall(Cs, CharsLimit, P, S, W, Other + charsLen(Str), [Str | Acc]);
  603. is_integer(Str) ->
  604. buildSmall(Cs, CharsLimit, P, S, W, Other + 1, [Str | Acc]);
  605. true ->
  606. buildSmall(Cs, CharsLimit, P, S, W, Other, [Str | Acc])
  607. end
  608. end;
  609. _ ->
  610. if
  611. is_binary(OneCA) orelse is_list(OneCA) ->
  612. buildSmall(Cs, CharsLimit, P, S, W, Other + charsLen(OneCA), [OneCA | Acc]);
  613. is_integer(OneCA) ->
  614. buildSmall(Cs, CharsLimit, P, S, W, Other + 1, [OneCA | Acc]);
  615. true ->
  616. buildSmall(Cs, CharsLimit, P, S, W, Other, [OneCA | Acc])
  617. end
  618. end.
  619. ctlSmall($e, Args, Width, Adjust, Precision, PadChar, _Encoding) ->
  620. floatE(Args, Width, Adjust, Precision, PadChar);
  621. ctlSmall($f, Args, Width, Adjust, Precision, PadChar, _Encoding) ->
  622. floatF(Args, Width, Adjust, Precision, PadChar);
  623. ctlSmall($g, Args, Width, Adjust, Precision, PadChar, _Encoding) ->
  624. floatG(Args, Width, Adjust, Precision, PadChar);
  625. ctlSmall($b, Args, Width, Adjust, Precision, PadChar, _Encoding) ->
  626. unPrefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, true);
  627. ctlSmall($B, Args, Width, Adjust, Precision, PadChar, _Encoding) ->
  628. unPrefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, false);
  629. ctlSmall($x, {Args, Prefix}, Width, Adjust, Precision, PadChar, _Encoding) ->
  630. case is_atom(Prefix) of
  631. true ->
  632. prefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, atom_to_binary(Prefix, utf8), true);
  633. _ ->
  634. prefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, Prefix, true)
  635. end;
  636. ctlSmall($X, {Args, Prefix}, Width, Adjust, Precision, PadChar, _Encoding) ->
  637. case is_atom(Prefix) of
  638. true ->
  639. prefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, atom_to_binary(Prefix, utf8), false);
  640. _ ->
  641. Base = ?base(Precision),
  642. prefixedInt(Args, Width, Adjust, Base, PadChar, integer_to_binary(Base), $#, true)
  643. end;
  644. ctlSmall($+, Args, Width, Adjust, Precision, PadChar, _Encoding) ->
  645. Base = ?base(Precision),
  646. prefixedInt(Args, Width, Adjust, Base, PadChar, integer_to_binary(Base), $#, true);
  647. ctlSmall($#, Args, Width, Adjust, Precision, PadChar, _Encoding) ->
  648. Base = ?base(Precision),
  649. prefixedInt(Args, Width, Adjust, Base, PadChar, integer_to_binary(Base), $#, false);
  650. ctlSmall($c, Args, Width, Adjust, Precision, PadChar, Encoding) ->
  651. case Encoding of
  652. unicode ->
  653. char(Args, Width, Adjust, Precision, PadChar);
  654. _ ->
  655. char(Args band 255, Width, Adjust, Precision, PadChar)
  656. end;
  657. ctlSmall($~, _Args, Width, Adjust, Precision, PadChar, _Encoding) -> char($~, Width, Adjust, Precision, PadChar);
  658. ctlSmall($n, _Args, Width, Adjust, Precision, PadChar, _Encoding) -> newline(Width, Adjust, Precision, PadChar);
  659. ctlSmall($i, _Args, _Width, _Adjust, _Precision, _PadChar, _Encoding) -> ignore;
  660. ctlSmall($s, Args, Width, Adjust, Precision, PadChar, Encoding) when is_atom(Args) ->
  661. case Encoding of
  662. latin1 ->
  663. AtomBinStr = writeAtom(Args, latin1);
  664. _ ->
  665. AtomBinStr = writeAtom(Args, uft8)
  666. end,
  667. string(AtomBinStr, Width, Adjust, Precision, PadChar, Encoding);
  668. ctlSmall(_C, _Args, _Width, _Adjust, _Precision, _PadChar, _Encoding) -> not_small.
  669. buildLimited([], _, _, _, _, Acc) -> Acc;
  670. buildLimited([OneCA | Cs], NumOfPs, Count, MaxLen, I, Acc) ->
  671. case OneCA of
  672. #fmtSpec{ctlChar = CtlChar, args = Args, width = Width, adjust = Adjust, precision = Precision, padChar = PadChar, encoding = Encoding, strings = Strings} ->
  673. MaxChars = if MaxLen < 0 -> MaxLen; true -> MaxLen div Count end,
  674. IoListStr = ctlLimited(CtlChar, Args, Width, Adjust, Precision, PadChar, Encoding, Strings, MaxChars, I),
  675. NewNumOfPs = ?IIF(CtlChar == $p orelse CtlChar == $P, NumOfPs - 1, NumOfPs),
  676. NewCount = Count - 1,
  677. NewMaxLen = ?IIF(MaxLen < 0, MaxLen, remainChars(MaxLen, charsLen(IoListStr))),
  678. if
  679. NewNumOfPs > 0 ->
  680. buildLimited(Cs, NewNumOfPs, NewCount, NewMaxLen, I, [IoListStr | Acc]);
  681. true ->
  682. buildLimited(Cs, NewNumOfPs, NewCount, NewMaxLen, I, [IoListStr | Acc])
  683. end;
  684. _ ->
  685. buildLimited(Cs, NumOfPs, Count, MaxLen, I + 1, [OneCA | Acc])
  686. end.
  687. %% (CtlChar, Args, Width, Adjust, Precision, PadChar, Encoding, Strings, MaxChars, I)
  688. ctlLimited($s, Args, Width, Adjust, Precision, PadChar, Encoding, _Strings, CharsLimit, _I) ->
  689. case Encoding of
  690. latin1 ->
  691. BinStr = iolist_to_binary(Args);
  692. _ ->
  693. BinStr =
  694. case catch unicode:characters_to_binary(Args, unicode) of
  695. Str when is_binary(Str) -> Str;
  696. _ -> toBinary(Args)
  697. end
  698. end,
  699. TemBinStr = strToChars(BinStr, Width, CharsLimit),
  700. string(TemBinStr, ?IIF(CharsLimit < 0 orelse Width =:= none, Width, max(3, min(Width, CharsLimit))), Adjust, Precision, PadChar, Encoding);
  701. ctlLimited($w, Args, Width, Adjust, Precision, PadChar, Encoding, _Strings, CharsLimit, _I) ->
  702. Chars = write(Args, -1, Encoding, CharsLimit),
  703. term(Chars, Width, Adjust, Precision, PadChar);
  704. ctlLimited($p, Args, Width, _Adjust, _Precision, _PadChar, Encoding, Strings, CharsLimit, _I) ->
  705. write(Args, -1, ?IIF(Width == none, ?LineCCnt, Width), CharsLimit, Encoding, Strings);
  706. ctlLimited($W, [Args, Depth], Width, Adjust, Precision, PadChar, Encoding, _Strings, CharsLimit, _I) ->
  707. Chars = write(Args, Depth, Encoding, CharsLimit),
  708. term(Chars, Width, Adjust, Precision, PadChar);
  709. ctlLimited($P, [Args, Depth], Width, _Adjust, _Precision, _PadChar, Encoding, Strings, CharsLimit, _I) ->
  710. write(Args, Depth, ?IIF(Width == none, ?LineCCnt, Width), CharsLimit, Encoding, Strings).
  711. term(BinStrOrIoList, Width, Adjust, Precision, PadChar) ->
  712. if
  713. Width == none andalso Precision == none ->
  714. BinStrOrIoList;
  715. Width == none ->
  716. StrLen = charsLen(BinStrOrIoList),
  717. NewPrecision = min(StrLen, Precision),
  718. if
  719. StrLen > NewPrecision ->
  720. adjust(Adjust, makePadChars($*, NewPrecision, <<>>), <<>>);
  721. true ->
  722. adjust(Adjust, BinStrOrIoList, makePadChars(PadChar, Precision - StrLen, <<>>))
  723. end;
  724. true ->
  725. StrLen = charsLen(BinStrOrIoList),
  726. NewPrecision = min(StrLen, case Precision of none -> Width; _ -> min(Precision, Width) end),
  727. if
  728. StrLen > NewPrecision ->
  729. adjust(Adjust, makePadChars($*, NewPrecision, <<>>), makePadChars(PadChar, Width - NewPrecision, <<>>));
  730. true ->
  731. adjust(Adjust, BinStrOrIoList, makePadChars(PadChar, Width - StrLen, <<>>))
  732. end
  733. end.
  734. floatE(Float, Width, Adjust, Precision, PadChar) ->
  735. NewPrecision = ?IIF(Precision == none, 6, Precision),
  736. case Width of
  737. none ->
  738. float_to_binary(Float, [{scientific, NewPrecision}]);
  739. _ ->
  740. term(float_to_binary(Float, [{scientific, NewPrecision}]), Width, Adjust, Width, PadChar)
  741. end.
  742. floatF(Float, Width, Adjust, Precision, PadChar) ->
  743. NewPrecision = ?IIF(Precision == none, 6, Precision),
  744. case Width of
  745. none ->
  746. float_to_binary(Float, [{decimals, NewPrecision}]);
  747. _ ->
  748. term(float_to_binary(Float, [{decimals, NewPrecision}]), Width, Adjust, Width, PadChar)
  749. end.
  750. floatG(Float, Width, Adjust, Precision, PadChar) ->
  751. case Float > -10000.0 andalso Float < 10000.0 of
  752. true ->
  753. floatF(Float, Width, Adjust, Precision, PadChar);
  754. _ ->
  755. floatE(Float, Width, Adjust, Precision, PadChar)
  756. end.
  757. floatG(Float) ->
  758. float_to_binary(Float, [{decimals, 6}]).
  759. strToChars(BinStr, Width, CharsLimit) ->
  760. ByteSize = byte_size(BinStr),
  761. if
  762. Width == none ->
  763. case CharsLimit < 0 orelse CharsLimit >= ByteSize of
  764. true ->
  765. BinStr;
  766. _ ->
  767. <<(part(BinStr, 0, CharsLimit))/binary, "...">>
  768. end;
  769. CharsLimit < 0 orelse CharsLimit >= Width ->
  770. BinStr;
  771. true ->
  772. <<(part(BinStr, 0, CharsLimit))/binary, "...">>
  773. end.
  774. string(Str, Width, Adjust, Precision, PadChar, Encoding) ->
  775. if
  776. Width == none andalso Precision == none ->
  777. Str;
  778. Precision == none ->
  779. strField(Str, Width, Adjust, charsLen(Str), PadChar, Encoding);
  780. Width == none ->
  781. strField(Str, Precision, left, charsLen(Str), PadChar, Encoding);
  782. true ->
  783. StrLen = charsLen(Str),
  784. if
  785. Width > Precision ->
  786. if
  787. StrLen > Precision ->
  788. adjust(Adjust, flatTrunc(Str, Precision, Encoding), makePadChars(PadChar, Width - Precision, <<>>));
  789. StrLen < Precision ->
  790. adjust(Adjust, [Str | makePadChars(PadChar, Precision - StrLen, <<>>)], makePadChars(PadChar, Width - Precision, <<>>));
  791. true -> % N == P
  792. adjust(Adjust, Str, makePadChars(PadChar, Width - Precision, <<>>))
  793. end;
  794. true -> % F == P
  795. strField(Str, Width, Adjust, StrLen, PadChar, Encoding)
  796. end
  797. end.
  798. strField(Str, Width, Adjust, StrLen, PadChar, Encoding) when StrLen > Width ->
  799. if
  800. StrLen > Width ->
  801. flatTrunc(Str, Width, Encoding);
  802. StrLen < Width ->
  803. adjust(Adjust, Str, makePadChars(PadChar, Width - StrLen, <<>>));
  804. true ->
  805. Str
  806. end.
  807. flatTrunc(List, Width, _Encoding) ->
  808. part(iolist_to_binary(List), 0, Width).
  809. makePadChars(PadChar, Cnt, BinStr) ->
  810. case Cnt > 0 of
  811. true ->
  812. makePadChars(PadChar, Cnt - 1, <<BinStr/binary, PadChar:8>>);
  813. _ ->
  814. BinStr
  815. end.
  816. adjust(left, Data, Pad) -> [Data, Pad];
  817. adjust(right, Data, Pad) -> [Pad, Data].
  818. unPrefixedInt(Int, Width, Adjust, Base, PadChar, Lowercase) ->
  819. case Lowercase of
  820. true ->
  821. term(toLowerStr(integer_to_binary(Int, Base)), Width, Adjust, none, PadChar);
  822. _ ->
  823. term(integer_to_binary(Int, Base), Width, Adjust, none, PadChar)
  824. end.
  825. prefixedInt(Int, Width, Adjust, Base, PadChar, Prefix, Lowercase) ->
  826. case Int < 0 of
  827. true ->
  828. case Lowercase of
  829. true ->
  830. term(<<"-", (toBinary(Prefix))/binary, (toLowerStr(integer_to_binary(-Int, Base)))/binary>>, Width, Adjust, none, PadChar);
  831. _ ->
  832. term(<<"-", (toBinary(Prefix))/binary, (integer_to_binary(-Int, Base))/binary>>, Width, Adjust, none, PadChar)
  833. end;
  834. _ ->
  835. case Lowercase of
  836. true ->
  837. term(<<(toBinary(Prefix))/binary, (toLowerStr(integer_to_binary(Int, Base)))/binary>>, Width, Adjust, none, PadChar);
  838. _ ->
  839. term(<<(toBinary(Prefix))/binary, (integer_to_binary(Int, Base))/binary>>, Width, Adjust, none, PadChar)
  840. end
  841. end.
  842. prefixedInt(Int, Width, Adjust, Base, PadChar, Prefix, Prefix2, Lowercase) ->
  843. case Int < 0 of
  844. true ->
  845. case Lowercase of
  846. true ->
  847. term(<<"-", (toBinary(Prefix))/binary, Prefix2:8, (toLowerStr(integer_to_binary(-Int, Base)))/binary>>, Width, Adjust, none, PadChar);
  848. _ ->
  849. term(<<"-", (toBinary(Prefix))/binary, Prefix2:8, (integer_to_binary(-Int, Base))/binary>>, Width, Adjust, none, PadChar)
  850. end;
  851. _ ->
  852. case Lowercase of
  853. true ->
  854. term(<<(toBinary(Prefix))/binary, Prefix2:8, (toLowerStr(integer_to_binary(Int, Base)))/binary>>, Width, Adjust, none, PadChar);
  855. _ ->
  856. term(<<(toBinary(Prefix))/binary, Prefix2:8, (integer_to_binary(Int, Base))/binary>>, Width, Adjust, none, PadChar)
  857. end
  858. end.
  859. char(Char, Width, Adjust, Precision, PadChar) ->
  860. if
  861. Width == none andalso Precision == none ->
  862. Char;
  863. Precision == none ->
  864. makePadChars(Char, Width, <<>>);
  865. Width == none ->
  866. makePadChars(Char, Precision, <<>>);
  867. true ->
  868. adjust(Adjust, makePadChars(Char, Precision, <<>>), makePadChars(PadChar, Width - Precision, <<>>))
  869. end.
  870. newline(none, _Adjust, _Precision, _PadChar) -> <<"\n">>;
  871. newline(Width, Adjust, _Precision, _PadChar) ->
  872. case Adjust of
  873. right ->
  874. makePadChars($\n, Width, <<>>);
  875. _ ->
  876. <<"\n">>
  877. end.
  878. remainChars(T, E) ->
  879. if
  880. T < 0 ->
  881. T;
  882. T >= E ->
  883. T - E;
  884. true ->
  885. 0
  886. end.
  887. %% ********************************************** eFmtFormat end *****************************************************
  888. %% ********************************************** utils start **********************************************************
  889. toLowerStr(BinStr) ->
  890. <<begin
  891. case C >= $A andalso C =< $Z of
  892. true ->
  893. <<(C + 32)>>;
  894. _ ->
  895. <<C>>
  896. end
  897. end || <<C:8>> <= BinStr
  898. >>.
  899. toUpperStr(BinStr) ->
  900. <<begin
  901. case C >= $a andalso C =< $z of
  902. true ->
  903. <<(C - 32)>>;
  904. _ ->
  905. <<C>>
  906. end
  907. end || <<C:8>> <= BinStr
  908. >>.
  909. -spec charsLen(chars()) -> non_neg_integer().
  910. charsLen(S) ->
  911. try
  912. iolist_size(S)
  913. catch
  914. _:_ ->
  915. string:length(S)
  916. end.
  917. getOpt(Key, TupleList, Default) ->
  918. case lists:keyfind(Key, 1, TupleList) of
  919. false ->
  920. Default;
  921. ValueTuple ->
  922. element(2, ValueTuple)
  923. end.
  924. toBinary(Value) when is_integer(Value) -> integer_to_binary(Value);
  925. toBinary(Value) when is_list(Value) -> list_to_binary(Value);
  926. toBinary(Value) when is_float(Value) -> float_to_binary(Value, [{decimals, 6}, compact]);
  927. toBinary(Value) when is_atom(Value) -> atom_to_binary(Value, utf8);
  928. toBinary(Value) when is_binary(Value) -> Value;
  929. toBinary(Value) -> term_to_binary(Value).
  930. visualList(L, Encoding) ->
  931. ?IIF(Encoding == latin1, visualLatin1List(L), visualUnicodeList(L, Encoding)).
  932. visualBin(Bin, Encoding) ->
  933. ?IIF(Encoding == latin1, visualLatin1Bin(Bin), visualUtf8Bin(Bin, io:printable_range())).
  934. visualLatin1List([]) -> true;
  935. visualLatin1List([C | Cs]) -> ?IIF(visualLatin1Char(C), visualLatin1List(Cs), false);
  936. visualLatin1List(_) -> false.
  937. visualUnicodeList([], _) -> true;
  938. visualUnicodeList([C | Cs], Encoding) -> ?IIF(visualUtf8Char(C, Encoding), visualUnicodeList(Cs, Encoding), false);
  939. visualUnicodeList(_, _) -> false.
  940. visualLatin1Bin(<<>>) -> true;
  941. visualLatin1Bin(<<C:8, Left/binary>>) -> ?IIF(visualLatin1Char(C), visualLatin1Bin(Left), false);
  942. visualLatin1Bin(_) -> false.
  943. visualUtf8Bin(<<>>, _) -> true;
  944. visualUtf8Bin(<<C/utf8, Left/binary>>, Range) -> ?IIF(visualUtf8Char(C, Range), visualUtf8Bin(Left, Range), false);
  945. visualUtf8Bin(_, _) -> false.
  946. visualLatin1Char($\n) -> true;
  947. visualLatin1Char($\r) -> true;
  948. visualLatin1Char($\t) -> true;
  949. visualLatin1Char($\v) -> true;
  950. visualLatin1Char($\b) -> true;
  951. visualLatin1Char($\f) -> true;
  952. visualLatin1Char($\e) -> true;
  953. visualLatin1Char(C) -> C >= $\040 andalso C =< $\176 orelse C >= $\240 andalso C =< $\377.
  954. visualUtf8Char($\n, _) -> true;
  955. visualUtf8Char($\r, _) -> true;
  956. visualUtf8Char($\t, _) -> true;
  957. visualUtf8Char($\v, _) -> true;
  958. visualUtf8Char($\b, _) -> true;
  959. visualUtf8Char($\f, _) -> true;
  960. visualUtf8Char($\e, _) -> true;
  961. visualUtf8Char(C, _Encoding) ->
  962. C >= $\s andalso C =< $~ orelse C >= 16#A0 andalso C < 16#D800 orelse C > 16#DFFF andalso C < 16#FFFE orelse C > 16#FFFF andalso C =< 16#10FFFF.
  963. %% case Encoding of
  964. %% latin1 ->
  965. %% C >= $\s andalso C =< $~ orelse C >= 16#A0 andalso C =< 16#FF;
  966. %% _ ->
  967. %% C >= $\s andalso C =< $~ orelse C >= 16#A0 andalso C < 16#D800 orelse C > 16#DFFF andalso C < 16#FFFE orelse C > 16#FFFF andalso C =< 16#10FFFF
  968. %% end.
  969. %% ********************************************** utils end **********************************************************