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}