可對任意類型數據進行編碼的Base64編解碼源碼

// 測試平臺: 在Win2K下的Cygwin gcc編譯通過,測試沒有發現問題(如果你發現了還請告訴我,謝謝!)
// 調用的庫: strlen() (  其實可以自己寫一個類似的功能函數來取長度的 )

/*
*********************************************************************************************************
*                                         昆明XXXX有限公司
*                                             技術研發部
*
*                                  (c) Copyright 2005-2006, kmajian
*                                        All Rights Reserved
*
*                                       Base-64的編解碼程序文件
*
* File : BASE64.C
* By   : kmajian
* Date : 2006-6-23
*********************************************************************************************************
*/
#include "CONFIG.H"
#include "base64.h"

#define  CH_EMPTY                     0xFF
static const uint8 baseAlp[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
*********************************************************************************************************
*                                              Base64編碼
*
* 函數名稱 : base64enc
* 功能描述 : 把特定內存塊編碼爲Base64編碼, 存入目的字符串
* 調用模塊 : 無
* 參    數 : *sOut      目標字符緩衝區
*            *pIn       需要轉變爲Base64編碼的內存塊
*            iLen       內存塊長度
* 返    回 : uint16     生成編碼的長度
*********************************************************************************************************
*/
uint16 base64enc(void *pIn, uint16 iLen, char * sOut)
{
    uint8 *pBuf = ( uint8 * )pIn;
    uint8 swiBuf[ 4 ];
   
    uint16 i, n;
    uint16 iReturn = 0;
    uint16 iLenM3 = iLen % 3;
    uint16 iLenD3 = iLen / 3;
    uint16 iLenD3p;
   
    if( iLenM3 == 0 )                                 // 如果iLenM3等於0則iLenD3p就爲iLenD3,否則爲(iLenD3+1)
     iLenD3p = iLenD3;
    else
     iLenD3p = iLenD3;
   
    if( iLen < 1 )
    {
      return iReturn;
    }
   
    for( i = 0; i < iLenD3p; i++ )
    {
      swiBuf[ 0 ] = ( *pBuf ) >> 2;                   // 把第一個字符右移2位得到一個個目標字符
      swiBuf[ 1 ] = ( ( *pBuf ) << 4 ) & 0x30;        // 把第一個字符左移四位,然後與0x30相與,
                                                      // 得到第二個目標字符的第5、6位
      pBuf++;
      swiBuf[ 1 ] = swiBuf[ 1 ] + ( ( *pBuf ) >> 4 ); // 把第二個字符右移4位,然後與得到的目標5、6位相加
                                                      // 得到第二個目標字符
      swiBuf[ 2 ] = ( ( *pBuf ) << 2 ) & 0x3C;        // 把第二個字符左移2位,然後與0x3C相與,
                                                      // 得到第二個目標字符的第3、4、5、6位
      pBuf++;
      swiBuf[ 2 ] = swiBuf[ 2 ] + ( ( *pBuf ) >> 6 ); // 把第三個字符右移6位,然後與得到的目標3、4、5、6
                                                      // 位相加,得到第三個目標字符
      swiBuf[ 3 ] = ( *pBuf ) & 0x3F;                 // 第三個字符與0x3F相與,得到第四個目標字符
      pBuf++;
      for( n = 0; n < 4; n++ )                        // 取得需要的Base64編碼
      {
        *sOut = baseAlp[ swiBuf[ n ] ];
        sOut++;
        iReturn++;
      }
    }
    switch( iLenM3 )                                  // 對不足三個字符的編碼處理
    {
      case 1: swiBuf[ 0 ] = ( *pBuf ) >> 2;         
              swiBuf[ 1 ] = ( ( *pBuf ) << 4 ) & 0x30;
              swiBuf[ 2 ] = '=';
              swiBuf[ 3 ] = '=';
              for( n = 0; n < 4; n++ )
              {
                if( swiBuf[ n ] == '=' )
                {
                 *sOut = '=';
                }
                else
                {
                 *sOut = baseAlp[ swiBuf[ n ] ];
                }
                sOut++;
                iReturn++;
              }
              break;
      case 2: swiBuf[ 0 ] = ( *pBuf ) >> 2;         
              swiBuf[ 1 ] = ( ( *pBuf ) << 4 ) & 0x30;
              pBuf++;
              swiBuf[ 1 ] = swiBuf[ 1 ] + ( ( *pBuf ) >> 4 );
              swiBuf[ 2 ] = ( ( *pBuf ) << 2 ) & 0x3C;
              swiBuf[ 3 ] = '=';
              for( n = 0; n < 4; n++ )
              {
                if( swiBuf[ n ] == '=' )
                {
                 *sOut = '=';
                }
                else
                {
                 *sOut = baseAlp[ swiBuf[ n ] ];
                }
                sOut++;
                iReturn++;
              }
              break;
      default:break;
    }
   
    *sOut = '/0';
   
    return iReturn;
}

/*
*********************************************************************************************************
*                                              Base64解碼
*
* 函數名稱 : base64dec
* 功能描述 : 把送入的字符串按Base64方式解碼, 存入目的緩衝區
* 調用模塊 : 無
* 參    數 : *sIn       源字符串
*            *pOut      輸出內存塊
* 返    回 : uint16     解碼後內容的長度
*********************************************************************************************************
*/
uint16 base64dec(const char *sIn, void * const pOut)
{
  uint8 *outBuf = ( uint8 * )pOut;
  uint8 cTemp;
  uint8 cBuf[ 3 ];
  uint16 iReturn = 0;
  uint16 i, n;
  uint16 cLen;
  uint16 aLen;
 
  cLen = strlen( sIn );
  if( ( cLen % 4 ) != 0 )
  {
   return iReturn;
  }
 
  aLen = cLen / 4;
  for( i = 0; i < aLen; i++ )
  {
   cTemp = GetB64Char( *sIn );
   sIn++;
   cBuf[ 0 ] = cTemp << 2;
   cTemp = GetB64Char( *sIn );
   sIn++;
   cBuf[ 0 ] = cBuf[ 0 ] + ( cTemp >> 4 );
   cBuf[ 1 ] = cTemp << 4;
   cTemp = GetB64Char( *sIn );
   sIn++;
   if( cTemp == CH_EMPTY )
   {
    *outBuf = cBuf[ 0 ];
    outBuf++;
    *outBuf = cBuf[ 1 ];
    iReturn = iReturn + 2;
    
    return iReturn;
   }
   else
   {
    cBuf[ 1 ] = cBuf[ 1 ] + ( cTemp >> 2 );
    cBuf[ 2 ] = cTemp << 6;
   }
   cTemp = GetB64Char( *sIn );
   sIn++;
   if( cTemp == CH_EMPTY )
   {
    *outBuf = cBuf[ 0 ];
    outBuf++;
    *outBuf = cBuf[ 1 ];
    outBuf++;
    *outBuf = cBuf[ 2 ];
    iReturn = iReturn + 3;
    
    return iReturn;
   }
   else
   {
    cBuf[ 2 ] = cBuf[ 2 ] + cTemp;
   }
   
   for( n = 0; n < 3; n++ )
   {
    *outBuf = cBuf[ n ];
    outBuf++;
    iReturn++;
   }
  }
   
  return iReturn;
}

// 獲取Base64編碼值
uint8 GetB64Char( const uint8 ch )
{
 uint8 n;
 
 if( ch == '=' )
 {
  return CH_EMPTY;
 }
 else
 {
  for( n = 0; n < strlen( baseAlp ); n++ )
  {
   if( ch == baseAlp[ n ] )
   {
    break;
   }
  }
  
  return n;
 }
}

/*
*********************************************************************************************************
*                                             END
*********************************************************************************************************
*/   

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章