#if !defined( _IOABITARRAY_H )
#define _IOABITARRAY_H

class IoABitArray
{
public:
    IoABitArray( ) : m_pBits( NULL ), m_nBits( 0 ) { }
    IoABitArray( int nBits ) : m_pBits( NULL ), m_nBits( 0 ) { Allocate( nBits ); }
    IoABitArray( const IoABitArray& BitArray ) : m_pBits( NULL ), m_nBits( 0 ) { Copy( BitArray ); }

    IoABitArray& operator= ( const IoABitArray& BitArray ) { Copy( BitArray ); return *this; }

    ~IoABitArray( ) { Free( ); }

    // Allocate + free memory
    int Allocate( int nBits );

    void Free( );

    int IsAllocated( ) const { return m_nBits > 0 && m_pBits != NULL; }

    // Size = number of bits
    int Size( ) const { return m_nBits; }

    int IsSameSizeAs( const IoABitArray& BitArray ) const
    {
        return IsAllocated( ) && BitArray.IsAllocated( ) && Size( ) == BitArray.Size( );
    }

    int IsSameAs( const IoABitArray& BitArray ) const
    {
        return IsSameSizeAs( BitArray ) && Address( ) == BitArray.Address( );
    }

    // Clear
    int Clear( );

    // Copy
    int Copy( const IoABitArray& BitArray );

    // Set + get bit (functions are implicitly declared inline for optimisation purposes)
    void SetBit( int Index, int Bit = 1 )
    {
        if ( m_pBits )
        {
            if ( 0 <= Index && Index < m_nBits )
            {
                m_pBits[ Index ] = ( Bit != 0 );
            }
        }
    }

    void ClearBit( int Index ) { SetBit( Index, 0 ); }

    int Bit( int Index ) const
    {
        int Bit = 0;

        if ( m_pBits )
        {
            if ( 0 <= Index && Index < m_nBits )
            {
                Bit = ( m_pBits[ Index ] != 0 );
            }
        }

        return Bit;
    }

    int operator[ ] ( int Index ) const { return Bit( Index ); }

    // Set + get value (bit-field <= 32 bits)
    void SetValue( int Value, int Index, int nBits, int LittleEndian = TRUE );

    int Value( int Index, int nBits, int LittleEndian = TRUE ) const;

    // Test for equality
    int IsEqual( const IoABitArray& BitArray ) const;

    int operator==( const IoABitArray& BitArray ) const { return   IsEqual( BitArray ); }
    int operator!=( const IoABitArray& BitArray ) const { return ! IsEqual( BitArray ); }

    // Compare bit-fields
    int IsBitFieldEqual( int Index, int nBits, const IoABitArray& BitArray, int BitArrayIndex = LONG_MAX ) const;

    int IsBitEqual( int Index, const IoABitArray& BitArray, int BitArrayIndex = LONG_MAX ) const;

    // Clear bit-field
    int ClearBitField( int Index, int nBits ) const;

    // Copy bit-field
    int CopyBitField( int Index, int nBits, const IoABitArray& BitArray, int BitArrayIndex = LONG_MAX ) const;

private:
    void *Address( ) const { return m_pBits; }

    unsigned char *m_pBits;
    int            m_nBits;
};

#endif
