// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

BALL_INLINE 
BALL::Size BitVector::getSize() const
{
  return size_;
}

BALL_INLINE
Bit::Bit(const BitVector* const bit_vector, Index index) 
	:	bitvector_(const_cast<BitVector*> (bit_vector)),
		index_(index),
		bitvector_muteable_(false)
{
	if (bit_vector == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}

	if (index < - (Index)bit_vector->getSize())
	{
		throw Exception::IndexUnderflow(__FILE__, __LINE__);
	}

	if (index >= (Index) bit_vector->getSize())
	{
		throw Exception::IndexOverflow(__FILE__, __LINE__);
	}
}

BALL_INLINE
Bit::Bit(BitVector* bit_vector, Index index) 
	:	bitvector_(const_cast<BitVector*> (bit_vector)),
		index_(index),
		bitvector_muteable_(true)
{
	if (bit_vector == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}
	if (index < (- (Index)bit_vector->getSize()))
	{
		throw Exception::IndexUnderflow(__FILE__, __LINE__);
	}

	if (index >= (Index) bit_vector->getSize())
	{
		throw Exception::IndexOverflow(__FILE__, __LINE__);
	}
}

BALL_INLINE
void Bit::clear() 
{
	bitvector_					= 0;
	index_							= 0;
	bitvector_muteable_ = false;
}


BALL_INLINE
BitVector::BlockType BitVector::mask_(Index index) const
{
	return (BitVector::BlockType)(1 << (index & BALL_BLOCK_MASK));
}

BALL_INLINE 
void BitVector::clear()
{
	setSize(0, false);
}

BALL_INLINE 
BitVector& BitVector::operator = (const BitVector& bit_vector)
{
  set(bit_vector);
  return *this;
}

BALL_INLINE 
BitVector& BitVector::operator = (const char* bit_string)
{
  set(bit_string);
  return *this;
}

BALL_INLINE 
void BitVector::get(BitVector& bit_vector) const
{
  bit_vector.set(*this);
}

BALL_INLINE 
BALL::BitVector::VectorType& BitVector::getBitSet()
{
  return bitset_;
}

BALL_INLINE 
const BALL::BitVector::VectorType& BitVector::getBitSet() const
{
  return bitset_;
}

BALL_INLINE 
BitVector BitVector::operator | (const BitVector& bit_vector)
{
  BitVector temp(*this);
  temp.bitwiseOr(bit_vector);
  return temp;
}

BALL_INLINE 
BitVector& BitVector::operator |= (const BitVector &bit_vector)
{
  bitwiseOr(bit_vector);
  return *this;
}

BALL_INLINE 
BitVector BitVector::operator & (const BitVector& bit_vector)
{
  BitVector temp(*this);
  temp.bitwiseAnd(bit_vector);
  return temp;
}

BALL_INLINE 
BitVector& BitVector::operator &= (const BitVector &bit_vector)
{
  bitwiseAnd(bit_vector);
  return *this;
}

BALL_INLINE 
BitVector BitVector::operator ^ (const BitVector& bit_vector)
{
  BitVector temp(*this);
  temp.bitwiseXor(bit_vector);
  return temp;
}

BALL_INLINE 
BitVector& BitVector::operator ^= (const BitVector &bit_vector)
{
  bitwiseXor(bit_vector);
  return *this;
}

BALL_INLINE 
BitVector BitVector::operator ~ ()
{
  BitVector temp(*this);
  temp.toggle();
  return temp;
}

BALL_INLINE 
bool BitVector::operator != (const BitVector &bit_vector) const
{
  return !(*this == bit_vector);
}

BALL_INLINE 
bool BitVector::isValid() const
{
  return true;
}

BALL_INLINE
Bit BitVector::operator [] (Index index)
{
	block_(index);
	return Bit(this, index);
}

BALL_INLINE
bool BitVector::getBit(Index index)
{
	validateIndex_(index);
	return ((bitset_[block_(index)] & mask_(index)) != 0);
}

BALL_INLINE
bool BitVector::getBit(Index index) const
{
	validateIndex_(index);
	return ((bitset_[block_(index)] & mask_(index)) != 0);
}

BALL_INLINE
bool BitVector::operator [] (Index index) const
{
	return getBit(index);
}
 
BALL_INLINE
void BitVector::setBit(Index index, bool value)
{
	validateIndex_(index);

	if (value == true)
	{
		bitset_[block_(index)] |= mask_(index);
	}
	else 
	{
		bitset_[block_(index)] &= ~mask_(index);
	}
}

BALL_INLINE
void BitVector::toggleBit(Index index)
{
	validateIndex_(index);
	bitset_[block_(index)] ^= mask_(index);
}

BALL_INLINE
bool Bit::operator == (bool bit) const 
{
	if (bitvector_ == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}

	return bitvector_->getBit(index_) == bit;
}

BALL_INLINE
bool Bit::operator != (bool bit) const 
{
	if (bitvector_ == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}
	
	return bitvector_->getBit(index_) != bit;
}

BALL_INLINE
bool Bit::operator == (const Bit& bit) const 
{
	return (bitvector_					== bit.bitvector_					&& 
					index_							== bit.index_							&&
					bitvector_muteable_	== bit.bitvector_muteable_	);
}

BALL_INLINE
bool Bit::operator != (const Bit& bit) const 
{
	return !(*this == bit);
}

BALL_INLINE
Bit::operator bool() const 
{
	if (bitvector_ == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}

	return bitvector_->getBit(index_);
}

BALL_INLINE
Bit& Bit::operator = (const Bit& bit)	
{
	bitvector_					= bit.bitvector_;
	index_							= bit.index_;
	bitvector_muteable_	= bit.bitvector_muteable_;

	return *this;
}

BALL_INLINE
Bit& Bit::operator = (const bool bit)
{
	if (bitvector_ == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}

	if (bitvector_muteable_ == false)
	{
		throw IllegalOperation(__FILE__, __LINE__);
	}

	bitvector_->setBit(index_, bit);
	return *this;
}
