📄 cbqueue.cpp
字号:
return( FALSE );
}
// Ensure m_pMax is the correct value for our size
if (m_pMax != m_pData + m_nSize)
{
return( FALSE );
}
// Everything looks good!
return( TRUE );
} // IsQueueValid()
/*
** UINT16 CByteQueue::Base_DeQueueBytes( pOutBuffer, nByteCount )
*
* PARAMETERS:
* void *pOutBuffer Pointer to buffer to receive data.
* UINT16 nAmount Number of bytes desired.
*
* DESCRIPTION:
* Attempts to dequeue nAmount bytes from the Queue and transfers them
* to pOutBuffer.
*
* RETURNS:
* Number of bytes written to pOutBuffer.
*/
UINT16 CByteQueue::Base_DeQueueBytes( void *pOutBuffer, UINT16 nByteCount )
{
UINT16 nRead;
HX_ASSERT( this );
HX_ASSERT( IsQueueValid() );
HX_ASSERT( pOutBuffer );
// First read the Queue into pOutBuffer
nRead = Base_PeekBuff( pOutBuffer, nByteCount );
// Now update m_pHead which is our read pointer
m_pHead = Base_Normalize( m_pHead, nRead );
HX_ASSERT( IsQueueValid() );
return( nRead );
} // Base_DeQueueBytes()
void
CByteQueue::SetMaxSize(UINT16 ulMax)
{
m_nMaxSize = ulMax;
}
/*
* Grow the queue to twice its size or at least big enough to hold n more,
* whichever is greater. returns 1 for good, 0 for bad.
*/
int
CByteQueue::Grow(UINT16 nItems)
{
//XXXPM Need to check for wrap around on these UINT16s
if (m_nSize == m_nMaxSize)
{
return 0;
}
/*
* Set our initial guess for the new target size by doubling the
* current size.
*/
UINT16 ulUsedBytes = Base_GetUsedByteCount();
UINT16 ulMinFinalCapacity = ulUsedBytes + nItems * GetElementSize() + 1;
UINT16 ulNewSize;
// check ulMinFinalCapacity for rollover
if (ulMinFinalCapacity < m_nSize)
{
return 0;
}
if (m_nMaxSize && ulMinFinalCapacity > m_nMaxSize)
{
return 0;
}
for (ulNewSize = 0xFFFF; ulNewSize && (ulNewSize >= ulMinFinalCapacity); ulNewSize = ulNewSize >> 1)
{
;
}
if (!ulNewSize)
return 0;
ulNewSize = (ulNewSize << 1) + 1;
if (m_nMaxSize && ulNewSize > m_nMaxSize)
{
ulNewSize = m_nMaxSize;
}
UCHAR* pNewBuf = new UCHAR[ulNewSize];
if( !pNewBuf )
{
// It would be nice to be able to return HXR_OUTOFMEMORY.
return 0;
}
/*
* Let the queue copy every thing over for us.
* +1 because its best to start out with head pointing at 0,
* and data starting at 1.
*/
Base_DeQueueBytes((void*)(pNewBuf + 1), ulUsedBytes);
/*
* Destroy current structure and re-create with new buffer.
*/
delete[] m_pData;
m_pData = pNewBuf;
m_nSize = ulNewSize;
//max points one past the end.
m_pMax = m_pData + m_nSize;
//head points at spot before first queued data
m_pHead = m_pData;
//tail points at last used byte
m_pTail = m_pData + ulUsedBytes;
return 1;
}
/*
** UINT16 CByteQueue::Base_EnQueueBytes( pInBuffer, nByteCount )
*
* PARAMETERS:
* void *pInBuffer Pointer to buffer containing data to EnQueue
* UINT16 nByteCount Number of bytes items in buffer for EnQueue.
*
* DESCRIPTION:
* Attempts to put nByteCount bytes into queue. If insufficient room, will
* not enqueue anything.
*
* RETURNS:
* Number of bytes written to pInBuffer.
* Should be nByteCount or 0 because we fail if we don't have
* room for ALL data
*/
UINT16 CByteQueue::Base_EnQueueBytes( void *pInBuffer, UINT16 nByteCount )
{
HX_ASSERT( this );
HX_ASSERT( IsQueueValid() );
HX_ASSERT( pInBuffer );
if (!nByteCount || Base_GetAvailableBytes() < nByteCount)
{
return( 0 );
}
// Ok, we've guaranteed that we have enough room to enqueue nAmount items
// Now switch on the state of our head & tail pointers
if (m_pTail < m_pHead)
{
// No need to normalize pointers, because we're guaranteed
// that we have room, hence m_pTail + nAmount HAS to be remain < m_pHead
// Remember that m_pTail points at the postion just BEFORE our next
// empty spot in the queue
memcpy( m_pTail + 1, pInBuffer, nByteCount ); /* Flawfinder: ignore */
m_pTail += nByteCount;
}
else
{
// m_pTail >= m_pHead
// This may require a copy in two passes if we have to wrap around the buffer
UINT16 nCopy;
UINT16 nPrevCopy;
void *pDest;
// Copying from (m_pTail + 1) to the end of the allocated buffer or nAmount
// which ever comes first.
pDest = Base_Normalize( m_pTail, 1);
nCopy = __min( (UINT16)(m_pMax - (UCHAR *)pDest), nByteCount );
memcpy( pDest, pInBuffer, nCopy ); /* Flawfinder: ignore */
m_pTail = (UCHAR *)pDest + nCopy - 1;
// Figure out how much more we have to copy (if any)
nPrevCopy = nCopy;
nCopy = nByteCount - nCopy;
if (nCopy)
{
// Now we're copying into the base of the allocated array
// whatever we didn't copy the first pass around
memcpy( m_pData, (UCHAR *)pInBuffer + nPrevCopy, nCopy ); /* Flawfinder: ignore */
m_pTail = m_pData + nCopy - 1;
}
}
HX_ASSERT( IsQueueValid() );
return( nByteCount );
} // Base_EnQueueBytes()
UINT16 CByteQueue::PeekAt( UINT16 nIndex, void *pOutBuffer ) const
{
UINT16 nCopy;
UINT16 nByteCount;
void *pHead;
void *pTail;
HX_ASSERT( pOutBuffer );
HX_ASSERT( this );
HX_ASSERT( IsQueueValid() );
if (nIndex >= GetQueuedItemCount())
{
return( 0 );
}
// We don't want to modify m_pTail or m_pHead here, so copy them
// and use our copies to manipulate the buffer.
pTail = m_pTail;
// Advance pHead till it points at the correct position
// relative to the index we want.
nByteCount = GetElementSize();
pHead = Base_Normalize( m_pHead, (nIndex * nByteCount + 1) );
if (pHead < pTail)
{
memcpy( pOutBuffer, (UCHAR *)pHead, nByteCount ); /* Flawfinder: ignore */
return( nByteCount );
}
else
{
// pHead > pTail
UINT16 nPrevCopy;
// Copying from (pHead + 1) to the end of the allocated buffer or
// nByteCount which ever comes first.
nCopy = __min( (UINT16)(m_pMax - (UCHAR *)pHead), nByteCount );
memcpy( pOutBuffer, pHead, nCopy ); /* Flawfinder: ignore */
// Figure out how much more we have to copy (if any)
nPrevCopy = nCopy;
nCopy = nByteCount - nCopy;
if (nCopy)
{
// Now we're copying from the base of the allocated array
// whatever we didn't copy the first pass around
memcpy( (UCHAR *)pOutBuffer + nPrevCopy, m_pData, nCopy ); /* Flawfinder: ignore */
}
return( nCopy + nPrevCopy );
}
}
/*
** UINT16 CByteQueue::Base_PeekBuff( pOutBuffer, nByteCount )
*
* PARAMETERS:
* pOutBuffer Pointer to buffer to receive data in queue.
* nByteCount Number of bytes to copy out of queue.
*
* DESCRIPTION:
* Private primitive used to copy data out of a queue buffer.
* This is a workhorse function used in DeQueue(), operator=(),
* and our copy constructor.
*
* RETURNS:
* The number of bytes copied out of the buffer.
*/
UINT16 CByteQueue::Base_PeekBuff( void *pOutBuffer, UINT16 nByteCount ) const
{
UINT16 nCopy;
void *pHead;
void *pTail;
HX_ASSERT( this );
HX_ASSERT( IsQueueValid() );
// if the Queue is empty, then we can't get anything
if (IsEmpty())
{
return( 0 );
}
// We don't want to modify m_pTail or m_pHead here, so copy them
// and use our copies to manipulate the buffer.
pTail = m_pTail;
pHead = m_pHead;
if (pHead < pTail)
{
// We can do the copy in one pass w/o having to Normalize() the pointer
nCopy = __min( nByteCount, Base_GetUsedByteCount() );
memcpy( pOutBuffer, (UCHAR *)pHead + 1, nCopy ); /* Flawfinder: ignore */
return( nCopy );
}
else
{
// pHead > pTail
UINT16 nPrevCopy;
UCHAR * pSrc;
// Copying from (pHead + 1) to the end of the allocated buffer or
// nByteCount which ever comes first.
pSrc = Base_Normalize( (UCHAR *)pHead, 1 );
nCopy = __min( (UINT16)(m_pMax - pSrc), nByteCount );
memcpy( pOutBuffer, pSrc, nCopy ); /* Flawfinder: ignore */
// The __min() above ensures we don't need to Normalize the pointer
pHead = pSrc + nCopy - 1;
// Figure out how much more we have to copy (if any)
nPrevCopy = nCopy;
nCopy = nByteCount - nCopy;
if (nCopy)
{
// Now we're copying from the base of the allocated array
// whatever we didn't copy the first pass around
memcpy( (UCHAR *)pOutBuffer + nPrevCopy, m_pData, nCopy ); /* Flawfinder: ignore */
}
return( nCopy + nPrevCopy );
}
} // Base_PeekBuff()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -