Base64Codec.h
1/*
2 * Copyright (C) 2005 by Marc Boris Duerner
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * As a special exception, you may use this file as part of a free
10 * software library without restriction. Specifically, if other files
11 * instantiate templates or use macros or inline functions from this
12 * file, or you compile this file and link it with other files to
13 * produce an executable, this file does not by itself cause the
14 * resulting executable to be covered by the GNU General Public
15 * License. This exception does not however invalidate any other
16 * reasons why the executable file might be covered by the GNU Library
17 * General Public License.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#ifndef Pt_Base64Codec_h
30#define Pt_Base64Codec_h
31
32#include <Pt/Api.h>
33#include <Pt/Types.h>
34#include <Pt/TextCodec.h>
35
36namespace Pt {
37
61class Base64Codec : public TextCodec<char, char>
62{
63 public:
66 explicit Base64Codec(std::size_t ref = 0)
67 : TextCodec<char, char>(ref)
68 {}
69
72 virtual ~Base64Codec()
73 {}
74
75 protected:
76 // inherit docs
77 result do_in(MBState& s,
78 const char* fromBegin,
79 const char* fromEnd,
80 const char*& fromNext,
81 char* toBegin,
82 char* toEnd,
83 char*& toNext) const;
84
85 // inherit docs
86 result do_out(MBState& s,
87 const char* fromBegin,
88 const char* fromEnd,
89 const char*& fromNext,
90 char* toBegin,
91 char* toEnd,
92 char*& toNext) const;
93
94 // inherit docs
95 result do_unshift(MBState& state,
96 char* toBegin,
97 char* toEnd,
98 char*& toNext) const;
99
100 // inherit docs
101 bool do_always_noconv() const throw()
102 {
103 return false;
104 }
105
106 // inherit docs
107 int do_length(MBState& s, const char* fromBegin,
108 const char* fromEnd, std::size_t max) const
109 {
110 const int from = static_cast<int>( (fromEnd - fromBegin) / 4 );
111 const int to = static_cast<int>( max / 3 );
112 return to > from ? from * 4 : to * 4;
113 }
114
115 // inherit docs
116 int do_encoding() const throw()
117 {
118 // stateful encoding
119 return -1;
120 }
121
122 // inherit docs
123 int do_max_length() const throw()
124 {
125 //worst case: XX== -> x
126 return 4;
127 }
128};
129
131inline char toBase64(uint8_t n)
132{
133 static const char b64enc[]
134 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
135
136 return b64enc[n];
137}
138
140inline uint8_t fromBase64(char b64)
141{
142 static const uint8_t b64dec[]
143 = { 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
144 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
145 255,255,255,255,255,255,255,255,255,255,255,62,255,255,255,63,
146 52,53,54,55,56,57,58,59,60,61,255,255,255,64,255,255,
147 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
148 15,16,17,18,19,20,21,22,23,24,25,255,255,255,255,255,
149 255,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
150 41,42,43,44,45,46,47,48,49,50,51,255,255,255,255,255,
151 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
152 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
153 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
154 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
155 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
156 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
157 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
158 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 };
159
160 return b64dec[(int)b64];
161}
162
163
164inline Base64Codec::result Base64Codec::do_in(MBState& s,
165 const char* fromBegin,
166 const char* fromEnd,
167 const char*& fromNext,
168 char* toBegin,
169 char* toEnd,
170 char*& toNext) const
171{
172 fromNext = fromBegin;
173 toNext = toBegin;
174
175 while( (fromEnd - fromNext) >= 4 && (toEnd - toNext) >= 3 )
176 {
177 Pt::uint8_t first = fromBase64( *(fromNext++) );
178 Pt::uint8_t second = fromBase64( *(fromNext++) );
179 Pt::uint8_t third = fromBase64( *(fromNext++) );
180 Pt::uint8_t fourth = fromBase64( *(fromNext++) );
181
182 *(toNext++) = (first << 2) + (second >> 4);
183
184 if(third != 64)
185 *(toNext++) = (second << 4) + (third >> 2);
186
187 if(fourth != 64)
188 *(toNext++) = (third << 6) + (fourth);
189 }
190
191 if( fromEnd == fromNext )
192 return std::codecvt_base::ok;
193
194 return std::codecvt_base::partial;
195}
196
197
198inline Base64Codec::result Base64Codec::do_out(Pt::MBState& state,
199 const char* fromBegin,
200 const char* fromEnd,
201 const char*& fromNext,
202 char* toBegin,
203 char* toEnd,
204 char*& toNext) const
205{
206 fromNext = fromBegin;
207 toNext = toBegin;
208
209 const char* first = 0;
210 const char* second = 0;
211 const char* third = 0;
212
213 if(fromEnd - fromNext < 1)
214 return std::codecvt_base::partial;
215
216 if(toEnd - toNext < 4)
217 return std::codecvt_base::partial;
218
219 switch( state.n )
220 {
221 case 2:
222 first = &state.value.mbytes[0];
223 second = &state.value.mbytes[1];
224 third = fromNext++;
225 break;
226
227 case 1:
228 if(fromEnd - fromNext < 2)
229 {
230 state.value.mbytes[1] = *fromNext++;
231 state.n = 2;
232 return std::codecvt_base::partial;
233 }
234
235 first = &state.value.mbytes[0];
236 second = fromNext++;
237 third = fromNext++;
238 break;
239
240 default:
241 if(fromEnd - fromNext == 1)
242 {
243 state.value.mbytes[0] = *fromNext++;
244 state.n = 1;
245 return std::codecvt_base::partial;
246 }
247
248 if(fromEnd - fromNext == 2)
249 {
250 state.value.mbytes[0] = *fromNext++;
251 state.value.mbytes[1] = *fromNext++;
252 state.n = 2;
253 return std::codecvt_base::partial;
254 }
255
256 first = fromNext++;
257 second = fromNext++;
258 third = fromNext++;
259 break;
260 }
261
262 while (true)
263 {
264 *toNext++ = toBase64( (uint8_t(*first) >> 2) & 0x3f );
265 *(toNext++) = toBase64( ((uint8_t(*first) << 4) + (uint8_t(*second) >> 4)) & 0x3f );
266 *(toNext++) = toBase64( ((uint8_t(*second) << 2) + (uint8_t(*third) >> 6)) & 0x3f );
267 *(toNext++) = toBase64( uint8_t(*third) & 0x3f );
268
269 if(toEnd - toNext < 4)
270 {
271 state = MBState();
272 return std::codecvt_base::partial;
273 }
274
275 if( fromEnd - fromNext < 3 )
276 break;
277
278 first = fromNext++;
279 second = fromNext++;
280 third = fromNext++;
281 }
282
283 switch( fromEnd - fromNext )
284 {
285 case 2:
286 state.value.mbytes[0] = *fromNext++;
287 state.value.mbytes[1] = *fromNext++;
288 state.n = 2;
289 break;
290
291 case 1:
292 state.value.mbytes[0] = *fromNext++;
293 state.n = 1;
294 break;
295
296 default:
297 state = MBState();
298 break;
299 }
300
301 return std::codecvt_base::ok;
302}
303
304
305inline Base64Codec::result Base64Codec::do_unshift(MBState& state,
306 char* toBegin,
307 char* toEnd,
308 char*& toNext) const
309{
310 toNext = toBegin;
311
312 if(toEnd - toBegin < 4)
313 {
314 return std::codecvt_base::partial;
315 }
316
317 switch(state.n)
318 {
319 case 2:
320 *toNext++ = toBase64( (uint8_t(state.value.mbytes[0]) >> 2) & 0x3f );
321 *(toNext++) = toBase64( ((uint8_t(state.value.mbytes[0]) << 4) + (uint8_t(state.value.mbytes[1]) >> 4)) & 0x3f );
322 *(toNext++) = toBase64( (uint8_t(state.value.mbytes[1]) << 2) & 0x3f );
323 *(toNext++) = '=';
324 break;
325
326 case 1:
327 *toNext++ = toBase64( (uint8_t(state.value.mbytes[0]) >> 2) & 0x3f );
328 *(toNext++) = toBase64( (uint8_t(state.value.mbytes[0]) << 4) & 0x3f );
329 *(toNext++) = '=';
330 *(toNext++) = '=';
331 break;
332
333 case 0:
334 return std::codecvt_base::noconv;
335 }
336
337 state = MBState();
338 return std::codecvt_base::ok;
339}
340
341} //namespace Pt
342
343#endif
virtual ~Base64Codec()
Destructor.
Definition Base64Codec.h:72
Base64Codec(std::size_t ref=0)
Default constructor.
Definition Base64Codec.h:66
TextCodec(std::size_t ref=0)
uint_type uint8_t
Unsigned 8-bit integer type.
Definition Api-Types.h:24
Core module.
Definition Allocator.h:33