#ifndef _lucene_util_BitSet_
#define _lucene_util_BitSet_

#if defined(_LUCENE_PRAGMA_ONCE)
# pragma once
#endif


CL_NS_DEF(util)
  class BitSet:LUCENE_BASE {
	typedef unsigned long wordType;	// base type for a storage word
	int32_t bitsperword; // bits in each word

    int32_t _size;
	BitSet::wordType *bits;
		
	BitSet( const BitSet& copy ) :
		bitsperword( copy.bitsperword ),
		_size( copy._size )
	{
		int32_t nwords = _size == 0 ? 0 : (_size - 1) / bitsperword;
		bits = _CL_NEWARRAY(BitSet::wordType, nwords+1);
		memcpy( bits, copy.bits, sizeof(BitSet::wordType)*(nwords+1) );
	}

  public:
    ///Create a bitset with the specified size
    BitSet ( int32_t size ):
      _size(size)
    {
		bitsperword = sizeof(char) * sizeof (BitSet::wordType);
    	int32_t nwords = size == 0 ? 0 : (size - 1) / bitsperword;
		bits = _CL_NEWARRAY(BitSet::wordType,nwords+1);
		memset(bits,0,sizeof(BitSet::wordType) * (nwords+1));
    }
    ///Destructor for the bit set
    ~BitSet(){
		_CLDELETE_ARRAY(bits);
    }
    ///get the value of the specified bit
    bool get(const int32_t bit) const{
        if ( bit < 0 || bit > _size-1 )
          _CLTHROWA(CL_ERR_IllegalArgument, "bit out of range" );

		return ((bits[bit / bitsperword] & ((BitSet::wordType)1 << bit % bitsperword)) != 0);
    }
    ///set the value of the specified bit
    void set(const int32_t bit, bool val=true){
		if ( bit < 0 || bit >= _size )
			_CLTHROWA(CL_ERR_IllegalArgument, "bit out of range" );

		if (val)
			bits[bit / bitsperword] |= (BitSet::wordType)1 << bit % bitsperword;
		else
			bits[bit / bitsperword] &= ~((BitSet::wordType)1 << bit % bitsperword);
    }
    ///returns the size of the bitset
    int32_t size() const {
      return _size;
    }
    BitSet *clone() const {
		return _CLNEW BitSet( *this );
	}
  };
CL_NS_END
#endif
