189 lines
5.1 KiB
C++
189 lines
5.1 KiB
C++
/*
|
|
* ZoneMinder Flexible Memory Interface, $Date$, $Revision$
|
|
* Copyright (C) 2001-2008 Philip Coombes
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifndef ZM_BUFFER_H
|
|
#define ZM_BUFFER_H
|
|
|
|
#include "zm_logger.h"
|
|
#include <cstring>
|
|
|
|
class Buffer {
|
|
protected:
|
|
unsigned char *mStorage;
|
|
unsigned int mAllocation;
|
|
unsigned int mSize;
|
|
unsigned char *mHead;
|
|
unsigned char *mTail;
|
|
|
|
public:
|
|
Buffer() :
|
|
mStorage(nullptr),
|
|
mAllocation(0),
|
|
mSize(0),
|
|
mHead(nullptr),
|
|
mTail(nullptr) {
|
|
}
|
|
explicit Buffer(unsigned int pSize) : mAllocation(pSize), mSize(0) {
|
|
mHead = mStorage = new unsigned char[mAllocation];
|
|
mTail = mHead;
|
|
}
|
|
Buffer(const unsigned char *pStorage, unsigned int pSize) :
|
|
mAllocation(pSize), mSize(pSize) {
|
|
mHead = mStorage = new unsigned char[mSize];
|
|
std::memcpy(mStorage, pStorage, mSize);
|
|
mTail = mHead + mSize;
|
|
}
|
|
Buffer(const Buffer &buffer) :
|
|
mAllocation(buffer.mSize),
|
|
mSize(buffer.mSize) {
|
|
mHead = mStorage = new unsigned char[mSize];
|
|
std::memcpy(mStorage, buffer.mHead, mSize);
|
|
mTail = mHead + mSize;
|
|
}
|
|
~Buffer() {
|
|
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 ); }
|
|
unsigned int size( unsigned int pSize ) {
|
|
if ( mSize < pSize ) {
|
|
expand(pSize-mSize);
|
|
}
|
|
return mSize;
|
|
}
|
|
// unsigned int Allocation() const { return( mAllocation ); }
|
|
|
|
void clear() {
|
|
mSize = 0;
|
|
mHead = mTail = mStorage;
|
|
}
|
|
|
|
unsigned int assign(const unsigned char *pStorage, unsigned int pSize);
|
|
unsigned int assign(const Buffer &buffer) {
|
|
return assign(buffer.mHead, buffer.mSize);
|
|
}
|
|
|
|
// Trim from the front of the buffer
|
|
unsigned int consume(unsigned int count) {
|
|
if ( count > mSize ) {
|
|
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
|
|
unsigned int shrink(unsigned int count) {
|
|
if (count > mSize) {
|
|
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);
|
|
|
|
// Return pointer to the first pSize bytes and advance the head
|
|
unsigned char *extract(unsigned int pSize) {
|
|
if (pSize > mSize) {
|
|
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
|
|
unsigned int append(const unsigned char *pStorage, unsigned int pSize) {
|
|
expand(pSize);
|
|
std::memcpy(mTail, pStorage, pSize);
|
|
mTail += pSize;
|
|
mSize += pSize;
|
|
return mSize;
|
|
}
|
|
unsigned int append(const char *pStorage, unsigned int pSize) {
|
|
return append((const unsigned char *)pStorage, pSize);
|
|
}
|
|
unsigned int append(const Buffer &buffer) {
|
|
return append(buffer.mHead, buffer.mSize);
|
|
}
|
|
void tidy(bool level=0) {
|
|
if (mHead != mStorage) {
|
|
if (mSize == 0) {
|
|
mHead = mTail = mStorage;
|
|
} else if (level) {
|
|
if (((uintptr_t)mHead-(uintptr_t)mStorage) > mSize) {
|
|
std::memcpy(mStorage, mHead, mSize);
|
|
mHead = mStorage;
|
|
mTail = mHead + mSize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Buffer &operator=(const Buffer &buffer) {
|
|
assign(buffer);
|
|
return *this;
|
|
}
|
|
Buffer &operator+=(const Buffer &buffer) {
|
|
append(buffer);
|
|
return *this;
|
|
}
|
|
Buffer &operator+=(unsigned int count) {
|
|
expand(count);
|
|
return *this;
|
|
}
|
|
Buffer &operator-=(unsigned int count) {
|
|
consume(count);
|
|
return *this;
|
|
}
|
|
operator unsigned char *() const {
|
|
return mHead;
|
|
}
|
|
operator char *() const {
|
|
return reinterpret_cast<char *>(mHead);
|
|
}
|
|
unsigned char *operator+(int offset) const {
|
|
return (unsigned char *)(mHead+offset);
|
|
}
|
|
unsigned char operator[](int index) const {
|
|
return *(mHead+index);
|
|
}
|
|
operator int () const {
|
|
return static_cast<int>(mSize);
|
|
}
|
|
int read_into(int sd, unsigned int bytes);
|
|
int read_into(int sd, unsigned int bytes, struct timeval timeout);
|
|
};
|
|
|
|
#endif // ZM_BUFFER_H
|