in src/main/java/org/apache/commons/compress/harmony/unpack200/ClassBands.java [991:1103]
private void parseMethodAttrBands(final InputStream in) throws IOException, Pack200Exception {
methodFlags = parseFlags("method_flags", in, classMethodCount, Codec.UNSIGNED5, options.hasMethodFlagsHi());
final int methodAttrCount = SegmentUtils.countBit16(methodFlags);
final int[] methodAttrCounts = decodeBandInt("method_attr_count", in, Codec.UNSIGNED5, methodAttrCount);
final int[][] methodAttrIndexes = decodeBandInt("method_attr_indexes", in, Codec.UNSIGNED5, methodAttrCounts);
final int callCount = getCallCount(methodAttrIndexes, methodFlags, AttributeLayout.CONTEXT_METHOD);
methodAttrCalls = decodeBandInt("method_attr_calls", in, Codec.UNSIGNED5, callCount);
// assign empty method attributes
methodAttributes = new ArrayList[classCount][];
for (int i = 0; i < classCount; i++) {
methodAttributes[i] = new ArrayList[methodFlags[i].length];
for (int j = 0; j < methodFlags[i].length; j++) {
methodAttributes[i][j] = new ArrayList<>();
}
}
// Parse method exceptions attributes
final AttributeLayout methodExceptionsLayout = attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_EXCEPTIONS, AttributeLayout.CONTEXT_METHOD);
final int count = SegmentUtils.countMatches(methodFlags, methodExceptionsLayout);
final int[] numExceptions = decodeBandInt("method_Exceptions_n", in, Codec.UNSIGNED5, count);
final int[][] methodExceptionsRS = decodeBandInt("method_Exceptions_RC", in, Codec.UNSIGNED5, numExceptions);
// Parse method signature attributes
final AttributeLayout methodSignatureLayout = attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE, AttributeLayout.CONTEXT_METHOD);
final int count1 = SegmentUtils.countMatches(methodFlags, methodSignatureLayout);
final int[] methodSignatureRS = decodeBandInt("method_signature_RS", in, Codec.UNSIGNED5, count1);
final AttributeLayout deprecatedLayout = attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_DEPRECATED, AttributeLayout.CONTEXT_METHOD);
// Add attributes to the attribute arrays
int methodExceptionsIndex = 0;
int methodSignatureIndex = 0;
for (int i = 0; i < methodAttributes.length; i++) {
for (int j = 0; j < methodAttributes[i].length; j++) {
final long flag = methodFlags[i][j];
if (methodExceptionsLayout.matches(flag)) {
final int n = numExceptions[methodExceptionsIndex];
final int[] exceptions = methodExceptionsRS[methodExceptionsIndex];
final CPClass[] exceptionClasses = new CPClass[n];
for (int k = 0; k < n; k++) {
exceptionClasses[k] = cpBands.cpClassValue(exceptions[k]);
}
methodAttributes[i][j].add(new ExceptionsAttribute(exceptionClasses));
methodExceptionsIndex++;
}
if (methodSignatureLayout.matches(flag)) {
// We've got a signature attribute
final long result = methodSignatureRS[methodSignatureIndex];
final String desc = methodDescr[i][j];
final int colon = desc.indexOf(':');
String type = desc.substring(colon + 1);
// TODO Got to get better at this ... in any case, it should
// be for example KIB or KIH
if (type.equals("B") || type.equals("H")) {
type = "I";
}
final CPUTF8 value = (CPUTF8) methodSignatureLayout.getValue(result, type, cpBands.getConstantPool());
methodAttributes[i][j].add(new SignatureAttribute(value));
methodSignatureIndex++;
}
if (deprecatedLayout.matches(flag)) {
methodAttributes[i][j].add(new DeprecatedAttribute());
}
}
}
// Parse non-predefined attribute bands
int backwardsCallIndex = parseMethodMetadataBands(in, methodAttrCalls);
final int limit = options.hasMethodFlagsHi() ? 62 : 31;
final AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
final int[] counts = new int[limit + 1];
for (int i = 0; i < limit; i++) {
final AttributeLayout layout = attrMap.getAttributeLayout(i, AttributeLayout.CONTEXT_METHOD);
if (layout != null && !layout.isDefaultLayout()) {
otherLayouts[i] = layout;
counts[i] = SegmentUtils.countMatches(methodFlags, layout);
}
}
final List<Attribute>[] otherAttributes = new List[limit + 1];
for (int i = 0; i < counts.length; i++) {
if (counts[i] > 0) {
final NewAttributeBands bands = attrMap.getAttributeBands(otherLayouts[i]);
otherAttributes[i] = bands.parseAttributes(in, counts[i]);
final int numBackwardsCallables = otherLayouts[i].numBackwardsCallables();
if (numBackwardsCallables > 0) {
final int[] backwardsCalls = new int[numBackwardsCallables];
System.arraycopy(methodAttrCalls, backwardsCallIndex, backwardsCalls, 0, numBackwardsCallables);
bands.setBackwardsCalls(backwardsCalls);
backwardsCallIndex += numBackwardsCallables;
}
}
}
// Non-predefined attributes
for (int i = 0; i < methodAttributes.length; i++) {
for (int j = 0; j < methodAttributes[i].length; j++) {
final long flag = methodFlags[i][j];
int othersAddedAtStart = 0;
for (int k = 0; k < otherLayouts.length; k++) {
if (otherLayouts[k] != null && otherLayouts[k].matches(flag)) {
// Add the next attribute
if (otherLayouts[k].getIndex() < 15) {
methodAttributes[i][j].add(othersAddedAtStart++, otherAttributes[k].get(0));
} else {
methodAttributes[i][j].add(otherAttributes[k].get(0));
}
otherAttributes[k].remove(0);
}
}
}
}
}