/* * Copyright 2004-2010 Brian S O'Neill * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.cojen.classfile; /** * A specialized, faster BitSet used by InstructionList. * * @author Brian S O'Neill */ final class BitList implements Cloneable { // Bits are stored little endian. private int[] mData; /** * @param capacity initial amount of bits to store */ public BitList(int capacity) { mData = new int[(capacity + 31) >> 5]; } public boolean get(int index) { return (mData[index >> 5] & (0x80000000 >>> index)) != 0; } /** * @param fromIndex inclusive * @return -1 if not found */ public int nextSetBit(int fromIndex) { int i = fromIndex >> 5; int[] data = mData; if (i >= data.length) { return -1; } int v = data[i] & (0xffffffff >>> fromIndex); while (true) { if (v != 0) { return (i << 5) + Integer.numberOfLeadingZeros(v); } if (++i >= data.length) { return -1; } v = data[i]; } } /** * @param fromIndex inclusive * @return non-negative index */ public int nextClearBit(int fromIndex) { int i = fromIndex >> 5; int[] data = mData; if (i >= data.length) { return fromIndex; } int v = ~data[i] & (0xffffffff >>> fromIndex); while (true) { if (v != 0) { return (i << 5) + Integer.numberOfLeadingZeros(v); } if (++i >= data.length) { return data.length << 32; } v = ~data[i]; } } /** * @return true if any change made */ public boolean set(int index) { int i = index >> 5; int v = mData[i]; return v != (mData[i] = v | (0x80000000 >>> index)); } /** * @return true if any changes made */ public boolean or(BitList list) { boolean changes = ensureCapacity(list.capacity()); for (int i=list.mData.length; --i >= 0; ) { int v = mData[i]; changes |= (v != (mData[i] = v | list.mData[i])); } return changes; } public boolean isAllClear() { for (int i=mData.length; --i >= 0; ) { if (mData[i] != 0) { return false; } } return true; } public boolean isAllSet() { for (int i=mData.length; --i >= 0; ) { if (mData[i] != 0xffffffff) { return false; } } return true; } /** * @return true if the bitwise or of the two lists is different than the * bitwise xor. */ public boolean intersects(BitList list) { if (list != null) { for (int i=Math.min(mData.length, list.mData.length); --i >= 0; ) { int v1 = mData[i]; int v2 = list.mData[i]; if ((v1 | v2) != (v1 ^ v2)) { return true; } } } return false; } public int hashCode() { int hash = 0; for (int i=mData.length; --i >= 0; ) { hash = hash * 31 + mData[i]; } return hash; } public int capacity() { return mData.length << 5; } public boolean equals(Object obj) { if (obj instanceof BitList) { return java.util.Arrays.equals(mData, ((BitList)obj).mData); } return false; } public BitList copy() { return (BitList)clone(); } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } } public String toString() { StringBuffer buf = new StringBuffer(mData.length + 2); buf.append('['); for (int i=0; i<mData.length; i++) { String binary = Integer.toBinaryString(mData[i]); for (int j=binary.length(); j<32; j++) { buf.append('0'); } buf.append(binary); } buf.append(']'); return buf.toString(); } private boolean ensureCapacity(int capacity) { int len = (capacity + 31) >> 5; if (len > mData.length) { int[] newData = new int[len]; System.arraycopy(mData, 0, newData, 0, mData.length); mData = newData; return true; } return false; } }