view src/main/java/org/icedrobot/daneel/dex/ClassDef.java @ 108:19915795c08c

Implemented information skipping for parser. * dex/ClassData.java (accept, acceptField, acceptMethod): See above. * dex/ClassDef.java (accept): Likewise. * dex/Code.java (accept): Likewise. * dex/DexFile.java (accept): Pass skipping flags.
author Michael Starzinger <michi@complang.tuwien.ac.at>
date Thu, 31 Mar 2011 00:54:29 +0200
parents ef7e8137da03
children 8bb44682be11
line wrap: on
line source

/*
 * Daneel - Dalvik to Java bytecode compiler
 * Copyright (C) 2011  IcedRobot team
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * This file is subject to the "Classpath" exception:
 *
 * Linking this library statically or dynamically with other modules is
 * making a combined work based on this library.  Thus, the terms and
 * conditions of the GNU General Public License cover the whole
 * combination.
 *
 * As a special exception, the copyright holders of this library give you
 * permission to link this library with independent modules to produce an
 * executable, regardless of the license terms of these independent
 * modules, and to copy and distribute the resulting executable under terms
 * of your choice, provided that you also meet, for each linked independent
 * module, the terms and conditions of the license of that module.  An
 * independent module is a module which is not derived from or based on
 * this library.  If you modify this library, you may extend this exception
 * to your version of the library, but you are not obligated to do so.  If
 * you do not wish to do so, delete this exception statement from your
 * version.
 */

package org.icedrobot.daneel.dex;

import java.nio.ByteBuffer;

/**
 * A parser class capable of parsing {@code class_def_item} structures as part
 * of DEX files. Keep package-private to hide internal API.
 */
class ClassDef {

    /**
     * Parses a {@code class_def_item} structure in a DEX file at the buffer's
     * current position.
     * 
     * @param buffer The byte buffer to read from.
     * @param dex The DEX file currently being parsed.
     * @return An object representing the parsed data.
     */
    static ClassDef parse(ByteBuffer buffer, DexFile dex) {
        return new ClassDef(buffer, dex);
    }

    private String className;

    private int accessFlags;

    private String superclass;

    private String[] interfaces;

    private String sourceFile;

    private final AnnotationsDirectory annotations;

    private ClassData classData;

    private final int staticValuesOff;

    private ClassDef(ByteBuffer buffer, DexFile dex) {
        int classIdx = buffer.getInt();
        accessFlags = buffer.getInt();
        int superclassIdx = buffer.getInt();
        int interfacesOff = buffer.getInt();
        int sourceFileIdx = buffer.getInt();
        int annotationsOff = buffer.getInt();
        int classDataOff = buffer.getInt();
        staticValuesOff = buffer.getInt();

        // Resolve string and type indices.
        className = dex.getTypeDescriptor(classIdx);
        if (superclassIdx != DexFile.NO_INDEX)
            superclass = dex.getTypeDescriptor(superclassIdx);
        if (sourceFileIdx != DexFile.NO_INDEX)
            sourceFile = dex.getString(sourceFileIdx);

        // Parse associated type_list structure and resolve type indices.
        if (interfacesOff != 0) {
            ByteBuffer buf = dex.getDataBuffer(interfacesOff);
            interfaces = new String[buf.getInt()];
            for (int i = 0; i < interfaces.length; i++)
                interfaces[i] = dex.getTypeDescriptor(buf.getShort());
        }

        // Parse associated annotations_directory_item structure.
        if (annotationsOff != 0) {
            ByteBuffer buf = dex.getDataBuffer(annotationsOff);
            annotations = AnnotationsDirectory.parse(buf, dex);
        } else
            annotations = null;

        // Parse associated class_data_item structure.
        if (classDataOff != 0) {
            ByteBuffer buf = dex.getDataBuffer(classDataOff);
            classData = ClassData.parse(buf, dex, this);
        }
    }

    public String getClassName() {
        return className;
    }

    public int getAccessFlags() {
        return accessFlags;
    }

    public String getSuperclass() {
        return superclass;
    }

    public String[] getInterfaces() {
        return interfaces;
    }

    public String getSourceFile() {
        return sourceFile;
    }

    public AnnotationsDirectory getAnnotations() {
        return annotations;
    }

    public ClassData getClassData() {
        return classData;
    }

    public int getStaticValuesOff() {
        return staticValuesOff;
    }

    /**
     * Allows the given visitor to visit this class definition.
     * 
     * @param visitor The given DEX class visitor object.
     * @param skip Flags indicating which information to skip while visiting.
     */
    public void accept(DexClassVisitor visitor, int skip) {
        visitor.visit(accessFlags, className, superclass, interfaces);
        if (sourceFile != null)
            visitor.visitSource(sourceFile);
        if (annotations != null && (skip & DexReader.SKIP_ANNOTATIONS) == 0)
            annotations.acceptClassAnnotations(visitor);
        if (classData != null)
            classData.accept(visitor, skip);
        visitor.visitEnd();
    }
}