程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 關於C++類庫KYLib: 固定緩沖區的壓縮/解壓縮類源碼

關於C++類庫KYLib: 固定緩沖區的壓縮/解壓縮類源碼

編輯:C++入門知識

固定緩沖區的壓縮/解壓縮算法,適用於網絡傳輸數據包的壓縮,具有壓縮速度快、壓縮率適中特點,而且壓縮後數據緩沖區可控。 其中包含固定緩沖區的壓縮類(TKYFixedPack)和解壓縮類(TKYFixedUnpack),源碼如下: [cpp]  // =======================================   // Unit   : 固定緩沖區的壓縮/解壓縮單元   // Version: 3.0.0.0 (build 2012.04.19)   // Author : Kyee Ye   // Email  : kyee_ye(at)126.com   // Copyright (C) Kyee workroom   // =======================================      #ifndef _KYFixedPack_H_   #define _KYFixedPack_H_      #include "KYPackObj.h"      namespace KYLib   {      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      /* TKYFixedPack - 固定緩沖區的壓縮類(基於LZ壓縮算法) */      class TKYFixedPack   {   public:      TKYFixedPack();      virtual ~TKYFixedPack();         // 屬性      char*          Dest() const         { return FDest; }       // default: NULL      Word           Size() const         { return FSize; }       // default: 0      Word           MaxSize() const      { return FMaxSize; }    // default: 0      Longword       DataSize() const     { return FDataSize; }   // default: 0      bool           IsPacking() const    { return FIsPacking; }  // default: false         // 設置壓縮結果緩沖區的最大尺寸      bool           SetMaxSize(Word ASize);         // 重置      void           Reset();         // 壓縮緩沖區      bool           Pack(const char* ABuffer, long ASize, Word AMax = 0xFFFF);      private:      void           DoCopy(const char* ABuffer, long ASize);      bool           DoMatch(Byte* APos, Byte* AEnd, Word& AOffset, Byte& ADepth);      private:      char           FContext[1024];      // 壓縮數據的上下文      Word           FHash[4096];         // 哈希表      char*          FDest;               // 壓縮後的緩沖區      Word           FSize;               // 壓縮後數據尺寸      Word           FMaxSize;            // 緩沖區最大尺寸      Longword       FDataSize;           // 總壓縮數據尺寸      Longword       FLastSize;           // 上一次 pack 結束後的尺寸      Byte           FBitBegin;           // 第一個字節數據開始位      bool           FIsPacking;          // 判斷是否正在壓縮      private:      // 編碼項      typedef struct      {         Byte        Length;              // 編碼位數         char        Bits[3];             // 編碼      } TCode, *PCode;      private:      // 初始化深度和偏移量的靜態編碼表      static void    _Init_Depth_Codes(TCode* ACodes, const Byte* ABase,                                  const Byte* ASuffix,      Byte  AHigh);      static void    _Init_Offset_Codes();      private:      // 深度和偏移量的靜態編碼表      static TCode   _Codes_Depth[256];      static TCode   _Codes_Offset[1024];         // TKYFixedPack 的靜態成員初始化類      static class TInitialization      {      public:         TInitialization();         ~TInitialization();      } _Initialization;         friend class TInitialization;   };      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      /* TKYFixedUnpack - 固定緩沖區的解壓縮類(基於LZ壓縮算法) */      class TKYFixedUnpack   {   public:      // 解壓縮緩沖區      // 1. ABuffer 存放 ASize 字節的已壓縮數據      // 2. ADest   存放解壓縮後的數據, ADestSize >= ASize      // 3. 若返回值 > 0 表示解壓縮後數據的尺寸      // 4. 若返回值為 0 表示解壓縮失敗, 可能 ADestSize 太小或數據未壓縮      // 5. 若返回值為 -1 表示參數不合法      // 6. 若返回值為 -2 表示解壓縮失敗, 原因是數據已損壞      static long    Unpack(const char* ABuffer, long ASize,                                  char* ADest,   long ADestSize);      };      }      #endif     [cpp]   // =======================================   // Unit   : 固定緩沖區的壓縮/解壓縮單元   // Version: 3.0.0.0 (build 2012.04.19)   // Author : Kyee Ye   // Email  : kyee_ye(at)126.com   // Copyright (C) Kyee workroom   // =======================================      #include "KYFixedPack.h"      namespace KYLib   {      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      /* 深度和偏移量編碼操作的相關靜態函數 */      // 常量   #define Max_Depth             258      // 最大匹配深度   #define Max_Offset           1024      // 最大偏移量   #define Mask_Index         0x7FFF      // 索引的掩碼   #define Mask_Hash          0x0FFF      // 哈希的掩碼   #define Hash_RandomGene     45673      // 哈希的隨機因子必須是素數,                                          // 且除以 4096 的商和余數也是素數      // 深度的編碼   #define High_Depth              8      // 後綴的最高項數      // 偏移量的編碼   #define Prefix_Offset           4      // 偏移量的前綴位數   #define High_Offset            15      // = 2^Prefix_Offset - 1      // 前綴碼的位值   static const Byte Bits_Prefix[8] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01};      // 高位與模值   static const Byte Bits_HiAnd[8]  = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE};      // 布爾位值   static const Byte Bits_Bool[8]   = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};      // 深度前綴編碼的基數   static const Byte _D_Base[9]     = {0,    2,    4,    8,   12,   20,   36,   68,                                     132};      // 深度前綴編碼的後綴位數   static const Byte _D_Bits[9]     = {1,    1,    2,    2,    3,    4,    5,    6,                                       7};      // 偏移量前綴編碼的基數   static const Word _O_Base[16]    = {0,    1,    2,    3,    4,    6,    8,   12,                                      16,   24,   32,   48,   64,  128,  256,  512};      // 偏移量前綴編碼的後綴位數   static const Byte _O_Bits[16]    = {0,    0,    0,    0,    1,    1,    2,    2,                                       3,    3,    4,    4,    6,    7,    8,    9};         // Prefix前綴碼 -> 緩沖區   // 注: APos 非空, ABitBegin 取值 [0..7], ACount + ABitBegin < 256   static void PrefixToBuffer(char* &APos, Byte& ABitBegin, Byte ACount)   {      // 初始化      Byte  byteRest;      Byte* pPos  = (Byte*)APos;         // 檢查前綴是否非空      if (ACount != 0)      {         // 檢查非空         if (ABitBegin != 0)         {            Byte byteCount = ACount + ABitBegin;            if (byteCount < 8)            {               *pPos    |= Bits_Prefix[ABitBegin] & Bits_HiAnd[byteCount];               ACount    = 0;               ABitBegin = (Byte)byteCount;            }            else            {               *pPos    |= Bits_Prefix[ABitBegin];               ACount   -= 8 - ABitBegin;               ABitBegin = 0;               pPos++;            }         }            // 判斷是否剩余前綴碼         if (ACount != 0)         {            byteRest = ACount & 0x07;            ACount   = ACount >> 3;               // 按字節添加            for (; ACount > 0; ACount--, pPos++)               *pPos = 0xFF;               // 剩下位數            if (byteRest != 0)            {               *pPos     = Bits_HiAnd[byteRest];               ABitBegin = byteRest;            }         }      }         // 處理前綴碼結束符 0      if (ABitBegin == 7)         pPos++;      else if (ABitBegin == 0)         *pPos = 0;         // 修改起始位      ABitBegin = (ABitBegin + 1) & 0x07;      APos      = (char*)pPos;   }      // 緩沖區 -> Prefix前綴碼   // 注: APos 和 AEnd 非空, ABitBegin 取值 [0..7], ACount + ABitBegin < 256   static bool BufferToPrefix(char* &APos, char* AEnd,   Byte& ABitBegin,                                           Byte& ACount, Byte  AMax)   {      // 初始化      bool result = false;         // 范圍檢查      if (APos < AEnd)      {         // 初始化         Byte* pPos        = (Byte*)APos;         Byte* pEnd        = (Byte*)AEnd;         Byte  byteAnd     = Bits_Prefix[ABitBegin];         Byte  byteCount   = 0;            // 掃描完整前綴碼         if ((*pPos & byteAnd) == byteAnd)         {            byteCount = 8 - ABitBegin;            ABitBegin = 0;            pPos++;               // 整個字符            for (; pPos < pEnd; pPos++, byteCount += 8)               if (*pPos != 0xFF)                  break;         }            // 范圍檢查         if (pPos < pEnd)         {            // 掃描剩余前綴碼            for (; ABitBegin < 8; ABitBegin++, byteCount++)               if ((*pPos & Bits_Bool[ABitBegin]) == 0)                  break;               // 判斷是否成功            if (byteCount <= AMax)            {               // 處理前綴碼結束符 0               ABitBegin++;               if (ABitBegin == 8)               {                  ABitBegin = 0;                  pPos++;               }                  // 結果               ACount   = byteCount;               result   = true;            }         }            // 更新位置         APos = (char*)pPos;      }         // 返回結果      return result;   }      // 緩沖區 -> Depth   // 注: APos 和 AEnd 非空, ABitBegin 取值 [0..7]   static bool BufferToDepth(char* &APos, char* AEnd, Byte& ABitBegin, Word& ADepth)   {      // 初始化      Byte byteIndex;      bool result = false;         // 取索引      if (BufferToPrefix(APos, AEnd, ABitBegin, byteIndex, High_Depth))      {         // 初始化         Byte byteValue = 0;         Byte byteBits  = _D_Bits[byteIndex];            // 取後綴         if (BufferToByte(APos, AEnd, ABitBegin, byteValue, byteBits))         {            ADepth = _D_Base[byteIndex] + byteValue;            result = true;         }      }         // 返回結果      return result;   }      // 緩沖區 -> Offset(含編/解碼)   // 注: APos 和 AEnd 非空, ABitBegin 取值 [0..7]   static bool BufferToOffset(char* &APos,      char* AEnd,                              Byte&  ABitBegin, Word& AOffset)   {      // 初始化      Byte byteIndex;      bool result = false;         // 取索引      if (BufferToByte(APos, AEnd, ABitBegin, byteIndex, Prefix_Offset))      {         // 初始化         Word wordValue = 0;         Byte byteBits  = _O_Bits[byteIndex];            // 取後綴         if ((byteBits == 0)            || BufferToWord(APos, AEnd, ABitBegin, wordValue, byteBits))         {            AOffset = _O_Base[byteIndex] + wordValue;            result  = true;         }      }         // 返回結果      return result;   }      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      /* TKYFixedPack - 固定緩沖區的壓縮類(基於LZ壓縮算法) */      // ---------------- 靜態成員 ----------------      // 深度和偏移量的靜態編碼表   TKYFixedPack::TCode TKYFixedPack::_Codes_Depth[256];   TKYFixedPack::TCode TKYFixedPack::_Codes_Offset[1024];      // TKYFixedPack 的靜態成員初始化對象   TKYFixedPack::TInitialization TKYFixedPack::_Initialization;      // TKYFixedPack 的靜態成員初始化類的構造函數   TKYFixedPack::TInitialization::TInitialization()   {      // 初始化深度和偏移量的靜態編碼表      _Init_Depth_Codes(_Codes_Depth, _D_Base, _D_Bits, High_Depth);      _Init_Offset_Codes();   }      // TKYFixedPack 的靜態成員初始化類的析構函數   TKYFixedPack::TInitialization::~TInitialization()   {   }      // ---------------- 靜態函數 ----------------   // 初始化深度的靜態編碼表   void TKYFixedPack::_Init_Depth_Codes(TCode* ACodes, const Byte* ABase,                                   const Byte* ASuffix,      Byte  AHigh)   {      // 初始化      char* pBits;      PCode pCodes, pEnd;      Byte  byteNo, byteBits, byteLength, byteBegin, byteValue;         // 循環添加靜態編碼表      for (byteNo = 0, pCodes = ACodes; byteNo <= AHigh; byteNo++)      {         pEnd        = ACodes + ((byteNo != AHigh) ? ABase[byteNo+1] : 256);         byteBits    = ASuffix[byteNo];         byteLength  = byteNo + 1 + byteBits;            // 判斷後綴碼位數是否非 0         if (byteBits != 0)            for (byteValue = 0; pCodes < pEnd; pCodes++, byteValue++)            {               pCodes->Length = byteLength;               pBits          = pCodes->Bits;               byteBegin      = 0;               PrefixToBuffer(pBits, byteBegin, byteNo);               ByteToBuffer(pBits, byteBegin, byteValue, byteBits);            }         else            for (; pCodes < pEnd; pCodes++)            {               pCodes->Length = byteLength;               pBits          = pCodes->Bits;               byteBegin      = 0;               PrefixToBuffer(pBits, byteBegin, byteNo);            }      }   }      // 初始化偏移量的靜態編碼表   void TKYFixedPack::_Init_Offset_Codes()   {      // 初始化      char* pBits;      PCode pCodes, pEnd;      Word  wValue;      Byte  byteNo, byteBits, byteLength, byteBegin;         // 循環添加靜態編碼表      for (byteNo = 0, pCodes = _Codes_Offset; byteNo <= High_Offset; byteNo++)      {         pEnd        = _Codes_Offset + ((byteNo < High_Offset)                                          ? _O_Base[byteNo+1] : Max_Offset);         byteBits    = _O_Bits[byteNo];         byteLength  = Prefix_Offset + byteBits;            // 判斷後綴碼位數是否非 0         if (byteBits != 0)            for (wValue = 0; pCodes < pEnd; pCodes++, wValue++)            {               pCodes->Length = byteLength;               pBits          = pCodes->Bits;               byteBegin      = 0;               ByteToBuffer(pBits, byteBegin, byteNo, Prefix_Offset);               WordToBuffer(pBits, byteBegin, wValue, byteBits);            }         else            for (; pCodes < pEnd; pCodes++)            {               pCodes->Length = byteLength;               pBits          = pCodes->Bits;               byteBegin      = 0;               ByteToBuffer(pBits, byteBegin, byteNo, Prefix_Offset);            }      }   }      // ---------------- 構造函數和析構函數 ----------------   // 構造函數   TKYFixedPack::TKYFixedPack()   {      // 初始化      FDest       = NULL;      FMaxSize    = 0;      FIsPacking  = false;         // 清空      Reset();   }      // 析構函數   TKYFixedPack::~TKYFixedPack()   {      if (FDest != NULL)      {         free(FDest);         FDest = NULL;      }   }      // ---------------- 私有函數 ----------------   // 拷貝上下文   void TKYFixedPack::DoCopy(const char* ABuffer, long ASize)   {      // 初始化      long  intSize;      char* pDest = (char*)FContext;      char* pPos  = (char*)ABuffer;      char* pEnd  = pPos + ASize;         // 檢查尺寸      if (ASize >= Max_Offset)         memcpy(pDest, pEnd - Max_Offset, Max_Offset);      else if (FLastSize >= Max_Offset)      {         intSize  = Max_Offset - ASize;         memmove(pDest, pDest + ASize, intSize);         memcpy(pDest + intSize, pPos, ASize);      }      else if (FLastSize + ASize > Max_Offset)      {         intSize  = Max_Offset - ASize;         memmove(pDest, pDest + (FLastSize - intSize), intSize);         memcpy(pDest + intSize, pPos, ASize);      }      else         memcpy(pDest + FLastSize, pPos, ASize);         // 修改最後尺寸      FDataSize   = FLastSize + ASize;      FLastSize   = FDataSize;   }      // 索引項匹配   bool TKYFixedPack::DoMatch(Byte* APos, Byte* AEnd, Word& AOffset, Byte& ADepth)   {      // 初始化      bool result = false;      Word wIndex, wHash, wValue;         // 計算 Hash 值      wHash       = ((Word)APos[0] << 8) ^ ((Word)APos[1] << 4) ^ (Word)APos[2];      wHash       = ((wHash * Hash_RandomGene) >> 4) & Mask_Hash;      wValue      = FHash[wHash];      wIndex      = (Word)FDataSize & Mask_Index;      AOffset     = (wIndex - wValue) & Mask_Index;      FHash[wHash]= wIndex;         // 判斷偏移量是否有效      if ((wValue <= Mask_Index) && (AOffset < Max_Offset) && (AOffset != 0))      {         // 初始化         Word wDepth = (Word)Min(AEnd - APos, Max_Depth);         Byte* pPos  = APos;         Byte* pEnd  = APos + wDepth;         Byte* pDest;            // 檢查是否超出上下文         if (FDataSize - FLastSize >= AOffset)         {            pDest = APos - AOffset;            while ((pPos < pEnd) && (*pPos == *pDest))            {               pPos++;               pDest++;            }         }         else         {            // 初始化            Word wSize  = (Word)(FDataSize - FLastSize);  // (FDataSize - FLastSize < AOffset)            Word wFront = AOffset - wSize;               // 計算起始位置            pDest = (Byte*)FContext;            if (FLastSize >= Max_Offset)               pDest += Max_Offset - wFront;            else               pDest += FLastSize - wFront;               // 判斷是否分二部分比較            if (wFront < wDepth)            {               // 初始化               Byte* pDestEnd = pDest + wFront;                  // 前半部分比較               while ((pDest < pDestEnd) && (*pPos == *pDest))               {                  pPos++;                  pDest++;               }                  // 判斷是否需要繼續匹配               if (pDest == pDestEnd)               {                  pDest = APos - wSize;                  while ((pPos < pEnd) && (*pPos == *pDest))                  {                     pPos++;                     pDest++;                  }               }            }            else               while ((pPos < pEnd) && (*pPos == *pDest))               {                  pPos++;                  pDest++;               }         }            // 檢查匹配長度         wDepth = (Word)(pPos - APos);         if (wDepth >= 3)         {            ADepth = (Byte)(wDepth - 3);            result = true;         }      }         // 返回結果      return result;   }      // ---------------- 保護函數 ----------------      // ---------------- 公有函數 ----------------   // 設置壓縮結果緩沖區的最大尺寸   bool TKYFixedPack::SetMaxSize(Word ASize)   {      // 初始化      bool result = true;         // 判斷狀態      if (FIsPacking)         result   = false;      else if (FMaxSize != ASize)      {         // 初始化         char* pData = NULL;            // 判斷是否需要分配         if (ASize != 0)         {            pData    = (char*)malloc(ASize + 8);   // 冗余長度, 防止編碼超出            result   = (pData != NULL);         }            // 判斷是否繼續         if (result)         {            // 先釋放            if (FDest != NULL)               free(FDest);               // 交換            FDest    = pData;            FMaxSize = ASize;         }      }         // 返回結果      return result;   }      // 重置   void TKYFixedPack::Reset()   {      if (!FIsPacking)      {         // 置空         FSize          = 0;         FBitBegin      = 0;         FDataSize      = 0;         FLastSize      = 0;            // 初始化哈希表         memset(FHash, -1, sizeof(FHash));      }   }      // 壓縮緩沖區   bool TKYFixedPack::Pack(const char* ABuffer, long ASize, Word AMax)   {      // 檢查是否正在壓縮及檢查參數      if (FIsPacking || (FDest == NULL) || (ASize <= 0) || (ABuffer == NULL))         return false;         // 初始化      bool result = false;         // 置壓縮狀態      FIsPacking  = true;         // 操作      try      {         // 初始化         Word  wSize, wOffset;         PCode pCode;         Byte* pSame;         Byte* pLast;         Byte* pPos     = (Byte*)ABuffer;         Byte* pEnd     = pPos + ASize - 2;         Byte* pBuffEnd = pPos + ASize;         char* pDest    = FDest + FSize - (Byte)(FBitBegin != 0);         char* pDestEnd = FDest + Min(FMaxSize, AMax);         Byte  byteDepth= 0;         Byte  byteBegin= FBitBegin;         bool  boolOver = false;         bool  boolSame, boolNext;         Byte  byteLen1, byteLen2;            // 循環匹配         while (pPos < pEnd)         {            // 檢查是否相同數據            pLast = Min(pBuffEnd, pPos + Max_Offset + 10);            pSame = pPos + 1;            while ((pSame < pLast) && (*pSame == *pPos))               pSame++;               // 檢查相同數據尺寸是否大於等於 3            wSize    = pSame - pPos;            boolSame = (wSize >= 3);            if (wSize <= 32)            {               boolNext = DoMatch(pPos, pBuffEnd, wOffset, byteDepth);               if (boolNext && boolSame && (byteDepth + 3 >= wSize) && (wOffset != 1))               {                  if (byteDepth + 3 != wSize)                     boolSame = false;                  else                  {                     byteLen1 = (wSize < 11) ? _Codes_Offset[0].Length + 11                                 : _Codes_Offset[0].Length + _Codes_Offset[wSize - 11].Length + 8;                     byteLen2 = _Codes_Offset[wOffset].Length + _Codes_Depth[byteDepth].Length;                     boolSame = (byteLen1 <= byteLen2);                  }               }            }               // 判斷壓縮為相同數據            if (boolSame)            {               // 壓縮標志               BoolToBuffer(pDest, byteBegin, true);                  // 偏移量編碼               pCode = &_Codes_Offset[wSize >= 11];               if (pCode->Length != 0)                  BitsToBuffer(pDest, byteBegin, pCode->Bits, pCode->Length);                  // 深度編碼               if (wSize < 11)                  ByteToBuffer(pDest, byteBegin, (Byte)(wSize - 3), 3);               else               {                  pCode    = &_Codes_Offset[wSize - 11];                  if (pCode->Length != 0)                     BitsToBuffer(pDest, byteBegin, pCode->Bits, pCode->Length);               }                  // 相同的字符               CharToBuffer(pDest, byteBegin, *pPos);               FDataSize  += wSize;               pPos        = pSame;            }            else if (boolNext)            {               // 壓縮標志               BoolToBuffer(pDest, byteBegin, true);                  // 偏移量編碼               pCode = &_Codes_Offset[wOffset];               if (pCode->Length != 0)                  BitsToBuffer(pDest, byteBegin, pCode->Bits, pCode->Length);                  // 深度編碼               pCode = &_Codes_Depth[byteDepth];               if (pCode->Length != 0)                  BitsToBuffer(pDest, byteBegin, pCode->Bits, pCode->Length);                  // 更新位置               wSize       = byteDepth + 3;               FDataSize  += wSize;               pPos       += wSize;            }            else            {               // 未壓縮標志並存放字節               BoolToBuffer(pDest, byteBegin, false);               CharToBuffer(pDest, byteBegin, *pPos);                  // 更新位置               FDataSize++;               pPos++;            }               // 檢查是否溢出            if (pDest >= pDestEnd)            {               boolOver = true;               break;            }         }            // 判斷是否未溢出         if (!boolOver)         {            // 末尾 2 個字節            while (pPos < pBuffEnd)            {               // 未壓縮標志並存放字節               BoolToBuffer(pDest, byteBegin, false);               CharToBuffer(pDest, byteBegin, *pPos);                  // 更新位置               FDataSize++;               pPos++;            }               // 檢查是否溢出            if (pDest < pDestEnd)            {               FSize       = (Word)(pDest - FDest) + (Byte)(byteBegin != 0);               FBitBegin   = byteBegin;               result      = true;                  // 拷貝上下文               DoCopy(ABuffer, ASize);            }         }      }      catch (...) {}         // 恢復數據尺寸      if (!result)      {         FDataSize = FLastSize;         if (FBitBegin != 0)            FDest[FSize - 1] &= Bits_HiAnd[FBitBegin];      }         // 返回結果      FIsPacking = false;      return result;   }      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      /* TKYFixedUnpack - 固定緩沖區的解壓縮類(基於LZ壓縮算法) */      // ---------------- 靜態函數 ----------------   // 解壓縮緩沖區   // 1. ABuffer 存放 ASize 字節的已壓縮數據   // 2. ADest   存放解壓縮後的數據, ADestSize >= ASize   // 3. 若返回值 > 0 表示解壓縮後數據的尺寸   // 4. 若返回值為 0 表示解壓縮失敗, 可能 ADestSize 太小或數據未壓縮   // 5. 若返回值為 -1 表示參數不合法   // 6. 若返回值為 -2 表示解壓縮失敗, 原因是數據已損壞   long TKYFixedUnpack::Unpack(const char* ABuffer, long ASize,                                     char* ADest,   long ADestSize)   {      // 檢查參數      if ((ABuffer == NULL) || (ASize <= 0) || (ADest == NULL) || (ADestSize < ASize))         return -1;         // 初始化      long result = -2;         // 操作      try      {         // 初始化         char* pLast;         char* pMatch;         char* pDest       = ADest;         char* pDestEnd    = ADest + ADestSize;         char* pPos        = (char*)ABuffer;         char* pEnd        = pPos + ASize - 1;         char* pBuffEnd    = pPos + ASize;         Byte  byteBegin   = 0;         bool  boolOver    = false;         bool  boolError   = false;         bool  boolMatched;         char  charValue;         Byte  byteSame;         Word  wDepth, wOffset;            // 循環匹配         while (pPos < pEnd)         {            // 取匹配標志            BufferToBool(pPos, byteBegin, boolMatched);               // 判斷是否匹配            if (boolMatched)            {               // 取偏移量和深度               if (!BufferToOffset(pPos, pBuffEnd, byteBegin, wOffset))               {                  boolError = true;                  break;               }               else if (wOffset == 0)  // 相同數據 (same < 11)               {                  // 取深度及字符                  if (!BufferToByte(pPos, pBuffEnd, byteBegin, byteSame, 3)                     || !BufferToChar(pPos, pBuffEnd, byteBegin, charValue))                  {                     boolError = true;                     break;                  }                  else if (pDest + byteSame + 3 > pDestEnd)                  {                     boolOver = true;                     break;                  }                  else                  {                     pLast = pDest + byteSame + 3;                     for (; pDest < pLast; pDest++)                        *pDest = charValue;                  }               }               else if (wOffset == 1)  // 相同數據               {                  // 取深度及字符                  if (!BufferToOffset(pPos, pBuffEnd, byteBegin, wDepth)                     || !BufferToChar(pPos, pBuffEnd, byteBegin, charValue))                  {                     boolError = true;                     break;                  }                  else if (pDest + wDepth + 11 > pDestEnd)                  {                     boolOver = true;                     break;                  }                  else                  {                     pLast = pDest + wDepth + 11;                     for (; pDest < pLast; pDest++)                        *pDest = charValue;                  }               }               else if ((wOffset > pDest - ADest)                  || !BufferToDepth(pPos, pBuffEnd, byteBegin, wDepth)                  || (wDepth > 0xFF))               {                  boolError = true;                  break;               }               else if (pDest + wDepth + 3 > pDestEnd)               {                  boolOver = true;                  break;               }               else               {                  pLast    = pDest + wDepth + 3;                  pMatch   = pDest - wOffset;                  for (; pDest < pLast; pDest++, pMatch++)                     *pDest = *pMatch;               }            }            else if (pDest < pDestEnd)            {               BufferToChar(pPos, byteBegin, charValue);               *(pDest++) = charValue;            }            else            {               boolOver = true;               break;            }         }            // 檢查最後一個字節         if (!boolOver && !boolError && (pPos < pBuffEnd) && (byteBegin <= 1))         {            // 取匹配標志            BufferToBool(pPos, byteBegin, boolMatched);               // 必須是匹配項            if (boolMatched && BufferToOffset(pPos, pBuffEnd, byteBegin, wOffset)                            && (wOffset != 0) && (wOffset <= pDest - ADest)                            && BufferToDepth(pPos, pBuffEnd, byteBegin, wDepth))            {               if (pDest + wDepth + 3 > pDestEnd)                  boolOver = true;               else               {                  pLast    = pDest + wDepth + 3;                  pMatch   = pDest - wOffset;                  for (; pDest < pLast; pDest++, pMatch++)                     *pDest = *pMatch;               }            }         }            // 判斷是否溢出         if (boolOver)            result = 0;         else if (!boolError)            result = pDest - ADest;      }      catch (...) {}         // 返回結果      return result;   }      }    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved