/*
* Copyright 2016 higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.lang.collection;
import net.openhft.lang.ReferenceCounted;
/**
* Most notable logical difference of this interface with {@code java.util.BitSet}
* is that {@code DirectBitSet} has a rigid {@link #size},
* attempts to {@link #get}, {@link #set} or {@link #clear} bits at indices
* exceeding the size cause {@code IndexOutOfBoundsException}. There is also
* a {@link #setAll()} method to set all bits within the size.
* {@code java.util.BitSet} doesn't have such rigid capacity.
*
* @see java.util.BitSet
*/
public interface DirectBitSet extends ReferenceCounted {
/**
* Returned if no entry is found
*/
long NOT_FOUND = -1L;
/**
* Sets the bit at the specified index to the complement of its
* current value.
*
* @param bitIndex the index of the bit to flip
* @return this {@code DirectBitSet} back
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size())}
*/
DirectBitSet flip(long bitIndex);
/**
* Sets each bit from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to the complement of its current
* value.
*
* @param fromIndex index of the first bit to flip
* @param toIndex index after the last bit to flip
* @return this {@code DirectBitSet} back
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code fromIndex} is larger than {@code toIndex},
* or {@code toIndex} is larger or equal to {@code size()}
*/
DirectBitSet flip(long fromIndex, long toIndex);
/**
* Sets the bit at the specified index to {@code true}.
*
* @param bitIndex a bit index
* @return this {@code DirectBitSet} back
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size())}
*/
DirectBitSet set(long bitIndex);
/**
* Sets the bit at the specified index to {@code true}.
*
* @param bitIndex a bit index
* @return true if the bit was zeroOut, or false if the bit was already set.
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size())}
*/
boolean setIfClear(long bitIndex);
/**
* Clears the bit at the specified index (sets it to {@code false}).
*
* @param bitIndex a bit index
* @return the previous value of the bit at the specified index
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size())}
*/
boolean clearIfSet(long bitIndex);
/**
* Sets the bit at the specified index to the specified value.
*
* @param bitIndex a bit index
* @param value a boolean value to set
* @return this {@code DirectBitSet} back
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size())}
*/
DirectBitSet set(long bitIndex, boolean value);
/**
* Sets the bits from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to {@code true}.
*
* @param fromIndex index of the first bit to be set
* @param toIndex index after the last bit to be set
* @return this {@code DirectBitSet} back
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code fromIndex} is larger than {@code toIndex},
* or {@code toIndex} is larger or equal to {@code size()}
*/
DirectBitSet set(long fromIndex, long toIndex);
/**
* Sets all bits, {@code bs.setAll()} is equivalent
* of {@code bs.set(0, bs.size()}.
*
* @return this bit set back
*/
DirectBitSet setAll();
/**
* Sets the bits from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to the specified value.
*
* @param fromIndex index of the first bit to be set
* @param toIndex index after the last bit to be set
* @param value value to set the selected bits to
* @return this {@code DirectBitSet} back
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code fromIndex} is larger than {@code toIndex},
* or {@code toIndex} is larger or equal to {@code size()}
*/
DirectBitSet set(long fromIndex, long toIndex, boolean value);
/**
* Sets the bit specified by the index to {@code false}.
*
* @param bitIndex the index of the bit to be cleared
* @return this {@code DirectBitSet} back
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size())}
*/
DirectBitSet clear(long bitIndex);
/**
* Sets the bits from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to {@code false}.
*
* @param fromIndex index of the first bit to be cleared
* @param toIndex index after the last bit to be cleared
* @return this {@code DirectBitSet} back
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code fromIndex} is larger than {@code toIndex},
* or {@code toIndex} is larger or equal to {@code size()}
*/
DirectBitSet clear(long fromIndex, long toIndex);
/**
* Sets all of the bits in this BitSet to {@code false}.
*
* @return this {@code DirectBitSet} back
*/
DirectBitSet clear();
/**
* Returns the value of the bit with the specified index. The value
* is {@code true} if the bit with the index {@code bitIndex}
* is currently set in this {@code DirectBitSet}; otherwise, the result
* is {@code false}.
*
* @param bitIndex the bit index
* @return the value of the bit with the specified index
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size())}
*/
boolean get(long bitIndex);
/**
* Synonym of {@link #get(long)}.
*
* @param bitIndex the bit index
* @return the value of the bit with the specified index
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size())}
*/
boolean isSet(long bitIndex);
/**
* Synonym of {@code !get(long)}.
* @param bitIndex the bit index
* @return {@code true} is the bit at the specified index is clear in this
* bit set; if the bit is set to {@code true} then returns {@code false}
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size())}
*/
boolean isClear(long bitIndex);
/**
* Returns the value of the long with the specified long index.
*
* @param longIndex the bit index
* @return the value of the long with the specified index
* @throws IndexOutOfBoundsException if the index is out of range
* {@code (index < 0 || index >= size() / 64)}
*/
long getLong(long longIndex);
/**
* Returns the index of the first bit that is set to {@code true}
* that occurs on or after the specified starting index. If no such
* bit exists then {@code -1} is returned.
*
* <p>To iterate over the {@code true} bits in a {@code DirectBitSet},
* use the following loop:
* <pre> {@code
* for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
* // operate on index i here
* }}</pre>
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the next set bit, or {@code -1} if there
* is no such bit
* @throws IndexOutOfBoundsException if the specified index is negative
* @see #clearNextSetBit(long)
*/
long nextSetBit(long fromIndex);
/**
* Returns the index of the first long that contains a bit set to {@code true}
* that occurs on or after the specified starting index. The index is the number of longs.
* If no such bit exists then {@code -1} is returned.
*
* @param fromLongIndex the index to start checking from (inclusive)
* @return the index of the next set long, or {@code -1} if there
* is no such long
* @throws IndexOutOfBoundsException if the specified index is negative
*/
long nextSetLong(long fromLongIndex);
/**
* Returns the index of the first bit that is set to {@code false}
* that occurs on or after the specified starting index. If no such
* bit exists then {@code -1} is returned.
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the next zeroOut bit,
* or {@code -1} if there is no such bit
* @throws IndexOutOfBoundsException if the specified index is negative
* @see #setNextClearBit(long)
*/
long nextClearBit(long fromIndex);
/**
* Returns the index of the first long that contains a bit is set to {@code false}
* that occurs on or after the specified starting index. If no such
* bit exists then {@code -1} is returned.
*
* @param fromLongIndex the index to start checking from (inclusive)
* @return the index of the next long containing a zeroOut bit,
* or {@code -1} if there is no such long
* @throws IndexOutOfBoundsException if the specified index is negative
*/
long nextClearLong(long fromLongIndex);
/**
* Returns the index of the nearest bit that is set to {@code true}
* that occurs on or before the specified starting index.
* If no such bit exists, or if {@code -1} is given as the
* starting index, then {@code -1} is returned.
*
* <p>To iterate over the {@code true} bits in a {@code DirectBitSet},
* use the following loop:
* <pre> {@code
* for (int i = bs.size(); (i = bs.previousSetBit(i-1)) >= 0; ) {
* // operate on index i here
* }}</pre>
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the previous set bit, or {@code -1} if there
* is no such bit
* @throws IndexOutOfBoundsException if the specified index is less
* than {@code -1}
* @see #clearPreviousSetBit(long)
*/
long previousSetBit(long fromIndex);
/**
* Returns the index of the nearest long that contains a bit set to {@code true}
* that occurs on or before the specified starting index.
* If no such bit exists, or if {@code -1} is given as the
* starting index, then {@code -1} is returned.
*
* @param fromLongIndex the index to start checking from (inclusive)
* @return the index of the previous long containing a set bit,
* or {@code -1} if there is no such long
* @throws IndexOutOfBoundsException if the specified index is less
* than {@code -1}
*/
long previousSetLong(long fromLongIndex);
/**
* Returns the index of the nearest bit that is set to {@code false}
* that occurs on or before the specified starting index.
* If no such bit exists, or if {@code -1} is given as the
* starting index, then {@code -1} is returned.
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the previous zeroOut bit, or {@code -1} if there
* is no such bit
* @throws IndexOutOfBoundsException if the specified index is less
* than {@code -1}
* @see #setPreviousClearBit(long)
*/
long previousClearBit(long fromIndex);
/**
* Returns the index of the nearest long that contains a bit set to {@code false}
* that occurs on or before the specified starting index.
* If no such bit exists, or if {@code -1} is given as the
* starting index, then {@code -1} is returned.
*
* @param fromLongIndex the index to start checking from (inclusive)
* @return the index of the previous long containing a zeroOut bit,
* or {@code -1} if there is no such long
* @throws IndexOutOfBoundsException if the specified index is less
* than {@code -1}
*/
long previousClearLong(long fromLongIndex);
/**
* Returns the number of bits of space actually in use by this BitSet to represent bit values.
* The index of the last bit in the set eligible to be set or zeroOut
* is {@code size() - 1}.
*
* @return the number of bits in this bit set
*/
long size();
/**
* Returns the number of bits set to {@code true} in this {@code DirectBitSet}.
*
* @return the number of bits set to {@code true} in this {@code DirectBitSet}
*/
long cardinality();
/**
* Performs a logical <b>AND</b> of the long at the specified index in this
* bit set with the argument long value.
*
* @param longIndex of long to AND
* @param value of long to AND
* @return this {@code DirectBitSet} back
*/
DirectBitSet and(long longIndex, long value);
/**
* Performs a logical <b>OR</b> of the long at the specified index in this
* bit set with the argument long value.
*
* @param longIndex of long to OR
* @param value of long to OR
* @return this {@code DirectBitSet} back
*/
DirectBitSet or(long longIndex, long value);
/**
* Performs a logical <b>XOR</b> of the long at the specified index in this
* bit set with the argument long value.
*
* @param longIndex of long to XOR
* @param value of long to XOR
* @return this {@code DirectBitSet} back
*/
DirectBitSet xor(long longIndex, long value);
/**
* Clears all of the bits in the long at the specified index in this
* {@code DirectBitSet} whose corresponding bit is set in the specified
* long value.
*
* @param longIndex of long to AND NOT
* @param value of long to AND NOT
* @return this {@code DirectBitSet} back
*/
DirectBitSet andNot(long longIndex, long value);
/**
* Finds and sets to {@code true} the first bit that is set to {@code false}
* that occurs on or after the specified starting index. If no such
* bit exists then {@code -1} is returned.
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the next zeroOut bit,
* or {@code -1} if there is no such bit
* @throws IndexOutOfBoundsException if the specified index is negative
* @see #nextClearBit(long)
*/
long setNextClearBit(long fromIndex);
/**
* Finds and clears the first bit that is set to {@code true}
* that occurs on or after the specified starting index. If no such
* bit exists then {@code -1} is returned.
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the next set bit, or {@code -1} if there
* is no such bit
* @throws IndexOutOfBoundsException if the specified index is negative
* @see #nextSetBit(long)
*/
long clearNextSetBit(long fromIndex);
/**
* Finds and sets to {@code true} the nearest bit that is set
* to {@code false} that occurs on or before the specified starting index.
* If no such bit exists, or if {@code -1} is given as the
* starting index, then {@code -1} is returned.
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the previous zeroOut bit, or {@code -1} if there
* is no such bit
* @throws IndexOutOfBoundsException if the specified index is less
* than {@code -1}
* @see #previousClearBit(long)
*/
long setPreviousClearBit(long fromIndex);
/**
* Finds and clears the nearest bit that is set to {@code true}
* that occurs on or before the specified starting index.
* If no such bit exists, or if {@code -1} is given as the
* starting index, then {@code -1} is returned.
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the previous set bit, or {@code -1} if there
* is no such bit
* @throws IndexOutOfBoundsException if the specified index is less
* than {@code -1}
* @see #previousSetBit(long)
*/
long clearPreviousSetBit(long fromIndex);
/**
* Finds the next {@code numberOfBits} consecutive bits set to {@code false},
* starting from the specified {@code fromIndex}. Then all bits of the found
* range are set to {@code true}. The first index of the found block
* is returned. If there is no such range of clear bits, {@code -1}
* is returned.
*
* <p>{@code fromIndex} could be the first index of the found range, thus
* {@code setNextNContinuousClearBits(i, 1)} is exact equivalent of
* {@code setNextClearBit(i)}.
*
* @param fromIndex the index to start checking from (inclusive)
* @param numberOfBits how many continuous clear bits to search and set
* @return the index of the first bit in the found range of clear bits,
* or {@code -1} if there is no such range
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative
* @throws java.lang.IllegalArgumentException if {@code numberOfBits <= 0}
*/
long setNextNContinuousClearBits(long fromIndex, int numberOfBits);
/**
* Finds the next {@code numberOfBits} consecutive bits set to {@code true},
* starting from the specified {@code fromIndex}. Then all bits of the found
* range are set to {@code false}. The first index of the found block
* is returned. If there is no such range of {@code true} bits, {@code -1}
* is returned.
*
* <p>{@code fromIndex} could be the first index of the found range, thus
* {@code clearNextNContinuousSetBits(i, 1)} is exact equivalent of
* {@code clearNextSetBit(i)}.
*
* @param fromIndex the index to start checking from (inclusive)
* @param numberOfBits how many continuous set bits to search and clear
* @return the index of the first bit in the found range
* of {@code true} bits, or {@code -1} if there is no such range
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative
* @throws java.lang.IllegalArgumentException if {@code numberOfBits <= 0}
*/
long clearNextNContinuousSetBits(long fromIndex, int numberOfBits);
/**
* Finds the previous {@code numberOfBits} consecutive bits
* set to {@code false}, starting from the specified {@code fromIndex}.
* Then all bits of the found range are set to {@code true}.
* The first index of the found block is returned. If there is no such
* range of clear bits, or if {@code -1} is given as the starting index,
* {@code -1} is returned.
*
* <p>{@code fromIndex} could be the last index of the found range, thus
* {@code setPreviousNContinuousClearBits(i, 1)} is exact equivalent of
* {@code setPreviousClearBit(i)}.
*
* @param fromIndex the index to start checking from (inclusive)
* @param numberOfBits how many continuous clear bits to search and set
* @return the index of the first bit in the found range of clear bits,
* or {@code -1} if there is no such range
* @throws IndexOutOfBoundsException if {@code fromIndex} is less
* than {@code -1}
* @throws java.lang.IllegalArgumentException if {@code numberOfBits <= 0}
*/
long setPreviousNContinuousClearBits(long fromIndex, int numberOfBits);
/**
* Finds the previous {@code numberOfBits} consecutive bits
* set to {@code true}, starting from the specified {@code fromIndex}.
* Then all bits of the found range are set to {@code false}.
* The first index of the found block is returned. If there is no such
* range of {@code true} bits, or if {@code -1} is given as the starting
* index, {@code -1} is returned.
*
* <p>{@code fromIndex} could be the last index of the found range, thus
* {@code clearPreviousNContinuousSetBits(i, 1)} is exact equivalent of
* {@code clearPreviousSetBit(i)}.
*
* @param fromIndex the index to start checking from (inclusive)
* @param numberOfBits how many continuous set bits to search and clear
* @return the index of the first bit in the found range
* of {@code true} bits, or {@code -1} if there is no such range
* @throws IndexOutOfBoundsException if {@code fromIndex} is less
* than {@code -1}
* @throws java.lang.IllegalArgumentException if {@code numberOfBits <= 0}
*/
long clearPreviousNContinuousSetBits(long fromIndex, int numberOfBits);
/**
* Returns an iteration of <i>set</i> bits in <i>direct</i> order
* (from 0 to the end of the bit set).
*
* @return an iteration of <i>set</i> bits in <i>direct</i> order
*/
Bits setBits();
/**
* An iteration of bits in a bit set.
*
* <p>Usage idiom: <pre>{@code
* Bits bits = bitSet.setBits();
* for (long bit; (bit = bits.next()) >= 0;) {
* // do something with the bit
* }}</pre>
*/
interface Bits {
/**
* Returns index of the next bit in the iteration,
* or {@code -1} if there are no more bits.
*
* @return index of the next bit in the iteration,
* or {@code -1} if there are no more bits
*/
long next();
}
}