2012-11-26 18:58:24 +00:00
|
|
|
#ifndef DATAQUEUE_H
|
|
|
|
#define DATAQUEUE_H
|
|
|
|
|
|
|
|
template< int maxItems, int maxBuffer >
|
2012-11-28 15:47:07 +00:00
|
|
|
class idDataQueue
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
public:
|
2012-11-28 15:47:07 +00:00
|
|
|
idDataQueue()
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
dataLength = 0;
|
|
|
|
}
|
2012-11-28 15:47:07 +00:00
|
|
|
bool Append( int sequence, const byte* b1, int b1Len, const byte* b2 = NULL, int b2Len = 0 );
|
2012-11-26 18:58:24 +00:00
|
|
|
void RemoveOlderThan( int sequence );
|
2012-11-28 15:47:07 +00:00
|
|
|
|
|
|
|
int GetDataLength() const
|
|
|
|
{
|
|
|
|
return dataLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Num() const
|
|
|
|
{
|
|
|
|
return items.Num();
|
|
|
|
}
|
|
|
|
int ItemSequence( int i ) const
|
|
|
|
{
|
|
|
|
return items[i].sequence;
|
|
|
|
}
|
|
|
|
int ItemLength( int i ) const
|
|
|
|
{
|
|
|
|
return items[i].length;
|
|
|
|
}
|
|
|
|
const byte* ItemData( int i ) const
|
|
|
|
{
|
|
|
|
return &data[items[i].dataOffset];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Clear()
|
|
|
|
{
|
|
|
|
dataLength = 0;
|
|
|
|
items.Clear();
|
|
|
|
memset( data, 0, sizeof( data ) );
|
|
|
|
}
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
private:
|
2012-11-28 15:47:07 +00:00
|
|
|
struct msgItem_t
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
int sequence;
|
|
|
|
int length;
|
|
|
|
int dataOffset;
|
|
|
|
};
|
|
|
|
idStaticList<msgItem_t, maxItems > items;
|
|
|
|
int dataLength;
|
|
|
|
byte data[ maxBuffer ];
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
========================
|
|
|
|
idDataQueue::RemoveOlderThan
|
|
|
|
========================
|
|
|
|
*/
|
|
|
|
template< int maxItems, int maxBuffer >
|
2012-11-28 15:47:07 +00:00
|
|
|
void idDataQueue< maxItems, maxBuffer >::RemoveOlderThan( int sequence )
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
int length = 0;
|
2012-11-28 15:47:07 +00:00
|
|
|
while( items.Num() > 0 && items[0].sequence < sequence )
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
length += items[0].length;
|
|
|
|
items.RemoveIndex( 0 );
|
|
|
|
}
|
2012-11-28 15:47:07 +00:00
|
|
|
if( length >= dataLength )
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
assert( items.Num() == 0 );
|
|
|
|
assert( dataLength == length );
|
|
|
|
dataLength = 0;
|
2012-11-28 15:47:07 +00:00
|
|
|
}
|
|
|
|
else if( length > 0 )
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
memmove( data, data + length, dataLength - length );
|
|
|
|
dataLength -= length;
|
|
|
|
}
|
|
|
|
length = 0;
|
2012-11-28 15:47:07 +00:00
|
|
|
for( int i = 0; i < items.Num(); i++ )
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
items[i].dataOffset = length;
|
|
|
|
length += items[i].length;
|
|
|
|
}
|
|
|
|
assert( length == dataLength );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
========================
|
|
|
|
idDataQueue::Append
|
|
|
|
========================
|
|
|
|
*/
|
|
|
|
template< int maxItems, int maxBuffer >
|
2012-11-28 15:47:07 +00:00
|
|
|
bool idDataQueue< maxItems, maxBuffer >::Append( int sequence, const byte* b1, int b1Len, const byte* b2, int b2Len )
|
|
|
|
{
|
|
|
|
if( items.Num() == items.Max() )
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-11-28 15:47:07 +00:00
|
|
|
if( dataLength + b1Len + b2Len >= maxBuffer )
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-11-28 15:47:07 +00:00
|
|
|
msgItem_t& item = *items.Alloc();
|
2012-11-26 18:58:24 +00:00
|
|
|
item.length = b1Len + b2Len;
|
|
|
|
item.sequence = sequence;
|
|
|
|
item.dataOffset = dataLength;
|
2012-11-28 15:47:07 +00:00
|
|
|
memcpy( data + dataLength, b1, b1Len );
|
|
|
|
dataLength += b1Len;
|
|
|
|
memcpy( data + dataLength, b2, b2Len );
|
|
|
|
dataLength += b2Len;
|
2012-11-26 18:58:24 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DATAQUEUE_H
|