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] = {0x80, 0x40, 0x20, 0x10,
29 0x08, 0x04, 0x02, 0x01};
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, -1, sizeof(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 、
源码