package com.colloquial.arithcode;
/** A set of bytes. Supports add operations, containment queries,
* and may be cleared.
*
* @author <a href="http://www.colloquial.com/carp/">Bob Carpenter</a>
* @version 1.1
* @since 1.0
*/
public final class ByteSet {
/** Construct a byte set.
*/
public ByteSet() {
// clear(); implied
}
/** Remove all of the bytes from this set.
*/
public void clear() {
_bits1 = 0;
_bits2 = 0;
_bits3 = 0;
_bits4 = 0;
}
/* Adds a byte, specified as an integer, to this set.
* @param i Byte to add to this set.
* @since 1.1
*/
public void add(int i) { add(Converter.integerToByte(i)); }
/** Add a byte to this set.
* @param b Byte to add to this set.
*/
public void add(byte b) {
if (b > 63) _bits4 |= ((long) 1) << (- 64 + (int) b);
else if (b >= 0) _bits3 |= ((long) 1) << (/* 0 +*/(int) b);
else if (b > -65) _bits2 |= ((long) 1) << ( 64 + (int) b);
else _bits1 |= ((long) 1) << ( 128 + (int) b);
}
/** Removes a byte, specified as an integer, from this set.
* @param i Integer specification of byte to remove from this set.
* @since 1.1
*/
public void remove(int i) { add(Converter.integerToByte(i)); }
/** Removes a byte from this set.
* @param b Byte to remove from this set.
* @since 1.1
*/
public void remove(byte b) {
if (b > 63) _bits4 &= ~(((long) 1) << (- 64 + (int) b));
else if (b >= 0) _bits3 &= ~(((long) 1) << (/* 0 +*/(int) b));
else if (b > -65) _bits2 &= ~(((long) 1) << ( 64 + (int) b));
else _bits1 &= ~(((long) 1) << ( 128 + (int) b));
}
/** Adds all the members of specified set to this set. The result is
* that this set's value is the union of its previous value with the
* specified set. The argument set is unchanged.
* @param that Byte set to add to this set.
* @since 1.1
*/
public void add(ByteSet that) {
_bits1 |= that._bits1;
_bits2 |= that._bits2;
_bits3 |= that._bits3;
_bits4 |= that._bits4;
}
/** Removes all the members of specified set from this set. The result is
* that this set's value is the complement of its previous value with the
* specified set. The argument set is unchanged.
* @param that Byte set to remove from this set.
* @since 1.1
*/
public void remove(ByteSet that) {
_bits1 &= ~that._bits1;
_bits2 &= ~that._bits2;
_bits3 &= ~that._bits3;
_bits4 &= ~that._bits4;
}
/** Removes all the elements of this set that are not in the specified
* set. The result is that this set's value is the intersection of its
* previous value with the specified set. The argument set is unchagned.
* @param that Byte set to restrict this set to.
* @since 1.1
*/
public void restrict(ByteSet that) {
_bits1 &= that._bits1;
_bits2 &= that._bits2;
_bits3 &= that._bits3;
_bits4 &= that._bits4;
}
/** Returns <code>true</code> if byte specified as an integer
* is a member of this set. Conversion is done by casting.
* @param i Integer representation of byte to be tested for membership.
* @return <code>true</code> if the specified byte is a member of this set.
* @since 1.0
*/
public boolean contains(int i) {
return contains(Converter.integerToByte(i));
}
/** Returns <code>true</code> if specified byte is a member
* of this set.
* @param b Byte to test for membership in this set.
* @return <code>true</code> if the specified byte is a member of this set.
*/
public boolean contains(byte b) {
// built-in ASCII order preference in first two test cases
// moving 0 inside ternary is *much* slower -- must be set up for ints, not bools
if (b > 63) return 0 != (_bits4 & ((long) 1) << (- 64 + (int) b));
if (b >= 0) return 0 != (_bits3 & ((long) 1) << ((int) b));
if (b > -65) return 0 != (_bits2 & ((long) 1) << ( 64 + (int) b));
return 0 != ((_bits1 & ((long) 1) << ( 128 + (int) b)));
}
/** Returns number of elements in this set.
* @return Number of elements in this set.
*/
public int size() {
int sum = 0;
for (int i = 0; i < 256; ++i) if (contains(i)) ++sum;
return sum;
}
/** An empty set. Unsafe, because nothing prevents
* the addition of elements. So it's kept to the package.
* The decision to do it this way was to keep ByteSet itself a final
* class for the sake of efficiency.
*/
static final ByteSet EMPTY_SET = new ByteSet();
/** Representation of bytes -128..-65.
* Longs are a real kick in the butt for 1.4 non-server.
*/
private long _bits1; // -128..-65
/** Representation of bytes -64..-1.
*/
private long _bits2;
/** Representation of bytes // 0..63.
*/
private long _bits3;
/** Representation of bytes 64..127.
*/
private long _bits4;
}