Base64编解码:C++
/************************************************************
*
* Base64编解码
*
*************************************************************/
static const char s_achBase64Table[] =
{
'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',
'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',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '='
};
static char GetCharByIndex(unsigned char byIndex)
{
return s_achBase64Table[byIndex];
}
static unsigned char GetIndexByChar(char ch)
{
if (ch >= 'A' && ch <= 'Z')
{
return (unsigned char)(ch - 'A');
}
else if (ch >= 'a' && ch <= 'z')
{
return (unsigned char)(ch - 'a') + 26;
}
else if (ch >= '0' && ch <= '9')
{
return (unsigned char)(ch - '0') + 52;
}
if (ch == '+')
{
return 61;
}
if (ch == '/')
{
return 62;
}
if (ch == '=')
{
return 63;
}
return 0;
}
/*
base64编码说明: 取输入流中连续的3个字节A、B、C作为一组, 步骤如下:
1、首先取A、B、C对应的二进制值拼成24位二进制码
2、以6位为一组,将24位二进制码分4组,每组6位前补00构成1个字节,这样得到4个值在0 ~ 2^6之间的字节,
3、这四个字节的十进制值作为数组索引,查表得到s_base64_table中对应的字符,得到的四个字符即3字节输入的编码输出
note:
如果余下一个字 符,前6个bit转换成一个Base64字符,剩下的低2位右边补0构成6bit, 然后转换成Base64,
在输出缓冲的最后补上两个'='。
如果余下两个字符,前12个bit转换成两个Base64字符后,剩下4个bit右边补0凑成6bit,然后转换成Base64,
在输出缓冲末尾要补上一个'=' 。
*/
int Base64Encode(const char *pchStrIn, char *pchOut, unsigned int dwLen, unsigned int &dwOutLen)
{
int nSrcLen = strlen(pchStrIn);
if (nSrcLen == 0 || NULL == pchOut)
{
return -1;
}
int nRoundCount = nSrcLen / 3;
int nLeft = nSrcLen % 3;
dwOutLen = nRoundCount * 4;
if (nLeft != 0)
{
dwOutLen += 4;
}
if (dwLen < dwOutLen)
{
return -1;
}
char *pchTmp = pchOut;
for (int i = 0; i < nRoundCount; i++)
{
unsigned int dwOffset = i * 3;
//00XXXXXX 00XXxxxx 00xxxxXX 00XXXXXX
unsigned char byA = pchStrIn[dwOffset];
unsigned char byB = pchStrIn[dwOffset + 1];
unsigned char byC = pchStrIn[dwOffset + 2];
pchTmp[0] = GetCharByIndex( byA >> 2 );
pchTmp[1] = GetCharByIndex( (byA & 0x03) << 4 | byB >> 4 );
pchTmp[2] = GetCharByIndex( (byB & 0x0f) << 2 | byC >> 6 );
pchTmp[3] = GetCharByIndex( byC & 0x3f );
pchTmp += 4;
}
if (nLeft == 1)
{
unsigned int dwOffset = nRoundCount * 3;
unsigned char byA = pchStrIn[dwOffset];
pchTmp[0] = GetCharByIndex(byA >> 2);
pchTmp[1] = GetCharByIndex((byA & 0x03) << 4);
pchTmp[2] = '=';
pchTmp[3] = '=';
}
else if (nLeft == 2)
{
unsigned int dwOffset = nRoundCount * 3;
unsigned char byA = pchStrIn[dwOffset];
unsigned char byB = pchStrIn[dwOffset + 1];
pchTmp[0] = GetCharByIndex(byA >> 2);
pchTmp[1] = GetCharByIndex((byA & 0x03) << 4 | byB >> 4);
pchTmp[2] = GetCharByIndex((byB & 0x0f) << 2);
pchTmp[3] = '=';
}
return 0;
}
int Base64Decode(const char *pchStrIn, char *pchOut, unsigned int dwLen, unsigned int &dwOutLen)
{
int nSrcLen = strlen(pchStrIn);
if (0 == nSrcLen || NULL == pchOut)
{
return -1;
}
dwOutLen = nSrcLen * 3 / 4;
int nLeft = 0;
int nRoundCount = nSrcLen / 4;
if (pchStrIn[nSrcLen - 1] == '=')
{
if (pchStrIn[nSrcLen - 2] == '=')
{
dwOutLen -= 2;
nLeft = 1;
}
else
{
nLeft = 2;
dwOutLen -= 1;
}
nRoundCount--;
}
if (dwOutLen > dwLen)
{
return -1;
}
char *pchTmpOut = pchOut;
for (int i = 0; i < nRoundCount; i++)
{
char *pchTmpIn = (char*)pchStrIn + i * 4;
unsigned char byA = GetIndexByChar(pchTmpIn[0]);
unsigned char byB = GetIndexByChar(pchTmpIn[1]);
unsigned char byC = GetIndexByChar(pchTmpIn[2]);
unsigned char byD = GetIndexByChar(pchTmpIn[3]);
//00XXXXXX 00XXxxxx 00xxxxXX 00XXXXXX
pchTmpOut[0] = (byA << 2) | (byB >> 4);
pchTmpOut[1] = (byB << 4) | (byC & 0x3c) >> 2;
pchTmpOut[2] = (byC << 6) | (byD & 0x3f);
pchTmpOut += 3;
}
if (nLeft == 1)
{
//00xxxxxx 00xx0000
char *pchTmpIn = (char*)pchStrIn + nRoundCount * 4;
unsigned char byA = GetIndexByChar(pchTmpIn[0]);
unsigned char byB = GetIndexByChar(pchTmpIn[1]);
pchTmpOut[0] = (byA << 2) | (byB >> 4);
}
else if (nLeft == 2)
{
//00xxxxxx 00xxXXXX 00XXXX00
char *pchTmpIn = (char*)pchStrIn + nRoundCount * 4;
unsigned char byA = GetIndexByChar(pchTmpIn[0]);
unsigned char byB = GetIndexByChar(pchTmpIn[1]);
unsigned char byC = GetIndexByChar(pchTmpIn[2]);
pchTmpOut[0] = (byA << 2) | (byB >> 4);
pchTmpOut[1] = (byB << 4) | (byC & 0x3c) >> 2;
}
return 0;
}