$search
00001 00002 00003 // base64.hpp 00004 // Autor Konstantin Pilipchuk 00005 // mailto:lostd@ukr.net 00006 // 00007 // 00008 00009 #if !defined(__BASE64_H_INCLUDED__) 00010 #define __BASE64_H_INCLUDED__ 1 00011 00012 #ifndef MAKEDEPEND 00013 # include <iterator> 00014 #endif 00015 00016 static 00017 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', 00018 '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', 00019 '0','1','2','3','4','5','6','7','8','9', 00020 '+','/' }; 00021 00022 00023 #define _0000_0011 0x03 00024 #define _1111_1100 0xFC 00025 #define _1111_0000 0xF0 00026 #define _0011_0000 0x30 00027 #define _0011_1100 0x3C 00028 #define _0000_1111 0x0F 00029 #define _1100_0000 0xC0 00030 #define _0011_1111 0x3F 00031 00032 #define _EQUAL_CHAR (-1) 00033 #define _UNKNOWN_CHAR (-2) 00034 00035 #define _IOS_FAILBIT std::ios_base::failbit 00036 #define _IOS_EOFBIT std::ios_base::eofbit 00037 #define _IOS_BADBIT std::ios_base::badbit 00038 #define _IOS_GOODBIT std::ios_base::goodbit 00039 00040 // TEMPLATE CLASS base64_put 00041 template<class _E = char, class _Tr = std::char_traits<_E> > 00042 class base64 00043 { 00044 public: 00045 00046 typedef unsigned char byte_t; 00047 typedef _E char_type; 00048 typedef _Tr traits_type; 00049 00050 // base64 requires max line length <= 72 characters 00051 // you can fill end of line 00052 // it may be crlf, crlfsp, noline or other class like it 00053 00054 00055 struct crlf 00056 { 00057 template<class _OI> 00058 _OI operator()(_OI _To) const{ 00059 *_To = _Tr::to_char_type('\r'); ++_To; 00060 *_To = _Tr::to_char_type('\n'); ++_To; 00061 00062 return (_To); 00063 } 00064 }; 00065 00066 00067 struct crlfsp 00068 { 00069 template<class _OI> 00070 _OI operator()(_OI _To) const{ 00071 *_To = _Tr::to_char_type('\r'); ++_To; 00072 *_To = _Tr::to_char_type('\n'); ++_To; 00073 *_To = _Tr::to_char_type(' '); ++_To; 00074 00075 return (_To); 00076 } 00077 }; 00078 00079 struct noline 00080 { 00081 template<class _OI> 00082 _OI operator()(_OI _To) const{ 00083 return (_To); 00084 } 00085 }; 00086 00087 struct three2four 00088 { 00089 void zero() 00090 { 00091 _data[0] = 0; 00092 _data[1] = 0; 00093 _data[2] = 0; 00094 } 00095 00096 byte_t get_0() const 00097 { 00098 return _data[0]; 00099 } 00100 byte_t get_1() const 00101 { 00102 return _data[1]; 00103 } 00104 byte_t get_2() const 00105 { 00106 return _data[2]; 00107 } 00108 00109 void set_0(byte_t _ch) 00110 { 00111 _data[0] = _ch; 00112 } 00113 00114 void set_1(byte_t _ch) 00115 { 00116 _data[1] = _ch; 00117 } 00118 00119 void set_2(byte_t _ch) 00120 { 00121 _data[2] = _ch; 00122 } 00123 00124 // 0000 0000 1111 1111 2222 2222 00125 // xxxx xxxx xxxx xxxx xxxx xxxx 00126 // 0000 0011 1111 2222 2233 3333 00127 00128 int b64_0() const {return (_data[0] & _1111_1100) >> 2;} 00129 int b64_1() const {return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);} 00130 int b64_2() const {return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);} 00131 int b64_3() const {return (_data[2] & _0011_1111);} 00132 00133 void b64_0(int _ch) {_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);} 00134 00135 void b64_1(int _ch) { 00136 _data[0] = ((_ch & _0011_0000) >> 4) | (_1111_1100 & _data[0]); 00137 _data[1] = ((_ch & _0000_1111) << 4) | (_0000_1111 & _data[1]); } 00138 00139 void b64_2(int _ch) { 00140 _data[1] = ((_ch & _0011_1100) >> 2) | (_1111_0000 & _data[1]); 00141 _data[2] = ((_ch & _0000_0011) << 6) | (_0011_1111 & _data[2]); } 00142 00143 void b64_3(int _ch){ 00144 _data[2] = (_ch & _0011_1111) | (_1100_0000 & _data[2]);} 00145 00146 private: 00147 byte_t _data[3]; 00148 00149 }; 00150 00151 00152 00153 00154 template<class _II, class _OI, class _State, class _Endline> 00155 _II put(_II _First, _II _Last, _OI _To, _State&, _Endline) const 00156 { 00157 three2four _3to4; 00158 int line_octets = 0; 00159 00160 while(_First != _Last) 00161 { 00162 _3to4.zero(); 00163 00164 _3to4.set_0(*_First); 00165 _First++; 00166 00167 if(_First == _Last) 00168 { 00169 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; 00170 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; 00171 *_To = _Tr::to_char_type('='); ++_To; 00172 *_To = _Tr::to_char_type('='); ++_To; 00173 goto __end; 00174 } 00175 00176 _3to4.set_1(*_First); 00177 _First++; 00178 00179 if(_First == _Last) 00180 { 00181 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; 00182 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; 00183 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To; 00184 *_To = _Tr::to_char_type('='); ++_To; 00185 goto __end; 00186 } 00187 00188 _3to4.set_2(*_First); 00189 _First++; 00190 00191 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; 00192 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; 00193 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To; 00194 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_3()]); ++_To; 00195 00196 if(line_octets == 17) 00197 { 00198 //_To = _Endl(_To); 00199 *_To = '\n'; ++_To; 00200 line_octets = 0; 00201 } 00202 else 00203 ++line_octets; 00204 } 00205 00206 __end: ; 00207 00208 return (_First); 00209 00210 } 00211 00212 00213 template<class _II, class _OI, class _State> 00214 _II get(_II _First, _II _Last, _OI _To, _State& _St) const 00215 { 00216 three2four _3to4; 00217 int _Char; 00218 00219 while(_First != _Last) 00220 { 00221 00222 // Take octet 00223 _3to4.zero(); 00224 00225 // -- 0 -- 00226 // Search next valid char... 00227 while((_Char = _getCharType(*_First)) < 0 && _Char == _UNKNOWN_CHAR) 00228 { 00229 if(++_First == _Last) 00230 { 00231 _St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF 00232 } 00233 } 00234 00235 if(_Char == _EQUAL_CHAR){ 00236 // Error! First character in octet can't be '=' 00237 _St |= _IOS_FAILBIT; 00238 return _First; 00239 } 00240 else 00241 _3to4.b64_0(_Char); 00242 00243 00244 // -- 1 -- 00245 // Search next valid char... 00246 while(++_First != _Last) 00247 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) 00248 break; 00249 00250 if(_First == _Last) { 00251 _St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF 00252 return _First; 00253 } 00254 00255 if(_Char == _EQUAL_CHAR){ 00256 // Error! Second character in octet can't be '=' 00257 _St |= _IOS_FAILBIT; 00258 return _First; 00259 } 00260 else 00261 _3to4.b64_1(_Char); 00262 00263 00264 // -- 2 -- 00265 // Search next valid char... 00266 while(++_First != _Last) 00267 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) 00268 break; 00269 00270 if(_First == _Last) { 00271 // Error! Unexpected EOF. Must be '=' or base64 character 00272 _St |= _IOS_FAILBIT|_IOS_EOFBIT; 00273 return _First; 00274 } 00275 00276 if(_Char == _EQUAL_CHAR){ 00277 // OK! 00278 _3to4.b64_2(0); 00279 _3to4.b64_3(0); 00280 00281 // chek for EOF 00282 if(++_First == _Last) 00283 { 00284 // Error! Unexpected EOF. Must be '='. Ignore it. 00285 //_St |= _IOS_BADBIT|_IOS_EOFBIT; 00286 _St |= _IOS_EOFBIT; 00287 } 00288 else 00289 if(_getCharType(*_First) != _EQUAL_CHAR) 00290 { 00291 // Error! Must be '='. Ignore it. 00292 //_St |= _IOS_BADBIT; 00293 } 00294 else 00295 ++_First; // Skip '=' 00296 00297 // write 1 byte to output 00298 *_To = (byte_t) _3to4.get_0(); 00299 return _First; 00300 } 00301 else 00302 _3to4.b64_2(_Char); 00303 00304 00305 // -- 3 -- 00306 // Search next valid char... 00307 while(++_First != _Last) 00308 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) 00309 break; 00310 00311 if(_First == _Last) { 00312 // Unexpected EOF. It's error. But ignore it. 00313 //_St |= _IOS_FAILBIT|_IOS_EOFBIT; 00314 _St |= _IOS_EOFBIT; 00315 00316 return _First; 00317 } 00318 00319 if(_Char == _EQUAL_CHAR) 00320 { 00321 // OK! 00322 _3to4.b64_3(0); 00323 00324 // write to output 2 bytes 00325 *_To = (byte_t) _3to4.get_0(); 00326 *_To = (byte_t) _3to4.get_1(); 00327 00328 ++_First; // set position to next character 00329 00330 return _First; 00331 } 00332 else 00333 _3to4.b64_3(_Char); 00334 00335 00336 // write to output 3 bytes 00337 *_To = (byte_t) _3to4.get_0(); 00338 *_To = (byte_t) _3to4.get_1(); 00339 *_To = (byte_t) _3to4.get_2(); 00340 00341 ++_First; 00342 00343 00344 } // while(_First != _Last) 00345 00346 return (_First); 00347 } 00348 00349 protected: 00350 00351 int _getCharType(int _Ch) const 00352 { 00353 if(_base64Chars[62] == _Ch) 00354 return 62; 00355 00356 if(_base64Chars[63] == _Ch) 00357 return 63; 00358 00359 if((_base64Chars[0] <= _Ch) && (_base64Chars[25] >= _Ch)) 00360 return _Ch - _base64Chars[0]; 00361 00362 if((_base64Chars[26] <= _Ch) && (_base64Chars[51] >= _Ch)) 00363 return _Ch - _base64Chars[26] + 26; 00364 00365 if((_base64Chars[52] <= _Ch) && (_base64Chars[61] >= _Ch)) 00366 return _Ch - _base64Chars[52] + 52; 00367 00368 if(_Ch == _Tr::to_int_type('=')) 00369 return _EQUAL_CHAR; 00370 00371 return _UNKNOWN_CHAR; 00372 } 00373 00374 00375 }; 00376 00377 00378 #endif