From 8b2705934fc8df02fd54dae20c1127faa1e3308d Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Tue, 12 Sep 2017 13:36:45 +0200 Subject: base64:decode(List) optimized reimplementation --- lib/stdlib/src/base64.erl | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl index 5885745fb1..0eea2c0f1a 100644 --- a/lib/stdlib/src/base64.erl +++ b/lib/stdlib/src/base64.erl @@ -115,7 +115,7 @@ encode_binary(Bin) -> decode(Bin) when is_binary(Bin) -> decode_binary(<<>>, Bin); decode(List) when is_list(List) -> - list_to_binary(decode_l(List)). + decode_list(<<>>, List). -spec mime_decode(Base64) -> Data when Base64 :: ascii_string() | ascii_binary(), @@ -262,6 +262,42 @@ mime_decode_binary_after_eq(Result0, <<>>, Eq) -> Result end. +decode_list(A, [C1 | Cs]) -> + case element(C1, ?DECODE_MAP) of + ws -> decode_list(A, Cs); + B1 -> decode_list(A, B1, Cs) + end; +decode_list(A, []) -> + A. + +decode_list(A, B1, [C2 | Cs]) -> + case element(C2, ?DECODE_MAP) of + ws -> decode_list(A, B1, Cs); + B2 -> decode_list(A, B1, B2, Cs) + end. + +decode_list(A, B1, B2, [C3 | Cs]) -> + case element(C3, ?DECODE_MAP) of + ws -> decode_list(A, B1, B2, Cs); + B3 -> decode_list(A, B1, B2, B3, Cs) + end. + +decode_list(A, B1, B2, B3, [C4 | Cs]) -> + case element(C4, ?DECODE_MAP) of + ws -> decode_list(A, B1, B2, B3, Cs); + eq when B3 =:= eq -> only_ws(<>, Cs); + eq -> only_ws(<>, Cs); + B4 -> decode_list(<>, Cs) + end. + +only_ws(A, []) -> + A; +only_ws(A, [C | Cs]) -> + case element(C, ?DECODE_MAP) of + ws -> only_ws(A, Cs); + _ -> erlang:error(function_clause) + end. + decode([], A) -> A; decode([$=,$=,C2,C1|Cs], A) -> Bits2x6 = (b64d(C1) bsl 18) bor (b64d(C2) bsl 12), -- cgit v1.2.3 From ec2b785a09959b7c0a85ac8e9ad9b36e7b2166a3 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Sun, 24 Sep 2017 12:46:28 +0200 Subject: base64:decode(List) put the List parameter first for improved performance --- lib/stdlib/src/base64.erl | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl index 0eea2c0f1a..6e96f7d1f7 100644 --- a/lib/stdlib/src/base64.erl +++ b/lib/stdlib/src/base64.erl @@ -115,7 +115,7 @@ encode_binary(Bin) -> decode(Bin) when is_binary(Bin) -> decode_binary(<<>>, Bin); decode(List) when is_list(List) -> - decode_list(<<>>, List). + decode_list(List, <<>>). -spec mime_decode(Base64) -> Data when Base64 :: ascii_string() | ascii_binary(), @@ -262,39 +262,39 @@ mime_decode_binary_after_eq(Result0, <<>>, Eq) -> Result end. -decode_list(A, [C1 | Cs]) -> +decode_list([C1 | Cs], A) -> case element(C1, ?DECODE_MAP) of - ws -> decode_list(A, Cs); - B1 -> decode_list(A, B1, Cs) + ws -> decode_list(Cs, A); + B1 -> decode_list(Cs, A, B1) end; -decode_list(A, []) -> +decode_list([], A) -> A. -decode_list(A, B1, [C2 | Cs]) -> +decode_list([C2 | Cs], A, B1) -> case element(C2, ?DECODE_MAP) of - ws -> decode_list(A, B1, Cs); - B2 -> decode_list(A, B1, B2, Cs) + ws -> decode_list(Cs, A, B1); + B2 -> decode_list(Cs, A, B1, B2) end. -decode_list(A, B1, B2, [C3 | Cs]) -> +decode_list([C3 | Cs], A, B1, B2) -> case element(C3, ?DECODE_MAP) of - ws -> decode_list(A, B1, B2, Cs); - B3 -> decode_list(A, B1, B2, B3, Cs) + ws -> decode_list(Cs, A, B1, B2); + B3 -> decode_list(Cs, A, B1, B2, B3) end. -decode_list(A, B1, B2, B3, [C4 | Cs]) -> +decode_list([C4 | Cs], A, B1, B2, B3) -> case element(C4, ?DECODE_MAP) of - ws -> decode_list(A, B1, B2, B3, Cs); - eq when B3 =:= eq -> only_ws(<>, Cs); - eq -> only_ws(<>, Cs); - B4 -> decode_list(<>, Cs) + ws -> decode_list(Cs, A, B1, B2, B3); + eq when B3 =:= eq -> only_ws(Cs, <>); + eq -> only_ws(Cs, <>); + B4 -> decode_list(Cs, <>) end. -only_ws(A, []) -> +only_ws([], A) -> A; -only_ws(A, [C | Cs]) -> +only_ws([C | Cs], A) -> case element(C, ?DECODE_MAP) of - ws -> only_ws(A, Cs); + ws -> only_ws(Cs, A); _ -> erlang:error(function_clause) end. -- cgit v1.2.3 From d14f1512b01261c1cfdff2effe587118d9ddc012 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Mon, 25 Sep 2017 22:11:28 +0200 Subject: base64:decode(Binary) optimized reimplementation --- lib/stdlib/src/base64.erl | 70 +++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl index 6e96f7d1f7..c8cf6fdffe 100644 --- a/lib/stdlib/src/base64.erl +++ b/lib/stdlib/src/base64.erl @@ -113,7 +113,7 @@ encode_binary(Bin) -> Data :: ascii_binary(). decode(Bin) when is_binary(Bin) -> - decode_binary(<<>>, Bin); + decode_binary(Bin, <<>>); decode(List) when is_list(List) -> decode_list(List, <<>>). @@ -186,31 +186,41 @@ mime_decode_to_string(List) when is_list(List) -> bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad}). -decode_binary(Result0, <>) -> - case element(C, ?DECODE_MAP) of - bad -> - erlang:error({badarg,C}); - ws -> - decode_binary(Result0, T0); - eq -> - case strip_ws(T0) of - <<$=:8,T/binary>> -> - <<>> = strip_ws(T), - Split = byte_size(Result0) - 1, - <> = Result0, - Result; - T -> - <<>> = strip_ws(T), - Split = byte_size(Result0) - 1, - <> = Result0, - Result - end; - Bits -> - decode_binary(<>, T0) +decode_binary(<>, A) -> + case element(C1, ?DECODE_MAP) of + ws -> decode_binary(Cs, A); + B1 -> decode_binary(Cs, A, B1) end; -decode_binary(Result, <<>>) -> - true = is_binary(Result), - Result. +decode_binary(<<>>, A) -> + A. + +decode_binary(<>, A, B1) -> + case element(C2, ?DECODE_MAP) of + ws -> decode_binary(Cs, A, B1); + B2 -> decode_binary(Cs, A, B1, B2) + end. + +decode_binary(<>, A, B1, B2) -> + case element(C3, ?DECODE_MAP) of + ws -> decode_binary(Cs, A, B1, B2); + B3 -> decode_binary(Cs, A, B1, B2, B3) + end. + +decode_binary(<>, A, B1, B2, B3) -> + case element(C4, ?DECODE_MAP) of + ws -> decode_binary(Cs, A, B1, B2, B3); + eq when B3 =:= eq -> only_ws_binary(Cs, <>); + eq -> only_ws_binary(Cs, <>); + B4 -> decode_binary(Cs, <>) + end. + +only_ws_binary(<<>>, A) -> + A; +only_ws_binary(<>, A) -> + case element(C, ?DECODE_MAP) of + ws -> only_ws_binary(Cs, A); + _ -> erlang:error(function_clause) + end. %% Skipping pad character if not at end of string. Also liberal about %% excess padding and skipping of other illegal (non-base64 alphabet) @@ -328,16 +338,6 @@ strip_spaces([$\r|Cs], A) -> strip_spaces(Cs, A); strip_spaces([$\n|Cs], A) -> strip_spaces(Cs, A); strip_spaces([C|Cs], A) -> strip_spaces(Cs, [C | A]). -strip_ws(<<$\t,T/binary>>) -> - strip_ws(T); -strip_ws(<<$\n,T/binary>>) -> - strip_ws(T); -strip_ws(<<$\r,T/binary>>) -> - strip_ws(T); -strip_ws(<<$\s,T/binary>>) -> - strip_ws(T); -strip_ws(T) -> T. - %% Skipping pad character if not at end of string. Also liberal about %% excess padding and skipping of other illegal (non-base64 alphabet) %% characters. See section 3.3 of RFC4648 -- cgit v1.2.3