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}