    001/*
    002 *  Licensed to the Apache Software Foundation (ASF) under one or more
    003 *  contributor license agreements.  See the NOTICE file distributed with
    004 *  this work for additional information regarding copyright ownership.
    005 *  The ASF licenses this file to You under the Apache License, Version 2.0
    006 *  (the "License"); you may not use this file except in compliance with
    007 *  the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 *  Unless required by applicable law or agreed to in writing, software
    012 *  distributed under the License is distributed on an "AS IS" BASIS,
    013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 *  See the License for the specific language governing permissions and
    015 *  limitations under the License.
    016 */
    017package org.apache.commons.compress.harmony.unpack200;
    018
    019/**
    020 * Utility class for unpack200
    021 */
    022public final class SegmentUtils {
    023
    024    public static int countArgs(final String descriptor) {
    025        return countArgs(descriptor, 1);
    026    }
    027
    028    public static int countInvokeInterfaceArgs(final String descriptor) {
    029        return countArgs(descriptor, 2);
    030    }
    031
    032    /**
    033     * Count the number of arguments in the descriptor. Each long or double counts as widthOfLongsAndDoubles; all other
    034     * arguments count as 1.
    035     *
    036     * @param descriptor String for which arguments are counted
    037     * @param widthOfLongsAndDoubles int increment to apply for longs doubles. This is typically 1 when counting
    038     *        arguments alone, or 2 when counting arguments for invokeinterface.
    039     * @return integer count
    040     */
    041    protected static int countArgs(final String descriptor, final int widthOfLongsAndDoubles) {
    042        final int bra = descriptor.indexOf('(');
    043        final int ket = descriptor.indexOf(')');
    044        if (bra == -1 || ket == -1 || ket < bra) {
    045            throw new IllegalArgumentException("No arguments");
    046        }
    047
    048        boolean inType = false;
    049        boolean consumingNextType = false;
    050        int count = 0;
    051        for (int i = bra + 1; i < ket; i++) {
    052            final char charAt = descriptor.charAt(i);
    053            if (inType && charAt == ';') {
    054                inType = false;
    055                consumingNextType = false;
    056            } else if (!inType && charAt == 'L') {
    057                inType = true;
    058                count++;
    059            } else if (charAt == '[') {
    060                consumingNextType = true;
    061            } else if (inType) {
    062                // NOP
    063            } else if (consumingNextType) {
    064                count++;
    065                consumingNextType = false;
    066            } else if (charAt == 'D' || charAt == 'J') {
    067                count += widthOfLongsAndDoubles;
    068            } else {
    069                count++;
    070            }
    071        }
    072        return count;
    073    }
    074
    075    public static int countMatches(final long[] flags, final IMatcher matcher) {
    076        int count = 0;
    077        for (int i = 0; i < flags.length; i++) {
    078            if (matcher.matches(flags[i])) {
    079                count++;
    080            }
    081        }
    082        return count;
    083    }
    084
    085    public static int countBit16(final int[] flags) {
    086        int count = 0;
    087        for (int i = 0; i < flags.length; i++) {
    088            if ((flags[i] & (1 << 16)) != 0) {
    089                count++;
    090            }
    091        }
    092        return count;
    093    }
    094
    095    public static int countBit16(final long[] flags) {
    096        int count = 0;
    097        for (int i = 0; i < flags.length; i++) {
    098            if ((flags[i] & (1 << 16)) != 0) {
    099                count++;
    100            }
    101        }
    102        return count;
    103    }
    104
    105    public static int countBit16(final long[][] flags) {
    106        int count = 0;
    107        for (int i = 0; i < flags.length; i++) {
    108            for (int j = 0; j < flags[i].length; j++) {
    109                if ((flags[i][j] & (1 << 16)) != 0) {
    110                    count++;
    111                }
    112            }
    113        }
    114        return count;
    115    }
    116
    117    public static int countMatches(final long[][] flags, final IMatcher matcher) {
    118        int count = 0;
    119        for (int i = 0; i < flags.length; i++) {
    120            count += countMatches(flags[i], matcher);
    121        }
    122        return count;
    123    }
    124
    125}