Fields Summary |
---|
private final DirectClassFile | cf{@code non-null;} class file being parsed |
private final com.android.dx.rop.cst.ConstantPool | pool{@code non-null;} constant pool to use |
private final com.android.dx.util.ByteArray | bytes{@code non-null;} bytes of the attribute data |
private final com.android.dx.cf.iface.ParseObserver | observer{@code null-ok;} parse observer, if any |
private final ByteArray.MyDataInputStream | input{@code non-null;} input stream to parse from |
private int | parseCursor{@code non-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
{@code 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();
CstString typeString = (CstString) pool.get(typeIndex);
CstType type = new CstType(Type.intern(typeString.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 CstString)
? ((CstString) 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();
CstString elementName = (CstString) 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) {
CstString humanTag = new CstString(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();
CstString value = (CstString) pool.get(classInfoIndex);
Type type = Type.internReturnType(value.getString());
if (observer != null) {
parsed(2, "class_info: " + type.toHuman());
}
return new CstType(type);
}
case 's": {
return parseConstant();
}
case 'e": {
requireLength(4);
int typeNameIndex = input.readUnsignedShort();
int constNameIndex = input.readUnsignedShort();
CstString typeName = (CstString) pool.get(typeNameIndex);
CstString constName = (CstString) 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 ({@code 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");
}
|