日历
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|
统计
- 随笔 - 58
- 文章 - 0
- 评论 - 55
- 引用 - 0
导航
常用链接
留言簿(3)
随笔分类(58)
随笔档案(58)
搜索
最新评论

阅读排行榜
评论排行榜
|
 /**//*
*Base64Coder.h
*/
#ifndef BASE64CODER_H
#define BASE64CODER_H

#include <string.h>

#ifdef __BORLANDC__
#define Boolean bool
#define False false
#define True true
#else

typedef unsigned Boolean;
#ifndef False
const Boolean False = 0;
#endif
#ifndef True
const Boolean True = 1;
#endif

#endif

class Base64Coder
  {
public:
Base64Coder();
~Base64Coder();

char* Base64Encode(char const* origSigned, unsigned origLength);
unsigned char* Base64Decode(char* in, unsigned& resultSize,Boolean trimTrailingZeros);

private:
Boolean haveInitedBase64DecodeTable;
void initBase64DecodeTable();
char* strDupSize(char const* str);
char base64DecodeTable[256];
char base64Char[64];
};
#endif
 /**//*
*Base64Coder.cpp
*/
#include "Base64Coder.h"

Base64Coder::Base64Coder()
  {
int i,j=0;
for (i = 'A'; i <= 'Z'; ++i) base64Char[j++] = i;
for (i = 'a'; i <= 'z'; ++i) base64Char[j++] = i;
for (i = '0'; i <= '9'; ++i) base64Char[j++] = i;
base64Char[j++] = '+';
base64Char[j++] = '/';

haveInitedBase64DecodeTable=False;
}

Base64Coder::~Base64Coder()
  {

}

void Base64Coder::initBase64DecodeTable()
  {
int i;
for (i = 0; i < 256; ++i) base64DecodeTable[i] = (char)0x80;
// default value: invalid

for (i = 'A'; i <= 'Z'; ++i) base64DecodeTable[i] = 0 + (i - 'A');
for (i = 'a'; i <= 'z'; ++i) base64DecodeTable[i] = 26 + (i - 'a');
for (i = '0'; i <= '9'; ++i) base64DecodeTable[i] = 52 + (i - '0');
base64DecodeTable[(unsigned char)'+'] = 62;
base64DecodeTable[(unsigned char)'/'] = 63;
base64DecodeTable[(unsigned char)'='] = 0;
}

unsigned char* Base64Coder::Base64Decode(char* in, unsigned& resultSize,Boolean trimTrailingZeros)
  {
 if (!haveInitedBase64DecodeTable) {
initBase64DecodeTable();
haveInitedBase64DecodeTable = True;
}

unsigned char* out = (unsigned char*)strDupSize(in); // ensures we have enough space
int k = 0;
int const jMax = strlen(in) - 3;
// in case "in" is not a multiple of 4 bytes (although it should be)
 for (int j = 0; j < jMax; j += 4) {
char inTmp[4], outTmp[4];
 for (int i = 0; i < 4; ++i) {
inTmp[i] = in[i+j];
outTmp[i] = base64DecodeTable[(unsigned char)inTmp[i]];
if ((outTmp[i]&0x80) != 0) outTmp[i] = 0; // pretend the input was 'A'
}

out[k++] = (outTmp[0]<<2) | (outTmp[1]>>4);
out[k++] = (outTmp[1]<<4) | (outTmp[2]>>2);
out[k++] = (outTmp[2]<<6) | outTmp[3];
}

 if (trimTrailingZeros) {
while (k > 0 && out[k-1] == '\0') --k;
}
resultSize = k;
unsigned char* result = new unsigned char[resultSize];
memmove(result, out, resultSize);
delete[] out;

return result;
}

char* Base64Coder::Base64Encode(char const* origSigned, unsigned origLength)
  {
unsigned char const* orig = (unsigned char const*)origSigned; // in case any input bytes have the MSB set
if (orig == NULL) return NULL;

unsigned const numOrig24BitValues = origLength/3;
Boolean havePadding = origLength > numOrig24BitValues*3;
Boolean havePadding2 = origLength == numOrig24BitValues*3 + 2;
unsigned const numResultBytes = 4*(numOrig24BitValues + havePadding);
char* result = new char[numResultBytes+1]; // allow for trailing '\0'

// Map each full group of 3 input bytes into 4 output base-64 characters:
unsigned i;
 for (i = 0; i < numOrig24BitValues; ++i) {
result[4*i+0] = base64Char[(orig[3*i]>>2)&0x3F];
result[4*i+1] = base64Char[(((orig[3*i]&0x3)<<4) | (orig[3*i+1]>>4))&0x3F];
result[4*i+2] = base64Char[((orig[3*i+1]<<2) | (orig[3*i+2]>>6))&0x3F];
result[4*i+3] = base64Char[orig[3*i+2]&0x3F];
}

// Now, take padding into account. (Note: i == numOrig24BitValues)
 if (havePadding) {
result[4*i+0] = base64Char[(orig[3*i]>>2)&0x3F];
 if (havePadding2) {
result[4*i+1] = base64Char[(((orig[3*i]&0x3)<<4) | (orig[3*i+1]>>4))&0x3F];
result[4*i+2] = base64Char[(orig[3*i+1]<<2)&0x3F];
 } else {
result[4*i+1] = base64Char[((orig[3*i]&0x3)<<4)&0x3F];
result[4*i+2] = '=';
}
result[4*i+3] = '=';
}

result[numResultBytes] = '\0';
return result;
}

char* Base64Coder::strDupSize(char const* str)
  {
if (str == NULL) return NULL;
int len = strlen(str) + 1;
char* copy = new char[len];

return copy;
}
下面是测试程序:
 /**//*
*main.cpp
*/
#include "Base64Coder.h"

#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))

int main(void)
  {
int i;
Base64Coder * p_Base64Coder=new Base64Coder();
 struct test {
unsigned char *data;
char *encoded_ref;
 } tests[] = {
 {(unsigned char*)"", ""},
 {(unsigned char*)"1", "MQ=="},
 {(unsigned char*)"22", "MjI="},
 {(unsigned char*)"333", "MzMz"},
 {(unsigned char*)"4444", "NDQ0NA=="},
 {(unsigned char*)"55555", "NTU1NTU="},
 {(unsigned char*)"666666", "NjY2NjY2"},
 {(unsigned char*)"abc:def", "YWJjOmRlZg=="},
};

printf("Encoding/decoding tests\n");
for (i = 0; i < FF_ARRAY_ELEMS(tests); i++)
 {
unsigned char * res;
unsigned length;
res=p_Base64Coder->Base64Decode(tests[i].encoded_ref,length,True);
if (strcmp((char *)res,(char *)tests[i].data)!=0)
 {
printf("Passed! ");
}
else
 {
printf("Failed! ");
}
for (int j=0;j<length;j++)
 {
printf("%c",res[j]);
}
printf(" Length:%d\n",length);
printf("\n");
}
return 0;
}
开始时不小心,以为ffmpeg的Base64解码不正确,就用了Live555的,后来发现ffmpeg的其实也是正确的。 Live555的Decode函数最后的参数trimTrailingZeros设置成True就和ffmpeg的Base64一样了,意为将尾部的0去掉。 可以将上面测试程序中的True改成False,然后看打印出来的结果就明白了(打印的尾部0是看不到的)。
|