From 158d215b33d5b5bf07f73bb7547aae1fb12593b3 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 18 Jun 2009 19:57:12 +0000 Subject: Added a new enum value to Bu::File, Bu::File::WriteNew which combines Write, Truncate, and Create, the flags used most commonly when writing a new file. Also added the Bu::Base64 filter class, it does base64 encoding and decoding, it may need a couple more interfaces added, but for the most part, it's solid. --- src/base64.cpp | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/base64.h | 45 ++++++++++++++++++ src/file.h | 4 +- src/tests/base64.cpp | 45 ++++++++++++++++++ 4 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 src/base64.cpp create mode 100644 src/base64.h create mode 100644 src/tests/base64.cpp diff --git a/src/base64.cpp b/src/base64.cpp new file mode 100644 index 0000000..723788b --- /dev/null +++ b/src/base64.cpp @@ -0,0 +1,132 @@ +#include "bu/base64.h" + +const char Bu::Base64::tblEnc[65] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" +}; + +Bu::Base64::Base64( Bu::Stream &rNext, Mode eMode ) : + Bu::Filter( rNext ), + iBPos( 0 ), + iBuf( 0 ), + iTotalIn( 0 ), + iTotalOut( 0 ), + eMode( eMode ) +{ + start(); + + memset( tblDec, 0, 80 ); + for( int j = 0; j < 64; j++ ) + { + tblDec[tblEnc[j]-'+'] = j; + // printf("'%c' = %d\n", tblEnc[j], j ); + } + /* + for( int j = 0; j < 64; j++ ) + { + printf("'%c' = '%c' (%d = %d)\n", + tblEnc[j], tblEnc[tblDec[tblEnc[j]-'+']], + j, tblDec[tblEnc[j]-'+'] ); + }*/ + + // The following is used to compute the table size for the decoding table. + /* + char low='A', high='A'; + for( int j = 0; j < 64; j++ ) + { + if( tblEnc[j] < low ) + low = tblEnc[j]; + if( tblEnc[j] > high ) + high = tblEnc[j]; + } + + printf("'%c' - '%c' (%d - %d) (%d)\n", low, high, low, high, high-low ); + */ +} + +Bu::Base64::~Base64() +{ + stop(); +} + +void Bu::Base64::start() +{ +} + +size_t Bu::Base64::stop() +{ + if( eMode == Write ) + { + char outBuf[4]; + int iBUsed = 4-(3-iBPos); + if( iBPos == 0 ) + return iTotalOut; + for( int k = 0; k < 4; k++ ) + { + outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; + } + for( int k = iBUsed; k < 4; k++ ) + { + outBuf[k] = '='; + } + iTotalOut += rNext.write( outBuf, 4 ); + return iTotalOut; + } + else + { + return iTotalIn; + } +} + +size_t Bu::Base64::read( void *pBuf, size_t nBytes ) +{ + size_t sIn = 0; + char buf[4]; + while( sIn < nBytes ) + { + if( rNext.read( buf, 4 ) == 0 ) + return sIn; + int iChars = 3; + for( int j = 0; j < 4; j++ ) + { + if( buf[j] == '=' ) + iChars--; + else + iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6); + printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) ); + } + for( int j = 0; j < iChars; j++ ) + { + ((unsigned char *)pBuf)[sIn++] = (iBuf>>(8*(2-j)))&0xFF; + } + iBuf = 0; + } + + return sIn; +} + +size_t Bu::Base64::write( const void *pBuf, size_t nBytes ) +{ + size_t sOut = 0; + char outBuf[4]; + for( size_t j = 0; j < nBytes; j++ ) + { + iBuf |= (((uint8_t *)pBuf)[j])<<((2-iBPos++)*8); + if( iBPos == 3 ) + { + for( int k = 0; k < 4; k++ ) + { + outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; + } + sOut += rNext.write( outBuf, 4 ); + iBPos = iBuf = 0; + } + } + iTotalOut += sOut; + return sOut; +} + +bool Bu::Base64::isOpen() +{ + return true; +} + diff --git a/src/base64.h b/src/base64.h new file mode 100644 index 0000000..2c3b331 --- /dev/null +++ b/src/base64.h @@ -0,0 +1,45 @@ +#ifndef BU_BASE64_H +#define BU_BASE64_H + +#include "bu/filter.h" + +namespace Bu +{ + /** + * + *@ingroup Streams + */ + class Base64 : public Bu::Filter + { + public: + enum Mode + { + Encode = 0x01, + Read = 0x01, + Decode = 0x02, + Write = 0x02 + }; + + public: + Base64( Bu::Stream &rNext, Mode eMode ); + virtual ~Base64(); + + virtual void start(); + virtual size_t stop(); + virtual size_t read( void *pBuf, size_t nBytes ); + virtual size_t write( const void *pBuf, size_t nBytes ); + + virtual bool isOpen(); + + private: + int iBPos; + int iBuf; + size_t iTotalIn; + size_t iTotalOut; + static const char tblEnc[65]; + char tblDec[80]; + Mode eMode; + }; +}; + +#endif diff --git a/src/file.h b/src/file.h index 84e0691..61addae 100644 --- a/src/file.h +++ b/src/file.h @@ -65,7 +65,9 @@ namespace Bu Exclusive = 0x44, ///< Create file, if it exists then fail // Helpful mixes - ReadWrite = 0x03 ///< Open for reading and writing + ReadWrite = 0x03, ///< Open for reading and writing + WriteNew = 0x0E ///< Create a file (or truncate) for writing. + /// Same as Write|Create|Truncate }; /** * Create a temp file and return its handle. The file is opened diff --git a/src/tests/base64.cpp b/src/tests/base64.cpp new file mode 100644 index 0000000..4f2d68b --- /dev/null +++ b/src/tests/base64.cpp @@ -0,0 +1,45 @@ +#include "bu/file.h" +#include "bu/base64.h" + +int main( int argc, char *argv[] ) +{ + argc--,argv++; + + if( argc < 3 ) + return 0; + + if( argv[0][0] == 'e' ) + { + argv++; + Bu::File fIn( argv[0], Bu::File::Read ); + Bu::File fOut( argv[1], Bu::File::WriteNew ); + Bu::Base64 bOut( fOut, Bu::Base64::Write ); + + char buf[900]; + for(;;) + { + int iRead = fIn.read( buf, 900 ); + bOut.write( buf, iRead ); + if( iRead < 900 ) + break; + } + } + else if( argv[0][0] == 'd' ) + { + argv++; + Bu::File fIn( argv[0], Bu::File::Read ); + Bu::File fOut( argv[1], Bu::File::WriteNew ); + Bu::Base64 bIn( fIn, Bu::Base64::Read ); + + char buf[900]; + for(;;) + { + int iRead = bIn.read( buf, 900 ); + fOut.write( buf, iRead ); + if( iRead < 900 ) + break; + } + } + + return 0; +} -- cgit v1.2.3