summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/base64.cpp132
-rw-r--r--src/base64.h45
-rw-r--r--src/file.h4
-rw-r--r--src/tests/base64.cpp45
4 files changed, 225 insertions, 1 deletions
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 @@
1#include "bu/base64.h"
2
3const char Bu::Base64::tblEnc[65] = {
4 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
5};
6
7Bu::Base64::Base64( Bu::Stream &rNext, Mode eMode ) :
8 Bu::Filter( rNext ),
9 iBPos( 0 ),
10 iBuf( 0 ),
11 iTotalIn( 0 ),
12 iTotalOut( 0 ),
13 eMode( eMode )
14{
15 start();
16
17 memset( tblDec, 0, 80 );
18 for( int j = 0; j < 64; j++ )
19 {
20 tblDec[tblEnc[j]-'+'] = j;
21 // printf("'%c' = %d\n", tblEnc[j], j );
22 }
23 /*
24 for( int j = 0; j < 64; j++ )
25 {
26 printf("'%c' = '%c' (%d = %d)\n",
27 tblEnc[j], tblEnc[tblDec[tblEnc[j]-'+']],
28 j, tblDec[tblEnc[j]-'+'] );
29 }*/
30
31 // The following is used to compute the table size for the decoding table.
32 /*
33 char low='A', high='A';
34 for( int j = 0; j < 64; j++ )
35 {
36 if( tblEnc[j] < low )
37 low = tblEnc[j];
38 if( tblEnc[j] > high )
39 high = tblEnc[j];
40 }
41
42 printf("'%c' - '%c' (%d - %d) (%d)\n", low, high, low, high, high-low );
43 */
44}
45
46Bu::Base64::~Base64()
47{
48 stop();
49}
50
51void Bu::Base64::start()
52{
53}
54
55size_t Bu::Base64::stop()
56{
57 if( eMode == Write )
58 {
59 char outBuf[4];
60 int iBUsed = 4-(3-iBPos);
61 if( iBPos == 0 )
62 return iTotalOut;
63 for( int k = 0; k < 4; k++ )
64 {
65 outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f];
66 }
67 for( int k = iBUsed; k < 4; k++ )
68 {
69 outBuf[k] = '=';
70 }
71 iTotalOut += rNext.write( outBuf, 4 );
72 return iTotalOut;
73 }
74 else
75 {
76 return iTotalIn;
77 }
78}
79
80size_t Bu::Base64::read( void *pBuf, size_t nBytes )
81{
82 size_t sIn = 0;
83 char buf[4];
84 while( sIn < nBytes )
85 {
86 if( rNext.read( buf, 4 ) == 0 )
87 return sIn;
88 int iChars = 3;
89 for( int j = 0; j < 4; j++ )
90 {
91 if( buf[j] == '=' )
92 iChars--;
93 else
94 iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6);
95 printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) );
96 }
97 for( int j = 0; j < iChars; j++ )
98 {
99 ((unsigned char *)pBuf)[sIn++] = (iBuf>>(8*(2-j)))&0xFF;
100 }
101 iBuf = 0;
102 }
103
104 return sIn;
105}
106
107size_t Bu::Base64::write( const void *pBuf, size_t nBytes )
108{
109 size_t sOut = 0;
110 char outBuf[4];
111 for( size_t j = 0; j < nBytes; j++ )
112 {
113 iBuf |= (((uint8_t *)pBuf)[j])<<((2-iBPos++)*8);
114 if( iBPos == 3 )
115 {
116 for( int k = 0; k < 4; k++ )
117 {
118 outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f];
119 }
120 sOut += rNext.write( outBuf, 4 );
121 iBPos = iBuf = 0;
122 }
123 }
124 iTotalOut += sOut;
125 return sOut;
126}
127
128bool Bu::Base64::isOpen()
129{
130 return true;
131}
132
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 @@
1#ifndef BU_BASE64_H
2#define BU_BASE64_H
3
4#include "bu/filter.h"
5
6namespace Bu
7{
8 /**
9 *
10 *@ingroup Streams
11 */
12 class Base64 : public Bu::Filter
13 {
14 public:
15 enum Mode
16 {
17 Encode = 0x01,
18 Read = 0x01,
19 Decode = 0x02,
20 Write = 0x02
21 };
22
23 public:
24 Base64( Bu::Stream &rNext, Mode eMode );
25 virtual ~Base64();
26
27 virtual void start();
28 virtual size_t stop();
29 virtual size_t read( void *pBuf, size_t nBytes );
30 virtual size_t write( const void *pBuf, size_t nBytes );
31
32 virtual bool isOpen();
33
34 private:
35 int iBPos;
36 int iBuf;
37 size_t iTotalIn;
38 size_t iTotalOut;
39 static const char tblEnc[65];
40 char tblDec[80];
41 Mode eMode;
42 };
43};
44
45#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
65 Exclusive = 0x44, ///< Create file, if it exists then fail 65 Exclusive = 0x44, ///< Create file, if it exists then fail
66 66
67 // Helpful mixes 67 // Helpful mixes
68 ReadWrite = 0x03 ///< Open for reading and writing 68 ReadWrite = 0x03, ///< Open for reading and writing
69 WriteNew = 0x0E ///< Create a file (or truncate) for writing.
70 /// Same as Write|Create|Truncate
69 }; 71 };
70 /** 72 /**
71 * Create a temp file and return its handle. The file is opened 73 * 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 @@
1#include "bu/file.h"
2#include "bu/base64.h"
3
4int main( int argc, char *argv[] )
5{
6 argc--,argv++;
7
8 if( argc < 3 )
9 return 0;
10
11 if( argv[0][0] == 'e' )
12 {
13 argv++;
14 Bu::File fIn( argv[0], Bu::File::Read );
15 Bu::File fOut( argv[1], Bu::File::WriteNew );
16 Bu::Base64 bOut( fOut, Bu::Base64::Write );
17
18 char buf[900];
19 for(;;)
20 {
21 int iRead = fIn.read( buf, 900 );
22 bOut.write( buf, iRead );
23 if( iRead < 900 )
24 break;
25 }
26 }
27 else if( argv[0][0] == 'd' )
28 {
29 argv++;
30 Bu::File fIn( argv[0], Bu::File::Read );
31 Bu::File fOut( argv[1], Bu::File::WriteNew );
32 Bu::Base64 bIn( fIn, Bu::Base64::Read );
33
34 char buf[900];
35 for(;;)
36 {
37 int iRead = bIn.read( buf, 900 );
38 fOut.write( buf, iRead );
39 if( iRead < 900 )
40 break;
41 }
42 }
43
44 return 0;
45}