From 8baf7e1e75a185c742dc6d5b27e50058635e5522 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 10 May 2010 03:31:08 +0000 Subject: Added the new QueueBuf. It's brilliant, and I've wanted it for a long time. ...I mean brilliant as in cool. --- src/cache.h | 5 ++ src/queuebuf.cpp | 233 +++++++++++++++++++++++++++++++++++++++++++++++++ src/queuebuf.h | 62 +++++++++++++ src/tests/queuebuf.cpp | 23 +++++ 4 files changed, 323 insertions(+) create mode 100644 src/queuebuf.cpp create mode 100644 src/queuebuf.h create mode 100644 src/tests/queuebuf.cpp (limited to 'src') diff --git a/src/cache.h b/src/cache.h index dc5ab39..7b55b80 100644 --- a/src/cache.h +++ b/src/cache.h @@ -112,6 +112,11 @@ namespace Bu return pData != NULL; } + bool isSet() const + { + return pCache != NULL; + } + const keytype &getKey() const { return kId; diff --git a/src/queuebuf.cpp b/src/queuebuf.cpp new file mode 100644 index 0000000..9404164 --- /dev/null +++ b/src/queuebuf.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2007-2010 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/queuebuf.h" + +#include "bu/sio.h" +using Bu::sio; + +Bu::QueueBuf::QueueBuf( int iBlockSize /*=256*/ ) : + iBlockSize( iBlockSize ), + iReadOffset( 0 ), + iWriteOffset( 0 ), + iTotalSize( 0 ) +{ +} + +Bu::QueueBuf::~QueueBuf() +{ + for( BlockList::iterator i = lBlocks.begin(); i; i++ ) + delete[] *i; +} + +int Bu::QueueBuf::getSize() +{ + return iTotalSize; +} + +void Bu::QueueBuf::close() +{ + for( BlockList::iterator i = lBlocks.begin(); i; i++ ) + delete[] *i; + lBlocks.clear(); + iReadOffset = iWriteOffset = iTotalSize = 0; +} + +size_t Bu::QueueBuf::read( void *pRawBuf, size_t nBytes ) +{ + if( nBytes <= 0 ) + return 0; + + if( lBlocks.isEmpty() ) + return 0; + + size_t iLeft = nBytes; + char *pBuf = (char *)pRawBuf; + + while( iLeft > 0 && iTotalSize > 0 ) + { + if( iReadOffset == iBlockSize ) + { + removeBlock(); + if( lBlocks.isEmpty() ) + { + return nBytes-iLeft; + } + iReadOffset = 0; + } + char *pBlock = lBlocks.first(); + size_t iCopy = iBlockSize-iReadOffset; + if( iLeft < iCopy ) + iCopy = iLeft; + if( iTotalSize < iCopy ) + iCopy = iTotalSize; + memcpy( pBuf, pBlock+iReadOffset, iCopy ); + iReadOffset += iCopy; + iLeft -= iCopy; + pBuf += iCopy; + iTotalSize -= iCopy; + sio << "Read " << iCopy << " bytes, new size: " << iTotalSize << sio.nl; + } + + return nBytes - iLeft; +} + +size_t QueueBuf::peek( void *pBuf, size_t nBytes ) +{ + if( nBytes <= 0 ) + return 0; + + if( lBlocks.isEmpty() ) + return 0; + + size_t iLeft = nBytes; + char *pBuf = (char *)pRawBuf; + + int iTmpReadOffset = iReadOffset; + int iTmpRemSize = iTotalSize; + while( iLeft > 0 && iTmpRemSize > 0 ) + { + + // Switching to use temp variables instead of iReadOffset and iTotalSize + if( iReadOffset == iBlockSize ) + { + if( lBlocks.isEmpty() ) + { + return nBytes-iLeft; + } + iReadOffset = 0; + } + char *pBlock = lBlocks.first(); + size_t iCopy = iBlockSize-iReadOffset; + if( iLeft < iCopy ) + iCopy = iLeft; + if( iTotalSize < iCopy ) + iCopy = iTotalSize; + memcpy( pBuf, pBlock+iReadOffset, iCopy ); + iReadOffset += iCopy; + iLeft -= iCopy; + pBuf += iCopy; + iTotalSize -= iCopy; + sio << "Read " << iCopy << " bytes, new size: " << iTotalSize << sio.nl; + } + + return nBytes - iLeft; +} + +size_t Bu::QueueBuf::write( const void *pRawBuf, size_t nBytes ) +{ + if( nBytes <= 0 ) + return 0; + + if( lBlocks.isEmpty() ) + { + addBlock(); + iWriteOffset = 0; + } + size_t iLeft = nBytes; + const char *pBuf = (const char *)pRawBuf; + + while( iLeft > 0 ) + { + if( iWriteOffset == iBlockSize ) + { + addBlock(); + iWriteOffset = 0; + } + char *pBlock = lBlocks.last(); + size_t iCopy = iBlockSize-iWriteOffset; + if( iLeft < iCopy ) + iCopy = iLeft; + memcpy( pBlock+iWriteOffset, pBuf, iCopy ); + iWriteOffset += iCopy; + iLeft -= iCopy; + pBuf += iCopy; + iTotalSize += iCopy; + sio << "Wrote " << iCopy << " bytes, new size: " << iTotalSize << sio.nl; + } + + return nBytes; +} + +long Bu::QueueBuf::tell() +{ + return -1; +} + +void Bu::QueueBuf::seek( long ) +{ +} + +void Bu::QueueBuf::setPos( long ) +{ +} + +void Bu::QueueBuf::setPosEnd( long ) +{ +} + +bool Bu::QueueBuf::isEos() +{ + return iTotalSize == 0; +} + +bool Bu::QueueBuf::isOpen() +{ + return true; +} + +void Bu::QueueBuf::flush() +{ +} + +bool Bu::QueueBuf::canRead() +{ + return iTotalSize > 0; +} + +bool Bu::QueueBuf::canWrite() +{ + return true; +} + +bool Bu::QueueBuf::isReadable() +{ + return true; +} + +bool Bu::QueueBuf::isWritable() +{ + return true; +} + +bool Bu::QueueBuf::isSeekable() +{ + return false; +} + +bool Bu::QueueBuf::isBlocking() +{ + return false; +} + +void Bu::QueueBuf::setBlocking( bool ) +{ +} + +void Bu::QueueBuf::addBlock() +{ + lBlocks.append( new char[iBlockSize] ); + sio << "Added new block." << sio.nl; +} + +void Bu::QueueBuf::removeBlock() +{ + delete[] lBlocks.first(); + lBlocks.erase( lBlocks.begin() ); + sio << "Removed block." << sio.nl; +} + diff --git a/src/queuebuf.h b/src/queuebuf.h new file mode 100644 index 0000000..3591959 --- /dev/null +++ b/src/queuebuf.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2010 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#ifndef BU_QUEUE_BUF_H +#define BU_QUEUE_BUF_H + +#include "bu/stream.h" + +namespace Bu +{ + /** + * A queuing buffer stream class. All data written to this class is + * appended to it, there is no stored position. All data read is read + * from the begining and then thrown away. It operates by using a linked + * list of small buffers, and deallocating or reusing them when it can. + */ + class QueueBuf : public Bu::Stream + { + public: + QueueBuf( int iBlockSize=256 ); + virtual ~QueueBuf(); + + int getSize(); + + virtual void close(); + virtual size_t read( void *pBuf, size_t nBytes ); + virtual size_t peek( void *pBuf, size_t nBytes ); + virtual size_t write( const void *pBuf, size_t nBytes ); + virtual long tell(); + virtual void seek( long offset ); + virtual void setPos( long pos ); + virtual void setPosEnd( long pos ); + virtual bool isEos(); + virtual bool isOpen(); + virtual void flush(); + virtual bool canRead(); + virtual bool canWrite(); + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + + private: + void addBlock(); + void removeBlock(); + + private: + int iBlockSize; + int iReadOffset; + int iWriteOffset; + size_t iTotalSize; + typedef Bu::List BlockList; + BlockList lBlocks; + }; +}; + +#endif diff --git a/src/tests/queuebuf.cpp b/src/tests/queuebuf.cpp new file mode 100644 index 0000000..accc723 --- /dev/null +++ b/src/tests/queuebuf.cpp @@ -0,0 +1,23 @@ +#include +#include + +using namespace Bu; + +int main() +{ + static const char *src = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%#"; + QueueBuf qb; + + for( int j = 0; j < 8; j++ ) + { + qb.write( src, 60 ); + } + + char buf[11]; + while( !qb.isEos() ) + { + buf[qb.read( buf, 9 )] = '\0'; + sio << "Read: >>" << buf << "<<" << sio.nl; + } +} + -- cgit v1.2.3