From 469bbcf0701e1eb8a6670c23145b0da87357e178 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 25 Mar 2012 20:00:08 +0000 Subject: Code is all reorganized. We're about ready to release. I should write up a little explenation of the arrangement. --- src/stable/base64.cpp | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 src/stable/base64.cpp (limited to 'src/stable/base64.cpp') diff --git a/src/stable/base64.cpp b/src/stable/base64.cpp new file mode 100644 index 0000000..4d659f0 --- /dev/null +++ b/src/stable/base64.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2007-2011 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/base64.h" + +namespace Bu { subExceptionDef( Base64Exception ) } + +const char Bu::Base64::tblEnc[65] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" +}; + +Bu::Base64::Base64( Bu::Stream &rNext, int iChunkSize ) : + Bu::Filter( rNext ), + iBPos( 0 ), + iBuf( 0 ), + iRPos( 0 ), + iChars( 0 ), + bEosIn( false ), + iTotalIn( 0 ), + iTotalOut( 0 ), + eMode( Nothing ), + iChunkSize( iChunkSize ), + iCurChunk( 0 ) +{ + 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() +{ + iCurChunk = 0; +} + +Bu::size Bu::Base64::stop() +{ + if( eMode == Encode ) + { + 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] = '='; + } + iCurChunk += 4; + if( iChunkSize && iCurChunk >= iChunkSize ) + { + iCurChunk = iCurChunk-iChunkSize; + iTotalOut += rNext.write( outBuf, 4-iCurChunk ); + iTotalOut += rNext.write("\r\n", 2 ); + iTotalOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); + } + else + iTotalOut += rNext.write( outBuf, 4 ); + return iTotalOut; + } + else + { + return iTotalIn; + } +} + +Bu::size Bu::Base64::read( void *pBuf, Bu::size nBytes ) +{ + if( eMode == Encode ) + throw Bu::Base64Exception("Cannot read from an output stream."); + eMode = Decode; + + if( bEosIn == true && iRPos == iChars ) + return 0; + Bu::size sIn = 0; + char buf[4]; + while( sIn < nBytes ) + { + for(; iRPos < iChars && sIn < nBytes; iRPos++, sIn++ ) + { + ((unsigned char *)pBuf)[sIn] = (iBuf>>(8*(2-iRPos)))&0xFF; + } + if( iRPos == iChars ) + { + if( bEosIn == true ) + return sIn; + else + iRPos = 0; + } + else if( sIn == nBytes ) + return sIn; + //if( rNext.read( buf, 4 ) == 0 ) + // return sIn; + for( int j = 0; j < 4; j++ ) + { + if( rNext.read( &buf[j], 1 ) == 0 ) + { + if( rNext.isEos() ) + { + if( iRPos == 0 ) + iRPos = iChars; + bEosIn = true; + if( j != 0 ) + { + throw Base64Exception( + "Premature end of stream detected while " + "decoding Base64 data." + ); + } + } + return sIn; + } + if( buf[j] == ' ' || buf[j] == '\t' || + buf[j] == '\n' || buf[j] == '\r' ) + { + j--; + } + } + iChars = 3; + iBuf = 0; + for( int j = 0; j < 4; j++ ) + { + if( buf[j] == '=' ) + { + iChars--; + bEosIn = true; + } + else + iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6); + //printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) ); + } + } + + return sIn; +} + +Bu::size Bu::Base64::write( const void *pBuf, Bu::size nBytes ) +{ + if( eMode == Decode ) + throw Bu::Base64Exception("Cannot write to an input stream."); + eMode = Encode; + + Bu::size sOut = 0; + char outBuf[4]; + for( Bu::size 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]; + } + iCurChunk += 4; + if( iChunkSize && iCurChunk >= iChunkSize ) + { + iCurChunk = iCurChunk-iChunkSize; + sOut += rNext.write( outBuf, 4-iCurChunk ); + sOut += rNext.write("\r\n", 2 ); + sOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); + } + else + sOut += rNext.write( outBuf, 4 ); + iBPos = iBuf = 0; + } + } + iTotalOut += sOut; + return sOut; +} + +bool Bu::Base64::isOpen() +{ + return true; +} + +bool Bu::Base64::isEos() +{ + if( bEosIn == true && iRPos == iChars ) + return true; + return false; +} + -- cgit v1.2.3