All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.je.utilint.BitMap Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.je.utilint;

import java.util.BitSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.sleepycat.je.EnvironmentFailureException;

/**
 * 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;

    /*
     * Map of segment value -> bitset, where the segment value is index >>16
     */
    private Map bitSegments;

    public BitMap() {
        bitSegments = new HashMap();
    }

    /*
     * @throws IndexOutOfBoundsException if index is negative.
     */
    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 EnvironmentFailureException.unexpectedState
                (index + " is out of bounds");
        }
        int useIndex = getIntIndex(index);
        bitset.set(useIndex);
    }

    /*
     * @throws IndexOutOfBoundsException if index is negative.
     */
    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);
    }

    /*
     * Since the BitMap is implemented by a collection of BitSets, return
     * the one which covers the numeric range for this index.
     *
     * @param index the bit we want to access
     * @param allowCreate if true, return the BitSet that would hold this
     * index even if it wasn't previously set. If false, return null
     * if the bit has not been set.
     */
    private BitSet getBitSet(long index, boolean allowCreate) {

        Long segmentId = Long.valueOf(index >> SEGMENT_SIZE);

        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);
    }

    /* For unit testing. */
    int getNumSegments() {
        return bitSegments.size();
    }

    /*
     * Currently for unit testing, though note that java.util.BitSet does
     * support cardinality().
     */
    int cardinality() {
        int count = 0;
        Iterator iter = bitSegments.values().iterator();
        while (iter.hasNext()) {
            BitSet b = iter.next();
            count += b.cardinality();
        }
        return count;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy