FileDocCategorySizeDatePackage
MemberListParser.javaAPI DocAndroid 5.1 API8192Thu Mar 12 22:18:30 GMT 2015com.android.dx.cf.direct

MemberListParser

public abstract class MemberListParser extends Object
Parser for lists of class file members (that is, fields and methods).

Fields Summary
private final DirectClassFile
cf
{@code non-null;} the class file to parse from
private final com.android.dx.rop.cst.CstType
definer
{@code non-null;} class being defined
private final int
offset
offset in the byte array of the classfile to the start of the list
private final AttributeFactory
attributeFactory
{@code non-null;} attribute factory to use
private int
endOffset
{@code >= -1;} the end offset of this list in the byte array of the classfile, or {@code -1} if not yet parsed
private com.android.dx.cf.iface.ParseObserver
observer
{@code null-ok;} parse observer, if any
Constructors Summary
public MemberListParser(DirectClassFile cf, com.android.dx.rop.cst.CstType definer, int offset, AttributeFactory attributeFactory)
Constructs an instance.

param
cf {@code non-null;} the class file to parse from
param
definer {@code non-null;} class being defined
param
offset offset in {@code bytes} to the start of the list
param
attributeFactory {@code non-null;} attribute factory to use

        if (cf == null) {
            throw new NullPointerException("cf == null");
        }

        if (offset < 0) {
            throw new IllegalArgumentException("offset < 0");
        }

        if (attributeFactory == null) {
            throw new NullPointerException("attributeFactory == null");
        }

        this.cf = cf;
        this.definer = definer;
        this.offset = offset;
        this.attributeFactory = attributeFactory;
        this.endOffset = -1;
    
Methods Summary
protected abstract intgetAttributeContext()
Gets the {@code CTX_*} constant to use when parsing attributes. Subclasses must override this method.

return
{@code non-null;} the human oriented name

protected final intgetCount()
Gets the count of elements in the list.

return
the count

        ByteArray bytes = cf.getBytes();
        return bytes.getUnsignedShort(offset);
    
protected final com.android.dx.rop.cst.CstTypegetDefiner()
Gets the class file being defined.

return
{@code non-null;} the class

        return definer;
    
public intgetEndOffset()
Gets the end offset of this constant pool in the {@code byte[]} which it came from.

return
{@code >= 0;} the end offset

        parseIfNecessary();
        return endOffset;
    
protected abstract java.lang.StringhumanAccessFlags(int accessFlags)
Gets the human-oriented string for the given access flags. Subclasses must override this method.

param
accessFlags the flags
return
{@code non-null;} the string form

protected abstract java.lang.StringhumanName()
Gets the human-oriented name for what this instance is parsing. Subclasses must override this method.

return
{@code non-null;} the human oriented name

private voidparse()
Does the actual parsing.

        int attributeContext = getAttributeContext();
        int count = getCount();
        int at = offset + 2; // Skip the count.

        ByteArray bytes = cf.getBytes();
        ConstantPool pool = cf.getConstantPool();

        if (observer != null) {
            observer.parsed(bytes, offset, 2,
                            humanName() + "s_count: " + Hex.u2(count));
        }

        for (int i = 0; i < count; i++) {
            try {
                int accessFlags = bytes.getUnsignedShort(at);
                int nameIdx = bytes.getUnsignedShort(at + 2);
                int descIdx = bytes.getUnsignedShort(at + 4);
                CstString name = (CstString) pool.get(nameIdx);
                CstString desc = (CstString) pool.get(descIdx);

                if (observer != null) {
                    observer.startParsingMember(bytes, at, name.getString(),
                                                desc.getString());
                    observer.parsed(bytes, at, 0, "\n" + humanName() +
                                    "s[" + i + "]:\n");
                    observer.changeIndent(1);
                    observer.parsed(bytes, at, 2,
                                    "access_flags: " +
                                    humanAccessFlags(accessFlags));
                    observer.parsed(bytes, at + 2, 2,
                                    "name: " + name.toHuman());
                    observer.parsed(bytes, at + 4, 2,
                                    "descriptor: " + desc.toHuman());
                }

                at += 6;
                AttributeListParser parser =
                    new AttributeListParser(cf, attributeContext, at,
                                            attributeFactory);
                parser.setObserver(observer);
                at = parser.getEndOffset();
                StdAttributeList attributes = parser.getList();
                attributes.setImmutable();
                CstNat nat = new CstNat(name, desc);
                Member member = set(i, accessFlags, nat, attributes);

                if (observer != null) {
                    observer.changeIndent(-1);
                    observer.parsed(bytes, at, 0, "end " + humanName() +
                                    "s[" + i + "]\n");
                    observer.endParsingMember(bytes, at, name.getString(),
                                              desc.getString(), member);
                }
            } catch (ParseException ex) {
                ex.addContext("...while parsing " + humanName() + "s[" + i +
                              "]");
                throw ex;
            } catch (RuntimeException ex) {
                ParseException pe = new ParseException(ex);
                pe.addContext("...while parsing " + humanName() + "s[" + i +
                              "]");
                throw pe;
            }
        }

        endOffset = at;
    
protected final voidparseIfNecessary()
Runs {@link #parse} if it has not yet been run successfully.

        if (endOffset < 0) {
            parse();
        }
    
protected abstract com.android.dx.cf.iface.Memberset(int n, int accessFlags, com.android.dx.rop.cst.CstNat nat, com.android.dx.cf.iface.AttributeList attributes)
Sets an element in the list. Subclasses must override this method.

param
n which element
param
accessFlags the {@code access_flags}
param
nat the interpreted name and type (based on the two {@code *_index} fields)
param
attributes list of parsed attributes
return
{@code non-null;} the constructed member

public final voidsetObserver(com.android.dx.cf.iface.ParseObserver observer)
Sets the parse observer for this instance.

param
observer {@code null-ok;} the observer

        this.observer = observer;