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