00001
00002
00003
00004
00005
00006
00007 #ifndef _MIMETIC_CODEC_BASE64_H_
00008 #define _MIMETIC_CODEC_BASE64_H_
00009 #include <mimetic/circular_buffer.h>
00010 #include <mimetic/codec/codec_base.h>
00011 #include <mimetic/codec/codec_chain.h>
00012
00013 namespace mimetic
00014 {
00015
00016
00017 class Base64
00018 {
00019 enum { LF = 0xA, CR = 0xD, NL = '\n' };
00020 enum { default_maxlen = 76 };
00021 enum { eq_sign = 100 };
00022 static const signed char sEncTable[];
00023 static const signed char sDecTable[];
00024 static const int sDecTableSz;
00025 public:
00026 class Encoder; class Decoder;
00027 typedef Encoder encoder_type;
00028 typedef Decoder decoder_type;
00029
00030
00031
00032
00033
00034
00035
00036 class Encoder: public buffered_codec, public chainable_codec<Encoder>
00037 {
00038 enum { pad_idx = 64 };
00039 char_type m_ch[3];
00040 int m_cidx;
00041 int m_pos, m_maxlen;
00042
00043 template<typename OutIt>
00044 inline void writeBuf(OutIt& out)
00045 {
00046 int pad_count = 3 - m_cidx;
00047 m_cidx = 0;
00048 int idx[4];
00049 idx[0] = m_ch[0] >> 2;
00050 switch(pad_count)
00051 {
00052 case 0:
00053 idx[1] = (((m_ch[0] & 3) << 4) | (m_ch[1] >> 4));
00054 idx[2] = ((m_ch[1] & 0xf) << 2) | (m_ch[2] >> 6);
00055 idx[3] = m_ch[2] & 0x3f;
00056 break;
00057 case 1:
00058 idx[1] = (((m_ch[0] & 3) << 4) | (m_ch[1] >> 4));
00059 idx[2] = (m_ch[1] & 0xf) << 2 ;
00060 idx[3] = pad_idx;
00061 break;
00062 case 2:
00063 idx[1] = (m_ch[0] & 3) << 4;
00064 idx[2] = idx[3] = pad_idx;
00065 break;
00066 }
00067 for(int i = 0; i < 4; ++i)
00068 {
00069 *out = sEncTable[ idx[i] ]; ++out;
00070 if(m_maxlen && ++m_pos > m_maxlen)
00071 {
00072 *out = NL; ++out;
00073 m_pos = 1;
00074 }
00075 }
00076 }
00077 public:
00078
00079
00080 double codeSizeMultiplier() const
00081 {
00082 return 1.5;
00083 }
00084
00085 Encoder(int maxlen = default_maxlen)
00086 : m_cidx(0), m_pos(1), m_maxlen(maxlen)
00087 {
00088 }
00089
00090 const char* name() const { return "Base64"; }
00091
00092
00093
00094 template<typename InIt, typename OutIt>
00095 void process(InIt bit, InIt eit, OutIt out)
00096 {
00097 for(; bit != eit; ++bit)
00098 {
00099 m_ch[m_cidx++] = (char_type)*bit;
00100 if(m_cidx < 3)
00101 continue;
00102 writeBuf(out);
00103 }
00104 if(m_cidx > 0)
00105 writeBuf(out);
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 template<typename OutIt>
00121 void process(char_type c, OutIt& out)
00122 {
00123 m_ch[m_cidx++] = c;
00124 if(m_cidx < 3)
00125 return;
00126 writeBuf(out);
00127 }
00128
00129
00130
00131 template<typename OutIt>
00132 void flush(OutIt& out)
00133 {
00134 if(m_cidx > 0)
00135 writeBuf(out);
00136 }
00137 };
00138
00139
00140
00141
00142
00143
00144 class Decoder: public buffered_codec, public chainable_codec<Decoder>
00145 {
00146 int m_cidx;
00147 char_type m_ch[4];
00148
00149 template<typename OutIt>
00150 inline void writeBuf(OutIt& out)
00151 {
00152 if(m_cidx < 4)
00153 {
00154 switch(m_cidx)
00155 {
00156 case 0:
00157 case 1:
00158 return;
00159 case 2:
00160 m_ch[2] = m_ch[3] = eq_sign;
00161 break;
00162 case 3:
00163 m_ch[3] = eq_sign;
00164 break;
00165 }
00166 }
00167 m_cidx = 0;
00168 *out = (m_ch[0] << 2 | ((m_ch[1] >> 4) & 0x3) ); ++out;
00169 if(m_ch[2] == eq_sign) return;
00170 *out = (m_ch[1] << 4 | ((m_ch[2] >> 2) & 0xF) ); ++out;
00171 if(m_ch[3] == eq_sign) return;
00172 *out = (m_ch[2] << 6 | m_ch[3]); ++out;
00173 }
00174 public:
00175
00176 Decoder()
00177 : m_cidx(0)
00178 {
00179 }
00180
00181 const char* name() const { return "Base64"; }
00182
00183
00184
00185
00186 template<typename InIt, typename OutIt>
00187 inline void process(InIt bit, InIt eit, OutIt out)
00188 {
00189 char_type c;
00190
00191 for(; bit != eit; ++bit)
00192 {
00193 c = *bit;
00194 if(c > sDecTableSz || sDecTable[c] == -1)
00195 continue;
00196 m_ch[m_cidx++] = sDecTable[c];
00197 if(m_cidx < 4)
00198 continue;
00199 writeBuf(out);
00200 }
00201 if(m_cidx > 0)
00202 writeBuf(out);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 template<typename OutIt>
00219 void process(char_type c, OutIt& out)
00220 {
00221 if(c > sDecTableSz || sDecTable[c] == -1)
00222 return;
00223 m_ch[m_cidx++] = sDecTable[c];
00224 if(m_cidx < 4)
00225 return;
00226 writeBuf(out);
00227 }
00228
00229
00230
00231 template<typename OutIt>
00232 void flush(OutIt& out)
00233 {
00234 if(m_cidx > 0)
00235 writeBuf(out);
00236 }
00237 };
00238
00239 };
00240
00241 }
00242 #endif
00243