aboutsummaryrefslogtreecommitdiff
path: root/java/com
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 01:06:44 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 01:06:44 +0000
commit528201492371d0e43dc1ceaa0cad22c0ae690d36 (patch)
tree0baa92251e9c2c2d2522d953021138893ae84133 /java/com
parentf8ef2ae5e79b3ca6ed5f1bcae0550ff0491b9933 (diff)
parentd4be1f10b831f4c3774091c74e4b904ec6450c9a (diff)
downloadturbine-aml_wif_341410080.tar.gz
Change-Id: I99a8d37bfdd2a99732d853191173908eb094c683
Diffstat (limited to 'java/com')
-rw-r--r--java/com/google/turbine/binder/FileManagerClassBinder.java5
-rw-r--r--java/com/google/turbine/bytecode/ByteReader.java2
-rw-r--r--java/com/google/turbine/bytecode/ClassReader.java20
-rw-r--r--java/com/google/turbine/main/Main.java10
-rw-r--r--java/com/google/turbine/options/LanguageVersion.java2
-rw-r--r--java/com/google/turbine/parse/ConstExpressionParser.java6
-rw-r--r--java/com/google/turbine/parse/Parser.java8
-rw-r--r--java/com/google/turbine/parse/StreamLexer.java162
-rw-r--r--java/com/google/turbine/processing/TurbineElements.java2
-rw-r--r--java/com/google/turbine/processing/TurbineFiler.java7
-rw-r--r--java/com/google/turbine/processing/TurbineTypes.java59
-rw-r--r--java/com/google/turbine/type/Type.java21
-rw-r--r--java/com/google/turbine/zip/Zip.java41
13 files changed, 252 insertions, 93 deletions
diff --git a/java/com/google/turbine/binder/FileManagerClassBinder.java b/java/com/google/turbine/binder/FileManagerClassBinder.java
index d36d2d8..a807dd7 100644
--- a/java/com/google/turbine/binder/FileManagerClassBinder.java
+++ b/java/com/google/turbine/binder/FileManagerClassBinder.java
@@ -19,7 +19,6 @@ package com.google.turbine.binder;
import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
-import com.google.common.io.ByteStreams;
import com.google.turbine.binder.bound.ModuleInfo;
import com.google.turbine.binder.bytecode.BytecodeBoundClass;
import com.google.turbine.binder.env.Env;
@@ -113,7 +112,7 @@ public final class FileManagerClassBinder {
@Override
public byte[] get() {
try {
- return ByteStreams.toByteArray(jfo.openInputStream());
+ return jfo.openInputStream().readAllBytes();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
@@ -162,7 +161,7 @@ public final class FileManagerClassBinder {
@Override
public byte[] get() {
try {
- return ByteStreams.toByteArray(fileObject.openInputStream());
+ return fileObject.openInputStream().readAllBytes();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
diff --git a/java/com/google/turbine/bytecode/ByteReader.java b/java/com/google/turbine/bytecode/ByteReader.java
index a9deff2..5458b49 100644
--- a/java/com/google/turbine/bytecode/ByteReader.java
+++ b/java/com/google/turbine/bytecode/ByteReader.java
@@ -20,11 +20,9 @@ import static com.google.common.base.Verify.verify;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.ByteArrayInputStream;
/** A {@link ByteArrayDataInput} wrapper that tracks the current byte array index. */
-@CanIgnoreReturnValue
public class ByteReader {
private final byte[] bytes;
diff --git a/java/com/google/turbine/bytecode/ClassReader.java b/java/com/google/turbine/bytecode/ClassReader.java
index 740026a..da35196 100644
--- a/java/com/google/turbine/bytecode/ClassReader.java
+++ b/java/com/google/turbine/bytecode/ClassReader.java
@@ -159,7 +159,7 @@ public class ClassReader {
/** Reads a JVMS 4.7.9 Signature attribute. */
private String readSignature(ConstantPoolReader constantPool) {
String signature;
- reader.u4(); // length
+ int unusedLength = reader.u4();
signature = constantPool.utf8(reader.u2());
return signature;
}
@@ -167,7 +167,7 @@ public class ClassReader {
/** Reads JVMS 4.7.6 InnerClasses attributes. */
private List<ClassFile.InnerClass> readInnerClasses(
ConstantPoolReader constantPool, String thisClass) {
- reader.u4(); // length
+ int unusedLength = reader.u4();
int numberOfClasses = reader.u2();
List<ClassFile.InnerClass> innerclasses = new ArrayList<>();
for (int i = 0; i < numberOfClasses; i++) {
@@ -197,7 +197,7 @@ public class ClassReader {
private void readAnnotations(
ImmutableList.Builder<ClassFile.AnnotationInfo> annotations,
ConstantPoolReader constantPool) {
- reader.u4(); // length
+ int unusedLength = reader.u4();
int numAnnotations = reader.u2();
for (int n = 0; n < numAnnotations; n++) {
annotations.add(readAnnotation(constantPool));
@@ -207,7 +207,7 @@ public class ClassReader {
/** Processes a JVMS 4.7.18 RuntimeVisibleParameterAnnotations attribute */
public void readParameterAnnotations(
List<ImmutableList.Builder<AnnotationInfo>> annotations, ConstantPoolReader constantPool) {
- reader.u4(); // length
+ int unusedLength = reader.u4();
int numParameters = reader.u1();
while (annotations.size() < numParameters) {
annotations.add(ImmutableList.builder());
@@ -223,7 +223,7 @@ public class ClassReader {
/** Processes a JVMS 4.7.24 MethodParameters attribute. */
private void readMethodParameters(
ImmutableList.Builder<ParameterInfo> parameters, ConstantPoolReader constantPool) {
- reader.u4(); // length
+ int unusedLength = reader.u4();
int numParameters = reader.u1();
for (int i = 0; i < numParameters; i++) {
String name = constantPool.utf8(reader.u2());
@@ -239,7 +239,7 @@ public class ClassReader {
/** Processes a JVMS 4.7.25 Module attribute. */
private ModuleInfo readModule(ConstantPoolReader constantPool) {
- reader.u4(); // length
+ int unusedLength = reader.u4();
String name = constantPool.moduleInfo(reader.u2());
int flags = reader.u2();
int versionIndex = reader.u2();
@@ -423,7 +423,7 @@ public class ClassReader {
signature = readSignature(constantPool);
break;
case "AnnotationDefault":
- reader.u4(); // length
+ int unusedLength = reader.u4();
defaultValue = readElementValue(constantPool);
break;
case "RuntimeInvisibleAnnotations":
@@ -470,7 +470,7 @@ public class ClassReader {
/** Reads an Exceptions attribute. */
private ImmutableList<String> readExceptions(ConstantPoolReader constantPool) {
ImmutableList.Builder<String> exceptions = ImmutableList.builder();
- reader.u4(); // length
+ int unusedLength = reader.u4();
int numberOfExceptions = reader.u2();
for (int exceptionIndex = 0; exceptionIndex < numberOfExceptions; exceptionIndex++) {
exceptions.add(constantPool.classInfo(reader.u2()));
@@ -496,7 +496,7 @@ public class ClassReader {
String attributeName = constantPool.utf8(reader.u2());
switch (attributeName) {
case "ConstantValue":
- reader.u4(); // length
+ int unusedLength = reader.u4();
value = constantPool.constant(reader.u2());
break;
case "RuntimeInvisibleAnnotations":
@@ -525,7 +525,7 @@ public class ClassReader {
}
private String readTurbineTransitiveJar(ConstantPoolReader constantPool) {
- reader.u4(); // length
+ int unusedLength = reader.u4();
return constantPool.utf8(reader.u2());
}
}
diff --git a/java/com/google/turbine/main/Main.java b/java/com/google/turbine/main/Main.java
index da97bcd..34984a8 100644
--- a/java/com/google/turbine/main/Main.java
+++ b/java/com/google/turbine/main/Main.java
@@ -58,7 +58,6 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
-import java.time.ZoneId;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
@@ -433,16 +432,11 @@ public final class Main {
}
/** Normalize timestamps. */
- static final long DEFAULT_TIMESTAMP =
- LocalDateTime.of(2010, 1, 1, 0, 0, 0)
- .atZone(ZoneId.systemDefault())
- .toInstant()
- .toEpochMilli();
+ static final LocalDateTime DEFAULT_TIMESTAMP = LocalDateTime.of(2010, 1, 1, 0, 0, 0);
private static void addEntry(JarOutputStream jos, String name, byte[] bytes) throws IOException {
JarEntry je = new JarEntry(name);
- // TODO(cushon): switch to setLocalTime after we migrate to JDK 9
- je.setTime(DEFAULT_TIMESTAMP);
+ je.setTimeLocal(DEFAULT_TIMESTAMP);
je.setMethod(ZipEntry.STORED);
je.setSize(bytes.length);
je.setCrc(Hashing.crc32().hashBytes(bytes).padToLong());
diff --git a/java/com/google/turbine/options/LanguageVersion.java b/java/com/google/turbine/options/LanguageVersion.java
index e2b0ea7..d8641b4 100644
--- a/java/com/google/turbine/options/LanguageVersion.java
+++ b/java/com/google/turbine/options/LanguageVersion.java
@@ -53,7 +53,7 @@ public abstract class LanguageVersion {
try {
return SourceVersion.valueOf("RELEASE_" + source());
} catch (IllegalArgumentException unused) {
- throw new IllegalArgumentException("invalid -source version: " + source());
+ return SourceVersion.latestSupported();
}
}
diff --git a/java/com/google/turbine/parse/ConstExpressionParser.java b/java/com/google/turbine/parse/ConstExpressionParser.java
index 8b7466f..e4aad6b 100644
--- a/java/com/google/turbine/parse/ConstExpressionParser.java
+++ b/java/com/google/turbine/parse/ConstExpressionParser.java
@@ -588,11 +588,11 @@ public class ConstExpressionParser {
}
eat();
int pos = position;
- Tree.ConstVarName constVarName = (Tree.ConstVarName) qualIdent();
- if (constVarName == null) {
+ Expression constVarName = qualIdent();
+ if (!(constVarName instanceof Tree.ConstVarName)) {
return null;
}
- ImmutableList<Ident> name = constVarName.name();
+ ImmutableList<Ident> name = ((Tree.ConstVarName) constVarName).name();
ImmutableList.Builder<Tree.Expression> args = ImmutableList.builder();
if (token == Token.LPAREN) {
eat();
diff --git a/java/com/google/turbine/parse/Parser.java b/java/com/google/turbine/parse/Parser.java
index c370ad8..acf84d7 100644
--- a/java/com/google/turbine/parse/Parser.java
+++ b/java/com/google/turbine/parse/Parser.java
@@ -547,6 +547,7 @@ public class Parser {
switch (token) {
case IDENT:
{
+ String javadoc = lexer.javadoc();
Ident name = eatIdent();
if (token == Token.LPAREN) {
dropParens();
@@ -569,7 +570,7 @@ public class Parser {
ImmutableList.of()),
name,
Optional.<Expression>empty(),
- null));
+ javadoc));
annos = ImmutableList.builder();
break;
}
@@ -719,6 +720,11 @@ public class Parser {
case IDENT:
Ident ident = ident();
+ if (ident.value().equals("sealed")) {
+ next();
+ access.add(TurbineModifier.SEALED);
+ break;
+ }
if (ident.value().equals("non")) {
int pos = position;
next();
diff --git a/java/com/google/turbine/parse/StreamLexer.java b/java/com/google/turbine/parse/StreamLexer.java
index 2348385..3d46b90 100644
--- a/java/com/google/turbine/parse/StreamLexer.java
+++ b/java/com/google/turbine/parse/StreamLexer.java
@@ -17,8 +17,11 @@
package com.google.turbine.parse;
import static com.google.common.base.Verify.verify;
+import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.turbine.parse.UnicodeEscapePreprocessor.ASCII_SUB;
+import static java.lang.Math.min;
+import com.google.common.collect.ImmutableList;
import com.google.turbine.diag.SourceFile;
import com.google.turbine.diag.TurbineError;
import com.google.turbine.diag.TurbineError.ErrorKind;
@@ -399,6 +402,15 @@ public class StreamLexer implements Lexer {
case '"':
{
eat();
+ if (ch == '"') {
+ eat();
+ if (ch != '"') {
+ saveValue("");
+ return Token.STRING_LITERAL;
+ }
+ eat();
+ return textBlock();
+ }
readFrom();
StringBuilder sb = new StringBuilder();
STRING:
@@ -436,6 +448,156 @@ public class StreamLexer implements Lexer {
}
}
+ private Token textBlock() {
+ OUTER:
+ while (true) {
+ switch (ch) {
+ case ' ':
+ case '\r':
+ case '\t':
+ eat();
+ break;
+ default:
+ break OUTER;
+ }
+ }
+ switch (ch) {
+ case '\r':
+ eat();
+ if (ch == '\n') {
+ eat();
+ }
+ break;
+ case '\n':
+ eat();
+ break;
+ default:
+ throw inputError();
+ }
+ readFrom();
+ StringBuilder sb = new StringBuilder();
+ while (true) {
+ switch (ch) {
+ case '"':
+ eat();
+ if (ch != '"') {
+ sb.append("\"");
+ continue;
+ }
+ eat();
+ if (ch != '"') {
+ sb.append("\"\"");
+ continue;
+ }
+ eat();
+ String value = sb.toString();
+ value = stripIndent(value);
+ value = translateEscapes(value);
+ saveValue(value);
+ return Token.STRING_LITERAL;
+ case ASCII_SUB:
+ if (reader.done()) {
+ return Token.EOF;
+ }
+ // falls through
+ default:
+ sb.appendCodePoint(ch);
+ eat();
+ continue;
+ }
+ }
+ }
+
+ static String stripIndent(String value) {
+ if (value.isEmpty()) {
+ return value;
+ }
+ ImmutableList<String> lines = value.lines().collect(toImmutableList());
+ // the amount of whitespace to strip from the beginning of every line
+ int strip = Integer.MAX_VALUE;
+ char last = value.charAt(value.length() - 1);
+ boolean trailingNewline = last == '\n' || last == '\r';
+ if (trailingNewline) {
+ // If the input contains a trailing newline, we have something like:
+ //
+ // |String s = """
+ // | foo
+ // |""";
+ //
+ // Because the final """ is unindented, nothing should be stripped.
+ strip = 0;
+ } else {
+ // find the longest common prefix of whitespace across all non-blank lines
+ for (int i = 0; i < lines.size(); i++) {
+ String line = lines.get(i);
+ int nonWhitespaceStart = nonWhitespaceStart(line);
+ if (nonWhitespaceStart == line.length()) {
+ continue;
+ }
+ strip = min(strip, nonWhitespaceStart);
+ }
+ }
+ StringBuilder result = new StringBuilder();
+ boolean first = true;
+ for (String line : lines) {
+ if (!first) {
+ result.append('\n');
+ }
+ int end = trailingWhitespaceStart(line);
+ if (strip <= end) {
+ result.append(line, strip, end);
+ }
+ first = false;
+ }
+ if (trailingNewline) {
+ result.append('\n');
+ }
+ return result.toString();
+ }
+
+ private static int nonWhitespaceStart(String value) {
+ int i = 0;
+ while (i < value.length() && Character.isWhitespace(value.charAt(i))) {
+ i++;
+ }
+ return i;
+ }
+
+ private static int trailingWhitespaceStart(String value) {
+ int i = value.length() - 1;
+ while (i >= 0 && Character.isWhitespace(value.charAt(i))) {
+ i--;
+ }
+ return i + 1;
+ }
+
+ private static String translateEscapes(String value) {
+ StreamLexer lexer =
+ new StreamLexer(new UnicodeEscapePreprocessor(new SourceFile(null, value + ASCII_SUB)));
+ return lexer.translateEscapes();
+ }
+
+ private String translateEscapes() {
+ readFrom();
+ StringBuilder sb = new StringBuilder();
+ OUTER:
+ while (true) {
+ switch (ch) {
+ case '\\':
+ eat();
+ sb.append(escape());
+ continue;
+ case ASCII_SUB:
+ break OUTER;
+ default:
+ sb.appendCodePoint(ch);
+ eat();
+ continue;
+ }
+ }
+ return sb.toString();
+ }
+
private char escape() {
boolean zeroToThree = false;
switch (ch) {
diff --git a/java/com/google/turbine/processing/TurbineElements.java b/java/com/google/turbine/processing/TurbineElements.java
index b5fd7f4..9b3ea26 100644
--- a/java/com/google/turbine/processing/TurbineElements.java
+++ b/java/com/google/turbine/processing/TurbineElements.java
@@ -384,7 +384,7 @@ public class TurbineElements implements Elements {
return false;
}
TypeMirror a = overrider.asType();
- TypeMirror b = types.asMemberOf((DeclaredType) type.asType(), overridden);
+ TypeMirror b = types.asMemberOfInternal((DeclaredType) type.asType(), overridden);
if (b == null) {
return false;
}
diff --git a/java/com/google/turbine/processing/TurbineFiler.java b/java/com/google/turbine/processing/TurbineFiler.java
index 45cdc22..8c522ba 100644
--- a/java/com/google/turbine/processing/TurbineFiler.java
+++ b/java/com/google/turbine/processing/TurbineFiler.java
@@ -24,7 +24,6 @@ import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
-import com.google.common.io.ByteStreams;
import com.google.turbine.diag.SourceFile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -232,7 +231,7 @@ public class TurbineFiler implements Filer {
@Override
public URI toUri() {
- return URI.create("file://" + path);
+ return URI.create("file:///" + path);
}
@Override
@@ -309,7 +308,7 @@ public class TurbineFiler implements Filer {
@Override
public URI toUri() {
- return URI.create("file://" + name + kind.extension);
+ return URI.create("file:///" + name + kind.extension);
}
@Override
@@ -380,7 +379,7 @@ public class TurbineFiler implements Filer {
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
- return new String(ByteStreams.toByteArray(openInputStream()), UTF_8);
+ return new String(openInputStream().readAllBytes(), UTF_8);
}
}
diff --git a/java/com/google/turbine/processing/TurbineTypes.java b/java/com/google/turbine/processing/TurbineTypes.java
index d2068dd..467059c 100644
--- a/java/com/google/turbine/processing/TurbineTypes.java
+++ b/java/com/google/turbine/processing/TurbineTypes.java
@@ -26,18 +26,11 @@ import com.google.common.collect.ImmutableMap;
import com.google.turbine.binder.bound.TypeBoundClass;
import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo;
import com.google.turbine.binder.sym.ClassSymbol;
-import com.google.turbine.binder.sym.FieldSymbol;
-import com.google.turbine.binder.sym.MethodSymbol;
-import com.google.turbine.binder.sym.ParamSymbol;
-import com.google.turbine.binder.sym.RecordComponentSymbol;
import com.google.turbine.binder.sym.Symbol;
import com.google.turbine.binder.sym.TyVarSymbol;
import com.google.turbine.model.TurbineConstantTypeKind;
import com.google.turbine.model.TurbineTyKind;
-import com.google.turbine.processing.TurbineElement.TurbineExecutableElement;
-import com.google.turbine.processing.TurbineElement.TurbineFieldElement;
import com.google.turbine.processing.TurbineElement.TurbineTypeElement;
-import com.google.turbine.processing.TurbineElement.TurbineTypeParameterElement;
import com.google.turbine.processing.TurbineTypeMirror.TurbineDeclaredType;
import com.google.turbine.processing.TurbineTypeMirror.TurbineErrorType;
import com.google.turbine.processing.TurbineTypeMirror.TurbineTypeVariable;
@@ -1127,41 +1120,6 @@ public class TurbineTypes implements Types {
.build()));
}
- private static ClassSymbol enclosingClass(Symbol symbol) {
- switch (symbol.symKind()) {
- case CLASS:
- return (ClassSymbol) symbol;
- case TY_PARAM:
- return enclosingClass(((TyVarSymbol) symbol).owner());
- case METHOD:
- return ((MethodSymbol) symbol).owner();
- case FIELD:
- return ((FieldSymbol) symbol).owner();
- case PARAMETER:
- return ((ParamSymbol) symbol).owner().owner();
- case RECORD_COMPONENT:
- return ((RecordComponentSymbol) symbol).owner();
- case MODULE:
- case PACKAGE:
- throw new IllegalArgumentException(symbol.symKind().toString());
- }
- throw new AssertionError(symbol.symKind());
- }
-
- private static Type type(Element element) {
- switch (element.getKind()) {
- case TYPE_PARAMETER:
- return TyVar.create(((TurbineTypeParameterElement) element).sym(), ImmutableList.of());
- case FIELD:
- return ((TurbineFieldElement) element).info().type();
- case METHOD:
- case CONSTRUCTOR:
- return ((TurbineExecutableElement) element).info().asType();
- default:
- throw new UnsupportedOperationException(element.toString());
- }
- }
-
/**
* Returns the {@link TypeMirror} of the given {@code element} as a member of {@code containing},
* or else {@code null} if it is not a member.
@@ -1171,13 +1129,24 @@ public class TurbineTypes implements Types {
*/
@Override
public TypeMirror asMemberOf(DeclaredType containing, Element element) {
+ TypeMirror result = asMemberOfInternal(containing, element);
+ if (result == null) {
+ throw new IllegalArgumentException(String.format("asMemberOf(%s, %s)", containing, element));
+ }
+ return result;
+ }
+
+ public @Nullable TypeMirror asMemberOfInternal(DeclaredType containing, Element element) {
ClassTy c = ((TurbineDeclaredType) containing).asTurbineType();
- ClassSymbol symbol = enclosingClass(((TurbineElement) element).sym());
- ImmutableList<ClassTy> path = factory.cha().search(c, enclosingClass(symbol));
+ Symbol enclosing = ((TurbineElement) element.getEnclosingElement()).sym();
+ if (!enclosing.symKind().equals(Symbol.Kind.CLASS)) {
+ return null;
+ }
+ ImmutableList<ClassTy> path = factory.cha().search(c, (ClassSymbol) enclosing);
if (path.isEmpty()) {
return null;
}
- Type type = type(element);
+ Type type = asTurbineType(element.asType());
for (ClassTy ty : path) {
ImmutableMap<TyVarSymbol, Type> mapping = getMapping(ty);
if (mapping == null) {
diff --git a/java/com/google/turbine/type/Type.java b/java/com/google/turbine/type/Type.java
index 085346a..5fbf1b1 100644
--- a/java/com/google/turbine/type/Type.java
+++ b/java/com/google/turbine/type/Type.java
@@ -17,6 +17,7 @@
package com.google.turbine.type;
import static com.google.common.collect.Iterables.getLast;
+import static java.lang.Math.max;
import static java.util.Objects.requireNonNull;
import com.google.auto.value.AutoValue;
@@ -144,15 +145,23 @@ public interface Type {
StringBuilder sb = new StringBuilder();
boolean first = true;
for (SimpleClassTy c : classes()) {
- for (AnnoInfo anno : c.annos()) {
- sb.append(anno);
- sb.append(' ');
- }
+ String binaryName = c.sym().binaryName();
if (!first) {
+ for (AnnoInfo anno : c.annos()) {
+ sb.append(anno);
+ sb.append(' ');
+ }
sb.append('.');
- sb.append(c.sym().binaryName().substring(c.sym().binaryName().lastIndexOf('$') + 1));
+ sb.append(binaryName, binaryName.lastIndexOf('$') + 1, binaryName.length());
} else {
- sb.append(c.sym().binaryName().replace('/', '.').replace('$', '.'));
+ int idx = max(binaryName.lastIndexOf('/'), binaryName.lastIndexOf('$')) + 1;
+ String name = binaryName.replace('/', '.').replace('$', '.');
+ sb.append(name, 0, idx);
+ for (AnnoInfo anno : c.annos()) {
+ sb.append(anno);
+ sb.append(' ');
+ }
+ sb.append(name, idx, name.length());
}
if (!c.targs().isEmpty()) {
sb.append('<');
diff --git a/java/com/google/turbine/zip/Zip.java b/java/com/google/turbine/zip/Zip.java
index fa0f0e0..c08999b 100644
--- a/java/com/google/turbine/zip/Zip.java
+++ b/java/com/google/turbine/zip/Zip.java
@@ -18,7 +18,6 @@ package com.google.turbine.zip;
import static java.nio.charset.StandardCharsets.UTF_8;
-import com.google.common.io.ByteStreams;
import com.google.common.primitives.UnsignedInts;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
@@ -65,7 +64,6 @@ import java.util.zip.ZipException;
* supported.
* <li>UTF-8 is the only supported encoding.
* <li>STORED and DEFLATE are the only supported compression methods.
- * <li>zip64 extensible data sectors are not supported.
* <li>Zip files larger than Integer.MAX_VALUE bytes are not supported.
* <li>The only supported ZIP64 field is ENDTOT. This implementation assumes that the ZIP64 end
* header is present only if ENDTOT in EOCD header is 0xFFFF.
@@ -74,6 +72,7 @@ import java.util.zip.ZipException;
public final class Zip {
static final int ZIP64_ENDSIG = 0x06064b50;
+ static final int ZIP64_LOCSIG = 0x07064b50;
static final int LOCHDR = 30; // LOC header size
static final int CENHDR = 46; // CEN header size
@@ -196,20 +195,44 @@ public final class Zip {
if (totalEntries == ZIP64_MAGICCOUNT) {
// Assume the zip64 EOCD has the usual size; we don't support zip64 extensible data sectors.
long zip64eocdOffset = size - ENDHDR - ZIP64_LOCHDR - ZIP64_ENDHDR;
- MappedByteBuffer zip64eocd = chan.map(MapMode.READ_ONLY, zip64eocdOffset, ZIP64_ENDHDR);
- zip64eocd.order(ByteOrder.LITTLE_ENDIAN);
// Note that zip reading is necessarily best-effort, since an archive could contain 0xFFFF
// entries and the last entry's data could contain a ZIP64_ENDSIG. Some implementations
// read the full EOCD records and compare them.
- if (zip64eocd.getInt(0) == ZIP64_ENDSIG) {
- cdsize = zip64eocd.getLong(ZIP64_ENDSIZ);
+ long zip64cdsize = zip64cdsize(chan, zip64eocdOffset);
+ if (zip64cdsize != -1) {
eocdOffset = zip64eocdOffset;
+ cdsize = zip64cdsize;
+ } else {
+ // If we couldn't find a zip64 EOCD at a fixed offset, either it doesn't exist
+ // or there was a zip64 extensible data sector, so try going through the
+ // locator. This approach doesn't work if data was prepended to the archive
+ // without updating the offset in the locator.
+ MappedByteBuffer zip64loc =
+ chan.map(MapMode.READ_ONLY, size - ENDHDR - ZIP64_LOCHDR, ZIP64_LOCHDR);
+ zip64loc.order(ByteOrder.LITTLE_ENDIAN);
+ if (zip64loc.getInt(0) == ZIP64_LOCSIG) {
+ zip64eocdOffset = zip64loc.getLong(8);
+ zip64cdsize = zip64cdsize(chan, zip64eocdOffset);
+ if (zip64cdsize != -1) {
+ eocdOffset = zip64eocdOffset;
+ cdsize = zip64cdsize;
+ }
+ }
}
}
this.cd = chan.map(MapMode.READ_ONLY, eocdOffset - cdsize, cdsize);
cd.order(ByteOrder.LITTLE_ENDIAN);
}
+ static long zip64cdsize(FileChannel chan, long eocdOffset) throws IOException {
+ MappedByteBuffer zip64eocd = chan.map(MapMode.READ_ONLY, eocdOffset, ZIP64_ENDHDR);
+ zip64eocd.order(ByteOrder.LITTLE_ENDIAN);
+ if (zip64eocd.getInt(0) == ZIP64_ENDSIG) {
+ return zip64eocd.getLong(ZIP64_ENDSIZ);
+ }
+ return -1;
+ }
+
@Override
public Iterator<Entry> iterator() {
return new ZipIterator(path, chan, cd);
@@ -308,9 +331,9 @@ public final class Zip {
fc.get(bytes);
if (deflate) {
bytes =
- ByteStreams.toByteArray(
- new InflaterInputStream(
- new ByteArrayInputStream(bytes), new Inflater(/*nowrap=*/ true)));
+ new InflaterInputStream(
+ new ByteArrayInputStream(bytes), new Inflater(/*nowrap=*/ true))
+ .readAllBytes();
}
return bytes;
} catch (IOException e) {