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    /**
029     * Count the number of arguments in the descriptor. Each long or double counts as widthOfLongsAndDoubles; all other arguments count as 1.
030     *
031     * @param descriptor             String for which arguments are counted
032     * @param widthOfLongsAndDoubles int increment to apply for longs doubles. This is typically 1 when counting arguments alone, or 2 when counting arguments
033     *                               for invokeinterface.
034     * @return integer count
035     */
036    protected static int countArgs(final String descriptor, final int widthOfLongsAndDoubles) {
037        final int bra = descriptor.indexOf('(');
038        final int ket = descriptor.indexOf(')');
039        if (bra == -1 || ket == -1 || ket < bra) {
040            throw new IllegalArgumentException("No arguments");
041        }
042
043        boolean inType = false;
044        boolean consumingNextType = false;
045        int count = 0;
046        for (int i = bra + 1; i < ket; i++) {
047            final char charAt = descriptor.charAt(i);
048            if (inType && charAt == ';') {
049                inType = false;
050                consumingNextType = false;
051            } else if (!inType && charAt == 'L') {
052                inType = true;
053                count++;
054            } else if (charAt == '[') {
055                consumingNextType = true;
056            } else if (inType) {
057                // NOP
058            } else if (consumingNextType) {
059                count++;
060                consumingNextType = false;
061            } else if (charAt == 'D' || charAt == 'J') {
062                count += widthOfLongsAndDoubles;
063            } else {
064                count++;
065            }
066        }
067        return count;
068    }
069
070    public static int countBit16(final int[] flags) {
071        int count = 0;
072        for (final int flag : flags) {
073            if ((flag & 1 << 16) != 0) {
074                count++;
075            }
076        }
077        return count;
078    }
079
080    public static int countBit16(final long[] flags) {
081        int count = 0;
082        for (final long flag : flags) {
083            if ((flag & 1 << 16) != 0) {
084                count++;
085            }
086        }
087        return count;
088    }
089
090    public static int countBit16(final long[][] flags) {
091        int count = 0;
092        for (final long[] flag : flags) {
093            for (final long element : flag) {
094                if ((element & 1 << 16) != 0) {
095                    count++;
096                }
097            }
098        }
099        return count;
100    }
101
102    public static int countInvokeInterfaceArgs(final String descriptor) {
103        return countArgs(descriptor, 2);
104    }
105
106    public static int countMatches(final long[] flags, final IMatcher matcher) {
107        int count = 0;
108        for (final long flag : flags) {
109            if (matcher.matches(flag)) {
110                count++;
111            }
112        }
113        return count;
114    }
115
116    public static int countMatches(final long[][] flags, final IMatcher matcher) {
117        int count = 0;
118        for (final long[] flag : flags) {
119            count += countMatches(flag, matcher);
120        }
121        return count;
122    }
123
124}