FIFO.CPP

// --fifo.cpp------------------------------------------------------------------- 
//
// Implements a FIFO buffer.
//
// Copyright (C) Microsoft Corp. 1986-1996. All Rights Reserved.
// -----------------------------------------------------------------------------

#include "edk.h"
#include "fifo.h"
#include "fifo.chk"

//$--CFIFO::CFIFO---------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
CFIFO::CFIFO()
{
DEBUGPRIVATE("CFIFO::CFIFIO()\n");

m_nElements = 0;
m_maxElements = 0;
m_iCurrentElement = 0;
m_padwFIFOBuffer = NULL;
}

//$--CFIFO::~CFIFO--------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
CFIFO::~CFIFO()
{
DEBUGPRIVATE("CFIFO::~CFIFIO()\n");

FREE(m_padwFIFOBuffer);
}


//$--CFIFO::HrReset-------------------------------------------------------------
// Resets the FIFO buffer. Should be called after object is constructed
// and before it is used.
// -----------------------------------------------------------------------------
HRESULT CFIFO::HrReset( // RETURNS: NOERROR if reset successful.
IN DWORD maxElements) // Maximum number of elements in buffer.
{
HRESULT hr = NOERROR;
DWORD cb = sizeof(DWORD) * maxElements;

DEBUGPRIVATE("CFIFO::HrReset()\n");

hr = CHK_CFIFO_HrReset(maxElements);
if (FAILED(hr))
RETURN(hr);

FREE(m_padwFIFOBuffer);

m_padwFIFOBuffer = (DWORD *) malloc( cb );
if (m_padwFIFOBuffer == NULL)
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}

FillMemory(m_padwFIFOBuffer,cb,0);

m_maxElements = maxElements;
m_nElements = 0;
m_iCurrentElement = 0;

cleanup:
RETURN(hr);

}


//$--CFIFO::PushElement---------------------------------------------------------
// Pushes a new element into the FIFO buffer. Returns the value pushed out
// the other side.
// -----------------------------------------------------------------------------
VOID CFIFO::PushElement(
IN DWORD dwValue, // New Value to Push into buffer.
OUT DWORD &dwPushedOut) // Recieves old value pushed out of buffer.
{
HRESULT hr = NOERROR;

DEBUGPRIVATE("CFIFO::PushElement()\n");

hr = CHK_CFIFO_PushElement(dwValue, dwPushedOut);
if (FAILED(hr))
return;

// Return whatever is at curent element.
// -------------------------------------
dwPushedOut = m_padwFIFOBuffer[m_iCurrentElement];
m_padwFIFOBuffer[m_iCurrentElement] = dwValue;

if (m_nElements < m_maxElements)
{
m_nElements++;
}

// Update current element pointer
//-------------------------------
m_iCurrentElement++;
if (m_iCurrentElement >= m_maxElements)
{
m_iCurrentElement = 0;
}

return;
}


//$--CFIFO::PushNNulls----------------------------------------------------------
// Push a number of 0 Values into the FIFO buffer. Returns a summation
// of the values pushed out the other side.
// -----------------------------------------------------------------------------
VOID CFIFO::PushNNulls(
IN DWORD cNulls, // Number of NULLS to push.
OUT DWORD &dwPushedOut) // Receives total values pushed out.
{
HRESULT hr = NOERROR;
DWORD i = 0;
DWORD cCurrentToEnd = 0;

DEBUGPRIVATE("CFIFO::PushNNulls()\n");

hr = CHK_CFIFO_PushNNulls(cNulls, dwPushedOut);
if (FAILED(hr))
return;

dwPushedOut = 0;

if (cNulls == 0)
goto cleanup;

// case: cNulls is larger than the max number of buffer elements.
// Action: Clear the entire buffer and reset the current index.
// ------------------------------------------------------------
if (cNulls >= m_maxElements)
{
for (i=0; i<m_maxElements; i++)
{
dwPushedOut += m_padwFIFOBuffer[i];
m_padwFIFOBuffer[i] = 0 ;
}

m_iCurrentElement = 0;
goto cleanup;
}

// case: cNulls will advance current index past end of buffer
// action: 1) clear the elements from current index+1 to end of buffer.
// 2) clear elements from start of buffer to new index.
// ---------------------------------------------------------------------
cCurrentToEnd = (m_maxElements-1) - m_iCurrentElement;
if (cNulls > cCurrentToEnd)
{
for (i=m_iCurrentElement; i<m_maxElements; i++)
{
dwPushedOut += m_padwFIFOBuffer[i];
m_padwFIFOBuffer[i] = 0;
}

m_iCurrentElement = cNulls - cCurrentToEnd - 1;
for (i=0; i< m_iCurrentElement; i++)
{
dwPushedOut += m_padwFIFOBuffer[i];
m_padwFIFOBuffer[i] = 0;
}
goto cleanup;
}

// case: cbDelta will not advance current pointer past end of buffer
// action: clear the elements between the old current index and the
// new current index.
// -----------------------------------------------------------------
for (i=0; i<cNulls; i++)
{
dwPushedOut += m_padwFIFOBuffer[m_iCurrentElement+i];
m_padwFIFOBuffer[m_iCurrentElement+i] = 0;
}
m_iCurrentElement += cNulls;

cleanup:
m_nElements += cNulls;
if (m_nElements > m_maxElements)
{
m_nElements = m_maxElements;
}

return;
}


//$--CFIFO::Min-----------------------------------------------------------------
// Returns the minimum value in the buffer.
// -----------------------------------------------------------------------------
VOID CFIFO::Min(
OUT DWORD &dwMin) // receives the minimum of all values in the buffer.
{
HRESULT hr = NOERROR;
DWORD i = 0;

DEBUGPRIVATE("CFIFO::Min()\n");

hr = CHK_CFIFO_Min(dwMin);
if (FAILED(hr))
return;

dwMin = MAXWORD;

if (m_nElements == 0)
{
dwMin = 0;
goto cleanup;
}

for (i=0; i<m_iCurrentElement; i++)
{
if (m_padwFIFOBuffer[i] < dwMin )
dwMin = m_padwFIFOBuffer[i];
}

for (i=m_iCurrentElement; i<m_nElements; i++)
{
if (m_padwFIFOBuffer[i] < dwMin )
dwMin = m_padwFIFOBuffer[i];
}

cleanup:
return;
}


//$--CFIFO::Max-----------------------------------------------------------------
// Returns the maximum value in a buffer.
// -----------------------------------------------------------------------------
VOID CFIFO::Max(
OUT DWORD &dwMax) // receives the maximum value in the buffer.
{
HRESULT hr = NOERROR;
DWORD i = 0;

DEBUGPRIVATE("CFIFO::Max()\n");

hr = CHK_CFIFO_Max(dwMax);
if (FAILED(hr))
return;

dwMax = 0;

for (i=0; i<m_iCurrentElement; i++)
{
if (m_padwFIFOBuffer[i] > dwMax )
dwMax = m_padwFIFOBuffer[i];
}

for (i=m_iCurrentElement; i<m_nElements; i++)
{
if (m_padwFIFOBuffer[i] > dwMax )
dwMax = m_padwFIFOBuffer[i];
}

return;
}


//$--CFIFO::Average-------------------------------------------------------------
// Returns the average value in the buffer.
// -----------------------------------------------------------------------------
VOID CFIFO::Average(
OUT DWORD &dwAverage) // receives buffer average
{
HRESULT hr = NOERROR;
DWORD i = 0;
DWORD dwSum = 0;

DEBUGPRIVATE("CFIFO::Average()\n");

hr = CHK_CFIFO_Average(dwAverage);
if (FAILED(hr))
return;

dwAverage = 0;

for (i=0; i<m_iCurrentElement; i++)
{
dwSum += m_padwFIFOBuffer[i];
}

for (i=m_iCurrentElement; i<m_nElements; i++)
{
dwSum += m_padwFIFOBuffer[i];
}

if (m_nElements != 0)
dwAverage = dwSum / m_nElements;
return;
}