• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 
3 //  base64.hpp
4 //  Autor Konstantin Pilipchuk
5 //  mailto:lostd@ukr.net
6 //
7 //
8 
9 #if !defined(__BASE64_H_INCLUDED__)
10 #define __BASE64_H_INCLUDED__ 1
11 
12 #ifndef MAKEDEPEND
13 # include <iostream>
14 # include <iterator>
15 #endif
16 
17 static
18 int _base64Chars[]= {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
19 				     'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
20 			         '0','1','2','3','4','5','6','7','8','9',
21 			         '+','/' };
22 
23 
24 #define _0000_0011 0x03
25 #define _1111_1100 0xFC
26 #define _1111_0000 0xF0
27 #define _0011_0000 0x30
28 #define _0011_1100 0x3C
29 #define _0000_1111 0x0F
30 #define _1100_0000 0xC0
31 #define _0011_1111 0x3F
32 
33 #define _EQUAL_CHAR   (-1)
34 #define _UNKNOWN_CHAR (-2)
35 
36 #define _IOS_FAILBIT   std::ios_base::failbit
37 #define _IOS_EOFBIT    std::ios_base::eofbit
38 #define _IOS_BADBIT    std::ios_base::badbit
39 #define _IOS_GOODBIT   std::ios_base::goodbit
40 
41 // TEMPLATE CLASS base64_put
42 template<class _E = char, class _Tr = std::char_traits<_E> >
43 class base64
44 {
45 public:
46 
47 	typedef unsigned char byte_t;
48 	typedef _E            char_type;
49 	typedef _Tr           traits_type;
50 
51 	// base64 requires max line length <= 72 characters
52 	// you can fill end of line
53 	// it may be crlf, crlfsp, noline or other class like it
54 
55 
56 	struct crlf
57 	{
58 		template<class _OI>
operatorcrlf59 			_OI operator()(_OI _To) const{
60 			*_To = _Tr::to_char_type('\r'); ++_To;
61 			*_To = _Tr::to_char_type('\n'); ++_To;
62 
63 			return (_To);
64 		}
65 	};
66 
67 
68 	struct crlfsp
69 	{
70 		template<class _OI>
operatorcrlfsp71 			_OI operator()(_OI _To) const{
72 			*_To = _Tr::to_char_type('\r'); ++_To;
73 			*_To = _Tr::to_char_type('\n'); ++_To;
74 			*_To = _Tr::to_char_type(' '); ++_To;
75 
76 			return (_To);
77 		}
78 	};
79 
80 	struct noline
81 	{
82 		template<class _OI>
operatornoline83 			_OI operator()(_OI _To) const{
84 			return (_To);
85 		}
86 	};
87 
88 	struct three2four
89 	{
zerothree2four90 		void zero()
91 		{
92 			_data[0] = 0;
93 			_data[1] = 0;
94 			_data[2] = 0;
95 		}
96 
get_0three2four97 		byte_t get_0()	const
98 		{
99 			return _data[0];
100 		}
get_1three2four101 		byte_t get_1()	const
102 		{
103 			return _data[1];
104 		}
get_2three2four105 		byte_t get_2()	const
106 		{
107 			return _data[2];
108 		}
109 
set_0three2four110 		void set_0(byte_t _ch)
111 		{
112 			_data[0] = _ch;
113 		}
114 
set_1three2four115 		void set_1(byte_t _ch)
116 		{
117 			_data[1] = _ch;
118 		}
119 
set_2three2four120 		void set_2(byte_t _ch)
121 		{
122 			_data[2] = _ch;
123 		}
124 
125 		// 0000 0000  1111 1111  2222 2222
126 		// xxxx xxxx  xxxx xxxx  xxxx xxxx
127 		// 0000 0011  1111 2222  2233 3333
128 
b64_0three2four129 		int b64_0()	const	{return (_data[0] & _1111_1100) >> 2;}
b64_1three2four130 		int b64_1()	const	{return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);}
b64_2three2four131 		int b64_2()	const	{return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);}
b64_3three2four132 		int b64_3()	const	{return (_data[2] & _0011_1111);}
133 
b64_0three2four134 		void b64_0(int _ch)	{_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);}
135 
b64_1three2four136 		void b64_1(int _ch)	{
137 			_data[0] = ((_ch & _0011_0000) >> 4) | (_1111_1100 & _data[0]);
138 			_data[1] = ((_ch & _0000_1111) << 4) | (_0000_1111 & _data[1]);	}
139 
b64_2three2four140 		void b64_2(int _ch)	{
141 			_data[1] = ((_ch & _0011_1100) >> 2) | (_1111_0000 & _data[1]);
142 			_data[2] = ((_ch & _0000_0011) << 6) | (_0011_1111 & _data[2]);	}
143 
b64_3three2four144 		void b64_3(int _ch){
145 			_data[2] = (_ch & _0011_1111) | (_1100_0000 & _data[2]);}
146 
147 	private:
148 		byte_t _data[3];
149 
150 	};
151 
152 
153 
154 
155 	template<class _II, class _OI, class _State, class _Endline>
put(_II _First,_II _Last,_OI _To,_State &,_Endline)156 		_II put(_II _First, _II _Last, _OI _To, _State& /* _St */, _Endline /* _Endl */)  const
157 	{
158 		three2four _3to4;
159 		int line_octets = 0;
160 
161 		while(_First != _Last)
162 		{
163 			_3to4.zero();
164 
165 			// ���� �� 3 �������
166 			_3to4.set_0(*_First);
167 			_First++;
168 
169 			if(_First == _Last)
170 			{
171 				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
172 				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
173 				*_To = _Tr::to_char_type('='); ++_To;
174 				*_To = _Tr::to_char_type('='); ++_To;
175 				goto __end;
176 			}
177 
178 			_3to4.set_1(*_First);
179 			_First++;
180 
181 			if(_First == _Last)
182 			{
183 				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
184 				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
185 				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
186 				*_To = _Tr::to_char_type('='); ++_To;
187 				goto __end;
188 			}
189 
190 			_3to4.set_2(*_First);
191 			_First++;
192 
193 			*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
194 			*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
195 			*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
196 			*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_3()]); ++_To;
197 
198 			if(line_octets == 17) // base64 ��������� ����� ������ �� ����� 72 ��������
199 			{
200 				//_To = _Endl(_To);
201         *_To = '\n'; ++_To;
202 				line_octets = 0;
203 			}
204 			else
205 				++line_octets;
206 		}
207 
208 		__end: ;
209 
210 		return (_First);
211 
212 	}
213 
214 
215 	template<class _II, class _OI, class _State>
get(_II _First,_II _Last,_OI _To,_State & _St)216 		_II get(_II _First, _II _Last, _OI _To, _State& _St) const
217 	{
218 		three2four _3to4;
219 		int _Char;
220 
221 		while(_First != _Last)
222 		{
223 
224 			// Take octet
225 			_3to4.zero();
226 
227 			// -- 0 --
228 			// Search next valid char...
229 			while((_Char =  _getCharType(*_First)) < 0 && _Char == _UNKNOWN_CHAR)
230 			{
231 				if(++_First == _Last)
232 				{
233 					_St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF
234 				}
235 			}
236 
237 			if(_Char == _EQUAL_CHAR){
238 				// Error! First character in octet can't be '='
239 				_St |= _IOS_FAILBIT;
240 				return _First;
241 			}
242 			else
243 				_3to4.b64_0(_Char);
244 
245 
246 			// -- 1 --
247 			// Search next valid char...
248 			while(++_First != _Last)
249 				if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
250 					break;
251 
252 			if(_First == _Last)	{
253 				_St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF
254 				return _First;
255 			}
256 
257 			if(_Char == _EQUAL_CHAR){
258 				// Error! Second character in octet can't be '='
259 				_St |= _IOS_FAILBIT;
260 				return _First;
261 			}
262 			else
263 				_3to4.b64_1(_Char);
264 
265 
266 			// -- 2 --
267 			// Search next valid char...
268 			while(++_First != _Last)
269 				if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
270 					break;
271 
272 			if(_First == _Last)	{
273 				// Error! Unexpected EOF. Must be '=' or base64 character
274 				_St |= _IOS_FAILBIT|_IOS_EOFBIT;
275 				return _First;
276 			}
277 
278 			if(_Char == _EQUAL_CHAR){
279 				// OK!
280 				_3to4.b64_2(0);
281 				_3to4.b64_3(0);
282 
283 				// chek for EOF
284 				if(++_First == _Last)
285 				{
286 					// Error! Unexpected EOF. Must be '='. Ignore it.
287 					//_St |= _IOS_BADBIT|_IOS_EOFBIT;
288 					_St |= _IOS_EOFBIT;
289 				}
290 				else
291 					if(_getCharType(*_First) != _EQUAL_CHAR)
292 					{
293 						// Error! Must be '='. Ignore it.
294 						//_St |= _IOS_BADBIT;
295 					}
296 				else
297 					++_First; // Skip '='
298 
299 				// write 1 byte to output
300 				*_To = (byte_t) _3to4.get_0();
301 				return _First;
302 			}
303 			else
304 				_3to4.b64_2(_Char);
305 
306 
307 			// -- 3 --
308 			// Search next valid char...
309 			while(++_First != _Last)
310 				if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
311 					break;
312 
313 			if(_First == _Last)	{
314 				// Unexpected EOF. It's error. But ignore it.
315 				//_St |= _IOS_FAILBIT|_IOS_EOFBIT;
316 					_St |= _IOS_EOFBIT;
317 
318 				return _First;
319 			}
320 
321 			if(_Char == _EQUAL_CHAR)
322 			{
323 				// OK!
324 				_3to4.b64_3(0);
325 
326 				// write to output 2 bytes
327 				*_To = (byte_t) _3to4.get_0();
328 				*_To = (byte_t) _3to4.get_1();
329 
330 				++_First; // set position to next character
331 
332 				return _First;
333 			}
334 			else
335 				_3to4.b64_3(_Char);
336 
337 
338 			// write to output 3 bytes
339 			*_To = (byte_t) _3to4.get_0();
340 			*_To = (byte_t) _3to4.get_1();
341 			*_To = (byte_t) _3to4.get_2();
342 
343 			++_First;
344 
345 
346 		} // while(_First != _Last)
347 
348 		return (_First);
349 	}
350 
351 protected:
352 
_getCharType(int _Ch)353 	int _getCharType(int _Ch) const
354 	{
355 		if(_base64Chars[62] == _Ch)
356 			return 62;
357 
358 		if(_base64Chars[63] == _Ch)
359 			return 63;
360 
361 		if((_base64Chars[0] <= _Ch) && (_base64Chars[25] >= _Ch))
362 			return _Ch - _base64Chars[0];
363 
364 		if((_base64Chars[26] <= _Ch) && (_base64Chars[51] >= _Ch))
365 			return _Ch - _base64Chars[26] + 26;
366 
367 		if((_base64Chars[52] <= _Ch) && (_base64Chars[61] >= _Ch))
368 			return _Ch - _base64Chars[52] + 52;
369 
370 		if(_Ch == _Tr::to_int_type('='))
371 			return _EQUAL_CHAR;
372 
373 		return _UNKNOWN_CHAR;
374 	}
375 
376 
377 };
378 
379 
380 #endif
381