2006-12-18 15:39:33 +01:00
|
|
|
/******************************************************************************\
|
2009-02-22 12:07:18 +01:00
|
|
|
* Copyright (c) 2004-2009
|
2006-12-18 15:39:33 +01:00
|
|
|
*
|
|
|
|
* Author(s):
|
2006-11-25 15:46:57 +01:00
|
|
|
* Volker Fischer
|
2006-01-28 12:29:22 +01:00
|
|
|
*
|
|
|
|
* Note: we assuming here that put and get operations are secured by a mutex
|
2006-12-18 15:39:33 +01:00
|
|
|
* and do not take place at the same time
|
|
|
|
*
|
|
|
|
******************************************************************************
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
|
|
* Foundation; either version 2 of the License, or (at your option) any later
|
|
|
|
* version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
\******************************************************************************/
|
|
|
|
|
|
|
|
#include "buffer.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* Implementation *************************************************************/
|
2009-08-02 19:44:45 +02:00
|
|
|
void CNetBuf::Init ( const int iNewBlockSize,
|
|
|
|
const int iNewNumBlocks )
|
2006-12-18 15:39:33 +01:00
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// total size -> size of one block times number of blocks
|
2006-12-18 15:39:33 +01:00
|
|
|
iBlockSize = iNewBlockSize;
|
2008-07-12 13:48:51 +02:00
|
|
|
iMemSize = iNewBlockSize * iNewNumBlocks;
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// allocate and clear memory for actual data buffer
|
2009-07-24 16:31:25 +02:00
|
|
|
vecbyMemory.Init ( iMemSize );
|
2006-12-18 15:39:33 +01:00
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// use the "get" flag to make sure the buffer is cleared
|
2007-09-08 12:45:14 +02:00
|
|
|
Clear ( CT_GET );
|
2006-12-18 15:39:33 +01:00
|
|
|
}
|
|
|
|
|
2009-07-31 20:53:40 +02:00
|
|
|
bool CNetBuf::Put ( const CVector<uint8_t>& vecbyData,
|
|
|
|
const int iInSize )
|
2006-12-18 15:39:33 +01:00
|
|
|
{
|
|
|
|
bool bPutOK = true;
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// Check if there is not enough space available -> correct
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( GetAvailSpace() < iInSize )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// not enough space in buffer for put operation, correct buffer to
|
|
|
|
// prepare for new data
|
2007-09-08 12:45:14 +02:00
|
|
|
Clear ( CT_PUT );
|
2006-11-25 15:46:57 +01:00
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
bPutOK = false; // return error flag
|
2009-03-01 22:06:11 +01:00
|
|
|
|
|
|
|
// check for special case: buffer memory is not sufficient
|
|
|
|
if ( iInSize > iMemSize )
|
|
|
|
{
|
|
|
|
// do nothing here, just return error code
|
|
|
|
return bPutOK;
|
|
|
|
}
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// copy new data in internal buffer
|
2006-12-18 15:39:33 +01:00
|
|
|
int iCurPos = 0;
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( iPutPos + iInSize > iMemSize )
|
2006-12-18 15:39:33 +01:00
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// remaining space size for second block
|
2006-12-18 15:39:33 +01:00
|
|
|
const int iRemSpace = iPutPos + iInSize - iMemSize;
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// data must be written in two steps because of wrap around
|
2009-02-12 18:15:17 +01:00
|
|
|
while ( iPutPos < iMemSize )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2009-07-24 16:31:25 +02:00
|
|
|
vecbyMemory[iPutPos++] = vecbyData[iCurPos++];
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
|
2007-09-08 12:45:14 +02:00
|
|
|
for ( iPutPos = 0; iPutPos < iRemSpace; iPutPos++ )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2009-07-24 16:31:25 +02:00
|
|
|
vecbyMemory[iPutPos] = vecbyData[iCurPos++];
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// data can be written in one step
|
2006-12-18 15:39:33 +01:00
|
|
|
const int iEnd = iPutPos + iInSize;
|
2007-09-08 12:45:14 +02:00
|
|
|
while ( iPutPos < iEnd )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2009-07-24 16:31:25 +02:00
|
|
|
vecbyMemory[iPutPos++] = vecbyData[iCurPos++];
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
}
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// set buffer state flag
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( iPutPos == iGetPos )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2006-12-18 15:39:33 +01:00
|
|
|
eBufState = CNetBuf::BS_FULL;
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
else
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2006-12-18 15:39:33 +01:00
|
|
|
eBufState = CNetBuf::BS_OK;
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
|
|
|
|
return bPutOK;
|
|
|
|
}
|
|
|
|
|
2009-07-24 16:31:25 +02:00
|
|
|
bool CNetBuf::Get ( CVector<uint8_t>& vecbyData )
|
2006-12-18 15:39:33 +01:00
|
|
|
{
|
2009-07-24 16:31:25 +02:00
|
|
|
bool bGetOK = true; // init return value
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// get size of data to be get from the buffer
|
2009-07-24 16:31:25 +02:00
|
|
|
const int iInSize = vecbyData.Size();
|
2006-12-18 15:39:33 +01:00
|
|
|
|
2009-08-02 09:54:15 +02:00
|
|
|
// check size
|
2009-08-13 18:12:49 +02:00
|
|
|
if ( ( iInSize == 0 ) || ( iInSize != iBlockSize ) )
|
2009-08-02 09:54:15 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-08-22 18:13:21 +02:00
|
|
|
// check for invalid data in buffer
|
|
|
|
if ( iNumInvalidElements > 0 )
|
|
|
|
{
|
|
|
|
// decrease number of invalid elements by the queried number (input
|
|
|
|
// size)
|
|
|
|
iNumInvalidElements -= iInSize;
|
|
|
|
|
|
|
|
bGetOK = false; // return error flag
|
|
|
|
}
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// Check if there is not enough data available -> correct
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( GetAvailData() < iInSize )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// not enough data in buffer for get operation, correct buffer to
|
|
|
|
// prepare for getting data
|
2007-09-08 12:45:14 +02:00
|
|
|
Clear ( CT_GET );
|
2006-11-25 15:46:57 +01:00
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
bGetOK = false; // return error flag
|
2009-03-01 22:06:11 +01:00
|
|
|
|
|
|
|
// check for special case: buffer memory is not sufficient
|
|
|
|
if ( iInSize > iMemSize )
|
|
|
|
{
|
|
|
|
// do nothing here, just return error code
|
|
|
|
return bGetOK;
|
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
}
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// copy data from internal buffer in output buffer
|
2006-12-18 15:39:33 +01:00
|
|
|
int iCurPos = 0;
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( iGetPos + iInSize > iMemSize )
|
2006-12-18 15:39:33 +01:00
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// remaining data size for second block
|
2006-12-18 15:39:33 +01:00
|
|
|
const int iRemData = iGetPos + iInSize - iMemSize;
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// data must be read in two steps because of wrap around
|
2007-09-08 12:45:14 +02:00
|
|
|
while ( iGetPos < iMemSize )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2009-07-24 16:31:25 +02:00
|
|
|
vecbyData[iCurPos++] = vecbyMemory[iGetPos++];
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
|
2007-09-08 12:45:14 +02:00
|
|
|
for ( iGetPos = 0; iGetPos < iRemData; iGetPos++ )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2009-07-24 16:31:25 +02:00
|
|
|
vecbyData[iCurPos++] = vecbyMemory[iGetPos];
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// data can be read in one step
|
2006-12-18 15:39:33 +01:00
|
|
|
const int iEnd = iGetPos + iInSize;
|
2007-09-08 12:45:14 +02:00
|
|
|
while ( iGetPos < iEnd )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2009-07-24 16:31:25 +02:00
|
|
|
vecbyData[iCurPos++] = vecbyMemory[iGetPos++];
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
}
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// set buffer state flag
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( iPutPos == iGetPos )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2006-12-18 15:39:33 +01:00
|
|
|
eBufState = CNetBuf::BS_EMPTY;
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
else
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
eBufState = CNetBuf::BS_OK;
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-11-25 15:46:57 +01:00
|
|
|
|
2006-12-18 15:39:33 +01:00
|
|
|
return bGetOK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetBuf::GetAvailSpace() const
|
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// calculate available space in buffer
|
2006-12-18 15:39:33 +01:00
|
|
|
int iAvSpace = iGetPos - iPutPos;
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// check for special case and wrap around
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( iAvSpace < 0 )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
iAvSpace += iMemSize; // wrap around
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2007-09-08 12:45:14 +02:00
|
|
|
else
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
|
|
|
if ( ( iAvSpace == 0 ) && ( eBufState == BS_EMPTY ) )
|
|
|
|
{
|
|
|
|
iAvSpace = iMemSize;
|
|
|
|
}
|
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
|
|
|
|
return iAvSpace;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetBuf::GetAvailData() const
|
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// calculate available data in buffer
|
2006-12-18 15:39:33 +01:00
|
|
|
int iAvData = iPutPos - iGetPos;
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// check for special case and wrap around
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( iAvData < 0 )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
iAvData += iMemSize; // wrap around
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2007-09-08 12:45:14 +02:00
|
|
|
else
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
|
|
|
if ( ( iAvData == 0 ) && ( eBufState == BS_FULL ) )
|
|
|
|
{
|
|
|
|
iAvData = iMemSize;
|
|
|
|
}
|
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
|
|
|
|
return iAvData;
|
|
|
|
}
|
|
|
|
|
2007-09-08 12:45:14 +02:00
|
|
|
void CNetBuf::Clear ( const EClearType eClearType )
|
2006-01-28 12:29:22 +01:00
|
|
|
{
|
2009-12-31 13:58:12 +01:00
|
|
|
// TEST defines
|
|
|
|
const bool bUseRandomInit = false;
|
|
|
|
const int iNumBlocksBoundForRandom = 6;
|
|
|
|
|
|
|
|
int iNewFillLevel = 0;
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2009-08-02 19:44:45 +02:00
|
|
|
if ( iBlockSize != 0 )
|
|
|
|
{
|
2009-12-31 13:58:12 +01:00
|
|
|
// with the following operation we set the fill level to a block
|
2009-08-22 17:57:51 +02:00
|
|
|
// boundary (one block below the middle of the buffer in case of odd
|
|
|
|
// number of blocks, e.g.:
|
|
|
|
// [buffer size]: [get pos]
|
2009-12-31 13:58:12 +01:00
|
|
|
// 1: 0 / 2: 0 / 3: 1 / 4: 1 / 5: 2 ...)
|
|
|
|
iNewFillLevel =
|
2009-08-22 17:57:51 +02:00
|
|
|
( ( ( iMemSize - iBlockSize) / 2 ) / iBlockSize ) * iBlockSize;
|
2009-12-31 13:58:12 +01:00
|
|
|
|
|
|
|
// TEST random init position
|
|
|
|
if ( bUseRandomInit )
|
|
|
|
{
|
|
|
|
const int iNumBlocks = iMemSize / iBlockSize;
|
|
|
|
if ( iNumBlocks < iNumBlocksBoundForRandom ) // just for very small buffers
|
|
|
|
{
|
|
|
|
// overwrite fill level with random value
|
|
|
|
iNewFillLevel = static_cast<int> ( static_cast<double> ( rand() ) *
|
|
|
|
iNumBlocks / RAND_MAX ) * iBlockSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-02 19:44:45 +02:00
|
|
|
}
|
2007-09-08 12:45:14 +02:00
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// different behaviour for get and put corrections
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( eClearType == CT_GET )
|
2006-12-18 15:39:33 +01:00
|
|
|
{
|
2009-12-31 13:58:12 +01:00
|
|
|
// clear buffer since we had a buffer underrun
|
2009-07-24 16:31:25 +02:00
|
|
|
vecbyMemory.Reset ( 0 );
|
2006-12-18 15:39:33 +01:00
|
|
|
|
2009-12-31 13:58:12 +01:00
|
|
|
// reset buffer pointers so that they are at maximum distance
|
2006-12-18 15:39:33 +01:00
|
|
|
iPutPos = 0;
|
2009-12-31 13:58:12 +01:00
|
|
|
iGetPos = iNewFillLevel;
|
2006-11-25 15:46:57 +01:00
|
|
|
|
2009-08-22 18:13:21 +02:00
|
|
|
// The buffer was cleared, the next time blocks are read from the
|
|
|
|
// buffer, these are invalid ones. Calculate the number of invalid
|
|
|
|
// elements
|
2009-12-31 13:58:12 +01:00
|
|
|
iNumInvalidElements = iMemSize - iNewFillLevel;
|
2009-08-22 18:13:21 +02:00
|
|
|
|
2009-08-02 09:54:15 +02:00
|
|
|
// check for special case
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( iPutPos == iGetPos )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
eBufState = CNetBuf::BS_FULL;
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-11-25 15:46:57 +01:00
|
|
|
else
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
eBufState = CNetBuf::BS_OK;
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-12-31 14:09:12 +01:00
|
|
|
// in case of "put" correction, do not delete old data but only shift
|
|
|
|
// the pointers
|
2009-12-31 13:58:12 +01:00
|
|
|
iPutPos = iNewFillLevel;
|
2006-11-25 15:46:57 +01:00
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// adjust put pointer relative to current get pointer, take care of
|
|
|
|
// wrap around
|
2006-11-25 15:46:57 +01:00
|
|
|
iPutPos += iGetPos;
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( iPutPos > iMemSize )
|
2009-02-22 12:07:18 +01:00
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
iPutPos -= iMemSize;
|
2009-02-22 12:07:18 +01:00
|
|
|
}
|
2006-11-25 15:46:57 +01:00
|
|
|
|
2009-08-22 18:13:21 +02:00
|
|
|
// in case of put correction, no invalid blocks are inserted
|
|
|
|
iNumInvalidElements = 0;
|
|
|
|
|
2007-12-31 14:09:12 +01:00
|
|
|
// check for special case
|
2007-09-08 12:45:14 +02:00
|
|
|
if ( iPutPos == iGetPos )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
|
|
|
eBufState = CNetBuf::BS_EMPTY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eBufState = CNetBuf::BS_OK;
|
|
|
|
}
|
|
|
|
}
|
2006-12-18 15:39:33 +01:00
|
|
|
}
|