From 9e8a4944e50fab432012878c66e1bdac20649f76 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 7 Jun 2007 19:56:20 +0000 Subject: The Stream Filter archetecture is finished, it's actually much cooler than I had anticipated, and much cleaner. I'll have to add some documentation to it, because it's not really obvious how any of it fits together from the outset, although I have to say that the bzip2 test program is the easiest general bzip2 compression program I've ever made...it just goes :) Decompression in Bu::BZip2 isn't finished yet, but that's ok, it's coming soon. --- src/bzip2.cpp | 123 ++++++++++++ src/bzip2.h | 35 ++++ src/entities/bu-class | 4 +- src/filter.cpp | 77 ++++++++ src/filter.h | 59 ++++++ src/fstring.h | 6 +- src/old/paramproc.cpp | 514 -------------------------------------------------- src/old/paramproc.h | 153 --------------- src/paramproc.cpp | 514 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/paramproc.h | 156 +++++++++++++++ src/stream.h | 3 + src/tests/bzip2.cpp | 23 +++ 12 files changed, 996 insertions(+), 671 deletions(-) create mode 100644 src/bzip2.cpp create mode 100644 src/bzip2.h create mode 100644 src/filter.cpp create mode 100644 src/filter.h delete mode 100644 src/old/paramproc.cpp delete mode 100644 src/old/paramproc.h create mode 100644 src/paramproc.cpp create mode 100644 src/paramproc.h create mode 100644 src/tests/bzip2.cpp (limited to 'src') diff --git a/src/bzip2.cpp b/src/bzip2.cpp new file mode 100644 index 0000000..b8c0f74 --- /dev/null +++ b/src/bzip2.cpp @@ -0,0 +1,123 @@ +#include "bu/bzip2.h" +#include "bu/exceptions.h" + +using namespace Bu; + +Bu::BZip2::BZip2( Bu::Stream &rNext, int nCompression ) : + Bu::Filter( rNext ), + nCompression( nCompression ) +{ + start(); +} + +Bu::BZip2::~BZip2() +{ + printf("-> Bu::BZip2::~BZip2()\n"); + stop(); +} + +void Bu::BZip2::start() +{ + printf("-> Bu::BZip2::start()\n"); + printf("Hey, it's starting...\n"); + bzState.state = NULL; + bzState.bzalloc = NULL; + bzState.bzfree = NULL; + bzState.opaque = NULL; + + nBufSize = 50000; + pBuf = new char[nBufSize]; +} + +void Bu::BZip2::stop() +{ + printf("-> Bu::BZip2::stop()\n"); + if( bzState.state ) + { + if( bReading ) + { + } + else + { + for(;;) + { + bzState.next_in = NULL; + bzState.avail_in = 0; + bzState.avail_out = nBufSize; + bzState.next_out = pBuf; + int res = BZ2_bzCompress( &bzState, BZ_FINISH ); + if( bzState.avail_out < nBufSize ) + { + rNext.write( pBuf, nBufSize-bzState.avail_out ); + } + if( res == BZ_STREAM_END ) + break; + } + BZ2_bzCompressEnd( &bzState ); + } + } +} + +void Bu::BZip2::bzError( int code ) +{ + switch( code ) + { + case BZ_OK: + return; + + case BZ_CONFIG_ERROR: + throw ExceptionBase("The bzip2 library has been miscompiled."); + + case BZ_PARAM_ERROR: + throw ExceptionBase("bzip2 parameter error."); + + case BZ_MEM_ERROR: + throw ExceptionBase("Not enough memory available for bzip2."); + } +} + +size_t Bu::BZip2::read( void *pData, size_t nBytes ) +{ + if( !bzState.state ) + { + bReading = true; + } + if( bReading == false ) + throw ExceptionBase("This bzip2 filter is in writing mode, you can't read."); + //bzState.next_in = pData; + //bzState.avail_in = nSizeIn; + + //printf("%db at [%08X] (%db)\n", bzState.avail_in, (uint32_t)bzState.next_in, bzState.total_in_lo32 ); + return 0; +} + +size_t Bu::BZip2::write( const void *pData, size_t nBytes ) +{ + if( !bzState.state ) + { + bReading = false; + BZ2_bzCompressInit( &bzState, nCompression, 0, 30 ); + } + if( bReading == true ) + throw ExceptionBase("This bzip2 filter is in reading mode, you can't write."); + + bzState.next_in = (char *)pData; + bzState.avail_in = nBytes; + for(;;) + { + bzState.avail_out = nBufSize; + bzState.next_out = pBuf; + + BZ2_bzCompress( &bzState, BZ_RUN ); + + if( bzState.avail_out < nBufSize ) + { + rNext.write( pBuf, nBufSize-bzState.avail_out ); + } + if( bzState.avail_in == 0 ) + break; + } + + return 0; +} + diff --git a/src/bzip2.h b/src/bzip2.h new file mode 100644 index 0000000..056f336 --- /dev/null +++ b/src/bzip2.h @@ -0,0 +1,35 @@ +#ifndef B_ZIP2_H +#define B_ZIP2_H + +#include +#include + +#include "bu/filter.h" + +namespace Bu +{ + /** + * + */ + class BZip2 : public Bu::Filter + { + public: + BZip2( Bu::Stream &rNext, int nCompression=9 ); + virtual ~BZip2(); + + virtual void start(); + virtual void stop(); + virtual size_t read( void *pBuf, size_t nBytes ); + virtual size_t write( const void *pBuf, size_t nBytes ); + + private: + void bzError( int code ); + bz_stream bzState; + bool bReading; + int nCompression; + char *pBuf; + uint32_t nBufSize; + }; +} + +#endif diff --git a/src/entities/bu-class b/src/entities/bu-class index 81e3d25..7b25291 100644 --- a/src/entities/bu-class +++ b/src/entities/bu-class @@ -10,7 +10,7 @@ #include <stdint.h> -{?parent:"#include \"{=parent:%tolower}.h\" +{?parent:"#include \"bu/{=parent:%tolower}.h\" "}namespace Bu { @@ -35,6 +35,8 @@ filename="{=name:%tolower}.cpp" >#include "bu/{=name:%tolower}.h" +using namespace Bu; + Bu::{=name}::{=name}() { } diff --git a/src/filter.cpp b/src/filter.cpp new file mode 100644 index 0000000..d3faa00 --- /dev/null +++ b/src/filter.cpp @@ -0,0 +1,77 @@ +#include "bu/filter.h" + +Bu::Filter::Filter( Bu::Stream &rNext ) : + rNext( rNext ) +{ +} + +Bu::Filter::~Filter() +{ + printf("-> Bu::Filter::~Filter()\n"); +} +/* +void Bu::Filter::start() +{ + printf("-> Bu::Filter::start()\n"); +} + +void Bu::Filter::stop() +{ +}*/ + +void Bu::Filter::close() +{ + stop(); + rNext.close(); +} + +long Bu::Filter::tell() +{ + return rNext.tell(); +} + +void Bu::Filter::seek( long offset ) +{ + rNext.seek( offset ); +} + +void Bu::Filter::setPos( long pos ) +{ + rNext.setPos( pos ); +} + +void Bu::Filter::setPosEnd( long pos ) +{ + rNext.setPosEnd( pos ); +} + +bool Bu::Filter::isEOS() +{ + return rNext.isEOS(); +} + +bool Bu::Filter::canRead() +{ + return rNext.canRead(); +} + +bool Bu::Filter::canWrite() +{ + return rNext.canWrite(); +} + +bool Bu::Filter::canSeek() +{ + return rNext.canSeek(); +} + +bool Bu::Filter::isBlocking() +{ + return rNext.isBlocking(); +} + +void Bu::Filter::setBlocking( bool bBlocking ) +{ + rNext.setBlocking( bBlocking ); +} + diff --git a/src/filter.h b/src/filter.h new file mode 100644 index 0000000..b068206 --- /dev/null +++ b/src/filter.h @@ -0,0 +1,59 @@ +#ifndef FILTER_H +#define FILTER_H + +#include + +#include "bu/stream.h" + +namespace Bu +{ + /** + * Data filter base class. Each data filter should contain a read and write + * section. Effectively, the write applies the filter, the read un-applies + * the filter, if possible. For example, BZip2 is a filter that compresses + * on write and decompresses on read. All bi-directional filters should + * follow: x == read( write( x ) ) (byte-for-byte comparison) + * + * Also, all returned buffers should be owned by the filter, and deleted + * when the filter is deleted. This means that the output of a read or + * write operation must be used before the next call to read or write or the + * data will be destroyed. Also, the internal buffer may be changed or + * recreated between calls, so always get a new pointer from a call to + * read or write. + * + * The close function can also return data, so make sure to check for it, + * many filters such as compression filters will buffer data until they have + * enough to create a compression block, in these cases the leftover data + * will be returned by close. + */ + class Filter : public Bu::Stream + { + public: + Filter( Bu::Stream &rNext ); + virtual ~Filter(); + + virtual void start()=0; + virtual void stop()=0; + virtual void close(); + virtual long tell(); + virtual void seek( long offset ); + virtual void setPos( long pos ); + virtual void setPosEnd( long pos ); + virtual bool isEOS(); + + virtual bool canRead(); + virtual bool canWrite(); + virtual bool canSeek(); + + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + + protected: + Bu::Stream &rNext; + + private: + + }; +} + +#endif diff --git a/src/fstring.h b/src/fstring.h index 43033b8..d0307b5 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -3,9 +3,9 @@ #include #include -#include "archival.h" -#include "archive.h" -#include "hash.h" +#include "bu/archival.h" +#include "bu/archive.h" +#include "bu/hash.h" #define min( a, b ) ((a - -#define ptrtype( iitype, iiname ) \ - ParamProc::ParamPtr::ParamPtr( iitype *iiname ) : \ - type( vt ##iiname ) { val.iiname = iiname; } - -ParamProc::ParamPtr::ParamPtr() -{ - val.str = NULL; - type = vtunset; -} - -ptrtype( std::string, str ); -ptrtype( uint64_t, uint64 ); -ptrtype( uint32_t, uint32 ); -ptrtype( uint16_t, uint16 ); -ptrtype( uint8_t, uint8 ); -ptrtype( int64_t, int64 ); -ptrtype( int32_t, int32 ); -ptrtype( int16_t, int16 ); -ptrtype( int8_t, int8 ); -ptrtype( float, float32 ); -ptrtype( double, float64 ); -ptrtype( long double, float96 ); -ptrtype( bool, bln ); - -ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( ParamProc::ParamPtr &ptr ) -{ - val = ptr.val; - type = ptr.type; - - return *this; -} - -bool ParamProc::ParamPtr::isSet() -{ - return type != vtunset; -} - -ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( const char *str ) -{ - if( !isSet() ) return *this; - switch( type ) - { - case vtstr: - (*val.str) = str; - break; - - case vtuint64: - (*val.uint64) = strtoull( str, NULL, 10 ); - break; - - case vtuint32: - (*val.uint32) = strtoul( str, NULL, 10 ); - break; - - case vtuint16: - (*val.uint16) = (uint16_t)strtoul( str, NULL, 10 ); - break; - - case vtuint8: - (*val.uint8) = (uint8_t)strtoul( str, NULL, 10 ); - break; - - case vtint64: - (*val.int64) = strtoll( str, NULL, 10 ); - break; - - case vtint32: - (*val.int32) = strtol( str, NULL, 10 ); - break; - - case vtint16: - (*val.int16) = (int16_t)strtol( str, NULL, 10 ); - break; - - case vtint8: - (*val.int8) = (int8_t)strtol( str, NULL, 10 ); - break; - - case vtfloat32: - (*val.float32) = strtof( str, NULL ); - break; - - case vtfloat64: - (*val.float64) = strtod( str, NULL ); - break; - - case vtfloat96: - (*val.float96) = strtold( str, NULL ); - break; - - case vtbln: - if( strcasecmp("yes", str ) == 0 || - strcasecmp("true", str ) == 0 ) - { - (*val.bln) = true; - } - else - { - (*val.bln) = false; - } - break; - } - - return *this; -} - -ParamProc::ParamProc() -{ -} - -ParamProc::~ParamProc() -{ - for( std::list::iterator i = lArg.begin(); - i != lArg.end(); i++ ) - { - delete *i; - } - - for( std::list::iterator i = lBan.begin(); - i != lBan.end(); i++ ) - { - delete *i; - } - -} -/* -void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val ) -{ - printf("Calling callback...\n"); - val = "Hello there, this is set in the ParamProc"; - (this->*proc)(); -}*/ - -void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, - ParamPtr val, const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - ArgSpec *as = new ArgSpec; - if( lpWord ) - as->sWord = lpWord; - - as->cChar = cChar; - as->proc = proc; - as->val = val; - if( lpDesc ) - as->sDesc = lpDesc; - if( lpExtra ) - as->sExtra = lpExtra; - if( lpValue ) - as->sValue = lpValue; - - lArg.push_back( as ); - - if( !lBan.empty() ) - { - if( lBan.back()->pBefore == NULL ) - lBan.back()->pBefore = as; - } -} - -void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, char cChar, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, cChar, NULL, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, Proc proc, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, '\0', proc, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, Proc proc, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, '\0', proc, ParamPtr(), lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, '\0', NULL, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( char cChar, Proc proc, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( NULL, cChar, proc, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( char cChar, Proc proc, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( NULL, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( char cChar, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( NULL, cChar, NULL, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::process( int argc, char *argv[] ) -{ - for( int arg = 1; arg < argc; arg++ ) - { - //printf(":::%d:::%s\n", arg, argv[arg] ); - if( argv[arg][0] == '-' ) - { - if( argv[arg][1] == '-' ) - { - ArgSpec *s = checkWord( argv[arg]+2 ); - if( s ) - { - if( argv[arg][s->sWord.getLength()+2] == '=' ) - { - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - s->val = argv[arg]+s->sWord.getLength()+3; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - char **tmp = new char*[argc-arg]; - tmp[0] = argv[arg]+s->sWord.getLength()+3; - for( int k = 1; k < argc-arg; k++ ) - tmp[k] = argv[arg+k]; - int ret = (this->*s->proc)( argc-arg, tmp ); - if( ret > 0 ) - { - arg += ret-1; - } - delete tmp; - } - } - else - { - int add = 0; - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - if( arg+1 >= argc ) - { - return; - } - s->val = argv[arg+1]; - add++; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - int ret = (this->*s->proc)( - argc-arg-1, argv+arg+1 ); - - if( ret > add ) - add = 0; - else - add -= ret; - arg += ret; - } - arg += add; - } - continue; - } - else - { - unknownParam( argc-arg, argv+arg ); - } - } - else - { - for( int chr = 1; argv[arg][chr]; chr++ ) - { - ArgSpec *s = checkLetr( argv[arg][chr] ); - if( s ) - { - if( argv[arg][chr+1] != '\0' ) - { - bool bUsed = false; - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - s->val = argv[arg]+chr+1; - bUsed = true; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - char **tmp = new char*[argc-arg]; - tmp[0] = argv[arg]+chr+1; - for( int k = 1; k < argc-arg; k++ ) - tmp[k] = argv[arg+k]; - int ret = (this->*s->proc)( argc-arg, tmp ); - if( ret > 0 ) - { - arg += ret - 1; - delete tmp; - break; - } - delete tmp; - } - if( bUsed ) - { - break; - } - } - else - { - bool bUsed = false; - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - s->val = argv[arg+1]; - bUsed = true; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - int ret = (this->*s->proc)( - argc-arg-1, argv+arg+1 - ); - if( ret > 0 ) - { - arg += ret; - break; - } - } - if( bUsed ) - { - arg++; - break; - } - } - } - else - { - unknownParam( argc-arg, argv+arg ); - } - } - } - } - else - { - cmdParam( argc-arg, argv+arg ); - } - } -} - -ParamProc::ArgSpec *ParamProc::checkWord( const char *arg ) -{ - //printf("Checking \"%s\"...\n", arg ); - std::list::const_iterator i; - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( (*i)->sWord.getString() == NULL ) - continue; - - if( !strcmp( (*i)->sWord, arg ) ) - return *i; - - if( (*i)->val.isSet() ) - { - if( !strncmp( (*i)->sWord, arg, (*i)->sWord.getLength() ) && - arg[(*i)->sWord.getLength()] == '=' ) - { - return *i; - } - } - } - - return NULL; -} - -ParamProc::ArgSpec *ParamProc::checkLetr( const char arg ) -{ - //printf("Checking \'%c\'...\n", arg ); - std::list::const_iterator i; - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( (*i)->cChar == '\0' ) - continue; - - if( (*i)->cChar == arg ) - { - return *i; - } - } - - return NULL; -} - -int ParamProc::cmdParam( int argc, char *argv[] ) -{ - printf("Unhandled command parameter \"%s\" found!\n", argv[0] ); - return 0; -} - -int ParamProc::unknownParam( int argc, char *argv[] ) -{ - printf("Unknown parameter \"%s\" found!\n", argv[0] ); - return 0; -} - -int ParamProc::help( int argc, char *argv[] ) -{ - std::list::const_iterator b = lBan.begin(); - std::list::const_iterator i; - int len=0; - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( len < (*i)->sWord.getLength() + (*i)->sExtra.getLength() ) - len = (*i)->sWord.getLength() + (*i)->sExtra.getLength(); - } - char fmt[10]; - sprintf( fmt, "%%-%ds ", len ); - - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( b != lBan.end() ) - { - if( (*b)->pBefore == (*i) ) - { - printf( (*b)->sBanner.getString() ); - b++; - } - } - printf(" "); - if( (*i)->cChar ) - { - if( (*i)->sWord.getString() ) - { - printf("-%c, ", (*i)->cChar ); - } - else - { - printf("-%c ", (*i)->cChar ); - } - } - else - { - printf(" "); - } - if( (*i)->sWord.getString() ) - { - printf("--"); - std::string sTmp = (*i)->sWord.getString(); - if( (*i)->sExtra.getString() ) - sTmp += (*i)->sExtra.getString(); - printf( fmt, sTmp.c_str() ); - } - else - { - printf(" "); - printf(fmt, "" ); - } - printf("%s\n", (*i)->sDesc.getString() ); - } - if( b != lBan.end() ) - { - if( (*b)->pBefore == NULL ) - { - printf( (*b)->sBanner.getString() ); - } - } - - exit( 0 ); -} - -void ParamProc::addHelpBanner( const char *sHelpBanner ) -{ - Banner *pBan = new Banner; - pBan->sBanner = sHelpBanner; - pBan->pBefore = NULL; - lBan.push_back( pBan ); -} - diff --git a/src/old/paramproc.h b/src/old/paramproc.h deleted file mode 100644 index d857193..0000000 --- a/src/old/paramproc.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef PARAM_PROC_H -#define PARAM_PROC_H - -#include -#include -#include -#include "staticstring.h" - -class ParamProc -{ -public: - class ParamPtr - { - public: - ParamPtr(); - ParamPtr( std::string *str ); - ParamPtr( uint64_t *uint64 ); - ParamPtr( uint32_t *uint32 ); - ParamPtr( uint16_t *uint16 ); - ParamPtr( uint8_t *uint8 ); - ParamPtr( int64_t *int64 ); - ParamPtr( int32_t *int32 ); - ParamPtr( int16_t *int16 ); - ParamPtr( int8_t *int8 ); - ParamPtr( float *float32 ); - ParamPtr( double *float64 ); - ParamPtr( long double *float96 ); - ParamPtr( bool *bln ); - - enum - { - vtunset, - vtstr, - vtuint64, - vtuint32, - vtuint16, - vtuint8, - vtint64, - vtint32, - vtint16, - vtint8, - vtfloat32, - vtfloat64, - vtfloat96, - vtbln, - }; - ParamPtr &operator=( ParamPtr &ptr ); - ParamPtr &operator=( const char *str ); - - bool isSet(); - - private: - int type; - union - { - std::string *str; - uint64_t *uint64; - uint32_t *uint32; - uint16_t *uint16; - uint8_t *uint8; - int64_t *int64; - int32_t *int32; - int16_t *int16; - int8_t *int8; - float *float32; - double *float64; - long double *float96; - bool *bln; - } val; - }; - - typedef int (ParamProc::*Proc)( int, char *[] ); - - typedef struct ArgSpec - { - uint8_t nFlags; - StaticString sWord; - char cChar; - Proc proc; - ParamProc::ParamPtr val; - StaticString sExtra; - StaticString sDesc; - StaticString sValue; - } ArgSpec; - -public: - ParamProc(); - virtual ~ParamProc(); - - void addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, char cChar, Proc proc, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, char cChar, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - - void addParam( const char *lpWord, Proc proc, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, Proc proc, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - - void addParam( char cChar, Proc proc, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( char cChar, Proc proc, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( char cChar, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - - void process( int argc, char *argv[] ); - void addHelpBanner( const char *sHelpBanner ); - -private: - ArgSpec *checkWord( const char *arg ); - ArgSpec *checkLetr( const char arg ); - -public: - virtual int cmdParam( int argc, char *argv[] ); - virtual int unknownParam( int argc, char *argv[] ); - virtual int help( int argc, char *argv[] ); - -private: - typedef struct Banner - { - StaticString sBanner; - ArgSpec *pBefore; - } Banner; - std::list lBan; - std::list lArg; -}; - -#define mkproc( cls ) static_cast(&cls) - -#endif diff --git a/src/paramproc.cpp b/src/paramproc.cpp new file mode 100644 index 0000000..34e973e --- /dev/null +++ b/src/paramproc.cpp @@ -0,0 +1,514 @@ +#include "paramproc.h" +#include + +#define ptrtype( iitype, iiname ) \ + Bu::ParamProc::ParamPtr::ParamPtr( iitype *iiname ) : \ + type( vt ##iiname ) { val.iiname = iiname; } + +Bu::ParamProc::ParamPtr::ParamPtr() +{ + val.str = NULL; + type = vtunset; +} + +ptrtype( std::string, str ); +ptrtype( uint64_t, uint64 ); +ptrtype( uint32_t, uint32 ); +ptrtype( uint16_t, uint16 ); +ptrtype( uint8_t, uint8 ); +ptrtype( int64_t, int64 ); +ptrtype( int32_t, int32 ); +ptrtype( int16_t, int16 ); +ptrtype( int8_t, int8 ); +ptrtype( float, float32 ); +ptrtype( double, float64 ); +ptrtype( long double, float96 ); +ptrtype( bool, bln ); + +Bu::ParamProc::ParamPtr &Bu::ParamProc::ParamPtr::operator=( ParamProc::ParamPtr &ptr ) +{ + val = ptr.val; + type = ptr.type; + + return *this; +} + +bool Bu::ParamProc::ParamPtr::isSet() +{ + return type != vtunset; +} + +Bu::ParamProc::ParamPtr &Bu::ParamProc::ParamPtr::operator=( const char *str ) +{ + if( !isSet() ) return *this; + switch( type ) + { + case vtstr: + (*val.str) = str; + break; + + case vtuint64: + (*val.uint64) = strtoull( str, NULL, 10 ); + break; + + case vtuint32: + (*val.uint32) = strtoul( str, NULL, 10 ); + break; + + case vtuint16: + (*val.uint16) = (uint16_t)strtoul( str, NULL, 10 ); + break; + + case vtuint8: + (*val.uint8) = (uint8_t)strtoul( str, NULL, 10 ); + break; + + case vtint64: + (*val.int64) = strtoll( str, NULL, 10 ); + break; + + case vtint32: + (*val.int32) = strtol( str, NULL, 10 ); + break; + + case vtint16: + (*val.int16) = (int16_t)strtol( str, NULL, 10 ); + break; + + case vtint8: + (*val.int8) = (int8_t)strtol( str, NULL, 10 ); + break; + + case vtfloat32: + (*val.float32) = strtof( str, NULL ); + break; + + case vtfloat64: + (*val.float64) = strtod( str, NULL ); + break; + + case vtfloat96: + (*val.float96) = strtold( str, NULL ); + break; + + case vtbln: + if( strcasecmp("yes", str ) == 0 || + strcasecmp("true", str ) == 0 ) + { + (*val.bln) = true; + } + else + { + (*val.bln) = false; + } + break; + } + + return *this; +} + +Bu::ParamProc::ParamProc() +{ +} + +Bu::ParamProc::~ParamProc() +{ + for( std::list::iterator i = lArg.begin(); + i != lArg.end(); i++ ) + { + delete *i; + } + + for( std::list::iterator i = lBan.begin(); + i != lBan.end(); i++ ) + { + delete *i; + } + +} +/* +void Bu::ParamProc::addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val ) +{ + printf("Calling callback...\n"); + val = "Hello there, this is set in the ParamProc"; + (this->*proc)(); +}*/ + +void Bu::ParamProc::addParam( const char *lpWord, char cChar, Proc proc, + ParamPtr val, const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + ArgSpec *as = new ArgSpec; + if( lpWord ) + as->sWord = lpWord; + + as->cChar = cChar; + as->proc = proc; + as->val = val; + if( lpDesc ) + as->sDesc = lpDesc; + if( lpExtra ) + as->sExtra = lpExtra; + if( lpValue ) + as->sValue = lpValue; + + lArg.push_back( as ); + + if( !lBan.empty() ) + { + if( lBan.back()->pBefore == NULL ) + lBan.back()->pBefore = as; + } +} + +void Bu::ParamProc::addParam( const char *lpWord, char cChar, Proc proc, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( const char *lpWord, char cChar, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, cChar, NULL, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( const char *lpWord, Proc proc, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, '\0', proc, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( const char *lpWord, Proc proc, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, '\0', proc, ParamPtr(), lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( const char *lpWord, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, '\0', NULL, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( char cChar, Proc proc, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( NULL, cChar, proc, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( char cChar, Proc proc, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( NULL, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( char cChar, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( NULL, cChar, NULL, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::process( int argc, char *argv[] ) +{ + for( int arg = 1; arg < argc; arg++ ) + { + //printf(":::%d:::%s\n", arg, argv[arg] ); + if( argv[arg][0] == '-' ) + { + if( argv[arg][1] == '-' ) + { + ArgSpec *s = checkWord( argv[arg]+2 ); + if( s ) + { + if( argv[arg][s->sWord.getSize()+2] == '=' ) + { + if( s->val.isSet() ) + { + if( s->sValue.getStr() == NULL ) + { + s->val = argv[arg]+s->sWord.getSize()+3; + } + else + { + s->val = s->sValue.getStr(); + } + } + if( s->proc ) + { + char **tmp = new char*[argc-arg]; + tmp[0] = argv[arg]+s->sWord.getSize()+3; + for( int k = 1; k < argc-arg; k++ ) + tmp[k] = argv[arg+k]; + int ret = (this->*s->proc)( argc-arg, tmp ); + if( ret > 0 ) + { + arg += ret-1; + } + delete tmp; + } + } + else + { + int add = 0; + if( s->val.isSet() ) + { + if( s->sValue.getStr() == NULL ) + { + if( arg+1 >= argc ) + { + return; + } + s->val = argv[arg+1]; + add++; + } + else + { + s->val = s->sValue.getStr(); + } + } + if( s->proc ) + { + int ret = (this->*s->proc)( + argc-arg-1, argv+arg+1 ); + + if( ret > add ) + add = 0; + else + add -= ret; + arg += ret; + } + arg += add; + } + continue; + } + else + { + unknownParam( argc-arg, argv+arg ); + } + } + else + { + for( int chr = 1; argv[arg][chr]; chr++ ) + { + ArgSpec *s = checkLetr( argv[arg][chr] ); + if( s ) + { + if( argv[arg][chr+1] != '\0' ) + { + bool bUsed = false; + if( s->val.isSet() ) + { + if( s->sValue.getStr() == NULL ) + { + s->val = argv[arg]+chr+1; + bUsed = true; + } + else + { + s->val = s->sValue.getStr(); + } + } + if( s->proc ) + { + char **tmp = new char*[argc-arg]; + tmp[0] = argv[arg]+chr+1; + for( int k = 1; k < argc-arg; k++ ) + tmp[k] = argv[arg+k]; + int ret = (this->*s->proc)( argc-arg, tmp ); + if( ret > 0 ) + { + arg += ret - 1; + delete tmp; + break; + } + delete tmp; + } + if( bUsed ) + { + break; + } + } + else + { + bool bUsed = false; + if( s->val.isSet() ) + { + if( s->sValue.getStr() == NULL ) + { + s->val = argv[arg+1]; + bUsed = true; + } + else + { + s->val = s->sValue.getStr(); + } + } + if( s->proc ) + { + int ret = (this->*s->proc)( + argc-arg-1, argv+arg+1 + ); + if( ret > 0 ) + { + arg += ret; + break; + } + } + if( bUsed ) + { + arg++; + break; + } + } + } + else + { + unknownParam( argc-arg, argv+arg ); + } + } + } + } + else + { + cmdParam( argc-arg, argv+arg ); + } + } +} + +Bu::ParamProc::ArgSpec *Bu::ParamProc::checkWord( const char *arg ) +{ + //printf("Checking \"%s\"...\n", arg ); + std::list::const_iterator i; + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( (*i)->sWord.getStr() == NULL ) + continue; + + if( !strcmp( (*i)->sWord.getStr(), arg ) ) + return *i; + + if( (*i)->val.isSet() ) + { + if( !strncmp( (*i)->sWord.getStr(), arg, (*i)->sWord.getSize() ) && + arg[(*i)->sWord.getSize()] == '=' ) + { + return *i; + } + } + } + + return NULL; +} + +Bu::ParamProc::ArgSpec *Bu::ParamProc::checkLetr( const char arg ) +{ + //printf("Checking \'%c\'...\n", arg ); + std::list::const_iterator i; + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( (*i)->cChar == '\0' ) + continue; + + if( (*i)->cChar == arg ) + { + return *i; + } + } + + return NULL; +} + +int Bu::ParamProc::cmdParam( int argc, char *argv[] ) +{ + printf("Unhandled command parameter \"%s\" found!\n", argv[0] ); + return 0; +} + +int Bu::ParamProc::unknownParam( int argc, char *argv[] ) +{ + printf("Unknown parameter \"%s\" found!\n", argv[0] ); + return 0; +} + +int Bu::ParamProc::help( int argc, char *argv[] ) +{ + std::list::const_iterator b = lBan.begin(); + std::list::const_iterator i; + int len=0; + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( len < (*i)->sWord.getSize() + (*i)->sExtra.getSize() ) + len = (*i)->sWord.getSize() + (*i)->sExtra.getSize(); + } + char fmt[10]; + sprintf( fmt, "%%-%ds ", len ); + + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( b != lBan.end() ) + { + if( (*b)->pBefore == (*i) ) + { + printf( (*b)->sBanner.getStr() ); + b++; + } + } + printf(" "); + if( (*i)->cChar ) + { + if( (*i)->sWord.getStr() ) + { + printf("-%c, ", (*i)->cChar ); + } + else + { + printf("-%c ", (*i)->cChar ); + } + } + else + { + printf(" "); + } + if( (*i)->sWord.getStr() ) + { + printf("--"); + std::string sTmp = (*i)->sWord.getStr(); + if( (*i)->sExtra.getStr() ) + sTmp += (*i)->sExtra.getStr(); + printf( fmt, sTmp.c_str() ); + } + else + { + printf(" "); + printf(fmt, "" ); + } + printf("%s\n", (*i)->sDesc.getStr() ); + } + if( b != lBan.end() ) + { + if( (*b)->pBefore == NULL ) + { + printf( (*b)->sBanner.getStr() ); + } + } + + exit( 0 ); +} + +void Bu::ParamProc::addHelpBanner( const char *sHelpBanner ) +{ + Banner *pBan = new Banner; + pBan->sBanner = sHelpBanner; + pBan->pBefore = NULL; + lBan.push_back( pBan ); +} + diff --git a/src/paramproc.h b/src/paramproc.h new file mode 100644 index 0000000..beee4a0 --- /dev/null +++ b/src/paramproc.h @@ -0,0 +1,156 @@ +#ifndef PARAM_PROC_H +#define PARAM_PROC_H + +#include +#include +#include +#include "bu/fstring.h" + +namespace Bu +{ + class ParamProc + { + public: + class ParamPtr + { + public: + ParamPtr(); + ParamPtr( std::string *str ); + ParamPtr( uint64_t *uint64 ); + ParamPtr( uint32_t *uint32 ); + ParamPtr( uint16_t *uint16 ); + ParamPtr( uint8_t *uint8 ); + ParamPtr( int64_t *int64 ); + ParamPtr( int32_t *int32 ); + ParamPtr( int16_t *int16 ); + ParamPtr( int8_t *int8 ); + ParamPtr( float *float32 ); + ParamPtr( double *float64 ); + ParamPtr( long double *float96 ); + ParamPtr( bool *bln ); + + enum + { + vtunset, + vtstr, + vtuint64, + vtuint32, + vtuint16, + vtuint8, + vtint64, + vtint32, + vtint16, + vtint8, + vtfloat32, + vtfloat64, + vtfloat96, + vtbln, + }; + ParamPtr &operator=( ParamPtr &ptr ); + ParamPtr &operator=( const char *str ); + + bool isSet(); + + private: + int type; + union + { + std::string *str; + uint64_t *uint64; + uint32_t *uint32; + uint16_t *uint16; + uint8_t *uint8; + int64_t *int64; + int32_t *int32; + int16_t *int16; + int8_t *int8; + float *float32; + double *float64; + long double *float96; + bool *bln; + } val; + }; + + typedef int (ParamProc::*Proc)( int, char *[] ); + + typedef struct ArgSpec + { + uint8_t nFlags; + Bu::FString sWord; + char cChar; + Proc proc; + ParamProc::ParamPtr val; + Bu::FString sExtra; + Bu::FString sDesc; + Bu::FString sValue; + } ArgSpec; + + public: + ParamProc(); + virtual ~ParamProc(); + + void addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, char cChar, Proc proc, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, char cChar, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + + void addParam( const char *lpWord, Proc proc, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, Proc proc, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + + void addParam( char cChar, Proc proc, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( char cChar, Proc proc, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( char cChar, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + + void process( int argc, char *argv[] ); + void addHelpBanner( const char *sHelpBanner ); + + private: + ArgSpec *checkWord( const char *arg ); + ArgSpec *checkLetr( const char arg ); + + public: + virtual int cmdParam( int argc, char *argv[] ); + virtual int unknownParam( int argc, char *argv[] ); + virtual int help( int argc, char *argv[] ); + + private: + typedef struct Banner + { + Bu::FString sBanner; + ArgSpec *pBefore; + } Banner; + std::list lBan; + std::list lArg; + }; +} + +#define mkproc( cls ) static_cast(&cls) + +#endif diff --git a/src/stream.h b/src/stream.h index 5f586e6..fa0a606 100644 --- a/src/stream.h +++ b/src/stream.h @@ -39,6 +39,9 @@ namespace Bu virtual bool isBlocking() = 0; virtual void setBlocking( bool bBlocking=true ) = 0; + public: // Filters + + private: }; diff --git a/src/tests/bzip2.cpp b/src/tests/bzip2.cpp new file mode 100644 index 0000000..683d3d7 --- /dev/null +++ b/src/tests/bzip2.cpp @@ -0,0 +1,23 @@ +#include "bu/bzip2.h" +#include "bu/file.h" + +int main( int argc, char *argv[] ) +{ + char buf[1024]; + size_t nRead; + + Bu::File f( "test.bz2", "wb" ); + Bu::BZip2 bz2( f ); + + Bu::File fin( argv[1], "rb"); + + for(;;) + { + nRead = fin.read( buf, 1024 ); + if( nRead > 0 ) + bz2.write( buf, nRead ); + if( fin.isEOS() ) + break; + } +} + -- cgit v1.2.3