base64.h

Go to the documentation of this file.
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& _St, _Endline _Endl)  const
00156         {
00157                 three2four _3to4;
00158                 int line_octets = 0;
00159 
00160                 while(_First != _Last)
00161                 {
00162                         _3to4.zero();
00163 
00164                         // берём по 3 символа
00165                         _3to4.set_0(*_First);
00166                         _First++;
00167 
00168                         if(_First == _Last)
00169                         {
00170                                 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
00171                                 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
00172                                 *_To = _Tr::to_char_type('='); ++_To;
00173                                 *_To = _Tr::to_char_type('='); ++_To;
00174                                 goto __end;
00175                         }
00176 
00177                         _3to4.set_1(*_First);
00178                         _First++;
00179 
00180                         if(_First == _Last)
00181                         {
00182                                 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
00183                                 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
00184                                 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
00185                                 *_To = _Tr::to_char_type('='); ++_To;
00186                                 goto __end;
00187                         }
00188 
00189                         _3to4.set_2(*_First);
00190                         _First++;
00191 
00192                         *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
00193                         *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
00194                         *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
00195                         *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_3()]); ++_To;
00196 
00197                         if(line_octets == 17) // base64 позволяет длину строки не более 72 символов
00198                         {
00199                                 //_To = _Endl(_To);
00200         *_To = '\n'; ++_To;
00201                                 line_octets = 0;
00202                         }
00203                         else
00204                                 ++line_octets;
00205                 }
00206 
00207                 __end: ;
00208 
00209                 return (_First);
00210 
00211         }
00212 
00213 
00214         template<class _II, class _OI, class _State>
00215                 _II get(_II _First, _II _Last, _OI _To, _State& _St) const
00216         {
00217                 three2four _3to4;
00218                 int _Char;
00219 
00220                 while(_First != _Last)
00221                 {
00222 
00223                         // Take octet
00224                         _3to4.zero();
00225 
00226                         // -- 0 --
00227                         // Search next valid char... 
00228                         while((_Char =  _getCharType(*_First)) < 0 && _Char == _UNKNOWN_CHAR)
00229                         {
00230                                 if(++_First == _Last)
00231                                 {
00232                                         _St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF
00233                                 }
00234                         }
00235 
00236                         if(_Char == _EQUAL_CHAR){
00237                                 // Error! First character in octet can't be '='
00238                                 _St |= _IOS_FAILBIT; 
00239                                 return _First; 
00240                         }
00241                         else
00242                                 _3to4.b64_0(_Char);
00243 
00244 
00245                         // -- 1 --
00246                         // Search next valid char... 
00247                         while(++_First != _Last)
00248                                 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
00249                                         break;
00250 
00251                         if(_First == _Last)     {
00252                                 _St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF 
00253                                 return _First;
00254                         }
00255 
00256                         if(_Char == _EQUAL_CHAR){
00257                                 // Error! Second character in octet can't be '='
00258                                 _St |= _IOS_FAILBIT; 
00259                                 return _First; 
00260                         }
00261                         else
00262                                 _3to4.b64_1(_Char);
00263 
00264 
00265                         // -- 2 --
00266                         // Search next valid char... 
00267                         while(++_First != _Last)
00268                                 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
00269                                         break;
00270 
00271                         if(_First == _Last)     {
00272                                 // Error! Unexpected EOF. Must be '=' or base64 character
00273                                 _St |= _IOS_FAILBIT|_IOS_EOFBIT; 
00274                                 return _First; 
00275                         }
00276 
00277                         if(_Char == _EQUAL_CHAR){
00278                                 // OK!
00279                                 _3to4.b64_2(0); 
00280                                 _3to4.b64_3(0); 
00281 
00282                                 // chek for EOF
00283                                 if(++_First == _Last)
00284                                 {
00285                                         // Error! Unexpected EOF. Must be '='. Ignore it.
00286                                         //_St |= _IOS_BADBIT|_IOS_EOFBIT;
00287                                         _St |= _IOS_EOFBIT;
00288                                 }
00289                                 else 
00290                                         if(_getCharType(*_First) != _EQUAL_CHAR)
00291                                         {
00292                                                 // Error! Must be '='. Ignore it.
00293                                                 //_St |= _IOS_BADBIT;
00294                                         }
00295                                 else
00296                                         ++_First; // Skip '='
00297 
00298                                 // write 1 byte to output
00299                                 *_To = (byte_t) _3to4.get_0();
00300                                 return _First;
00301                         }
00302                         else
00303                                 _3to4.b64_2(_Char);
00304 
00305 
00306                         // -- 3 --
00307                         // Search next valid char... 
00308                         while(++_First != _Last)
00309                                 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
00310                                         break;
00311 
00312                         if(_First == _Last)     {
00313                                 // Unexpected EOF. It's error. But ignore it.
00314                                 //_St |= _IOS_FAILBIT|_IOS_EOFBIT; 
00315                                         _St |= _IOS_EOFBIT; 
00316                                 
00317                                 return _First; 
00318                         }
00319 
00320                         if(_Char == _EQUAL_CHAR)
00321                         {
00322                                 // OK!
00323                                 _3to4.b64_3(0); 
00324 
00325                                 // write to output 2 bytes
00326                                 *_To = (byte_t) _3to4.get_0();
00327                                 *_To = (byte_t) _3to4.get_1();
00328 
00329                                 ++_First; // set position to next character
00330 
00331                                 return _First;
00332                         }
00333                         else
00334                                 _3to4.b64_3(_Char);
00335 
00336 
00337                         // write to output 3 bytes
00338                         *_To = (byte_t) _3to4.get_0();
00339                         *_To = (byte_t) _3to4.get_1();
00340                         *_To = (byte_t) _3to4.get_2();
00341 
00342                         ++_First;
00343                         
00344 
00345                 } // while(_First != _Last)
00346 
00347                 return (_First);
00348         }
00349 
00350 protected:
00351         
00352         int _getCharType(int _Ch) const
00353         {
00354                 if(_base64Chars[62] == _Ch)
00355                         return 62;
00356 
00357                 if(_base64Chars[63] == _Ch)
00358                         return 63;
00359 
00360                 if((_base64Chars[0] <= _Ch) && (_base64Chars[25] >= _Ch))
00361                         return _Ch - _base64Chars[0];
00362 
00363                 if((_base64Chars[26] <= _Ch) && (_base64Chars[51] >= _Ch))
00364                         return _Ch - _base64Chars[26] + 26;
00365 
00366                 if((_base64Chars[52] <= _Ch) && (_base64Chars[61] >= _Ch))
00367                         return _Ch - _base64Chars[52] + 52;
00368 
00369                 if(_Ch == _Tr::to_int_type('='))
00370                         return _EQUAL_CHAR;
00371 
00372                 return _UNKNOWN_CHAR;
00373         }
00374 
00375 
00376 };
00377 
00378 
00379 #endif
Generated on Wed May 26 16:21:13 2010 for OverSim by  doxygen 1.6.3