    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}