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