diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java index 443ef77a..107bf5be 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java @@ -109,7 +109,7 @@ public class DexBackedMethodImplementation implements MethodImplementation { @Nonnull @Override - public List getDebugItems() { + public Iterable getDebugItems() { final int debugInfoOffset = dexBuf.readSmallUint(codeOffset + DEBUG_OFFSET_OFFSET); if (debugInfoOffset > 0) { return new DebugItemList(dexBuf, debugInfoOffset, method); diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugItemList.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugItemList.java index 0ae92c77..146dc589 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugItemList.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugItemList.java @@ -46,9 +46,10 @@ import org.jf.util.ExceptionWithContext; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Iterator; import java.util.NoSuchElementException; -public class DebugItemList extends VariableSizeListWithContext { +public class DebugItemList implements Iterable { @Nonnull public final DexBuffer dexBuf; private final int debugInfoOffset; @Nonnull private final Method method; @@ -75,7 +76,7 @@ public class DebugItemList extends VariableSizeListWithContext { @Nonnull @Override - public Iterator listIterator() { + public Iterator iterator() { DexReader initialReader = dexBuf.readerAt(debugInfoOffset); // TODO: this unsigned value could legitimally be > MAX_INT final int lineNumberStart = initialReader.readSmallUleb128(); @@ -89,7 +90,7 @@ public class DebugItemList extends VariableSizeListWithContext { // information, the method obviously has an implementation. VariableSizeList parameters = (VariableSizeList)method.getParameters(); - VariableSizeList.Iterator parameterIterator = parameters.listIterator(); + final VariableSizeList.Iterator parameterIterator = parameters.listIterator(); { // local scope for i int i=0; @@ -113,23 +114,25 @@ public class DebugItemList extends VariableSizeListWithContext { } } - return new Iterator(dexBuf, parameterIterator.getReaderOffset()) { + return new Iterator() { + @Nonnull private DexReader reader = dexBuf.readerAt(parameterIterator.getReaderOffset()); private boolean finished = false; private int codeAddress = 0; private int lineNumber = lineNumberStart; - @Nonnull - @Override - protected DebugItem readItem(@Nonnull DexReader reader, int index) { + @Nullable private DebugItem nextItem; + + @Nullable + protected DebugItem readItem() { if (finished) { - throw new NoSuchElementException(); + return null; } while (true) { int next = reader.readUbyte(); switch (next) { case DebugItemType.END_SEQUENCE: { finished = true; - throw new NoSuchElementException(); + return null; } case DebugItemType.ADVANCE_PC: { int addressDiff = reader.readSmallUleb128(); @@ -209,19 +212,36 @@ public class DebugItemList extends VariableSizeListWithContext { } @Override - protected void skipItem(@Nonnull DexReader reader, int index) { - super.skipItem(reader, index); + public boolean hasNext() { + if (finished || nextItem != null) { + return false; + } + nextItem = readItem(); + return nextItem != null; + } + + @Nonnull + @Override + public DebugItem next() { + if (finished) { + throw new NoSuchElementException(); + } + if (nextItem == null) { + DebugItem ret = readItem(); + if (ret == null) { + throw new NoSuchElementException(); + } + return ret; + } + DebugItem ret = nextItem; + nextItem = null; + return ret; } @Override - protected void checkBounds(int index) { - // skip the bounds check here. We'll throw NoSuchElementException directly from readItem + public void remove() { + throw new UnsupportedOperationException(); } }; } - - @Override - public int size() { - throw new UnsupportedOperationException(); - } } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodImplementation.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodImplementation.java index 50ad0f3d..1a6a2749 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodImplementation.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodImplementation.java @@ -41,5 +41,5 @@ public interface MethodImplementation { int getRegisterCount(); @Nonnull List getInstructions(); @Nonnull List getTryBlocks(); - @Nonnull List getDebugItems(); + @Nonnull Iterable getDebugItems(); } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodImplementation.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodImplementation.java index a07caa78..d30b8d6c 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodImplementation.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodImplementation.java @@ -53,7 +53,7 @@ public class ImmutableMethodImplementation implements MethodImplementation { public ImmutableMethodImplementation(int registerCount, @Nullable List instructions, @Nullable List tryBlocks, - @Nullable List debugItems) { + @Nullable Iterable debugItems) { this.registerCount = registerCount; this.instructions = ImmutableInstruction.immutableListOf(instructions); this.tryBlocks = ImmutableTryBlock.immutableListOf(tryBlocks); diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableDebugItem.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableDebugItem.java index 0e5beedf..d2165bb4 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableDebugItem.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableDebugItem.java @@ -77,7 +77,7 @@ public abstract class ImmutableDebugItem implements DebugItem { @Override public int getCodeAddress() { return codeAddress; } @Nonnull - public static ImmutableList immutableListOf(@Nullable List list) { + public static ImmutableList immutableListOf(@Nullable Iterable list) { return CONVERTER.convert(list); } diff --git a/util/src/main/java/org/jf/util/ImmutableListConverter.java b/util/src/main/java/org/jf/util/ImmutableListConverter.java index a1c902d8..03b5ddbe 100644 --- a/util/src/main/java/org/jf/util/ImmutableListConverter.java +++ b/util/src/main/java/org/jf/util/ImmutableListConverter.java @@ -36,7 +36,6 @@ import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Iterator; -import java.util.List; /** * This class converts a list of items to an immutable list of immutable items @@ -51,18 +50,18 @@ public abstract class ImmutableListConverter { * If the provided list is already an ImmutableList of ImmutableItems, then the list is not copied and is returned * as-is. If the list is null, an empty ImmutableList will be returned * - * @param list The list of items to convert. + * @param iterable The iterable of items to convert. * @return An ImmutableList of ImmutableItem. If list is null, an empty list will be returned. */ @Nonnull - public ImmutableList convert(@Nullable final List list) { - if (list == null) { + public ImmutableList convert(@Nullable final Iterable iterable) { + if (iterable == null) { return ImmutableList.of(); } boolean needsCopy = false; - if (list instanceof ImmutableList) { - for (Item element: list) { + if (iterable instanceof ImmutableList) { + for (Item element: iterable) { if (isImmutable(element)) { needsCopy = true; break; @@ -73,28 +72,15 @@ public abstract class ImmutableListConverter { } if (!needsCopy) { - return (ImmutableList)list; + return (ImmutableList)iterable; } + final Iterator iter = iterable.iterator(); + return ImmutableList.copyOf(new Iterator() { - protected int index = 0; - - @Override - public boolean hasNext() { - return index < list.size(); - } - - @Override - public ImmutableItem next() { - ImmutableItem item = makeImmutable(list.get(index)); - index++; - return item; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } + @Override public boolean hasNext() { return iter.hasNext(); } + @Override public ImmutableItem next() { return makeImmutable(iter.next()); } + @Override public void remove() { iter.remove(); } }); }