Dragon  
Dragon
日历
<2010年12月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
统计
  • 随笔 - 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是看不到的)。
posted on 2010-12-14 14:10 Dragon 阅读(1179) 评论(0)  编辑 收藏 引用 所属分类: C++

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


 
Copyright © Dragon Powered by: 博客园 模板提供:沪江博客