StdAttributeFactorypublic class StdAttributeFactory extends AttributeFactory Standard subclass of {@link AttributeFactory}, which knows how to parse
all the standard attribute types. |
Fields Summary |
---|
public static final StdAttributeFactory | THE_ONE{@code non-null;} shared instance of this class |
Constructors Summary |
---|
public StdAttributeFactory()Constructs an instance.
// This space intentionally left blank.
|
Methods Summary |
---|
private com.android.dx.cf.iface.Attribute | annotationDefault(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses an {@code AnnotationDefault} attribute.
if (length < 2) {
throwSeverelyTruncated();
}
AnnotationParser ap =
new AnnotationParser(cf, offset, length, observer);
Constant cst = ap.parseValueAttribute();
return new AttAnnotationDefault(cst, length);
| private com.android.dx.cf.iface.Attribute | code(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code Code} attribute.
if (length < 12) {
return throwSeverelyTruncated();
}
ByteArray bytes = cf.getBytes();
ConstantPool pool = cf.getConstantPool();
int maxStack = bytes.getUnsignedShort(offset); // u2 max_stack
int maxLocals = bytes.getUnsignedShort(offset + 2); // u2 max_locals
int codeLength = bytes.getInt(offset + 4); // u4 code_length
int origOffset = offset;
if (observer != null) {
observer.parsed(bytes, offset, 2,
"max_stack: " + Hex.u2(maxStack));
observer.parsed(bytes, offset + 2, 2,
"max_locals: " + Hex.u2(maxLocals));
observer.parsed(bytes, offset + 4, 4,
"code_length: " + Hex.u4(codeLength));
}
offset += 8;
length -= 8;
if (length < (codeLength + 4)) {
return throwTruncated();
}
int codeOffset = offset;
offset += codeLength;
length -= codeLength;
BytecodeArray code =
new BytecodeArray(bytes.slice(codeOffset, codeOffset + codeLength),
pool);
if (observer != null) {
code.forEach(new CodeObserver(code.getBytes(), observer));
}
// u2 exception_table_length
int exceptionTableLength = bytes.getUnsignedShort(offset);
ByteCatchList catches = (exceptionTableLength == 0) ?
ByteCatchList.EMPTY :
new ByteCatchList(exceptionTableLength);
if (observer != null) {
observer.parsed(bytes, offset, 2,
"exception_table_length: " +
Hex.u2(exceptionTableLength));
}
offset += 2;
length -= 2;
if (length < (exceptionTableLength * 8 + 2)) {
return throwTruncated();
}
for (int i = 0; i < exceptionTableLength; i++) {
if (observer != null) {
observer.changeIndent(1);
}
int startPc = bytes.getUnsignedShort(offset);
int endPc = bytes.getUnsignedShort(offset + 2);
int handlerPc = bytes.getUnsignedShort(offset + 4);
int catchTypeIdx = bytes.getUnsignedShort(offset + 6);
CstType catchType = (CstType) pool.get0Ok(catchTypeIdx);
catches.set(i, startPc, endPc, handlerPc, catchType);
if (observer != null) {
observer.parsed(bytes, offset, 8,
Hex.u2(startPc) + ".." + Hex.u2(endPc) +
" -> " + Hex.u2(handlerPc) + " " +
((catchType == null) ? "<any>" :
catchType.toHuman()));
}
offset += 8;
length -= 8;
if (observer != null) {
observer.changeIndent(-1);
}
}
catches.setImmutable();
AttributeListParser parser =
new AttributeListParser(cf, CTX_CODE, offset, this);
parser.setObserver(observer);
StdAttributeList attributes = parser.getList();
attributes.setImmutable();
int attributeByteCount = parser.getEndOffset() - offset;
if (attributeByteCount != length) {
return throwBadLength(attributeByteCount + (offset - origOffset));
}
return new AttCode(maxStack, maxLocals, code, catches, attributes);
| private com.android.dx.cf.iface.Attribute | constantValue(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code ConstantValue} attribute.
if (length != 2) {
return throwBadLength(2);
}
ByteArray bytes = cf.getBytes();
ConstantPool pool = cf.getConstantPool();
int idx = bytes.getUnsignedShort(offset);
TypedConstant cst = (TypedConstant) pool.get(idx);
Attribute result = new AttConstantValue(cst);
if (observer != null) {
observer.parsed(bytes, offset, 2, "value: " + cst);
}
return result;
| private com.android.dx.cf.iface.Attribute | deprecated(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code Deprecated} attribute.
if (length != 0) {
return throwBadLength(0);
}
return new AttDeprecated();
| private com.android.dx.cf.iface.Attribute | enclosingMethod(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses an {@code EnclosingMethod} attribute.
if (length != 4) {
throwBadLength(4);
}
ByteArray bytes = cf.getBytes();
ConstantPool pool = cf.getConstantPool();
int idx = bytes.getUnsignedShort(offset);
CstType type = (CstType) pool.get(idx);
idx = bytes.getUnsignedShort(offset + 2);
CstNat method = (CstNat) pool.get0Ok(idx);
Attribute result = new AttEnclosingMethod(type, method);
if (observer != null) {
observer.parsed(bytes, offset, 2, "class: " + type);
observer.parsed(bytes, offset + 2, 2, "method: " +
DirectClassFile.stringOrNone(method));
}
return result;
| private com.android.dx.cf.iface.Attribute | exceptions(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses an {@code Exceptions} attribute.
if (length < 2) {
return throwSeverelyTruncated();
}
ByteArray bytes = cf.getBytes();
int count = bytes.getUnsignedShort(offset); // number_of_exceptions
if (observer != null) {
observer.parsed(bytes, offset, 2,
"number_of_exceptions: " + Hex.u2(count));
}
offset += 2;
length -= 2;
if (length != (count * 2)) {
throwBadLength((count * 2) + 2);
}
TypeList list = cf.makeTypeList(offset, count);
return new AttExceptions(list);
| private com.android.dx.cf.iface.Attribute | innerClasses(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses an {@code InnerClasses} attribute.
if (length < 2) {
return throwSeverelyTruncated();
}
ByteArray bytes = cf.getBytes();
ConstantPool pool = cf.getConstantPool();
int count = bytes.getUnsignedShort(offset); // number_of_classes
if (observer != null) {
observer.parsed(bytes, offset, 2,
"number_of_classes: " + Hex.u2(count));
}
offset += 2;
length -= 2;
if (length != (count * 8)) {
throwBadLength((count * 8) + 2);
}
InnerClassList list = new InnerClassList(count);
for (int i = 0; i < count; i++) {
int innerClassIdx = bytes.getUnsignedShort(offset);
int outerClassIdx = bytes.getUnsignedShort(offset + 2);
int nameIdx = bytes.getUnsignedShort(offset + 4);
int accessFlags = bytes.getUnsignedShort(offset + 6);
CstType innerClass = (CstType) pool.get(innerClassIdx);
CstType outerClass = (CstType) pool.get0Ok(outerClassIdx);
CstString name = (CstString) pool.get0Ok(nameIdx);
list.set(i, innerClass, outerClass, name, accessFlags);
if (observer != null) {
observer.parsed(bytes, offset, 2,
"inner_class: " +
DirectClassFile.stringOrNone(innerClass));
observer.parsed(bytes, offset + 2, 2,
" outer_class: " +
DirectClassFile.stringOrNone(outerClass));
observer.parsed(bytes, offset + 4, 2,
" name: " +
DirectClassFile.stringOrNone(name));
observer.parsed(bytes, offset + 6, 2,
" access_flags: " +
AccessFlags.innerClassString(accessFlags));
}
offset += 8;
}
list.setImmutable();
return new AttInnerClasses(list);
| private com.android.dx.cf.iface.Attribute | lineNumberTable(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code LineNumberTable} attribute.
if (length < 2) {
return throwSeverelyTruncated();
}
ByteArray bytes = cf.getBytes();
int count = bytes.getUnsignedShort(offset); // line_number_table_length
if (observer != null) {
observer.parsed(bytes, offset, 2,
"line_number_table_length: " + Hex.u2(count));
}
offset += 2;
length -= 2;
if (length != (count * 4)) {
throwBadLength((count * 4) + 2);
}
LineNumberList list = new LineNumberList(count);
for (int i = 0; i < count; i++) {
int startPc = bytes.getUnsignedShort(offset);
int lineNumber = bytes.getUnsignedShort(offset + 2);
list.set(i, startPc, lineNumber);
if (observer != null) {
observer.parsed(bytes, offset, 4,
Hex.u2(startPc) + " " + lineNumber);
}
offset += 4;
}
list.setImmutable();
return new AttLineNumberTable(list);
| private com.android.dx.cf.iface.Attribute | localVariableTable(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code LocalVariableTable} attribute.
if (length < 2) {
return throwSeverelyTruncated();
}
ByteArray bytes = cf.getBytes();
int count = bytes.getUnsignedShort(offset);
if (observer != null) {
observer.parsed(bytes, offset, 2,
"local_variable_table_length: " + Hex.u2(count));
}
LocalVariableList list = parseLocalVariables(
bytes.slice(offset + 2, offset + length), cf.getConstantPool(),
observer, count, false);
return new AttLocalVariableTable(list);
| private com.android.dx.cf.iface.Attribute | localVariableTypeTable(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code LocalVariableTypeTable} attribute.
if (length < 2) {
return throwSeverelyTruncated();
}
ByteArray bytes = cf.getBytes();
int count = bytes.getUnsignedShort(offset);
if (observer != null) {
observer.parsed(bytes, offset, 2,
"local_variable_type_table_length: " + Hex.u2(count));
}
LocalVariableList list = parseLocalVariables(
bytes.slice(offset + 2, offset + length), cf.getConstantPool(),
observer, count, true);
return new AttLocalVariableTypeTable(list);
| protected com.android.dx.cf.iface.Attribute | parse0(DirectClassFile cf, int context, java.lang.String name, int offset, int length, com.android.dx.cf.iface.ParseObserver observer){@inheritDoc}
switch (context) {
case CTX_CLASS: {
if (name == AttDeprecated.ATTRIBUTE_NAME) {
return deprecated(cf, offset, length, observer);
}
if (name == AttEnclosingMethod.ATTRIBUTE_NAME) {
return enclosingMethod(cf, offset, length, observer);
}
if (name == AttInnerClasses.ATTRIBUTE_NAME) {
return innerClasses(cf, offset, length, observer);
}
if (name == AttRuntimeInvisibleAnnotations.ATTRIBUTE_NAME) {
return runtimeInvisibleAnnotations(cf, offset, length,
observer);
}
if (name == AttRuntimeVisibleAnnotations.ATTRIBUTE_NAME) {
return runtimeVisibleAnnotations(cf, offset, length,
observer);
}
if (name == AttSynthetic.ATTRIBUTE_NAME) {
return synthetic(cf, offset, length, observer);
}
if (name == AttSignature.ATTRIBUTE_NAME) {
return signature(cf, offset, length, observer);
}
if (name == AttSourceFile.ATTRIBUTE_NAME) {
return sourceFile(cf, offset, length, observer);
}
break;
}
case CTX_FIELD: {
if (name == AttConstantValue.ATTRIBUTE_NAME) {
return constantValue(cf, offset, length, observer);
}
if (name == AttDeprecated.ATTRIBUTE_NAME) {
return deprecated(cf, offset, length, observer);
}
if (name == AttRuntimeInvisibleAnnotations.ATTRIBUTE_NAME) {
return runtimeInvisibleAnnotations(cf, offset, length,
observer);
}
if (name == AttRuntimeVisibleAnnotations.ATTRIBUTE_NAME) {
return runtimeVisibleAnnotations(cf, offset, length,
observer);
}
if (name == AttSignature.ATTRIBUTE_NAME) {
return signature(cf, offset, length, observer);
}
if (name == AttSynthetic.ATTRIBUTE_NAME) {
return synthetic(cf, offset, length, observer);
}
break;
}
case CTX_METHOD: {
if (name == AttAnnotationDefault.ATTRIBUTE_NAME) {
return annotationDefault(cf, offset, length, observer);
}
if (name == AttCode.ATTRIBUTE_NAME) {
return code(cf, offset, length, observer);
}
if (name == AttDeprecated.ATTRIBUTE_NAME) {
return deprecated(cf, offset, length, observer);
}
if (name == AttExceptions.ATTRIBUTE_NAME) {
return exceptions(cf, offset, length, observer);
}
if (name == AttRuntimeInvisibleAnnotations.ATTRIBUTE_NAME) {
return runtimeInvisibleAnnotations(cf, offset, length,
observer);
}
if (name == AttRuntimeVisibleAnnotations.ATTRIBUTE_NAME) {
return runtimeVisibleAnnotations(cf, offset, length,
observer);
}
if (name == AttRuntimeInvisibleParameterAnnotations.
ATTRIBUTE_NAME) {
return runtimeInvisibleParameterAnnotations(
cf, offset, length, observer);
}
if (name == AttRuntimeVisibleParameterAnnotations.
ATTRIBUTE_NAME) {
return runtimeVisibleParameterAnnotations(
cf, offset, length, observer);
}
if (name == AttSignature.ATTRIBUTE_NAME) {
return signature(cf, offset, length, observer);
}
if (name == AttSynthetic.ATTRIBUTE_NAME) {
return synthetic(cf, offset, length, observer);
}
break;
}
case CTX_CODE: {
if (name == AttLineNumberTable.ATTRIBUTE_NAME) {
return lineNumberTable(cf, offset, length, observer);
}
if (name == AttLocalVariableTable.ATTRIBUTE_NAME) {
return localVariableTable(cf, offset, length, observer);
}
if (name == AttLocalVariableTypeTable.ATTRIBUTE_NAME) {
return localVariableTypeTable(cf, offset, length,
observer);
}
break;
}
}
return super.parse0(cf, context, name, offset, length, observer);
| private com.android.dx.cf.code.LocalVariableList | parseLocalVariables(com.android.dx.util.ByteArray bytes, com.android.dx.rop.cst.ConstantPool pool, com.android.dx.cf.iface.ParseObserver observer, int count, boolean typeTable)Parse the table part of either a {@code LocalVariableTable}
or a {@code LocalVariableTypeTable}.
if (bytes.size() != (count * 10)) {
// "+ 2" is for the count.
throwBadLength((count * 10) + 2);
}
ByteArray.MyDataInputStream in = bytes.makeDataInputStream();
LocalVariableList list = new LocalVariableList(count);
try {
for (int i = 0; i < count; i++) {
int startPc = in.readUnsignedShort();
int length = in.readUnsignedShort();
int nameIdx = in.readUnsignedShort();
int typeIdx = in.readUnsignedShort();
int index = in.readUnsignedShort();
CstString name = (CstString) pool.get(nameIdx);
CstString type = (CstString) pool.get(typeIdx);
CstString descriptor = null;
CstString signature = null;
if (typeTable) {
signature = type;
} else {
descriptor = type;
}
list.set(i, startPc, length, name,
descriptor, signature, index);
if (observer != null) {
observer.parsed(bytes, i * 10, 10, Hex.u2(startPc) +
".." + Hex.u2(startPc + length) + " " +
Hex.u2(index) + " " + name.toHuman() + " " +
type.toHuman());
}
}
} catch (IOException ex) {
throw new RuntimeException("shouldn't happen", ex);
}
list.setImmutable();
return list;
| private com.android.dx.cf.iface.Attribute | runtimeInvisibleAnnotations(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code RuntimeInvisibleAnnotations} attribute.
if (length < 2) {
throwSeverelyTruncated();
}
AnnotationParser ap =
new AnnotationParser(cf, offset, length, observer);
Annotations annotations =
ap.parseAnnotationAttribute(AnnotationVisibility.BUILD);
return new AttRuntimeInvisibleAnnotations(annotations, length);
| private com.android.dx.cf.iface.Attribute | runtimeInvisibleParameterAnnotations(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code RuntimeInvisibleParameterAnnotations} attribute.
if (length < 2) {
throwSeverelyTruncated();
}
AnnotationParser ap =
new AnnotationParser(cf, offset, length, observer);
AnnotationsList list =
ap.parseParameterAttribute(AnnotationVisibility.BUILD);
return new AttRuntimeInvisibleParameterAnnotations(list, length);
| private com.android.dx.cf.iface.Attribute | runtimeVisibleAnnotations(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code RuntimeVisibleAnnotations} attribute.
if (length < 2) {
throwSeverelyTruncated();
}
AnnotationParser ap =
new AnnotationParser(cf, offset, length, observer);
Annotations annotations =
ap.parseAnnotationAttribute(AnnotationVisibility.RUNTIME);
return new AttRuntimeVisibleAnnotations(annotations, length);
| private com.android.dx.cf.iface.Attribute | runtimeVisibleParameterAnnotations(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code RuntimeVisibleParameterAnnotations} attribute.
if (length < 2) {
throwSeverelyTruncated();
}
AnnotationParser ap =
new AnnotationParser(cf, offset, length, observer);
AnnotationsList list =
ap.parseParameterAttribute(AnnotationVisibility.RUNTIME);
return new AttRuntimeVisibleParameterAnnotations(list, length);
| private com.android.dx.cf.iface.Attribute | signature(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code Signature} attribute.
if (length != 2) {
throwBadLength(2);
}
ByteArray bytes = cf.getBytes();
ConstantPool pool = cf.getConstantPool();
int idx = bytes.getUnsignedShort(offset);
CstString cst = (CstString) pool.get(idx);
Attribute result = new AttSignature(cst);
if (observer != null) {
observer.parsed(bytes, offset, 2, "signature: " + cst);
}
return result;
| private com.android.dx.cf.iface.Attribute | sourceFile(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code SourceFile} attribute.
if (length != 2) {
throwBadLength(2);
}
ByteArray bytes = cf.getBytes();
ConstantPool pool = cf.getConstantPool();
int idx = bytes.getUnsignedShort(offset);
CstString cst = (CstString) pool.get(idx);
Attribute result = new AttSourceFile(cst);
if (observer != null) {
observer.parsed(bytes, offset, 2, "source: " + cst);
}
return result;
| private com.android.dx.cf.iface.Attribute | synthetic(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)Parses a {@code Synthetic} attribute.
if (length != 0) {
return throwBadLength(0);
}
return new AttSynthetic();
| private static com.android.dx.cf.iface.Attribute | throwBadLength(int expected)Throws the right exception when an attribute has an unexpected length
(given its contents).
throw new ParseException("bad attribute length; expected length " +
Hex.u4(expected));
| private static com.android.dx.cf.iface.Attribute | throwSeverelyTruncated()Throws the right exception when a known attribute has a way too short
length.
throw new ParseException("severely truncated attribute");
| private static com.android.dx.cf.iface.Attribute | throwTruncated()Throws the right exception when a known attribute has a too short
length.
throw new ParseException("truncated attribute");
|
|