Mercurial > hg > icedrobot > daneel
changeset 19:d6245f2a61a6
Implemented parser interface to accept visitors.
* dex/DexFile.java (classDefs): Switched to map for efficient lookup by name.
* (accept): Implemented according to parser interface.
* (getClassDef): Deprecated, should be removed soon.
author | Michael Starzinger <michi@complang.tuwien.ac.at> |
---|---|
date | Wed, 16 Mar 2011 00:39:45 +0100 |
parents | 3a79fec307ae |
children | 03d932822bf7 |
files | src/main/java/org/icedrobot/daneel/dex/DexFile.java |
diffstat | 1 files changed, 43 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/org/icedrobot/daneel/dex/DexFile.java Wed Mar 16 00:38:21 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/dex/DexFile.java Wed Mar 16 00:39:45 2011 +0100 @@ -2,10 +2,17 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.LinkedHashMap; +import java.util.Map; import org.icedrobot.daneel.util.BufferUtil; -public class DexFile { +/** + * This class reads the contents of a DEX file. It is the main entry point into + * our parser implementation and optimized towards {@link java.nio.ByteBuffer} + * data sources. + */ +public class DexFile implements DexReader { /** Constant used to indicate that an index value is absent. */ public static final int NO_INDEX = 0xffffffff; @@ -30,7 +37,7 @@ private final MethodId[] methodIds; - private ClassDef[] classDefs; + private final Map<String, ClassDef> classDefs; private final ByteBuffer dataBuffer; @@ -80,10 +87,15 @@ methodIds[i] = MethodId.parse(buf, this); // Parse class_def_item structures. - classDefs = new ClassDef[header.getClassDefsSize()]; + int classDefsSize = header.getClassDefsSize(); + classDefs = new LinkedHashMap<String, ClassDef>(classDefsSize); buf.position(header.getClassDefsOff()); - for (int i = 0; i < classDefs.length; i++) - classDefs[i] = ClassDef.parse(buf, this); + for (int i = 0; i < classDefsSize; i++) { + ClassDef classDef = ClassDef.parse(buf, this); + if (classDefs.put(classDef.getClassName(), classDef) != null) + throw new DexParseException("Redefinition of class: " + + classDef.getClassName()); + } } Header getHeader() { @@ -124,8 +136,13 @@ return methodIds[idx]; } + @Deprecated + // XXX Direct access of class definition is not allowed, remove me! public ClassDef getClassDef(int idx) { - return classDefs[idx]; + // XXX I know this is hacky, but it is only used by the prototype test. + if (idx != 0) + throw new DexParseException("You shouldn't have used me!"); + return classDefs.values().iterator().next(); } /** @@ -156,12 +173,31 @@ * * @param visitor The given DEX file visitor object. */ + @Override public void accept(DexFileVisitor visitor) { - for (ClassDef classDef : classDefs) { + for (ClassDef classDef : classDefs.values()) { DexClassVisitor dcv = visitor.visitClass(classDef.getClassName()); if (dcv != null) classDef.accept(dcv); } visitor.visitEnd(); } + + /** + * Allows the given visitor to visit a class inside this DEX file. + * + * @param className The name of the class to visit as a type descriptor. + * @param visitor The given DEX class visitor object. + * @throws ClassNotFoundException In case the given class is not defined + * inside this DEX file. + */ + @Override + public void accept(String className, DexClassVisitor visitor) + throws ClassNotFoundException { + ClassDef classDef = classDefs.get(className); + if (classDef == null) + throw new ClassNotFoundException("Class not defined in DEX file: " + + className); + classDef.accept(visitor); + } }