package com.sleepycat.je.utilint;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import de.ovgu.cide.jakutil.*;
/**
* Bitmap which supports indexing with long arguments. java.util.BitSet
* provides all the functionality and performance we need, but requires integer
* indexing.
* Long indexing is implemented by keeping a Map of java.util.BitSets, where
* each bitset covers 2^16 bits worth of values. The Bitmap may be sparse, in
* that each segment is only instantiated when needed.
* Note that this class is currently not thread safe; adding a new bitset
* segment is not protected.
*/
public class BitMap {
private static final int SEGMENT_SIZE=16;
private static final int SEGMENT_MASK=0xffff;
private Map bitSegments;
public BitMap(){
bitSegments=new HashMap();
}
public void set( long index) throws IndexOutOfBoundsException {
if (index < 0) {
throw new IndexOutOfBoundsException(index + " is negative.");
}
BitSet bitset=getBitSet(index,true);
if (bitset == null) {
throw new IllegalArgumentException(index + " is out of bounds");
}
int useIndex=getIntIndex(index);
bitset.set(useIndex);
}
public boolean get( long index) throws IndexOutOfBoundsException {
if (index < 0) {
throw new IndexOutOfBoundsException(index + " is negative.");
}
BitSet bitset=getBitSet(index,false);
if (bitset == null) {
return false;
}
int useIndex=getIntIndex(index);
return bitset.get(useIndex);
}
private BitSet getBitSet( long index, boolean allowCreate){
Long segmentId=new Long(index >> SEGMENT_SIZE);
BitSet bitset=(BitSet)bitSegments.get(segmentId);
if (allowCreate) {
if (bitset == null) {
bitset=new BitSet();
bitSegments.put(segmentId,bitset);
}
}
return bitset;
}
private int getIntIndex( long index){
return (int)(index & SEGMENT_MASK);
}
int getNumSegments(){
return bitSegments.size();
}
int cardinality(){
int count=0;
Iterator iter=bitSegments.values().iterator();
while (iter.hasNext()) {
BitSet b=(BitSet)iter.next();
count+=b.cardinality();
}
return count;
}
}