Get rid of the separate DexBackedDexFile.Impl class

This commit is contained in:
Ben Gruver 2013-03-06 20:32:06 -08:00
parent 132eeaedf7
commit 12659ec7db
3 changed files with 139 additions and 166 deletions

View File

@ -93,7 +93,7 @@ public final class DexFileFactory {
dexBytes = Files.toByteArray(dexFile); dexBytes = Files.toByteArray(dexFile);
} }
return new DexBackedDexFile.Impl(dexBytes); return new DexBackedDexFile(dexBytes);
} }
public static void writeDexFile(String path, DexFile dexFile) throws IOException { public static void writeDexFile(String path, DexFile dexFile) throws IOException {

View File

@ -40,197 +40,170 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Set; import java.util.Set;
public abstract class DexBackedDexFile extends BaseDexBuffer implements DexFile { public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
public DexBackedDexFile(@Nonnull byte[] buf) { private final int stringCount;
super(buf); private final int stringStartOffset;
private final int typeCount;
private final int typeStartOffset;
private final int protoCount;
private final int protoStartOffset;
private final int fieldCount;
private final int fieldStartOffset;
private final int methodCount;
private final int methodStartOffset;
private final int classCount;
private final int classStartOffset;
public DexBackedDexFile (@Nonnull BaseDexBuffer buf) {
this(buf.buf);
} }
@Nonnull public abstract String getString(int stringIndex); public DexBackedDexFile (@Nonnull byte[] buf) {
@Nullable public abstract String getOptionalString(int stringIndex); super(buf);
@Nonnull public abstract String getType(int typeIndex);
@Nullable public abstract String getOptionalType(int typeIndex);
// TODO: refactor how dex items are read verifyMagic();
public abstract int getMethodIdItemOffset(int methodIndex); verifyEndian();
public abstract int getProtoIdItemOffset(int protoIndex); stringCount = readSmallUint(HeaderItem.STRING_COUNT_OFFSET);
public abstract int getFieldIdItemOffset(int fieldIndex); stringStartOffset = readSmallUint(HeaderItem.STRING_START_OFFSET);
public abstract int getClassDefItemOffset(int classIndex); typeCount = readSmallUint(HeaderItem.TYPE_COUNT_OFFSET);
typeStartOffset = readSmallUint(HeaderItem.TYPE_START_OFFSET);
protoCount = readSmallUint(HeaderItem.PROTO_COUNT_OFFSET);
protoStartOffset = readSmallUint(HeaderItem.PROTO_START_OFFSET);
fieldCount = readSmallUint(HeaderItem.FIELD_COUNT_OFFSET);
fieldStartOffset = readSmallUint(HeaderItem.FIELD_START_OFFSET);
methodCount = readSmallUint(HeaderItem.METHOD_COUNT_OFFSET);
methodStartOffset = readSmallUint(HeaderItem.METHOD_START_OFFSET);
classCount = readSmallUint(HeaderItem.CLASS_COUNT_OFFSET);
classStartOffset = readSmallUint(HeaderItem.CLASS_START_OFFSET);
}
@Override @Nonnull public abstract DexReader readerAt(int offset); @Nonnull
@Override
public static class Impl extends DexBackedDexFile { public Set<? extends DexBackedClassDef> getClasses() {
private final int stringCount; return new FixedSizeSet<DexBackedClassDef>() {
private final int stringStartOffset; @Nonnull
private final int typeCount; @Override
private final int typeStartOffset; public DexBackedClassDef readItem(int index) {
private final int protoCount; return new DexBackedClassDef(DexBackedDexFile.this, getClassDefItemOffset(index));
private final int protoStartOffset;
private final int fieldCount;
private final int fieldStartOffset;
private final int methodCount;
private final int methodStartOffset;
private final int classCount;
private final int classStartOffset;
public Impl(@Nonnull BaseDexBuffer buf) {
this(buf.buf);
}
public Impl(@Nonnull byte[] buf) {
super(buf);
verifyMagic();
verifyEndian();
stringCount = readSmallUint(HeaderItem.STRING_COUNT_OFFSET);
stringStartOffset = readSmallUint(HeaderItem.STRING_START_OFFSET);
typeCount = readSmallUint(HeaderItem.TYPE_COUNT_OFFSET);
typeStartOffset = readSmallUint(HeaderItem.TYPE_START_OFFSET);
protoCount = readSmallUint(HeaderItem.PROTO_COUNT_OFFSET);
protoStartOffset = readSmallUint(HeaderItem.PROTO_START_OFFSET);
fieldCount = readSmallUint(HeaderItem.FIELD_COUNT_OFFSET);
fieldStartOffset = readSmallUint(HeaderItem.FIELD_START_OFFSET);
methodCount = readSmallUint(HeaderItem.METHOD_COUNT_OFFSET);
methodStartOffset = readSmallUint(HeaderItem.METHOD_START_OFFSET);
classCount = readSmallUint(HeaderItem.CLASS_COUNT_OFFSET);
classStartOffset = readSmallUint(HeaderItem.CLASS_START_OFFSET);
}
@Nonnull
@Override
public Set<? extends DexBackedClassDef> getClasses() {
return new FixedSizeSet<DexBackedClassDef>() {
@Nonnull
@Override
public DexBackedClassDef readItem(int index) {
return new DexBackedClassDef(Impl.this, getClassDefItemOffset(index));
}
@Override
public int size() {
return classCount;
}
};
}
private void verifyMagic() {
outer: for (byte[] magic: HeaderItem.MAGIC_VALUES) {
for (int i=0; i<magic.length; i++) {
if (buf[i] != magic[i]) {
continue outer;
}
}
return;
} }
StringBuilder sb = new StringBuilder("Invalid magic value:");
for (int i=0; i<8; i++) { @Override
sb.append(String.format(" %02x", buf[i])); public int size() {
return classCount;
}
};
}
private void verifyMagic() {
outer: for (byte[] magic: HeaderItem.MAGIC_VALUES) {
for (int i=0; i<magic.length; i++) {
if (buf[i] != magic[i]) {
continue outer;
}
}
return;
}
StringBuilder sb = new StringBuilder("Invalid magic value:");
for (int i=0; i<8; i++) {
sb.append(String.format(" %02x", buf[i]));
}
throw new ExceptionWithContext(sb.toString());
}
private void verifyEndian() {
int endian = readInt(HeaderItem.ENDIAN_TAG_OFFSET);
if (endian == HeaderItem.BIG_ENDIAN_TAG) {
throw new ExceptionWithContext("dexlib does not currently support big endian dex files.");
} else if (endian != HeaderItem.LITTLE_ENDIAN_TAG) {
StringBuilder sb = new StringBuilder("Invalid endian tag:");
for (int i=0; i<4; i++) {
sb.append(String.format(" %02x", buf[HeaderItem.ENDIAN_TAG_OFFSET+i]));
} }
throw new ExceptionWithContext(sb.toString()); throw new ExceptionWithContext(sb.toString());
} }
}
private void verifyEndian() { public int getStringIdItemOffset(int stringIndex) {
int endian = readInt(HeaderItem.ENDIAN_TAG_OFFSET); if (stringIndex < 0 || stringIndex >= stringCount) {
if (endian == HeaderItem.BIG_ENDIAN_TAG) { throw new ExceptionWithContext("String index out of bounds: %d", stringIndex);
throw new ExceptionWithContext("dexlib does not currently support big endian dex files.");
} else if (endian != HeaderItem.LITTLE_ENDIAN_TAG) {
StringBuilder sb = new StringBuilder("Invalid endian tag:");
for (int i=0; i<4; i++) {
sb.append(String.format(" %02x", buf[HeaderItem.ENDIAN_TAG_OFFSET+i]));
}
throw new ExceptionWithContext(sb.toString());
}
} }
return stringStartOffset + stringIndex*StringIdItem.ITEM_SIZE;
}
public int getStringIdItemOffset(int stringIndex) { public int getTypeIdItemOffset(int typeIndex) {
if (stringIndex < 0 || stringIndex >= stringCount) { if (typeIndex < 0 || typeIndex >= typeCount) {
throw new ExceptionWithContext("String index out of bounds: %d", stringIndex); throw new ExceptionWithContext("Type index out of bounds: %d", typeIndex);
}
return stringStartOffset + stringIndex*StringIdItem.ITEM_SIZE;
} }
return typeStartOffset + typeIndex*TypeIdItem.ITEM_SIZE;
}
public int getTypeIdItemOffset(int typeIndex) { public int getFieldIdItemOffset(int fieldIndex) {
if (typeIndex < 0 || typeIndex >= typeCount) { if (fieldIndex < 0 || fieldIndex >= fieldCount) {
throw new ExceptionWithContext("Type index out of bounds: %d", typeIndex); throw new ExceptionWithContext("Field index out of bounds: %d", fieldIndex);
}
return typeStartOffset + typeIndex*TypeIdItem.ITEM_SIZE;
} }
return fieldStartOffset + fieldIndex*FieldIdItem.ITEM_SIZE;
}
@Override public int getMethodIdItemOffset(int methodIndex) {
public int getFieldIdItemOffset(int fieldIndex) { if (methodIndex < 0 || methodIndex >= methodCount) {
if (fieldIndex < 0 || fieldIndex >= fieldCount) { throw new ExceptionWithContext("Method index out of bounds: %d", methodIndex);
throw new ExceptionWithContext("Field index out of bounds: %d", fieldIndex);
}
return fieldStartOffset + fieldIndex*FieldIdItem.ITEM_SIZE;
} }
return methodStartOffset + methodIndex*MethodIdItem.ITEM_SIZE;
}
@Override public int getProtoIdItemOffset(int protoIndex) {
public int getMethodIdItemOffset(int methodIndex) { if (protoIndex < 0 || protoIndex >= protoCount) {
if (methodIndex < 0 || methodIndex >= methodCount) { throw new ExceptionWithContext("Proto index out of bounds: %d", protoIndex);
throw new ExceptionWithContext("Method index out of bounds: %d", methodIndex);
}
return methodStartOffset + methodIndex*MethodIdItem.ITEM_SIZE;
} }
return protoStartOffset + protoIndex*ProtoIdItem.ITEM_SIZE;
}
@Override public int getClassDefItemOffset(int classIndex) {
public int getProtoIdItemOffset(int protoIndex) { if (classIndex < 0 || classIndex >= classCount) {
if (protoIndex < 0 || protoIndex >= protoCount) { throw new ExceptionWithContext("Class index out of bounds: %d", classIndex);
throw new ExceptionWithContext("Proto index out of bounds: %d", protoIndex);
}
return protoStartOffset + protoIndex*ProtoIdItem.ITEM_SIZE;
} }
return classStartOffset + classIndex*ClassDefItem.ITEM_SIZE;
}
@Override public int getClassCount() {
public int getClassDefItemOffset(int classIndex) { return classCount;
if (classIndex < 0 || classIndex >= classCount) { }
throw new ExceptionWithContext("Class index out of bounds: %d", classIndex);
}
return classStartOffset + classIndex*ClassDefItem.ITEM_SIZE;
}
public int getClassCount() { @Nonnull
return classCount; public String getString(int stringIndex) {
} int stringOffset = getStringIdItemOffset(stringIndex);
int stringDataOffset = readSmallUint(stringOffset);
DexReader reader = readerAt(stringDataOffset);
int utf16Length = reader.readSmallUleb128();
return reader.readString(utf16Length);
}
@Override @Nullable
@Nonnull public String getOptionalString(int stringIndex) {
public String getString(int stringIndex) { if (stringIndex == -1) {
int stringOffset = getStringIdItemOffset(stringIndex); return null;
int stringDataOffset = readSmallUint(stringOffset);
DexReader reader = readerAt(stringDataOffset);
int utf16Length = reader.readSmallUleb128();
return reader.readString(utf16Length);
} }
return getString(stringIndex);
}
@Override @Nonnull
@Nullable public String getType(int typeIndex) {
public String getOptionalString(int stringIndex) { int typeOffset = getTypeIdItemOffset(typeIndex);
if (stringIndex == -1) { int stringIndex = readSmallUint(typeOffset);
return null; return getString(stringIndex);
} }
return getString(stringIndex);
}
@Override @Nullable
@Nonnull public String getOptionalType(int typeIndex) {
public String getType(int typeIndex) { if (typeIndex == -1) {
int typeOffset = getTypeIdItemOffset(typeIndex); return null;
int stringIndex = readSmallUint(typeOffset);
return getString(stringIndex);
} }
return getType(typeIndex);
}
@Override @Override
@Nullable @Nonnull
public String getOptionalType(int typeIndex) { public DexReader readerAt(int offset) {
if (typeIndex == -1) { return new DexReader(this, offset);
return null;
}
return getType(typeIndex);
}
@Override
@Nonnull
public DexReader readerAt(int offset) {
return new DexReader(this, offset);
}
} }
} }

View File

@ -43,7 +43,7 @@ import java.io.Writer;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
public class RawDexFile extends DexBackedDexFile.Impl { public class RawDexFile extends DexBackedDexFile {
@Nonnull public final HeaderItem headerItem; @Nonnull public final HeaderItem headerItem;
public RawDexFile(BaseDexBuffer buf) { public RawDexFile(BaseDexBuffer buf) {