#include "stdafx.h"
#include "Buffer.h"

int IoABuffer::Allocate( int Elements, int Size)
{
    Free( );

    if ( Elements <= 0 || Size <= 0 ) return FALSE;

    switch ( Size )
    {
        case 1:  m_pBuffer = (void *) new char  [ Elements ]; break;
        case 2:  m_pBuffer = (void *) new short [ Elements ]; break;
        case 4:  m_pBuffer = (void *) new int   [ Elements ]; break;
        case 8:  m_pBuffer = (void *) new double[ Elements ]; break;

        default: m_pBuffer = (void *) new char[ Elements * Size ];
    }

    if ( m_pBuffer == NULL ) return FALSE;

    m_nElements = Elements;
    m_nSize     = Size;

    return TRUE;
}

void IoABuffer::Free( )
{
    if ( m_pBuffer )
    {
        switch ( m_nSize )
        {
            case 1:  delete [ ] (char   *) m_pBuffer; break;
            case 2:  delete [ ] (short  *) m_pBuffer; break;
            case 4:  delete [ ] (int    *) m_pBuffer; break;
            case 8:  delete [ ] (double *) m_pBuffer; break;

            default: delete [ ] (char *) m_pBuffer;
        }

        m_pBuffer = NULL;
    }

    m_nElements = 0;
    m_nSize     = 0;
}

int IoARingBuffer::PopHead( unsigned char *Bytes, int nBytes )
{
    if ( ! IsAllocated( ) || Bytes == NULL || nBytes < 0 || nBytes > Count( ) ) return FALSE;

    for ( int i = 0; i < nBytes; i++ )
    {
        Bytes[ i ] = Address( )[ m_iHead++ ];

        if ( m_iHead == Size( ) ) m_iHead = 0;
    }

    m_nCount -= nBytes;

    return TRUE;
}

int IoARingBuffer::PopTail( unsigned char *Bytes, int nBytes )
{
    if ( ! IsAllocated( ) || Bytes == NULL || nBytes < 0 || nBytes > Count( ) ) return FALSE;

    for ( int i = nBytes - 1; i >= 0; i-- )  // bytes popped in reverse order to maintain correct order in buffer
    {
        if ( m_iTail == 0 ) m_iTail = Size( );

        Bytes[ i ] = Address( )[ --m_iTail ];
    }

    m_nCount -= nBytes;

    return TRUE;
}

int IoARingBuffer::PushHead( const unsigned char *Bytes, int nBytes )
{
    if ( ! IsAllocated( ) || Bytes == NULL || nBytes < 0 || nBytes > Space( ) ) return FALSE;

    for ( int i = nBytes - 1; i >= 0; i-- )  // bytes pushed in reverse order to maintain correct order in buffer
    {
        Address( )[ m_iHead++ ] = Bytes[ i ];

        if ( m_iHead == Size( ) ) m_iHead = 0;
    }

    m_nCount += nBytes;

    return TRUE;
}

int IoARingBuffer::PushTail( const unsigned char *Bytes, int nBytes )
{
    if ( ! IsAllocated( ) || Bytes == NULL || nBytes < 0 || nBytes > Space( ) ) return FALSE;

    for ( int i = 0; i < nBytes; i++ )
    {
        Address( )[ m_iTail++ ] = Bytes[ i ];

        if ( m_iTail == Size( ) ) m_iTail = 0;
    }

    m_nCount += nBytes;

    return TRUE;
}

