#include "stdafx.h"
#include "BitArray.h"

int IoABitArray::Allocate( int nBits )
{
    if ( nBits <= 0 ) return FALSE;

    Free( );

    unsigned char *pBits = new unsigned char[ nBits ];

    if ( pBits == NULL ) return FALSE;

    ::ZeroMemory( pBits, nBits );

    m_pBits = pBits;
    m_nBits = nBits;

    return TRUE;
}

void IoABitArray::Free( )
{
    delete [ ] m_pBits;
    
    m_pBits = NULL;
    m_nBits = 0;
}

void IoABitArray::SetValue( int Value, int Index, int nBits, int LittleEndian )
{
    if ( nBits > 32 ) nBits = 32;  // maximum of 32 bits

    if ( LittleEndian )  // LSBit first (little-endian format)
    {
        for ( int i = 0; i < nBits; i++ )
        {
            SetBit( Index + i, Value & ( 0x00000001 << i ) );
        }
    }
    else  // MSBit first (big-endian format)
    {
        for ( int i = 0; i < nBits; i++ )
        {
            SetBit( Index + ( nBits - 1 ) - i, Value & ( 0x00000001 << i ) );
        }
    }
}

int IoABitArray::Value( int Index, int nBits, int LittleEndian ) const
{
    if ( nBits > 32 ) nBits = 32;  // maximum of 32 bits

    int Value = 0;

    if ( LittleEndian )  // LSBit first (little-endian format)
    {
        for ( int i = 0; i < nBits; i++ )
        {
            Value |= Bit( Index + i ) << i;
        }
    }
    else  // MSBit first (big-endian format)
    {
        for ( int i = 0; i < nBits; i++ )
        {
            Value |= Bit( Index + ( nBits - 1 ) - i ) << i;
        }
    }

    return Value;
}

int IoABitArray::IsEqual( const IoABitArray& BitArray ) const
{
    if ( ! IsSameSizeAs( BitArray ) ) return FALSE;

    for ( int i = 0; i < Size( ); i++ )
    {
        if ( Bit( i ) != BitArray.Bit( i ) ) return FALSE;
    }

    return TRUE;
}

int IoABitArray::IsBitFieldEqual( int Index, int nBits, const IoABitArray& BitArray, int BitArrayIndex ) const
{
    // Implement default argument expression: BitArrayIndex = Index
    if ( BitArrayIndex == LONG_MAX ) BitArrayIndex = Index;

    if ( !          IsAllocated( ) ) return FALSE;
    if ( ! BitArray.IsAllocated( ) ) return FALSE;

    if (         Index < 0 ||         Index + nBits >          Size( ) ) return FALSE;
    if ( BitArrayIndex < 0 || BitArrayIndex + nBits > BitArray.Size( ) ) return FALSE;

    for ( int i = 0; i < nBits; i++ )
    {
        if ( Bit( Index + i ) != BitArray.Bit( BitArrayIndex + i ) ) return FALSE;
    }

    return TRUE;
}

int IoABitArray::IsBitEqual( int Index, const IoABitArray& BitArray, int BitArrayIndex ) const
{
    // Implement default argument expression: BitArrayIndex = Index
    if ( BitArrayIndex == LONG_MAX ) BitArrayIndex = Index;

    if ( !          IsAllocated( ) ) return FALSE;
    if ( ! BitArray.IsAllocated( ) ) return FALSE;

    if (         Index < 0 ||         Index >=          Size( ) ) return FALSE;
    if ( BitArrayIndex < 0 || BitArrayIndex >= BitArray.Size( ) ) return FALSE;

    return Bit( Index ) == BitArray.Bit( BitArrayIndex );
}

int IoABitArray::Clear( )
{
    if ( ! IsAllocated( ) ) return FALSE;
        
    ::ZeroMemory( m_pBits, m_nBits );

    return TRUE;
}

int IoABitArray::Copy( const IoABitArray& BitArray )
{
    if ( ! IsSameSizeAs( BitArray ) ) Allocate( BitArray.Size( ) );

    if ( ! IsAllocated( ) ) return FALSE;
        
    ::CopyMemory( m_pBits, BitArray.m_pBits, m_nBits );

    return TRUE;
}

int IoABitArray::ClearBitField( int Index, int nBits ) const
{
    if ( ! IsAllocated( ) ) return FALSE;

    if ( Index < 0 || Index + nBits > Size( ) ) return FALSE;

//    for ( int i = 0; i < nBits; i++ )
//    {
//        m_pBits[ Index + i ] = 0;
//    }

    ::ZeroMemory( m_pBits + Index, nBits );

    return TRUE;
}

int IoABitArray::CopyBitField( int Index, int nBits, const IoABitArray& BitArray, int BitArrayIndex ) const
{
    // Implement default argument expression: BitArrayIndex = Index
    if ( BitArrayIndex == LONG_MAX ) BitArrayIndex = Index;

    if ( !          IsAllocated( ) ) return FALSE;
    if ( ! BitArray.IsAllocated( ) ) return FALSE;

    if (         Index < 0 ||         Index + nBits >          Size( ) ) return FALSE;
    if ( BitArrayIndex < 0 || BitArrayIndex + nBits > BitArray.Size( ) ) return FALSE;

//    for ( int i = 0; i < nBits; i++ )
//    {
//        m_pBits[ Index + i ] = BitArray.m_pBits[ BitArrayIndex + i ];
//    }

    ::CopyMemory( m_pBits + Index, BitArray.m_pBits + BitArrayIndex, nBits );

    return TRUE;
}
