FileDocCategorySizeDatePackage
MemberListParser.javaAPI DocAndroid 1.5 API8100Wed May 06 22:41:02 BST 2009com.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
non-null; the class file to parse from
private final com.android.dx.rop.cst.CstType
definer
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
non-null; attribute factory to use
private int
endOffset
>= -1; the end offset of this list in the byte array of the classfile, or -1 if not yet parsed
private com.android.dx.cf.iface.ParseObserver
observer
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 non-null; the class file to parse from
param
definer non-null; class being defined
param
offset offset in bytes to the start of the list
param
attributeFactory 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 CTX_* constant to use when parsing attributes. Subclasses must override this method.

return
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
non-null; the class

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

return
>= 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
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
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);
                CstUtf8 name = (CstUtf8) pool.get(nameIdx);
                CstUtf8 desc = (CstUtf8) 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 access_flags
param
nat the interpreted name and type (based on the two *_index fields)
param
attributes list of parsed attributes
return
non-null; the constructed member

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

param
observer null-ok; the observer

        this.observer = observer;