
// (C) 1996 Glynn Clements <glynn@sensei.co.uk> - Freely Redistributable

// Modified 1998/7/18 by Charles Briscoe-Smith:
//  ensureSize: copy data.length items, not words

package JLex;

final class JavaLexBitSet extends Object implements Cloneable
{ 
	// Fields

	protected long[] data;

	// Private Methods

	private void ensureSize(int words)
	{
		if (words <= data.length)
			return;

		long[] newData = new long[words];

		System.arraycopy(
			(Object) data, 0,
			(Object) newData, 0,
			data.length
		);

		data = newData;
	}

	// Public Methods

	public boolean get(int bit)
	{
		int d = bit >> 6;
		if (d >= data.length)
			return false;
		int r = bit & 0x3F;
		return (data[d] & (1L << r)) != 0L;
	}


	public void clear(int bit)
	{
		int d = bit >> 6;
		int r = bit & 0x3F;
		ensureSize(d + 1);
		data[d] &= ~(1L << r);
	}

	public void set(int bit)
	{
		int d = bit >> 6;
		int r = bit & 0x3F;
		ensureSize(d + 1);
		data[d] |= (1L << r);
	}

	public void and(JavaLexBitSet set)
	{
		ensureSize(set.data.length);
		for (int i = 0; i < set.data.length; i++)
			data[i] &= set.data[i];
		for (int i = set.data.length; i < data.length; i++)
			data[i] = 0L;
	}

	public void or(JavaLexBitSet set)
	{
		ensureSize(set.data.length);
		for (int i = 0; i < set.data.length; i++)
			data[i] |= set.data[i];
	}

	public void xor(JavaLexBitSet set)
	{
		ensureSize(set.data.length);
		for (int i = 0; i < set.data.length; i++)
			data[i] ^= set.data[i];
	}

	public Object clone()
	{
		JavaLexBitSet set;
		
		try
		{
			set = (JavaLexBitSet)(super.clone());
		}
		catch (CloneNotSupportedException e)
		{
			return null;
		}

		set.data = new long[data.length];
		System.arraycopy(
			(Object) data, 0,
			(Object) set.data, 0,
			data.length
		);

		return set;
	}

	public boolean equals(Object obj)
	{
		if (obj == null)
			return false;

		JavaLexBitSet set;

		try
		{
			set = (JavaLexBitSet) obj;
		}
		catch (ClassCastException e)
		{
			return false;
		}

		int i;

		for (i = 0; i < Math.min(data.length, set.data.length); i++)
			if (data[i] != set.data[i])
				return false;

		if (set.data.length > data.length)
			for ( ; i < set.data.length; i++)
				if (set.data[i] != 0L)
					return false;
		else
			for ( ; i < data.length; i++)
				if (data[i] != 0L)
					return false;

		return true;
	}

	public int size()
	{
		return data.length * 64;
	}

	public final String toString()
	{
		StringBuffer buff = new StringBuffer("{");
		int n = 0;

		for (int i = 0; i < data.length; i++)
		{
			long word = data[i];

			for (int j = 0; j < 64; j++, n++, word >>= 1)
			{
				if ((word & 1) == 0)
					continue;
				if (n > 0)
					buff.append(", ");
				buff.append(Integer.toString(n));
			}
		}

		buff.append("}");

		return buff.toString();
	}

	public synchronized int hashCode()
	{
		// from 'The Java Language Specification', p620

		long h = 1234;

		for (int i = 0; i < data.length; i++)
			h ^= data[i] * (i + 1);

		return (int)((h >> 32) ^ h);
	}

	// Constructors

	public JavaLexBitSet(int nbits)
	{
		data = new long[(nbits + 63) / 64];
	}

	public JavaLexBitSet()
	{
		this(64);
	}
}

