Main Page   Class Hierarchy   Alphabetical List   Compound List   Examples  

base64.h

00001 /***************************************************************************
00002     copyright            : (C) 2002-2005 by Stefano Barbato
00003     email                : [email protected]
00004 
00005     $Id: base64_8h-source.html,v 1.4 2006-03-12 12:28:31 tat Exp $
00006  ***************************************************************************/
00007 
00008 /***************************************************************************
00009  *                                                                         *
00010  *   This program is free software; you can redistribute it and/or modify  *
00011  *   it under the terms of the GNU General Public License as published by  *
00012  *   the Free Software Foundation; either version 2 of the License, or     *
00013  *   (at your option) any later version.                                   *
00014  *                                                                         *
00015  ***************************************************************************/
00016 #ifndef _MIMETIC_CODEC_BASE64_H_
00017 #define _MIMETIC_CODEC_BASE64_H_
00018 #include <mimetic/circular_buffer.h>
00019 #include <mimetic/codec/codec_base.h>
00020 #include <mimetic/codec/codec_chain.h>
00021 
00022 namespace mimetic
00023 {
00024 
00025 
00026 class Base64
00027 {
00028     enum { LF = 0xA, CR = 0xD, NL = '\n' };
00029     enum { default_maxlen = 76 };
00030     enum { eq_sign = 100 };
00031     static const char sEncTable[];
00032     static const char sDecTable[];
00033     static const int sDecTableSz;
00034 public:
00035     class Encoder; class Decoder;
00036     typedef Encoder encoder_type;
00037     typedef Decoder decoder_type;
00038 
00039 
00040 /// Base64 encoder
00041 /*!
00042 
00043  \sa encode decode
00044  */
00045 class Encoder: public buffered_codec, public chainable_codec<Encoder>
00046 {
00047     enum { pad_idx = 64 };
00048     char_type m_ch[3];
00049     int m_cidx;
00050     int m_pos, m_maxlen;
00051 
00052     template<typename OutIt>
00053     inline void writeBuf(OutIt& out)
00054     {
00055         int pad_count = 3 - m_cidx;
00056         m_cidx = 0;    
00057         int idx[4];
00058         idx[0] = m_ch[0] >> 2;
00059         switch(pad_count)
00060         {
00061         case 0:
00062             idx[1] = (((m_ch[0] & 3) << 4) |  (m_ch[1] >> 4));
00063             idx[2] = ((m_ch[1] & 0xf) << 2) | (m_ch[2] >> 6);
00064             idx[3] = m_ch[2] & 0x3f;
00065             break;
00066         case 1:
00067             idx[1] = (((m_ch[0] & 3) << 4) |  (m_ch[1] >> 4));
00068             idx[2] = (m_ch[1] & 0xf) << 2 ;
00069             idx[3] = pad_idx;
00070             break;
00071         case 2:
00072             idx[1] = (m_ch[0] & 3) << 4;
00073             idx[2] = idx[3] = pad_idx;
00074             break;
00075         }
00076         for(int i = 0; i < 4; ++i)
00077         {
00078             *out = sEncTable[ idx[i] ]; ++out;
00079             if(m_maxlen && ++m_pos > m_maxlen)
00080             {
00081                 *out = NL; ++out;
00082                 m_pos = 1;
00083             }
00084         }
00085     }
00086 public:
00087     /*! return the multiplier of the required (max) size of the output buffer 
00088      * when encoding */
00089     double codeSizeMultiplier() const
00090     {
00091         return 1.5;
00092     }
00093     /*! Constructor, maxlen is the maximum length of every encoded line */
00094     Encoder(int maxlen = default_maxlen)
00095     : m_cidx(0), m_pos(1), m_maxlen(maxlen)
00096     {
00097     }
00098     /*! Returns the name of the codec ("Base64") */
00099     const char* name() const { return "Base64"; }
00100     /*! 
00101      Encodes [\p bit,\p eit) and write any encoded char to \p out.
00102      */
00103     template<typename InIt, typename OutIt>
00104     void process(InIt bit, InIt eit, OutIt out)
00105     {
00106         for(; bit != eit; ++bit)
00107         {
00108             m_ch[m_cidx++] = (char_type)*bit; 
00109             if(m_cidx < 3)
00110                 continue;
00111             writeBuf(out);
00112         } 
00113         if(m_cidx > 0)
00114             writeBuf(out);
00115     }
00116     /*! 
00117      Encodes \p c and write any encoded output char to \p out.
00118      \warning You must call flush() when all chars have been 
00119      processed by the encode funcion.
00120      \n
00121      \code
00122         while( (c = getchar()) != EOF )
00123             b64.encode(c, out);    
00124         b64.flush();
00125      \endcode
00126      \n
00127      \sa flush()
00128      */
00129     template<typename OutIt>
00130     void process(char_type c, OutIt& out)
00131     {
00132         m_ch[m_cidx++] = c;
00133         if(m_cidx < 3)
00134             return;
00135         writeBuf(out);
00136     }
00137     /*!
00138     Write to \p out any buffered encoded char.
00139      */
00140     template<typename OutIt>
00141     void flush(OutIt& out)
00142     {
00143         if(m_cidx > 0)
00144             writeBuf(out);
00145     }
00146 };
00147 
00148 /// Base64 decoder
00149 /*!
00150 
00151  \sa encode decode
00152  */
00153 class Decoder: public buffered_codec, public chainable_codec<Decoder>
00154 {
00155     int m_cidx;
00156     char_type m_ch[4];
00157 
00158     template<typename OutIt>
00159     inline void writeBuf(OutIt& out)
00160     {
00161         if(m_cidx < 4)
00162         {  // malformed, missing chars will be cosidered pad 
00163             switch(m_cidx)
00164             {
00165             case 0:
00166             case 1:
00167                 return; // ignore;
00168             case 2:
00169                 m_ch[2] = m_ch[3] = eq_sign;
00170                 break;
00171             case 3:
00172                 m_ch[3] = eq_sign;
00173                 break;
00174             }
00175         }
00176         m_cidx = 0;    
00177         *out = (m_ch[0] << 2 | ((m_ch[1] >> 4) & 0x3) ); ++out;
00178         if(m_ch[2] == eq_sign) return;
00179         *out = (m_ch[1] << 4 | ((m_ch[2] >> 2) & 0xF) ); ++out;
00180         if(m_ch[3] == eq_sign) return;
00181         *out = (m_ch[2] << 6 | m_ch[3]); ++out;
00182     }
00183 public:
00184     /*! Constructor */
00185     Decoder()
00186     : m_cidx(0)
00187     {
00188     }
00189     /*! Returns the name of the codec ("Base64") */
00190     const char* name() const { return "Base64"; }
00191 
00192     /*! 
00193      Decodes [\p bit,\p eit) and write any decoded char to \p out.
00194      */
00195     template<typename InIt, typename OutIt>
00196     inline void process(InIt bit, InIt eit, OutIt out)
00197     {
00198         char_type c;
00199 
00200         for(; bit != eit; ++bit)
00201         {
00202             c = *bit; 
00203             if(c > sDecTableSz || sDecTable[c] == -1)
00204                 continue; // malformed or newline
00205             m_ch[m_cidx++] = sDecTable[c]; 
00206             if(m_cidx < 4)
00207                 continue;
00208             writeBuf(out);
00209         } 
00210         if(m_cidx > 0)
00211             writeBuf(out);
00212     }
00213     /*! 
00214      Decodes \p c and write any decoded output char to \p out.
00215      
00216      \warning You must call flush() when all chars have been 
00217      processed by the decode funcion.
00218      \n
00219      \code
00220         while( (c = getchar()) != EOF )
00221             b64.decode(c, out);    
00222         b64.flush();
00223      \endcode
00224      \n
00225      \sa flush()
00226      */
00227     template<typename OutIt>
00228     void process(char_type c, OutIt& out)
00229     {
00230         if(c > sDecTableSz || sDecTable[c] == -1)
00231             return; // malformed or newline
00232         m_ch[m_cidx++] = sDecTable[c];
00233         if(m_cidx < 4)
00234             return;
00235         writeBuf(out);
00236     }
00237     /*!
00238     Write to \p out any buffered decoded char.
00239      */
00240     template<typename OutIt>
00241     void flush(OutIt& out)
00242     {
00243         if(m_cidx > 0)
00244             writeBuf(out);
00245     }
00246 };
00247 
00248 }; // Base64
00249 
00250 }
00251 #endif
00252