brooklyn.util.math.BitList Maven / Gradle / Ivy
Show all versions of brooklyn-utils-common Show documentation
package brooklyn.util.math;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import com.google.common.collect.Lists;
import com.google.common.primitives.Bytes;
/** represents an immutable ordered collection of bits with a known length
*
* when converting to and from bytes and larger numbers, this representation
* uses the least-significant first convention both for bits and for bytes (little endian)
*
* (i.e. least significant byte is first, as is the least significant bit;
* ninth element in this list is the least significant bit in the second byte,
* so a list {0,0,0,0,0,0,0,0,1,0} represents 256)
**/
public class BitList {
private final BitSet bits;
protected final int length;
protected BitList(BitSet bits, int length) {
assert length >= bits.length();
this.bits = bits;
this.length = length;
}
public static BitList newInstance(BitSet bits, int length) {
return new BitList(bits, length);
}
public int length() {
return length;
}
public boolean get(int index) {
if (index<0 || index>=length)
throw new IndexOutOfBoundsException("Index "+index+" in "+this);
return bits.get(index);
}
public static BitList newInstance(byte ...bytes) {
BitSet bits = new BitSet();
for (int i=0; i < bytes.length*8; i++)
if ((bytes[i/8] & (1 << (i%8))) > 0)
bits.set(i);
return newInstance(bits, bytes.length*8);
}
/** as {@link #newInstance(byte...)}, but accepting ints for convenience;
* only the least significant 8 bits of the parameters are considered */
public static BitList newInstanceFromBytes(int ...bytes) {
BitSet bits = new BitSet();
for (int i=0; i < bytes.length*8; i++)
if ((bytes[i/8] & (1 << (i%8))) > 0)
bits.set(i);
return newInstance(bits, bytes.length*8);
}
public static BitList newInstance(List l) {
BitSet bs = new BitSet();
for (int i=0; i
* NB this may be different to BitSet.valueOf available since java 7 (as late as that!)
* which reverses the order of the bytes */
public byte[] asBytes() {
byte[] bytes = new byte[(length+7)/8];
for (int i=0; i asList() {
List list = new ArrayList();
for (int i=0; ilength)
b2.clear(length, b2.length());
return newInstance(b2, length);
}
public BitList reversed() {
BitSet b = new BitSet();
for (int from=bits.length()-1, to=length-bits.length(); from>=0; from--, to++) {
if (get(from)) b.set(to);
}
return new BitList(b, length);
}
public int commonPrefixLength(BitList other) {
int i=0;
while (i asByteList() {
return Bytes.asList(asBytes());
}
/** returns value of this as a byte(ignoring any too-high bits) */
public byte byteValue() {
return asBigInteger().byteValue();
}
/** returns value of this as an integer (ignoring any too-high bits) */
public int intValue() {
return asBigInteger().intValue();
}
/** returns value of this as a long (ignoring any too-high bits) */
public long longValue() {
return asBigInteger().longValue();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((bits == null) ? 0 : bits.hashCode());
result = prime * result + length;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BitList other = (BitList) obj;
if (bits == null) {
if (other.bits != null)
return false;
} else if (!bits.equals(other.bits))
return false;
if (length != other.length)
return false;
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i=0; i0) sb.append(":"); //for readability
sb.append(get(i) ? '1' : '0');
}
return sb.toString();
}
}