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}