private void parseMethodAttrBands()

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);
                    }
                }
            }
        }
    }