2004-03-13 22:06:53 +08:00
|
|
|
/*
|
|
|
|
* ZoneMinder Flexible Memory Interface, $Date$, $Revision$
|
2008-07-25 17:33:23 +08:00
|
|
|
* Copyright (C) 2001-2008 Philip Coombes
|
2004-03-13 22:06:53 +08:00
|
|
|
*
|
|
|
|
* 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
|
2015-09-19 15:30:07 +08:00
|
|
|
* GNU General Public License for more details.
|
2004-03-13 22:06:53 +08:00
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2016-12-26 23:23:16 +08:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2004-03-13 22:06:53 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef ZM_BUFFER_H
|
|
|
|
#define ZM_BUFFER_H
|
|
|
|
|
2008-07-16 16:35:59 +08:00
|
|
|
#include "zm.h"
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
2004-03-13 22:06:53 +08:00
|
|
|
class Buffer
|
|
|
|
{
|
|
|
|
protected:
|
2016-04-04 22:11:48 +08:00
|
|
|
unsigned char *mStorage;
|
|
|
|
unsigned int mAllocation;
|
|
|
|
unsigned int mSize;
|
|
|
|
unsigned char *mHead;
|
|
|
|
unsigned char *mTail;
|
2004-03-13 22:06:53 +08:00
|
|
|
|
|
|
|
public:
|
2017-10-20 05:12:36 +08:00
|
|
|
Buffer() : mStorage( 0 ), mAllocation( 0 ), mSize( 0 ), mHead( 0 ), mTail( 0 ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
}
|
2017-11-16 22:19:27 +08:00
|
|
|
explicit Buffer( unsigned int pSize ) : mAllocation( pSize ), mSize( 0 ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
mHead = mStorage = new unsigned char[mAllocation];
|
|
|
|
mTail = mHead;
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
Buffer( const unsigned char *pStorage, unsigned int pSize ) : mAllocation( pSize ), mSize( pSize ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
mHead = mStorage = new unsigned char[mSize];
|
|
|
|
memcpy( mStorage, pStorage, mSize );
|
|
|
|
mTail = mHead + mSize;
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
Buffer( const Buffer &buffer ) : mAllocation( buffer.mSize ), mSize( buffer.mSize ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
mHead = mStorage = new unsigned char[mSize];
|
|
|
|
memcpy( mStorage, buffer.mHead, mSize );
|
|
|
|
mTail = mHead + mSize;
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
~Buffer() {
|
2016-04-04 22:11:48 +08:00
|
|
|
delete[] mStorage;
|
|
|
|
}
|
|
|
|
unsigned char *head() const { return( mHead ); }
|
|
|
|
unsigned char *tail() const { return( mTail ); }
|
|
|
|
unsigned int size() const { return( mSize ); }
|
|
|
|
bool empty() const { return( mSize == 0 ); }
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned int size( unsigned int pSize ) {
|
|
|
|
if ( mSize < pSize ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
expand( pSize-mSize );
|
|
|
|
}
|
|
|
|
return( mSize );
|
|
|
|
}
|
|
|
|
//unsigned int Allocation() const { return( mAllocation ); }
|
2004-03-13 22:06:53 +08:00
|
|
|
|
2017-10-20 05:12:36 +08:00
|
|
|
void clear() {
|
2016-04-04 22:11:48 +08:00
|
|
|
mSize = 0;
|
|
|
|
mHead = mTail = mStorage;
|
|
|
|
}
|
2004-03-13 22:06:53 +08:00
|
|
|
|
2016-04-04 22:11:48 +08:00
|
|
|
unsigned int assign( const unsigned char *pStorage, unsigned int pSize );
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned int assign( const Buffer &buffer ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
return( assign( buffer.mHead, buffer.mSize ) );
|
|
|
|
}
|
2004-03-13 22:06:53 +08:00
|
|
|
|
2016-04-04 22:11:48 +08:00
|
|
|
// Trim from the front of the buffer
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned int consume( unsigned int count ) {
|
|
|
|
if ( count > mSize ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
Warning( "Attempt to consume %d bytes of buffer, size is only %d bytes", count, mSize );
|
|
|
|
count = mSize;
|
|
|
|
}
|
|
|
|
mHead += count;
|
|
|
|
mSize -= count;
|
|
|
|
tidy( 0 );
|
|
|
|
return( count );
|
|
|
|
}
|
|
|
|
// Trim from the end of the buffer
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned int shrink( unsigned int count ) {
|
|
|
|
if ( count > mSize ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
Warning( "Attempt to shrink buffer by %d bytes, size is only %d bytes", count, mSize );
|
|
|
|
count = mSize;
|
|
|
|
}
|
|
|
|
mSize -= count;
|
|
|
|
if ( mTail > (mHead + mSize) )
|
|
|
|
mTail = mHead + mSize;
|
|
|
|
tidy( 0 );
|
|
|
|
return( count );
|
|
|
|
}
|
|
|
|
// Add to the end of the buffer
|
|
|
|
unsigned int expand( unsigned int count );
|
2008-10-09 17:15:23 +08:00
|
|
|
|
2016-04-04 22:11:48 +08:00
|
|
|
// Return pointer to the first pSize bytes and advance the head
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned char *extract( unsigned int pSize ) {
|
|
|
|
if ( pSize > mSize ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
Warning( "Attempt to extract %d bytes of buffer, size is only %d bytes", pSize, mSize );
|
|
|
|
pSize = mSize;
|
|
|
|
}
|
|
|
|
unsigned char *oldHead = mHead;
|
|
|
|
mHead += pSize;
|
|
|
|
mSize -= pSize;
|
|
|
|
tidy( 0 );
|
|
|
|
return( oldHead );
|
|
|
|
}
|
|
|
|
// Add bytes to the end of the buffer
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned int append( const unsigned char *pStorage, unsigned int pSize ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
expand( pSize );
|
|
|
|
memcpy( mTail, pStorage, pSize );
|
|
|
|
mTail += pSize;
|
|
|
|
mSize += pSize;
|
|
|
|
return( mSize );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned int append( const char *pStorage, unsigned int pSize ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
return( append( (const unsigned char *)pStorage, pSize ) );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned int append( const Buffer &buffer ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
return( append( buffer.mHead, buffer.mSize ) );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
void tidy( bool level=0 ) {
|
|
|
|
if ( mHead != mStorage ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
if ( mSize == 0 )
|
|
|
|
mHead = mTail = mStorage;
|
2017-10-20 05:12:36 +08:00
|
|
|
else if ( level ) {
|
|
|
|
if ( ((uintptr_t)mHead-(uintptr_t)mStorage) > mSize ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
memcpy( mStorage, mHead, mSize );
|
|
|
|
mHead = mStorage;
|
|
|
|
mTail = mHead + mSize;
|
2008-10-09 16:27:39 +08:00
|
|
|
}
|
2016-04-04 22:11:48 +08:00
|
|
|
}
|
2008-10-09 16:27:39 +08:00
|
|
|
}
|
2016-04-04 22:11:48 +08:00
|
|
|
}
|
2004-03-13 22:06:53 +08:00
|
|
|
|
2017-10-20 05:12:36 +08:00
|
|
|
Buffer &operator=( const Buffer &buffer ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
assign( buffer );
|
|
|
|
return( *this );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
Buffer &operator+=( const Buffer &buffer ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
append( buffer );
|
|
|
|
return( *this );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
Buffer &operator+=( unsigned int count ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
expand( count );
|
|
|
|
return( *this );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
Buffer &operator-=( unsigned int count ) {
|
2016-04-04 22:11:48 +08:00
|
|
|
consume( count );
|
|
|
|
return( *this );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
operator unsigned char *() const {
|
2016-04-04 22:11:48 +08:00
|
|
|
return( mHead );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
operator char *() const {
|
2016-04-04 22:11:48 +08:00
|
|
|
return( (char *)mHead );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned char *operator+(int offset) const {
|
2016-04-04 22:11:48 +08:00
|
|
|
return( (unsigned char *)(mHead+offset) );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
unsigned char operator[](int index) const {
|
2016-04-04 22:11:48 +08:00
|
|
|
return( *(mHead+index) );
|
|
|
|
}
|
2017-10-20 05:12:36 +08:00
|
|
|
operator int () const {
|
2016-04-04 22:11:48 +08:00
|
|
|
return( (int)mSize );
|
|
|
|
}
|
|
|
|
int read_into( int sd, unsigned int bytes );
|
2004-03-13 22:06:53 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // ZM_BUFFER_H
|