Home | History | Annotate | Download | only in src
      1 
      2 
      3 //  base64.hpp
      4 //  Autor Konstantin Pilipchuk
      5 //  mailto:lostd (at) 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>
     59 			_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>
     71 			_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>
     83 			_OI operator()(_OI _To) const{
     84 			return (_To);
     85 		}
     86 	};
     87 
     88 	struct three2four
     89 	{
     90 		void zero()
     91 		{
     92 			_data[0] = 0;
     93 			_data[1] = 0;
     94 			_data[2] = 0;
     95 		}
     96 
     97 		byte_t get_0()	const
     98 		{
     99 			return _data[0];
    100 		}
    101 		byte_t get_1()	const
    102 		{
    103 			return _data[1];
    104 		}
    105 		byte_t get_2()	const
    106 		{
    107 			return _data[2];
    108 		}
    109 
    110 		void set_0(byte_t _ch)
    111 		{
    112 			_data[0] = _ch;
    113 		}
    114 
    115 		void set_1(byte_t _ch)
    116 		{
    117 			_data[1] = _ch;
    118 		}
    119 
    120 		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 
    129 		int b64_0()	const	{return (_data[0] & _1111_1100) >> 2;}
    130 		int b64_1()	const	{return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);}
    131 		int b64_2()	const	{return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);}
    132 		int b64_3()	const	{return (_data[2] & _0011_1111);}
    133 
    134 		void b64_0(int _ch)	{_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);}
    135 
    136 		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 
    140 		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 
    144 		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>
    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>
    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 
    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