/* * 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 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(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(mSize); } int read_into(int sd, unsigned int bytes); int read_into(int sd, unsigned int bytes, struct timeval timeout); }; #endif // ZM_BUFFER_H