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 Mon Nov 23 08:01:43 2009 for MIPP(E907) by  doxygen 1.4.7