/* * 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 Bu::QueueBuf::peek( void *pBuf, size_t nBytes ) { return peek( pBuf, nBytes, 0 ); } size_t Bu::QueueBuf::peek( void *pRawBuf, size_t nBytes, size_t nSkip ) { if( nBytes <= 0 ) return 0; if( lBlocks.isEmpty() ) return 0; size_t iLeft = nBytes; char *pBuf = (char *)pRawBuf; int iTmpReadOffset = iReadOffset + nSkip; size_t iTmpRemSize = iTotalSize; BlockList::iterator iBlock = lBlocks.begin(); while( iTmpReadOffset > iBlockSize ) { iTmpReadOffset -= iBlockSize; iBlock++; } while( iLeft > 0 && iTmpRemSize > 0 ) { if( iTmpReadOffset == iBlockSize ) { iBlock++; if( iBlock == lBlocks.end() ) { return nBytes-iLeft; } iTmpReadOffset = 0; } char *pBlock = *iBlock; size_t iCopy = iBlockSize-iTmpReadOffset; if( iLeft < iCopy ) iCopy = iLeft; if( iTmpRemSize < iCopy ) iCopy = iTmpRemSize; memcpy( pBuf, pBlock+iTmpReadOffset, iCopy ); iTmpReadOffset += iCopy; iLeft -= iCopy; pBuf += iCopy; iTmpRemSize -= iCopy; // sio << "Read (peek) " << iCopy << " bytes, new temp size: " // << iTmpRemSize << 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 iAmnt ) { if( iAmnt <= 0 ) return; if( iAmnt >= iTotalSize ) { // sio << "seek: clear all data (" << iAmnt << ">=" << iTotalSize // << ")." << sio.nl; close(); return; } iReadOffset += iAmnt; iTotalSize -= iAmnt; while( iReadOffset >= iBlockSize ) { removeBlock(); iReadOffset -= iBlockSize; // sio << "seek: removal step (" << iReadOffset << ")" << sio.nl; } } 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; }