/* * Copyright (C) 2007-2019 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; } void Bu::QueueBuf::close() { for( BlockList::iterator i = lBlocks.begin(); i; i++ ) delete[] *i; lBlocks.clear(); iReadOffset = iWriteOffset = iTotalSize = 0; } Bu::size Bu::QueueBuf::read( void *pRawBuf, Bu::size nBytes ) { if( nBytes <= 0 ) return 0; if( lBlocks.isEmpty() ) return 0; Bu::size 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(); Bu::size 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; } Bu::size Bu::QueueBuf::peek( void *pBuf, Bu::size nBytes ) { return peek( pBuf, nBytes, 0 ); } Bu::size Bu::QueueBuf::peek( void *pRawBuf, Bu::size nBytes, Bu::size nSkip ) { if( nBytes <= 0 ) return 0; if( lBlocks.isEmpty() ) return 0; Bu::size iLeft = nBytes; char *pBuf = (char *)pRawBuf; int iTmpReadOffset = iReadOffset + nSkip; Bu::size 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; Bu::size 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; } Bu::size Bu::QueueBuf::write( const void *pRawBuf, Bu::size nBytes ) { if( nBytes <= 0 ) return 0; if( lBlocks.isEmpty() ) { addBlock(); iWriteOffset = 0; } Bu::size iLeft = nBytes; const char *pBuf = (const char *)pRawBuf; while( iLeft > 0 ) { if( iWriteOffset == iBlockSize ) { addBlock(); iWriteOffset = 0; } char *pBlock = lBlocks.last(); Bu::size 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; } Bu::size Bu::QueueBuf::tell() { return -1; } void Bu::QueueBuf::seek( Bu::size iAmnt ) { if( iAmnt <= 0 ) return; if( (Bu::size)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( Bu::size ) { } void Bu::QueueBuf::setPosEnd( Bu::size ) { } 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::setSize( Bu::size ) { } Bu::size Bu::QueueBuf::getSize() const { return iTotalSize; } Bu::size Bu::QueueBuf::getBlockSize() const { return iBlockSize; } Bu::String Bu::QueueBuf::getLocation() const { return ""; } 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; }