00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
00041
00042
00043
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
00088
00089 double codeSizeMultiplier() const
00090 {
00091 return 1.5;
00092 }
00093
00094 Encoder(int maxlen = default_maxlen)
00095 : m_cidx(0), m_pos(1), m_maxlen(maxlen)
00096 {
00097 }
00098
00099 const char* name() const { return "Base64"; }
00100
00101
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
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
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
00139
00140 template<typename OutIt>
00141 void flush(OutIt& out)
00142 {
00143 if(m_cidx > 0)
00144 writeBuf(out);
00145 }
00146 };
00147
00148
00149
00150
00151
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 {
00163 switch(m_cidx)
00164 {
00165 case 0:
00166 case 1:
00167 return;
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
00185 Decoder()
00186 : m_cidx(0)
00187 {
00188 }
00189
00190 const char* name() const { return "Base64"; }
00191
00192
00193
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;
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
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 template<typename OutIt>
00228 void process(char_type c, OutIt& out)
00229 {
00230 if(c > sDecTableSz || sDecTable[c] == -1)
00231 return;
00232 m_ch[m_cidx++] = sDecTable[c];
00233 if(m_cidx < 4)
00234 return;
00235 writeBuf(out);
00236 }
00237
00238
00239
00240 template<typename OutIt>
00241 void flush(OutIt& out)
00242 {
00243 if(m_cidx > 0)
00244 writeBuf(out);
00245 }
00246 };
00247
00248 };
00249
00250 }
00251 #endif
00252