Fields Summary |
---|
private final DirectClassFile | cfnon-null; class file being parsed |
private final com.android.dx.rop.cst.ConstantPool | poolnon-null; constant pool to use |
private final com.android.dx.util.ByteArray | bytesnon-null; bytes of the attribute data |
private final com.android.dx.cf.iface.ParseObserver | observernull-ok; parse observer, if any |
private final ByteArray.MyDataInputStream | inputnon-null; input stream to parse from |
private int | parseCursornon-null; cursor for use when informing the observer of what
was parsed |
Methods Summary |
---|
private void | changeIndent(int indent)Convenience wrapper that simply calls through to
observer.changeIndent() .
observer.changeIndent(indent);
|
private com.android.dx.rop.annotation.Annotation | parseAnnotation(com.android.dx.rop.annotation.AnnotationVisibility visibility)Parses a single annotation.
requireLength(4);
int typeIndex = input.readUnsignedShort();
int numElements = input.readUnsignedShort();
CstUtf8 typeUtf8 = (CstUtf8) pool.get(typeIndex);
CstType type = new CstType(Type.intern(typeUtf8.getString()));
if (observer != null) {
parsed(2, "type: " + type.toHuman());
parsed(2, "num_elements: " + numElements);
}
Annotation annotation = new Annotation(type, visibility);
for (int i = 0; i < numElements; i++) {
if (observer != null) {
parsed(0, "elements[" + i + "]:");
changeIndent(1);
}
NameValuePair element = parseElement();
annotation.add(element);
if (observer != null) {
changeIndent(-1);
}
}
annotation.setImmutable();
return annotation;
|
public com.android.dx.rop.annotation.Annotations | parseAnnotationAttribute(com.android.dx.rop.annotation.AnnotationVisibility visibility)Parses an annotation attribute, per se.
Annotations result;
try {
result = parseAnnotations(visibility);
if (input.available() != 0) {
throw new ParseException("extra data in attribute");
}
} catch (IOException ex) {
// ByteArray.MyDataInputStream should never throw.
throw new RuntimeException("shouldn't happen", ex);
}
return result;
|
private com.android.dx.rop.annotation.Annotations | parseAnnotations(com.android.dx.rop.annotation.AnnotationVisibility visibility)Parses an annotation list.
int count = input.readUnsignedShort();
if (observer != null) {
parsed(2, "num_annotations: " + Hex.u2(count));
}
Annotations annotations = new Annotations();
for (int i = 0; i < count; i++) {
if (observer != null) {
parsed(0, "annotations[" + i + "]:");
changeIndent(1);
}
Annotation annotation = parseAnnotation(visibility);
annotations.add(annotation);
if (observer != null) {
observer.changeIndent(-1);
}
}
annotations.setImmutable();
return annotations;
|
private com.android.dx.rop.annotation.AnnotationsList | parseAnnotationsList(com.android.dx.rop.annotation.AnnotationVisibility visibility)Parses a list of annotation lists.
int count = input.readUnsignedByte();
if (observer != null) {
parsed(1, "num_parameters: " + Hex.u1(count));
}
AnnotationsList outerList = new AnnotationsList(count);
for (int i = 0; i < count; i++) {
if (observer != null) {
parsed(0, "parameter_annotations[" + i + "]:");
changeIndent(1);
}
Annotations annotations = parseAnnotations(visibility);
outerList.set(i, annotations);
if (observer != null) {
observer.changeIndent(-1);
}
}
outerList.setImmutable();
return outerList;
|
private com.android.dx.rop.cst.Constant | parseConstant()Helper for {@link #parseValue}, which parses a constant reference
and returns the referred-to constant value.
int constValueIndex = input.readUnsignedShort();
Constant value = (Constant) pool.get(constValueIndex);
if (observer != null) {
String human = (value instanceof CstUtf8)
? ((CstUtf8) value).toQuoted()
: value.toHuman();
parsed(2, "constant_value: " + human);
}
return value;
|
private com.android.dx.rop.annotation.NameValuePair | parseElement()Parses a {@link NameValuePair}.
requireLength(5);
int elementNameIndex = input.readUnsignedShort();
CstUtf8 elementName = (CstUtf8) pool.get(elementNameIndex);
if (observer != null) {
parsed(2, "element_name: " + elementName.toHuman());
parsed(0, "value: ");
changeIndent(1);
}
Constant value = parseValue();
if (observer != null) {
changeIndent(-1);
}
return new NameValuePair(elementName, value);
|
public com.android.dx.rop.annotation.AnnotationsList | parseParameterAttribute(com.android.dx.rop.annotation.AnnotationVisibility visibility)Parses a parameter annotation attribute.
AnnotationsList result;
try {
result = parseAnnotationsList(visibility);
if (input.available() != 0) {
throw new ParseException("extra data in attribute");
}
} catch (IOException ex) {
// ByteArray.MyDataInputStream should never throw.
throw new RuntimeException("shouldn't happen", ex);
}
return result;
|
private com.android.dx.rop.cst.Constant | parseValue()Parses an annotation value.
int tag = input.readUnsignedByte();
if (observer != null) {
CstUtf8 humanTag = new CstUtf8(Character.toString((char) tag));
parsed(1, "tag: " + humanTag.toQuoted());
}
switch (tag) {
case 'B": {
CstInteger value = (CstInteger) parseConstant();
return CstByte.make(value.getValue());
}
case 'C": {
CstInteger value = (CstInteger) parseConstant();
int intValue = value.getValue();
return CstChar.make(value.getValue());
}
case 'D": {
CstDouble value = (CstDouble) parseConstant();
return value;
}
case 'F": {
CstFloat value = (CstFloat) parseConstant();
return value;
}
case 'I": {
CstInteger value = (CstInteger) parseConstant();
return value;
}
case 'J": {
CstLong value = (CstLong) parseConstant();
return value;
}
case 'S": {
CstInteger value = (CstInteger) parseConstant();
return CstShort.make(value.getValue());
}
case 'Z": {
CstInteger value = (CstInteger) parseConstant();
return CstBoolean.make(value.getValue());
}
case 'c": {
int classInfoIndex = input.readUnsignedShort();
CstUtf8 value = (CstUtf8) pool.get(classInfoIndex);
Type type = Type.internReturnType(value.getString());
if (observer != null) {
parsed(2, "class_info: " + type.toHuman());
}
return new CstType(type);
}
case 's": {
CstString value = new CstString((CstUtf8) parseConstant());
return value;
}
case 'e": {
requireLength(4);
int typeNameIndex = input.readUnsignedShort();
int constNameIndex = input.readUnsignedShort();
CstUtf8 typeName = (CstUtf8) pool.get(typeNameIndex);
CstUtf8 constName = (CstUtf8) pool.get(constNameIndex);
if (observer != null) {
parsed(2, "type_name: " + typeName.toHuman());
parsed(2, "const_name: " + constName.toHuman());
}
return new CstEnumRef(new CstNat(constName, typeName));
}
case '@": {
Annotation annotation =
parseAnnotation(AnnotationVisibility.EMBEDDED);
return new CstAnnotation(annotation);
}
case '[": {
requireLength(2);
int numValues = input.readUnsignedShort();
CstArray.List list = new CstArray.List(numValues);
if (observer != null) {
parsed(2, "num_values: " + numValues);
changeIndent(1);
}
for (int i = 0; i < numValues; i++) {
if (observer != null) {
changeIndent(-1);
parsed(0, "element_value[" + i + "]:");
changeIndent(1);
}
list.set(i, parseValue());
}
if (observer != null) {
changeIndent(-1);
}
list.setImmutable();
return new CstArray(list);
}
default: {
throw new ParseException("unknown annotation tag: " +
Hex.u1(tag));
}
}
|
public com.android.dx.rop.cst.Constant | parseValueAttribute()Parses an annotation value (element_value ) attribute.
Constant result;
try {
result = parseValue();
if (input.available() != 0) {
throw new ParseException("extra data in attribute");
}
} catch (IOException ex) {
// ByteArray.MyDataInputStream should never throw.
throw new RuntimeException("shouldn't happen", ex);
}
return result;
|
private void | parsed(int length, java.lang.String message)Helper which indicates that some bytes were just parsed. This should
only be used (for efficiency sake) if the parse is known to be
observed.
observer.parsed(bytes, parseCursor, length, message);
parseCursor += length;
|
private void | requireLength(int requiredLength)Helper which will throw an exception if the given number of bytes
is not available to be read.
if (input.available() < requiredLength) {
throw new ParseException("truncated annotation attribute");
}
|