/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.util;
/**
* A list of bits.
*/
//下标都是从0开始计数的,data[0]表示0到63,data[1]表示64到127。。。
public final class BitField {
private static final int ADDRESS_BITS = 6; //表示2的6次方,刚好等于64, i >> ADDRESS_BITS时能确定是在data中那个下标
private static final int BITS = 64;
private static final int ADDRESS_MASK = BITS - 1;
private long[] data;
private int maxLength;
public BitField() {
this(64);
}
// 我加上的
public String toString() {
return stringArray2(data);
}
// 我加上的
public static String stringArray2(long[] array) {
if (array == null) {
return "null";
}
StatementBuilder buff = new StatementBuilder("[");
for (Object a : array) {
buff.appendExceptFirst(", ");
buff.append(a.toString());
}
buff.append("]");
return buff.toString();
}
//capacity表示总位数
public BitField(int capacity) {
//如果capacity小于8(2的三次方),那么不预先分配data
//capacity>8时,分配capacity >>> 3个long,一个long能表示64倍,
//所以capacity>8时预分配的data能表示的位数是: (capacity >>> 3) *64 约等于 (capacity/8)*64 = capacity*8
//即是原来capacity的8倍(约等于)
data = new long[capacity >>> 3];
}
/**
* Get the index of the next bit that is not set.
*
* @param fromIndex where to start searching
* @return the index of the next disabled bit
*/
public int nextClearBit(int fromIndex) {
int i = fromIndex >> ADDRESS_BITS;
int max = data.length;
for (; i < max; i++) {
if (data[i] == -1) { //long的所有位都是1时,值时-1
continue;
}
int j = Math.max(fromIndex, i << ADDRESS_BITS);
for (int end = j + 64; j < end; j++) {
if (!get(j)) {
return j;
}
}
}
return max << ADDRESS_BITS;
}
/**
* Get the bit at the given index.
*
* @param i the index
* @return true if the bit is enabled
*/
public boolean get(int i) {
int addr = i >> ADDRESS_BITS;
if (addr >= data.length) {
return false;
}
return (data[addr] & getBitMask(i)) != 0;
}
/**
* Get the next 8 bits at the given index.
* The index must be a multiple of 8.
*
* @param i the index
* @return the next 8 bits
*/
public int getByte(int i) {
int addr = i >> ADDRESS_BITS;
if (addr >= data.length) {
return 0;
}
return (int) (data[addr] >>> (i & (7 << 3)) & 255);
}
/**
* Combine the next 8 bits at the given index with OR.
* The index must be a multiple of 8.
*
* @param i the index
* @param x the next 8 bits (0 - 255)
*/
public void setByte(int i, int x) {
int addr = i >> ADDRESS_BITS;
checkCapacity(addr);
data[addr] |= ((long) x) << (i & (7 << 3));
if (maxLength < i && x != 0) {
maxLength = i + 7;
}
}
/**
* Set bit at the given index to 'true'.
*
* @param i the index
*/
public void set(int i) {
int addr = i >> ADDRESS_BITS;
checkCapacity(addr);
data[addr] |= getBitMask(i);
if (maxLength < i) {
maxLength = i;
}
}
/**
* Set bit at the given index to 'false'.
*
* @param i the index
*/
public void clear(int i) {
int addr = i >> ADDRESS_BITS;
if (addr >= data.length) {
return;
}
data[addr] &= ~getBitMask(i);
}
//比如,如果i是63,返回的long值的第64(因为i从0开始,所以是i+1)位是1,
//如果i是65,按63取模后是1,返回的long值的第2位是1,
private static long getBitMask(int i) {
return 1L << (i & ADDRESS_MASK); //(i & ADDRESS_MASK)相当于按63取模(得到的值是0到63)
}
private void checkCapacity(int size) {
if (size >= data.length) {
expandCapacity(size);
}
}
private void expandCapacity(int size) {
while (size >= data.length) {
int newSize = data.length == 0 ? 1 : data.length * 2;
long[] d = new long[newSize];
System.arraycopy(data, 0, d, 0, data.length);
data = d;
}
}
/**
* Enable or disable a number of bits.
*
* @param fromIndex the index of the first bit to enable or disable
* @param toIndex one plus the index of the last bit to enable or disable
* @param value the new value
*/
public void set(int fromIndex, int toIndex, boolean value) {
// go backwards so that OutOfMemory happens
// before some bytes are modified
for (int i = toIndex - 1; i >= fromIndex; i--) {
set(i, value);
}
if (value) {
if (toIndex > maxLength) {
maxLength = toIndex;
}
} else {
if (toIndex >= maxLength) {
maxLength = fromIndex;
}
}
}
private void set(int i, boolean value) {
if (value) {
set(i);
} else {
clear(i);
}
}
/**
* Get the index of the highest set bit plus one, or 0 if no bits are set.
*
* @return the length of the bit field
*/
public int length() {
int m = maxLength >> ADDRESS_BITS;
while (m > 0 && data[m] == 0) {
m--;
}
maxLength = (m << ADDRESS_BITS) +
(64 - Long.numberOfLeadingZeros(data[m]));
return maxLength;
}
}