package com.snowcattle.game.common.util;
/**
* 以字节数组实现的BitSet
* <p>
* 该实现是在初始化对象时即固定位长度的,当获取和设置位时使用的索引上越界时, 将不会自动增加位长度。
*
*
*/
public class ByteArrayBitSet {
private final static int ADDRESS_BITS_PER_BYTE = 3;
private final static int BITS_PER_BYTE = 1 << ADDRESS_BITS_PER_BYTE;
/** 每字节索引掩码 */
private final static int MASK_INDEX_PER_BYTE = BITS_PER_BYTE - 1;
/** 字节数组 */
private byte[] bytes;
/**
* @param nbits
* 位数,大于0
* @exception IllegalArgumentException
* 指定位数不大于0时抛出
*/
public ByteArrayBitSet(int nbits) {
if (nbits <= 0) {
throw new IllegalArgumentException("nbits <= 0: " + nbits);
}
initByteArray(nbits);
}
/**
* 以指定字节数组作为初始化数据
*
* @param byteArray
* @exception NullPointerException
* 字节数组为空时
* @exception IllegalArgumentException
* 在字节数组长度为0时抛出
*/
public ByteArrayBitSet(byte[] byteArray) {
if (byteArray.length == 0) {
throw new IllegalArgumentException(
"Length of byte array can't not be zero!");
}
bytes = byteArray.clone();
}
private void initByteArray(int nbits) {
bytes = new byte[byteIndex(nbits - 1) + 1];
}
private int byteIndex(int bitIndex) {
return bitIndex >> ADDRESS_BITS_PER_BYTE;
}
private int indexMarkInByte(int bitIndex) {
return 1 << (bitIndex & MASK_INDEX_PER_BYTE);
}
/**
* 获得指定索引上的位值
*
* @param bitIndex
* @return 返回指定索引上的值,上越界时该值始终返回false
* @exception IndexOutOfBoundsException
* 在索引小于0时抛出
*/
public boolean get(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int _byteIndex = byteIndex(bitIndex);
return (_byteIndex < bytes.length)
&& ((bytes[_byteIndex] & indexMarkInByte(bitIndex)) != 0);
}
/**
* 将指定索引上的位置为给定值
*
* @param bitIndex
* 若该索引上越界,则该操作没有意义
* @param value
* @exception IndexOutOfBoundsException
* 指定索引为负时抛出
*/
public void set(int bitIndex, boolean value) {
if (value) {
set(bitIndex);
} else {
clear(bitIndex);
}
}
/**
* 将指定索引上位的值置1
*
* @param bitIndex
* 若该索引上越界,则该操作没有意义
* @exception IndexOutOfBoundsException
* 指定索引为负时抛出
*/
public void set(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int _byteIndex = byteIndex(bitIndex);
if (_byteIndex < bytes.length) {
bytes[_byteIndex] |= indexMarkInByte(bitIndex);
}
}
/**
* 将指定索引上位的值置0
*
* @param bitIndex
* 若该索引上越界,则该操作没有意义
* @exception IndexOutOfBoundsException
* 指定索引为负时抛出
*/
public void clear(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int _byteIndex = byteIndex(bitIndex);
if (_byteIndex < bytes.length) {
bytes[_byteIndex] &= ~indexMarkInByte(bitIndex);
}
}
/**
* 返回可表示的位大小
*
* @return
*/
public int size() {
return bytes.length << ADDRESS_BITS_PER_BYTE;
}
/**
* 获得当前表示位的字节数组
*
* @return
*/
public byte[] getByteArray() {
return bytes;
}
}