aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src
diff options
context:
space:
mode:
authorDan Gudmundsson <[email protected]>2015-08-26 12:59:28 +0200
committerDan Gudmundsson <[email protected]>2015-08-26 12:59:28 +0200
commitbfdc9f97f1738d072d09b98a8980b0b59639db0b (patch)
tree43e14fa64e0bd13f4960914b2b90ab0f422a7580 /lib/stdlib/src
parentc830c78c88684f0f88f2c50941ed73e7829abba8 (diff)
parent02abeffc9d753b5fcd1ce7da93f437887f574bad (diff)
downloadotp-bfdc9f97f1738d072d09b98a8980b0b59639db0b.tar.gz
otp-bfdc9f97f1738d072d09b98a8980b0b59639db0b.tar.bz2
otp-bfdc9f97f1738d072d09b98a8980b0b59639db0b.zip
Merge branch 'dgud/stdlib/zip-optimize/OTP-12950' into maint
* dgud/stdlib/zip-optimize/OTP-12950: Optimize zip:unzip/2 when uncompressing to memory
Diffstat (limited to 'lib/stdlib/src')
-rw-r--r--lib/stdlib/src/zip.erl68
1 files changed, 22 insertions, 46 deletions
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index d6031dabbc..bec0bd3f6d 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -1550,57 +1550,33 @@ unix_extra_field_and_var_from_bin(_) ->
%% A pwrite-like function for iolists (used by memory-option)
-split_iolist(B, Pos) when is_binary(B) ->
- split_binary(B, Pos);
-split_iolist(L, Pos) when is_list(L) ->
- splitter([], L, Pos).
-
-splitter(Left, Right, 0) ->
- {Left, Right};
-splitter(Left, [A | Right], RelPos) when is_list(A) or is_binary(A) ->
- Sz = erlang:iolist_size(A),
- case Sz > RelPos of
- true ->
- {Leftx, Rightx} = split_iolist(A, RelPos),
- {[Left | Leftx], [Rightx, Right]};
- _ ->
- splitter([Left | A], Right, RelPos - Sz)
- end;
-splitter(Left, [A | Right], RelPos) when is_integer(A) ->
- splitter([Left, A], Right, RelPos - 1);
-splitter(Left, Right, RelPos) when is_binary(Right) ->
- splitter(Left, [Right], RelPos).
+pwrite_binary(B, Pos, Bin) when byte_size(B) =:= Pos ->
+ append_bins(Bin, B);
+pwrite_binary(B, Pos, Bin) ->
+ erlang:iolist_to_binary(pwrite_iolist(B, Pos, Bin)).
-skip_iolist(B, Pos) when is_binary(B) ->
- case B of
- <<_:Pos/binary, Bin/binary>> -> Bin;
- _ -> <<>>
- end;
-skip_iolist(L, Pos) when is_list(L) ->
- skipper(L, Pos).
-
-skipper(Right, 0) ->
- Right;
-skipper([A | Right], RelPos) when is_list(A) or is_binary(A) ->
- Sz = erlang:iolist_size(A),
- case Sz > RelPos of
- true ->
- Rightx = skip_iolist(A, RelPos),
- [Rightx, Right];
- _ ->
- skip_iolist(Right, RelPos - Sz)
- end;
-skipper([A | Right], RelPos) when is_integer(A) ->
- skip_iolist(Right, RelPos - 1).
+append_bins([Bin|Bins], B) when is_binary(Bin) ->
+ append_bins(Bins, <<B/binary, Bin/binary>>);
+append_bins([List|Bins], B) when is_list(List) ->
+ append_bins(Bins, append_bins(List, B));
+append_bins(Bin, B) when is_binary(Bin) ->
+ <<B/binary, Bin/binary>>;
+append_bins([_|_]=List, B) ->
+ <<B/binary, (iolist_to_binary(List))/binary>>;
+append_bins([], B) ->
+ B.
-pwrite_iolist(Iolist, Pos, Bin) ->
- {Left, Right} = split_iolist(Iolist, Pos),
+pwrite_iolist(B, Pos, Bin) ->
+ {Left, Right} = split_binary(B, Pos),
Sz = erlang:iolist_size(Bin),
- R = skip_iolist(Right, Sz),
+ R = skip_bin(Right, Sz),
[Left, Bin | R].
-pwrite_binary(B, Pos, Bin) ->
- erlang:iolist_to_binary(pwrite_iolist(B, Pos, Bin)).
+skip_bin(B, Pos) when is_binary(B) ->
+ case B of
+ <<_:Pos/binary, Bin/binary>> -> Bin;
+ _ -> <<>>
+ end.
%% ZIP header manipulations