From 3f0f30442de297859cccc18f28db83b4e755d36f Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 30 Jul 2009 17:05:47 +0000 Subject: Bu::Buffer actually works, and works really well. I dig it. Bu::BZip2 now follows the new filter guidelines, where read and write report the amount of data consumed, not the amount processed. I.e. when writing, it reports how much of your incoming data it used, not how many bytes it wrote on the other end. --- src/buffer.cpp | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/buffer.h | 15 +++++++ src/bzip2.cpp | 2 +- src/tests/buffer.cpp | 38 ++++++++++++++++ 4 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 src/tests/buffer.cpp diff --git a/src/buffer.cpp b/src/buffer.cpp index fef64b1..5e7fb9a 100644 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -1,18 +1,31 @@ +/* + * Copyright (C) 2007-2008 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/buffer.h" -Bu::Buffer::Buffer( Bu::Stream &rNext, int iBufsize ) : +Bu::Buffer::Buffer( Bu::Stream &rNext, int iBufSize ) : Bu::Filter( rNext ), sSoFar( 0 ), iBufSize( iBufSize ), sReadBuf( NULL ), sWriteBuf( NULL ), iReadBufFill( 0 ), - iWriteBufFill( 0 ) + iReadPos( 0 ), + iWriteBufFill( 0 ), + iWritePos( 0 ) { + sReadBuf = new char[iBufSize]; + sWriteBuf = new char[iBufSize]; } Bu::Buffer::~Buffer() { + delete[] sReadBuf; + delete[] sWriteBuf; } void Bu::Buffer::start() @@ -23,15 +36,118 @@ size_t Bu::Buffer::stop() { } +void Bu::Buffer::fillReadBuf() +{ + if( iReadBufFill+iReadPos < iBufSize ) + { + printf("Buffer: Attempting to read %db.\n", iBufSize-iReadBufFill-iReadPos ); + iReadBufFill += rNext.read( + sReadBuf+iReadPos+iReadBufFill, + iBufSize-iReadBufFill-iReadPos + ); + printf("Buffer: Read from stream, %db now in buffer.\n", iReadBufFill ); + } +} + size_t Bu::Buffer::read( void *pBuf, size_t nBytes ) { + if( nBytes <= 0 ) + { + fillReadBuf(); + return 0; + } + + size_t nTotRead = 0; +// fillReadBuf(); + + do + { + int iAmnt = nBytes-nTotRead; + if( iAmnt > iReadBufFill ) + { + iAmnt = iReadBufFill; + } + if( iAmnt > 0 ) + { + memcpy( ((char *)pBuf)+nTotRead, sReadBuf+iReadPos, iAmnt ); + iReadPos += iAmnt; + nTotRead += iAmnt; + iReadBufFill -= iAmnt; + } + if( iReadBufFill == 0 ) + { + iReadPos = 0; + fillReadBuf(); + } + } + while( nTotRead < nBytes && iReadBufFill > 0 ); + + printf("Buffer: %db returned, %db remain in buffer.\n", nTotRead, iReadBufFill ); + + return nTotRead; } size_t Bu::Buffer::write( const void *pBuf, size_t nBytes ) { + size_t nTotWrote = 0; + + do + { + int iAmnt = nBytes-nTotWrote; + if( iAmnt > iBufSize-iWritePos-iWriteBufFill ) + { + iAmnt = iBufSize-iWritePos-iWriteBufFill; + } + if( iAmnt > 0 ) + { + memcpy( + sWriteBuf+iWritePos+iWriteBufFill, + ((char *)pBuf)+nTotWrote, + iAmnt + ); + nTotWrote += iAmnt; + iWriteBufFill += iAmnt; + printf("Buffer: Moved %db to write buffer, %db filled now.\n", + iAmnt, iWriteBufFill ); + } + while( iWritePos+iWriteBufFill == iBufSize ) + { + printf("iWritePos = %d\n", iWritePos ); + int iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); + printf("Buffer: Wrote %db from buffer to stream, %db filled now.\n", iWr, iWriteBufFill-iWr ); + if( iWr == 0 ) + { + return nTotWrote; + } + else if( iWr == iWriteBufFill ) + { + iWritePos = iWriteBufFill = 0; + } + else + { + iWritePos += iWr; + iWriteBufFill -= iWr; + } + } + } + while( nTotWrote < nBytes && iWriteBufFill < iBufSize+iWritePos ); + + return nTotWrote; } void Bu::Buffer::flush() { + if( iWriteBufFill > 0 ) + { + printf("Buffer: Flushing remaining data, %db.\n", iWriteBufFill ); + int iWr = 0; + do + { + iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); + printf("Buffer: %db written to stream.\n", iWr ); + iWritePos += iWr; + iWriteBufFill -= iWr; + } while( iWriteBufFill > 0 && iWr > 0 ); + } } diff --git a/src/buffer.h b/src/buffer.h index beb4b08..a18be11 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -1,3 +1,10 @@ +/* + * Copyright (C) 2007-2008 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_BUFFER_H #define BU_BUFFER_H @@ -18,15 +25,23 @@ namespace Bu virtual size_t write( const void *pBuf, size_t nBytes ); using Stream::write; + size_t getReadFill() { return iReadBufFill; } + bool isWritePending() { return iWriteBufFill > 0; } + virtual void flush(); + private: + void fillReadBuf(); + private: size_t sSoFar; int iBufSize; char *sReadBuf; char *sWriteBuf; int iReadBufFill; + int iReadPos; int iWriteBufFill; + int iWritePos; }; }; diff --git a/src/bzip2.cpp b/src/bzip2.cpp index 10cfe8a..0a56f83 100644 --- a/src/bzip2.cpp +++ b/src/bzip2.cpp @@ -200,7 +200,7 @@ size_t Bu::BZip2::write( const void *pData, size_t nBytes ) break; } - return sTotalOut; + return nBytes; } bool Bu::BZip2::isOpen() diff --git a/src/tests/buffer.cpp b/src/tests/buffer.cpp new file mode 100644 index 0000000..a1a1105 --- /dev/null +++ b/src/tests/buffer.cpp @@ -0,0 +1,38 @@ +#include "bu/membuf.h" +#include "bu/buffer.h" +#include "bu/file.h" + +using namespace Bu; + +int main( int argc, char *argv[] ) +{ + argc--,argv++; + if( argc == 0 ) + { + MemBuf mOut; + Buffer bOut( mOut, 10 ); + + for( int j = 0; j < 4; j++ ) + bOut.write("hi ", 3 ); + + printf("Preflush: \"%s\"\n", mOut.getString().getStr() ); + bOut.flush(); + + printf("Final: \"%s\"\n", mOut.getString().getStr() ); + } + else + { + File fIn( *argv, File::Read ); + Buffer bIn( fIn, 10 ); + + char buf[5]; + for( int j = 0; j < 5; j++ ) + { + buf[bIn.read( buf, 4 )] = '\0'; + printf("Four chars: \"%s\"\n", buf ); + } + } + + return 0; +} + -- cgit v1.2.3