# HG changeset patch # User martin # Date 1526246169 25200 # Sun May 13 14:16:09 2018 -0700 # Node ID 42e605cdc50a17c7eb931f9226caad82670b16c8 # Parent 5bed0f4ce51bf729c64824c95412931d33c3c536 0000000: Optimize ZipCoder Reviewed-by: sherman diff --git a/src/java.base/share/classes/java/util/zip/ZipCoder.java b/src/java.base/share/classes/java/util/zip/ZipCoder.java --- a/src/java.base/share/classes/java/util/zip/ZipCoder.java +++ b/src/java.base/share/classes/java/util/zip/ZipCoder.java @@ -33,8 +33,6 @@ import java.nio.charset.CharsetEncoder; import java.nio.charset.CharacterCodingException; import java.nio.charset.CodingErrorAction; -import static java.nio.charset.StandardCharsets.UTF_8; - /** * Utility class for zipfile name and comment decoding and encoding */ @@ -46,9 +44,7 @@ class ZipCoder { static final class UTF8 extends ZipCoder { - UTF8(Charset utf8) { - super(utf8); - } + UTF8() { super(java.nio.charset.StandardCharsets.UTF_8); } @Override boolean isUTF8() { @@ -67,10 +63,10 @@ class ZipCoder { } // UTF_8.ArrayEn/Decoder is stateless, so make it singleton. - private static ZipCoder utf8 = new UTF8(UTF_8); + private static final ZipCoder utf8 = new UTF8(); public static ZipCoder get(Charset charset) { - if (charset == UTF_8) + if (charset == java.nio.charset.StandardCharsets.UTF_8) return utf8; return new ZipCoder(charset); } @@ -107,24 +103,23 @@ class ZipCoder { } } - // assume invoked only if "this" is not utf8 - byte[] getBytesUTF8(String s) { - return utf8.getBytes(s); + static byte[] getBytesUTF8(String s) { + return JLA.getBytesUTF8NoRepl(s); } - String toStringUTF8(byte[] ba, int len) { - return utf8.toString(ba, 0, len); + static String toStringUTF8(byte[] ba, int len) { + return JLA.newStringUTF8NoRepl(ba, 0, len); } - String toStringUTF8(byte[] ba, int off, int len) { - return utf8.toString(ba, off, len); + static String toStringUTF8(byte[] ba, int off, int len) { + return JLA.newStringUTF8NoRepl(ba, off, len); } boolean isUTF8() { return false; } - private Charset cs; + private final Charset cs; private CharsetDecoder dec; private CharsetEncoder enc; @@ -133,20 +128,18 @@ class ZipCoder { } protected CharsetDecoder decoder() { - if (dec == null) { - dec = cs.newDecoder() - .onMalformedInput(CodingErrorAction.REPORT) - .onUnmappableCharacter(CodingErrorAction.REPORT); - } - return dec; + final CharsetDecoder dec = this.dec; + return (dec != null) ? dec : + (this.dec = cs.newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT)); } protected CharsetEncoder encoder() { - if (enc == null) { - enc = cs.newEncoder() - .onMalformedInput(CodingErrorAction.REPORT) - .onUnmappableCharacter(CodingErrorAction.REPORT); - } - return enc; + final CharsetEncoder enc = this.enc; + return (enc != null) ? enc : + (this.enc = cs.newEncoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT)); } } diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -377,8 +377,8 @@ class ZipFile implements ZipConstants, C ensureOpen(); if (Objects.equals(lastEntryName, entry.name)) { pos = lastEntryPos; - } else if (!zc.isUTF8() && (entry.flag & EFS) != 0) { - pos = zsrc.getEntryPos(zc.getBytesUTF8(entry.name), false); + } else if (zc.isUTF8() || (entry.flag & EFS) != 0) { + pos = zsrc.getEntryPos(ZipCoder.getBytesUTF8(entry.name), false); } else { pos = zsrc.getEntryPos(zc.getBytes(entry.name), false); } @@ -555,6 +555,56 @@ class ZipFile implements ZipConstants, C } } + private static class MartinSpliterator extends Spliterators.AbstractIntSpliterator { + private int index; + private final @Stable int fence; + //private final @Stable byte[] cen; + private final @Stable int[] entries; + + MartinSpliterator(int fence, int[] entries) { + super(fence, Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.IMMUTABLE); + this.index = 0; + this.fence = fence; + this.entries = entries; + } + + @Override + public boolean tryAdvance(java.util.function.IntConsumer action) { + if (action == null) throw new NullPointerException(); + //if (closeRequested) throw new IllegalStateException("zip file closed"); + if (index >= fence) + return false; + action.accept(entries[(index++ * 3) + 2]); + return true; + } + } + + private Stream martinNames() { + final byte[] cen; + final java.util.stream.IntStream intStream; + synchronized (this) { + ensureOpen(); + cen = res.zsrc.cen; + intStream = StreamSupport.intStream( + new MartinSpliterator(res.zsrc.total, res.zsrc.entries), + false); + } + return (zc.isUTF8()) + ? intStream.mapToObj(i -> martinNameUTF8(zc, cen, i)) + : intStream.mapToObj(i -> martinName(zc, cen, i)); + } + + private static String martinNameUTF8(ZipCoder zc, byte[] cen, int pos) { + return ZipCoder.toStringUTF8(cen, pos + CENHDR, CENNAM(cen, pos)); + } + + private static String martinName(ZipCoder zc, byte[] cen, int pos) { + int nlen = CENNAM(cen, pos); + return ((CENFLG(cen, pos) & EFS) != 0) + ? ZipCoder.toStringUTF8(cen, pos + CENHDR, nlen) + : zc.toString(cen, pos + CENHDR, nlen); + } + private class EntrySpliterator extends Spliterators.AbstractSpliterator { private int index; private final int fence; @@ -606,7 +656,7 @@ class ZipFile implements ZipConstants, C byte[] cen = res.zsrc.cen; int nlen = CENNAM(cen, pos); if (!zc.isUTF8() && (CENFLG(cen, pos) & EFS) != 0) { - return zc.toStringUTF8(cen, pos + CENHDR, nlen); + return ZipCoder.toStringUTF8(cen, pos + CENHDR, nlen); } else { return zc.toString(cen, pos + CENHDR, nlen); } @@ -666,7 +716,7 @@ class ZipFile implements ZipConstants, C // (2) not equal to the name stored, a slash is appended during // getEntryPos() search. if (!zc.isUTF8() && (flag & EFS) != 0) { - name = zc.toStringUTF8(cen, pos + CENHDR, nlen); + name = ZipCoder.toStringUTF8(cen, pos + CENHDR, nlen); } else { name = zc.toString(cen, pos + CENHDR, nlen); } @@ -685,7 +735,7 @@ class ZipFile implements ZipConstants, C if (clen != 0) { int start = pos + CENHDR + nlen + elen; if (!zc.isUTF8() && (flag & EFS) != 0) { - e.comment = zc.toStringUTF8(cen, start, clen); + e.comment = ZipCoder.toStringUTF8(cen, start, clen); } else { e.comment = zc.toString(cen, start, clen); } diff --git a/src/java.base/share/classes/java/util/zip/ZipInputStream.java b/src/java.base/share/classes/java/util/zip/ZipInputStream.java --- a/src/java.base/share/classes/java/util/zip/ZipInputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipInputStream.java @@ -297,7 +297,7 @@ class ZipInputStream extends InflaterInp readFully(b, 0, len); // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8 ZipEntry e = createZipEntry(((flag & EFS) != 0) - ? zc.toStringUTF8(b, len) + ? ZipCoder.toStringUTF8(b, len) : zc.toString(b, len)); // now get the remaining fields for the entry if ((flag & 1) == 1) {