随笔-3  评论-5  文章-13  trackbacks-0
TKYQuickPack(快速压缩类), TKYQuickUnpack(快速解压缩类), 源码如下:

KYQuickPack.h 文件

 1 // =======================================
 2 // Unit   : 快速压缩/解压缩单元 (KYQuickPack.h)
 3 // Version: 3.0.0.0 (build 2011.03.18)
 4 // Author : Kyee Ye
 5 // Email  : kyee_ye(at)126.com
 6 // Copyright (C) Kyee workroom
 7 // =======================================
 8 
 9 #ifndef _KYQuickPack_H_
10 #define _KYQuickPack_H_
11 
12 #include "KYPackObj.h"
13 
14 // KYLib 2.0 开始使用 KYLib 命名空间
15 namespace KYLib
16 {
17 
18 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 
20 /* TKYQuickPack - 快速压缩类(基于LZRW压缩算法) */
21 
22 class TKYQuickPack: public TKYCustomPack
23 {
24 public:
25    TKYQuickPack();
26    virtual ~TKYQuickPack();
27 
28    // 属性
29    bool           IsPacking() const    { return FIsPacking; }  // default: false
30 
31    // 重置
32    virtual void   Reset();
33 
34    // 压缩缓冲区
35    // 1. ABuffer 存放 ASize 字节的待压缩数据
36    // 2. ADest   存放压缩后的数据, 缓冲区尺寸至少为 ASize
37    // 3. 若返回值 > 0 表示压缩后数据的尺寸
38    // 4. 若返回值为 0 表示压缩失败, 即待压缩数据无法再压缩
39    // 5. 若返回值为 -1 表示参数不合法
40    // 6. 若返回值为 -2 表示压缩失败, 原因是正在压缩
41    virtual long   Pack(const char* ABuffer, char* ADest, long ASize);
42 
43 private:
44    void           DoCopy(const char* ABuffer, long ASize);
45    bool           DoMatch(Byte* APos, Byte* AEnd, Word& AOffset, Byte& ADepth);
46 
47 private:
48    Word           FHash[4096];         // 哈希表
49    char           FContext[4096];      // 压缩数据的上下文
50    Longword       FLastSize;           // 上一次 pack 结束后的尺寸
51    bool           FIsPacking;          // 判断是否正在压缩
52    bool           FIsOverflow;         // 判断上下文列表是否溢出
53 };
54 
55 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56 
57 /* TKYQuickUnpack - 快速解压缩类(基于LZRW压缩算法) */
58 
59 class TKYQuickUnpack: public TKYCustomUnpack
60 {
61 public:
62    TKYQuickUnpack();
63    virtual ~TKYQuickUnpack();
64 
65    // 属性
66    bool           IsUnpacking() const  { return FIsUnpacking; }// default: false
67 
68    // 重置
69    virtual void   Reset();
70 
71    // 解压缩缓冲区
72    // 1. 若 AIsPacked 为 false 表示数据未压缩, 即为解压缩的上下文相关性而操作,
73    //    但不会拷贝数据到 ADest, 并返回值为 0
74    // 2. ABuffer 存放 ASize 字节的已压缩数据
75    // 3. ADest   存放解压缩后的数据, ADestSize >= ASize
76    // 4. 若返回值 > 0 表示解压缩后数据的尺寸
77    // 5. 若返回值为 0 表示解压缩失败, 可能 ADestSize 太小或数据未压缩
78    // 6. 若返回值为 -1 表示参数不合法
79    // 7. 若返回值为 -2 表示解压缩失败, 原因是数据已损坏
80    // 8. 若返回值为 -3 表示解压缩失败, 原因是正在解压缩
81    virtual long   Unpack(const char* ABuffer, long ASize,
82                                char* ADest,   long ADestSize,
83                                bool  AIsPacked = true);
84 
85 private:
86    void           DoCopy(const char* ABuffer, long ASize);
87    bool           DoInsert(char* &APos, Word AOffset, Byte ADepth);
88 
89 private:
90    char           FContext[4096];      // 已解压的上下文
91    Longword       FLastSize;           // 上一次 unpack 结束后的尺寸
92    bool           FIsOverflow;         // 判断上下文列表是否溢出
93    bool           FIsUnpacking;        // 判断是否正在解压缩
94 };
95 
96 }
97 
98 #endif
99 

 


KYQuickPack.cpp 文件:

  1 // =======================================
  2 // Unit   : 快速压缩/解压缩单元 (KYQuickPack.cpp)
  3 // Version: 3.0.0.0 (build 2011.03.18)
  4 // Author : Kyee Ye
  5 // Email  : kyee_ye(at)126.com
  6 // Copyright (C) Kyee workroom
  7 // =======================================
  8 
  9 #include "KYQuickPack.h"
 10 
 11 // KYLib 2.0 开始使用 KYLib 命名空间
 12 namespace KYLib
 13 {
 14 
 15 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 16 
 17 /* 常量定义 */
 18 
 19 // 常量
 20 #define Max_Depth              18      // 最大匹配深度
 21 #define Max_Offset           4096      // 最大偏移量
 22 #define Mask_Index         0x7FFF      // 索引的掩码
 23 #define Mask_Hash          0x0FFF      // 哈希的掩码
 24 #define Hash_RandomGene     45673      // 哈希的随机因子必须是素数,
 25                                        // 且除以 4096 的商和余数也是素数
 26 
 27 // 布尔位值
 28 static const Byte Bits_Bool[8]   = {0x800x400x200x10,
 29                                     0x080x040x020x01};
 30 
 31 // 取 Word 的高 8 位字节
 32 static inline Byte HiByte(Word AValue)
 33 {
 34    return (Byte)(AValue >> 8);
 35 }
 36 
 37 // 取 Word 的低 8 位字节
 38 static inline Byte LoByte(Word AValue)
 39 {
 40    return (Byte)AValue;
 41 }
 42 
 43 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 44 
 45 /* TKYQuickPack - 快速压缩类(基于LZRW压缩算法) */
 46 
 47 // ---------------- 构造函数和析构函数 ----------------
 48 // 构造函数
 49 TKYQuickPack::TKYQuickPack()
 50 {
 51    // 清空
 52    FIsPacking  = false;
 53    Reset();
 54 }
 55 
 56 // 析构函数
 57 TKYQuickPack::~TKYQuickPack()
 58 {
 59 }
 60 
 61 // ---------------- 私有函数 ----------------
 62 // 拷贝上下文
 63 void TKYQuickPack::DoCopy(const char* ABuffer, long ASize)
 64 {
 65    // 初始化
 66    long  intSize;
 67    char* pDest = (char*)FContext;
 68    char* pPos  = (char*)ABuffer;
 69    char* pEnd  = pPos + ASize;
 70 
 71    // 检查尺寸
 72    if (ASize >= Max_Offset)
 73       memcpy(pDest, pEnd - Max_Offset, Max_Offset);
 74    else if ((FLastSize >= Max_Offset) || FIsOverflow)
 75    {
 76       intSize  = Max_Offset - ASize;
 77       memmove(pDest, pDest + ASize, intSize);
 78       memcpy(pDest + intSize, pPos, ASize);
 79    }
 80    else if (FLastSize + ASize > Max_Offset)
 81    {
 82       intSize  = Max_Offset - ASize;
 83       memmove(pDest, pDest + (FLastSize - intSize), intSize);
 84       memcpy(pDest + intSize, pPos, ASize);
 85    }
 86    else
 87       memcpy(pDest + FLastSize, pPos, ASize);
 88 
 89    // 修改最后尺寸
 90    FSize       = FLastSize + ASize;
 91    FIsOverflow = FIsOverflow || (FSize < FLastSize);
 92    FLastSize   = FSize;
 93 }
 94 
 95 // 索引项匹配
 96 bool TKYQuickPack::DoMatch(Byte* APos, Byte* AEnd, Word& AOffset, Byte& ADepth)
 97 {
 98    // 初始化
 99    bool result = false;
100    Word wIndex, wHash, wValue;
101 
102    // 计算 Hash 值
103    wHash       = ((Word)APos[0<< 8^ ((Word)APos[1<< 4^ (Word)APos[2];
104    wHash       = ((wHash * Hash_RandomGene) >> 4& Mask_Hash;
105    wValue      = FHash[wHash];
106    wIndex      = (Word)FSize & Mask_Index;
107    AOffset     = (wIndex - wValue) & Mask_Index;
108    FHash[wHash]= wIndex;
109 
110    // 判断偏移量是否有效
111    if ((wValue <= Mask_Index) && (AOffset < Max_Offset) && (AOffset != 0))
112    {
113       // 初始化
114       Word wDepth = (Word)Min(AEnd - APos, Max_Depth);
115       Byte* pPos  = APos;
116       Byte* pEnd  = APos + wDepth;
117       Byte* pDest;
118 
119       // 检查是否超出上下文
120       if (FSize - FLastSize >= AOffset)
121       {
122          pDest = APos - AOffset;
123          while ((pPos < pEnd) && (*pPos == *pDest))
124          {
125             pPos++;
126             pDest++;
127          }
128       }
129       else
130       {
131          // 初始化
132          Word wSize  = (Word)(FSize - FLastSize);  // (FSize - FLastSize < AOffset)
133          Word wFront = AOffset - wSize;
134 
135          // 计算起始位置
136          pDest = (Byte*)FContext;
137          if ((FLastSize >= Max_Offset) || FIsOverflow)
138             pDest += Max_Offset - wFront;
139          else
140             pDest += FLastSize - wFront;
141 
142          // 判断是否分二部分比较
143          if (wFront < wDepth)
144          {
145             // 初始化
146             Byte* pDestEnd = pDest + wFront;
147 
148             // 前半部分比较
149             while ((pDest < pDestEnd) && (*pPos == *pDest))
150             {
151                pPos++;
152                pDest++;
153             }
154 
155             // 判断是否需要继续匹配
156             if (pDest == pDestEnd)
157             {
158                pDest = APos - wSize;
159                while ((pPos < pEnd) && (*pPos == *pDest))
160                {
161                   pPos++;
162                   pDest++;
163                }
164             }
165          }
166          else
167             while ((pPos < pEnd) && (*pPos == *pDest))
168             {
169                pPos++;
170                pDest++;
171             }
172       }
173 
174       // 检查匹配长度
175       ADepth = (Byte)(pPos - APos);
176       result = (ADepth >= 3);
177    }
178 
179    // 返回结果
180    return result;
181 }
182 
183 // ---------------- 保护函数 ----------------
184 
185 // ---------------- 公有函数 ----------------
186 // 重置
187 void TKYQuickPack::Reset()
188 {
189    if (!FIsPacking)
190    {
191       // 置空
192       FSize          = 0;
193       FLastSize      = 0;
194       FIsOverflow    = false;
195 
196       // 初始化哈希表
197       memset(FHash, -1sizeof(FHash));
198    }
199 }
200 
201 // 压缩缓冲区
202 // 1. ABuffer 存放 ASize 字节的待压缩数据
203 // 2. ADest   存放压缩后的数据, 缓冲区尺寸至少为 ASize
204 // 3. 若返回值 > 0 表示压缩后数据的尺寸
205 // 4. 若返回值为 0 表示压缩失败, 即待压缩数据无法再压缩
206 // 5. 若返回值为 -1 表示参数不合法
207 // 6. 若返回值为 -2 表示压缩失败, 原因是正在压缩
208 long TKYQuickPack::Pack(const char* ABuffer, char* ADest, long ASize)
209 {
210    // 检查是否正在压缩
211    if (FIsPacking)
212       return -2;
213 
214    // 置压缩状态
215    FIsPacking = true;
216 
217    // 初始化
218    long result = 0;
219 
220    // 检查参数
221    if ((ASize <= 0|| (ABuffer == NULL) || (ADest == NULL))
222       result = -1;
223    else
224    {
225       try
226       {
227          // 初始化
228          Word  wSize, wOffset;
229          Byte* pSame;
230          Byte* pLast;
231          Byte* pPos     = (Byte*)ABuffer;
232          Byte* pEnd     = pPos + ASize - 2;
233          Byte* pBuffEnd = pPos + ASize;
234          Byte* pFlag    = (Byte*)ADest;
235          Byte* pDest    = pFlag + 1;
236          Byte* pDestEnd = pFlag + ASize;
237          Byte  byteDepth= 0;
238          Byte  byteFlag = 0;
239          Byte  byteBit  = 0;
240          bool  boolOver = false;
241 
242          // 循环匹配
243          while (pPos < pBuffEnd)
244          {
245             // 检查标志位是否已满
246             if (byteBit == 8)
247             {
248                *pFlag   = byteFlag;
249                pFlag    = pDest++;
250                byteBit  = 0;
251                byteFlag = 0;
252             }
253 
254             // 检查是否相同数据
255             pLast = Min(pBuffEnd, pPos + Max_Offset + 8);
256             pSame = pPos + 1;
257             while ((pSame < pLast) && (*pSame == *pPos))
258                pSame++;
259 
260             // 检查相同数据尺寸是否大于等于 8
261             wSize = pSame - pPos - 1;
262             if (wSize >= 8)
263             {
264                if (pDest < pDestEnd - 4)
265                {
266                   wSize      -= 8;
267                   *(pDest++)  = 0;
268                   *(pDest++)  = HiByte(wSize);
269                   *(pDest++)  = LoByte(wSize);
270                   *(pDest++)  = *pPos;
271                   byteFlag   |= Bits_Bool[byteBit];
272                   FSize      += wSize + 9;
273                   pPos        = pSame;
274                }
275                else
276                {
277                   boolOver = true;
278                   break;
279                }
280             }
281             else if ((pPos < pEnd) && DoMatch(pPos, pBuffEnd, wOffset, byteDepth))
282             {
283                if (pDest < pDestEnd - 2)
284                {
285                   wOffset     = (wOffset << 4+ (byteDepth - 3);
286                   *(pDest++)  = HiByte(wOffset);
287                   *(pDest++)  = LoByte(wOffset);
288                   byteFlag   |= Bits_Bool[byteBit];
289                   FSize      += byteDepth;
290                   pPos       += byteDepth;
291                }
292                else
293                {
294                   boolOver = true;
295                   break;
296                }
297             }
298             else if (pDest < pDestEnd)
299             {
300                *(pDest++)  = *(pPos++);
301                FSize++;
302             }
303             else
304             {
305                boolOver = true;
306                break;
307             }
308 
309             // 位数加 1
310             byteBit++;
311          }
312 
313          // 检查是否溢出
314          if (!boolOver && (pDest < pDestEnd))
315          {
316             *pFlag   = byteFlag;
317             result   = pDest - (Byte*)ADest;
318          }
319       }
320       catch () {}
321 
322       // 拷贝上下文
323       DoCopy(ABuffer, ASize);
324    }
325 
326    // 返回结果
327    FIsPacking = false;
328    return result;
329 }
330 
331 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
332 
333 /* TKYQuickUnpack - 快速解压缩类(基于LZRW压缩算法) */
334 
335 // ---------------- 构造函数和析构函数 ----------------
336 // 构造函数
337 TKYQuickUnpack::TKYQuickUnpack()
338 {
339    // 初始化
340    FSize          = 0;
341    FLastSize      = 0;
342    FIsOverflow    = false;
343    FIsUnpacking   = false;
344 }
345 
346 // 析构函数
347 TKYQuickUnpack::~TKYQuickUnpack()
348 {
349 }
350 
351 // ---------------- 私有函数 ----------------
352 // 拷贝上下文
353 void TKYQuickUnpack::DoCopy(const char* ABuffer, long ASize)
354 {
355    // 初始化
356    long  intSize;
357    char* pDest = (char*)FContext;
358    char* pPos  = (char*)ABuffer;
359    char* pEnd  = pPos + ASize;
360 
361    // 检查尺寸
362    if (ASize >= Max_Offset)
363       memcpy(pDest, pEnd - Max_Offset, Max_Offset);
364    else if ((FLastSize >= Max_Offset) || FIsOverflow)
365    {
366       intSize  = Max_Offset - ASize;
367       memmove(pDest, pDest + ASize, intSize);
368       memcpy(pDest + intSize, pPos, ASize);
369    }
370    else if (FLastSize + ASize > Max_Offset)
371    {
372       intSize  = Max_Offset - ASize;
373       memmove(pDest, pDest + (FLastSize - intSize), intSize);
374       memcpy(pDest + intSize, pPos, ASize);
375    }
376    else
377       memcpy(pDest + FLastSize, pPos, ASize);
378 
379    // 修改最后尺寸
380    FSize       = FLastSize + ASize;
381    FIsOverflow = FIsOverflow || (FSize < FLastSize);
382    FLastSize   = FSize;
383 }
384 
385 // 插入指定偏移量的数据
386 bool TKYQuickUnpack::DoInsert(char* &APos, Word AOffset, Byte ADepth)
387 {
388    // 初始化
389    bool  result = true;
390    char* pEnd   = APos + ADepth;
391    char* pDest;
392 
393    // 检查是否属于当前数据段
394    if (FSize - FLastSize >= AOffset)
395    {
396       pDest = APos - AOffset;
397       for (; APos < pEnd; APos++, pDest++)
398          *APos = *pDest;
399    }
400    else
401    {
402       // 初始化
403       Word wSize  = (Word)(FSize - FLastSize);
404       Word wFront = AOffset - wSize;
405 
406       // 计算起始位置
407       pDest = FContext;
408       if ((FLastSize >= Max_Offset) || FIsOverflow)
409          pDest += Max_Offset - wFront;
410       else if (wFront <= FLastSize)
411          pDest += FLastSize - wFront;
412       else
413          result = false;
414 
415       // 判断偏移量是否合法
416       if (result)
417       {
418          // 判断是否分二部分拷贝
419          if (wFront < ADepth)
420          {
421             // 初始化
422             char* pDestEnd = pDest + wFront;
423             char* pBegin   = APos - wSize;
424 
425             // 拷贝前半部
426             for (; pDest < pDestEnd; APos++, pDest++)
427                *APos = *pDest;
428 
429             // 后半部的开始
430             pDest = pBegin;
431          }
432 
433          // 拷贝后半部
434          for (; APos < pEnd; APos++, pDest++)
435             *APos = *pDest;
436       }
437    }
438 
439    // 返回结果
440    return result;
441 }
442 
443 // ---------------- 保护函数 ----------------
444 
445 // ---------------- 公有函数 ----------------
446 // 重置
447 void TKYQuickUnpack::Reset()
448 {
449    if (!FIsUnpacking)
450    {
451       FSize       = 0;
452       FLastSize   = 0;
453       FIsOverflow = false;
454    }
455 }
456 
457 // 解压缩缓冲区
458 // 1. 若 AIsPacked 为 false 表示数据未压缩, 即为解压缩的上下文相关性而操作,
459 //    但不会拷贝数据到 ADest, 并返回值为 0
460 // 2. ABuffer 存放 ASize 字节的已压缩数据
461 // 3. ADest   存放解压缩后的数据, ADestSize >= ASize
462 // 4. 若返回值 > 0 表示解压缩后数据的尺寸
463 // 5. 若返回值为 0 表示解压缩失败, 可能 ADestSize 太小或数据未压缩
464 // 6. 若返回值为 -1 表示参数不合法
465 // 7. 若返回值为 -2 表示解压缩失败, 原因是数据已损坏
466 // 8. 若返回值为 -3 表示解压缩失败, 原因是正在解压缩
467 long TKYQuickUnpack::Unpack(const char* ABuffer, long ASize,
468                                   char* ADest,   long ADestSize, bool AIsPacked)
469 {
470    // 检查是否正在压缩
471    if (FIsUnpacking)
472       return -3;
473 
474    // 置压缩状态
475    FIsUnpacking = true;
476 
477    // 初始化
478    long result = -1;
479 
480    // 检查参数
481    if ((ABuffer == NULL) || (ASize <= 0))
482       ;
483    else if (!AIsPacked)
484    {
485       DoCopy(ABuffer, ASize);
486       result = 0;
487    }
488    else if ((ADestSize >= ASize) && (ADest != NULL))
489    {
490       // 初始化
491       result = -2;
492 
493       // 操作
494       try
495       {
496          // 初始化
497          char  charSame;
498          Byte  byteFlag, byteDepth;
499          Word  wSize, wOffset;
500          char* pLast;
501          char* pDest       = ADest;
502          char* pDestEnd    = ADest + ADestSize;
503          Byte* pPos        = (Byte*)ABuffer;
504          Byte* pEnd        = pPos + ASize - 2;
505          Byte* pBuffEnd    = pPos + ASize;
506          Byte  byteBit     = 8;
507          bool  boolOver    = false;
508          bool  boolError   = false;
509 
510          // 循环匹配
511          while (pPos < pBuffEnd)
512          {
513             // 检查标志位是否已满
514             if (byteBit == 8)
515             {
516                byteFlag = *pPos;
517                byteBit  = 0;
518 
519                // 检查是否错误
520                if (++pPos >= pBuffEnd)
521                {
522                   boolError = true;
523                   break;
524                }
525             }
526 
527             // 判断是否压缩
528             if ((byteFlag & Bits_Bool[byteBit]) != 0)
529             {
530                if (pPos <= pEnd)
531                {
532                   // 取偏移量
533                   wOffset  = ((Word)pPos[0<< 4+ (pPos[1>> 4);
534                   pPos++;
535 
536                   // 判断是否为匹配串
537                   if (wOffset != 0)
538                   {
539                      byteDepth = (*(pPos++& 0x0F+ 3;
540                      if (pDest + byteDepth > pDestEnd)
541                      {
542                         boolOver = true;
543                         break;
544                      }
545                      else if (DoInsert(pDest, wOffset, byteDepth))
546                         FSize += byteDepth;
547                      else
548                      {
549                         boolError = true;
550                         break;
551                      }
552                   }
553                   else if (pPos < pEnd)
554                   {
555                      // 取相同尺寸及字符
556                      wSize    = ((Word)pPos[0<< 8+ pPos[1+ 9;
557                      pLast    = pDest + wSize;
558                      charSame = (char)pPos[2];
559                      pPos    += 3;
560 
561                      // 检查是否溢出
562                      if (pLast > pDestEnd)
563                      {
564                         boolOver = true;
565                         break;
566                      }
567                      else
568                      {
569                         FSize += wSize;
570                         for (; pDest < pLast; pDest++)
571                            *pDest = charSame;
572                      }
573                   }
574                   else
575                   {
576                      boolError = true;
577                      break;
578                   }
579                }
580                else
581                {
582                   boolError = true;
583                   break;
584                }
585             }
586             else if (pDest < pDestEnd)
587             {
588                *(pDest++= (char)*(pPos++);
589                FSize++;
590             }
591             else
592             {
593                boolOver = true;
594                break;
595             }
596 
597             // 位数加 1
598             byteBit++;
599          }
600 
601          // 判断是否溢出
602          if (boolOver)
603             result = 0;
604          else if (!boolError)
605             result = pDest - ADest;
606       }
607       catch () {}
608 
609       // 判断是否成功
610       if (result > 0)
611          DoCopy(ADest, result);
612       else
613          FSize = FLastSize;
614    }
615 
616    // 返回结果
617    FIsUnpacking = false;
618    return result;
619 }
620 
621 }
622 

 

posted on 2011-05-22 12:24 Kyee Ye 阅读(1054) 评论(0)  编辑 收藏 引用 所属分类: C++类库KYLib 源码

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理