template
class BaseMod
{
public:
    const static
unsigned char decStop = 255u;
    const static
unsigned char decSkip = 254u;
    const
unsigned char* const encstr;
   
private:
 const char* m_err;
protected:
    unsigned
char m_dectab[256];
 void clearError(void){ m_err = 0u; }
 void setError(const char* err){ m_err = err;
}
public:
   
   
BaseMod(const char* encodeStr):
encstr(reinterpret_cast(encodeStr)), m_err(0u) {
       
for(int i=0; i!= 256; ++i) m_dectab[i] = decStop; //基类构造函数先执行
       
for(const char* p = " \t\r\n"; *p; ++p) m_dectab[*p] =
decSkip;//设置解码时,错过空白字符
       
    }
    const char*
error(void){ return m_err; }
 virtual int getEncodeLen(const int
nEncByteCount)=0;
 
   
//编码接口,完成后生成一个编码串(尾部添加空字符),返回串长
   
//此接口除非传入非法参数,否则不可能错误,所以无捡错机制
    virtual int
encode(const char* in, const int inLen, Char* out) =
0;     
   
//解码接口,输入是以base16或base64格式的编码串,返回解码之后的字节数。成功执行返回>0
   
//解码字符之间可以存在空白字符,但不可存在非编码字符,它的有效字符总数应是2或4的整数倍,否则函数将会设置一个错误
   
//调用此函数之后,应调用接口,if(!getError()) 捡查是否成功执行
    virtual int
decode(const Char* in, const int inLen, char* out) = 0;
   
~BaseMod(void){
        
//static_assert(sizeof(uint16) == 2, "uint16 not is 4 byte");
        
//static_assert(sizeof(uint32) == 4, "uint32 not is 4 byte");
       
//基于本模块的字符类型必须只占1或2字节的内存
       
static_assert( sizeof(Char) == 1 || sizeof(Char) == 2 , "Char type
only can is one byte or two byte");
    }
};
 
template class Base16: public BaseMod
{
public:
    Base16(const
bool xiao = true): BaseMod( xiao ? 
"0123456789abcdef" : "0123456789ABCDEF"){
       
for(int i=0; i!= 16; ++i) m_dectab[encstr[i]] = i;
    }
 int getEncodeLen(const int nEncByteCount){
return nEncByteCount*2; }
    int
encode(const char* in, const int inLen, Char* out){
       
int i = 0;
       
for(const unsigned char* p = reinterpret_cast(in); i
         
*out++ = encstr[p[i] >> 4];
         
*out++ = encstr[(p[i] & 0x0f)];
       
}
       
*out = 0;
       
return i*2;
    }
    //
    int
decode(const Char* in, const int inLen, char* out){
       
int i=0, o = 0;
       
unsigned char n = 0;
       
unsigned char* p = reinterpret_cast(out);
       
clearError();
       
for(; i
           
if(in[i] > decStop) { setError("illegal encode
char.");  break; }
           
n = m_dectab[in[i]];
           
if(decStop == n) { setError("illegal encode
char.");  break; }
           
if(decSkip == n) continue;
           
if(0 == o){
           
*p = n << 4;
              
o = 1;
           
}else{
             
*p = *p | n;
             
o = 0;  ++p;
           
}           
       
}
       
if(1==o)if(!error()) setError("this encode string size not is
Multiple of 2");
       
return p - reinterpret_cast(out);
    }
};
 
 
 
 
template class Base64: public BaseMod
{
public:
   
Base64(void): BaseMod(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
){
       
for(int i=0; i!= 64; ++i) m_dectab[encstr[i]] = i;
    }
 int getEncodeLen(const int
nEncByteCount){
  int group = nEncByteCount /
3;
  int mod = nEncByteCount %
3;
  return (group * 4) + (mod ? 4 :
0);
 }
    int
encode(const char* in, const int inLen, Char* out){
       
int i = inLen;
       
Char* const outbeg = out;
       
const unsigned char* p = reinterpret_cast(in);
 //开始编码,输入每3字节为一分组(p组),输出每4字节为一分组(o组),
方括号内位运算的结果是编码索引(假定名为t,不大于63)
 for(; i>2; i -= 3)
 {
 out[0] = encstr[ p[0] >>
2                  
];//取p组首字节高6位放入t的低六位,据t值在表中找到对应字符,将该字符放入o组首字节
 out[1] = encstr[ ((p[0]&3u)<<4) |
(p[1]>>4) 
];//取p组首字节低2位放入t的6至5位,取p组第2字节高4位放入t的低4位,
 out[2] = encstr[ ((p[1]&15u)<<2) |
(p[2]>>6) ];//取p组第2字节低4位放入t的6至3位,取p组第3字节高2位放入t的低2位,
 out[3] = encstr[ p[2] &
63u                 
];//取p组第3字节低6位放入t的低6位,
 out += 4;  p += 3;
 }
 if(i==2)
 {
 out[0] = encstr[ p[0] >>
2                  
];
 out[1] = encstr[ ((p[0]&3u)<<4) |
(p[1]>>4)  ];
 out[2] = encstr[
((p[1]&15u)<<2)            
];
 out[3] =
'=';     
out += 4;
 }else if(i==1)
 {
 out[0] = encstr[ p[0] >>
2                  
];
 out[1] = encstr[
((p[0]&3u)<<4)             
];
 out[2] = '=';
 out[3] =
'=';     
out += 4;
 }
       
*out = '\0';
       
return out - outbeg;
    }
    //
    int
decode(const Char* in, const int inLen, char* out){
       
int i=0, groupIndex = 0;
       
unsigned char n=0;
       
unsigned char* p = reinterpret_cast(out);
       
clearError();
       
for(; i
           
if(in[i] > decStop) break;
           
n = m_dectab[in[i]];
           
if(decStop == n)  break;
           
if(decSkip == n) continue;
           
p[groupIndex] = n;
           
if(3 == groupIndex){
               
p[0] = (p[0] << 2) | (p[1] >> 4);
               
p[1] = (p[1] << 4) | (p[2] >> 2);
               
p[2] = ((p[2] & 3u) << 6) | p[3];
               
groupIndex = 0;  p += 3;
           
}else
++groupIndex;          
       
}
       
if(i < inLen){
          
if('=' == in[i])
          
{
             
p[0] = (p[0] << 2) | (p[1] >> 4);