aboutsummaryrefslogtreecommitdiff
path: root/src/stable/base64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/base64.cpp')
-rw-r--r--src/stable/base64.cpp219
1 files changed, 219 insertions, 0 deletions
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 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/base64.h"
9
10namespace Bu { subExceptionDef( Base64Exception ) }
11
12const char Bu::Base64::tblEnc[65] = {
13 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
14};
15
16Bu::Base64::Base64( Bu::Stream &rNext, int iChunkSize ) :
17 Bu::Filter( rNext ),
18 iBPos( 0 ),
19 iBuf( 0 ),
20 iRPos( 0 ),
21 iChars( 0 ),
22 bEosIn( false ),
23 iTotalIn( 0 ),
24 iTotalOut( 0 ),
25 eMode( Nothing ),
26 iChunkSize( iChunkSize ),
27 iCurChunk( 0 )
28{
29 start();
30
31 memset( tblDec, 0, 80 );
32 for( int j = 0; j < 64; j++ )
33 {
34 tblDec[tblEnc[j]-'+'] = j;
35 // printf("'%c' = %d\n", tblEnc[j], j );
36 }
37 /*
38 for( int j = 0; j < 64; j++ )
39 {
40 printf("'%c' = '%c' (%d = %d)\n",
41 tblEnc[j], tblEnc[tblDec[tblEnc[j]-'+']],
42 j, tblDec[tblEnc[j]-'+'] );
43 }*/
44
45 // The following is used to compute the table size for the decoding table.
46 /*
47 char low='A', high='A';
48 for( int j = 0; j < 64; j++ )
49 {
50 if( tblEnc[j] < low )
51 low = tblEnc[j];
52 if( tblEnc[j] > high )
53 high = tblEnc[j];
54 }
55
56 printf("'%c' - '%c' (%d - %d) (%d)\n", low, high, low, high, high-low );
57 */
58}
59
60Bu::Base64::~Base64()
61{
62 stop();
63}
64
65void Bu::Base64::start()
66{
67 iCurChunk = 0;
68}
69
70Bu::size Bu::Base64::stop()
71{
72 if( eMode == Encode )
73 {
74 char outBuf[4];
75 int iBUsed = 4-(3-iBPos);
76 if( iBPos == 0 )
77 return iTotalOut;
78 for( int k = 0; k < 4; k++ )
79 {
80 outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f];
81 }
82 for( int k = iBUsed; k < 4; k++ )
83 {
84 outBuf[k] = '=';
85 }
86 iCurChunk += 4;
87 if( iChunkSize && iCurChunk >= iChunkSize )
88 {
89 iCurChunk = iCurChunk-iChunkSize;
90 iTotalOut += rNext.write( outBuf, 4-iCurChunk );
91 iTotalOut += rNext.write("\r\n", 2 );
92 iTotalOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk );
93 }
94 else
95 iTotalOut += rNext.write( outBuf, 4 );
96 return iTotalOut;
97 }
98 else
99 {
100 return iTotalIn;
101 }
102}
103
104Bu::size Bu::Base64::read( void *pBuf, Bu::size nBytes )
105{
106 if( eMode == Encode )
107 throw Bu::Base64Exception("Cannot read from an output stream.");
108 eMode = Decode;
109
110 if( bEosIn == true && iRPos == iChars )
111 return 0;
112 Bu::size sIn = 0;
113 char buf[4];
114 while( sIn < nBytes )
115 {
116 for(; iRPos < iChars && sIn < nBytes; iRPos++, sIn++ )
117 {
118 ((unsigned char *)pBuf)[sIn] = (iBuf>>(8*(2-iRPos)))&0xFF;
119 }
120 if( iRPos == iChars )
121 {
122 if( bEosIn == true )
123 return sIn;
124 else
125 iRPos = 0;
126 }
127 else if( sIn == nBytes )
128 return sIn;
129 //if( rNext.read( buf, 4 ) == 0 )
130 // return sIn;
131 for( int j = 0; j < 4; j++ )
132 {
133 if( rNext.read( &buf[j], 1 ) == 0 )
134 {
135 if( rNext.isEos() )
136 {
137 if( iRPos == 0 )
138 iRPos = iChars;
139 bEosIn = true;
140 if( j != 0 )
141 {
142 throw Base64Exception(
143 "Premature end of stream detected while "
144 "decoding Base64 data."
145 );
146 }
147 }
148 return sIn;
149 }
150 if( buf[j] == ' ' || buf[j] == '\t' ||
151 buf[j] == '\n' || buf[j] == '\r' )
152 {
153 j--;
154 }
155 }
156 iChars = 3;
157 iBuf = 0;
158 for( int j = 0; j < 4; j++ )
159 {
160 if( buf[j] == '=' )
161 {
162 iChars--;
163 bEosIn = true;
164 }
165 else
166 iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6);
167 //printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) );
168 }
169 }
170
171 return sIn;
172}
173
174Bu::size Bu::Base64::write( const void *pBuf, Bu::size nBytes )
175{
176 if( eMode == Decode )
177 throw Bu::Base64Exception("Cannot write to an input stream.");
178 eMode = Encode;
179
180 Bu::size sOut = 0;
181 char outBuf[4];
182 for( Bu::size j = 0; j < nBytes; j++ )
183 {
184 iBuf |= (((uint8_t *)pBuf)[j])<<((2-iBPos++)*8);
185 if( iBPos == 3 )
186 {
187 for( int k = 0; k < 4; k++ )
188 {
189 outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f];
190 }
191 iCurChunk += 4;
192 if( iChunkSize && iCurChunk >= iChunkSize )
193 {
194 iCurChunk = iCurChunk-iChunkSize;
195 sOut += rNext.write( outBuf, 4-iCurChunk );
196 sOut += rNext.write("\r\n", 2 );
197 sOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk );
198 }
199 else
200 sOut += rNext.write( outBuf, 4 );
201 iBPos = iBuf = 0;
202 }
203 }
204 iTotalOut += sOut;
205 return sOut;
206}
207
208bool Bu::Base64::isOpen()
209{
210 return true;
211}
212
213bool Bu::Base64::isEos()
214{
215 if( bEosIn == true && iRPos == iChars )
216 return true;
217 return false;
218}
219