Lz77.h
Upload User: szqxhk
Upload Date: 2010-02-15
Package Size: 54k
Code Size: 5k
Development Platform:

Visual C++

  1. //////////////////////////////
  2. // LZ77.h
  3. //////////////////////////////
  4. // 使用在自己的堆中分配索引节点,不滑动窗口
  5. // 每次最多压缩 65536 字节数据
  6. // 的优化版本
  7. #ifndef _WIX_LZ77_COMPRESS_HEADER_001_
  8. #define _WIX_LZ77_COMPRESS_HEADER_001_
  9. // 滑动窗口的字节大小
  10. #define _MAX_WINDOW_SIZE 65536
  11. class CCompress
  12. {
  13. public:
  14. CCompress() {};
  15. virtual ~CCompress() {};
  16. public:
  17. virtual int Compress(BYTE* src, int srclen, BYTE* dest) = 0;
  18. virtual BOOL Decompress(BYTE* src, int srclen, BYTE* dest) = 0;
  19. protected:
  20. // tools 
  21. /////////////////////////////////////////////////////////
  22. // CopyBitsInAByte : 在一个字节范围内复制位流
  23. // 参数含义同 CopyBits 的参数
  24. // 说明:
  25. // 此函数由 CopyBits 调用,不做错误检查,即
  26. // 假定要复制的位都在一个字节范围内
  27. void CopyBitsInAByte(BYTE* memDest, int nDestPos, 
  28.   BYTE* memSrc, int nSrcPos, int nBits);
  29. ////////////////////////////////////////////////////////
  30. // CopyBits : 复制内存中的位流
  31. // memDest - 目标数据区
  32. // nDestPos - 目标数据区第一个字节中的起始位
  33. // memSrc - 源数据区
  34. // nSrcPos - 源数据区第一个字节的中起始位
  35. // nBits - 要复制的位数
  36. // 说明:
  37. // 起始位的表示约定为从字节的高位至低位(由左至右)
  38. // 依次为 0,1,... , 7
  39. // 要复制的两块数据区不能有重合
  40. void CopyBits(BYTE* memDest, int nDestPos, 
  41.   BYTE* memSrc, int nSrcPos, int nBits);
  42. //////////////////////////////////////////////////////////////
  43. // 将DWORD值从高位字节到低位字节排列
  44. void InvertDWord(DWORD* pDW);
  45. /////////////////////////////////////////////////////////////
  46. // 设置byte的第iBit位为aBit
  47. // iBit顺序为高位起从0记数(左起)
  48. void SetBit(BYTE* byte, int iBit, BYTE aBit);
  49. ////////////////////////////////////////////////////////////
  50. // 得到字节byte第pos位的值
  51. // pos顺序为高位起从0记数(左起)
  52. BYTE GetBit(BYTE byte, int pos);
  53. ////////////////////////////////////////////////////////////
  54. // 将位指针*piByte(字节偏移), *piBit(字节内位偏移)后移num位
  55. void MovePos(int* piByte, int* piBit, int num);
  56. /////////////////////////////////////////////////////////
  57. // 取log2(n)的upper_bound
  58. int UpperLog2(int n);
  59. /////////////////////////////////////////////////////////
  60. // 取log2(n)的lower_bound
  61. int LowerLog2(int n);
  62. };
  63. class CCompressLZ77 : public CCompress
  64. {
  65. public:
  66. CCompressLZ77();
  67. virtual ~CCompressLZ77();
  68. public:
  69. /////////////////////////////////////////////
  70. // 压缩一段字节流
  71. // src - 源数据区
  72. // srclen - 源数据区字节长度, srclen <= 65536
  73. // dest - 压缩数据区,调用前分配srclen字节内存
  74. // 返回值 > 0 压缩数据长度
  75. // 返回值 = 0 数据无法压缩
  76. // 返回值 < 0 压缩中异常错误
  77. int Compress(BYTE* src, int srclen, BYTE* dest);
  78. /////////////////////////////////////////////
  79. // 解压缩一段字节流
  80. // src - 接收原始数据的内存区, srclen <= 65536
  81. // srclen - 源数据区字节长度
  82. // dest - 压缩数据区
  83. // 返回值 - 成功与否
  84. BOOL Decompress(BYTE* src, int srclen, BYTE* dest);
  85. protected:
  86. BYTE* pWnd;
  87. // 窗口大小最大为 64k ,并且不做滑动
  88. // 每次最多只压缩 64k 数据,这样可以方便从文件中间开始解压
  89. // 当前窗口的长度
  90. int nWndSize;
  91. // 对滑动窗口中每一个2字节串排序
  92. // 排序是为了进行快速术语匹配
  93. // 排序的方法是用一个64k大小的指针数组
  94. // 数组下标依次对应每一个2字节串:(00 00) (00 01) ... (01 00) (01 01) ...
  95. // 每一个指针指向一个链表,链表中的节点为该2字节串的每一个出现位置
  96. struct STIDXNODE
  97. {
  98. WORD off; // 在src中的偏移
  99. WORD off2; // 用于对应的2字节串为重复字节的节点
  100. // 指从 off 到 off2 都对应了该2字节串
  101. WORD next; // 在SortHeap中的指针
  102. };
  103. WORD SortTable[65536];  // 256 * 256 指向SortHeap中下标的指针
  104. // 因为窗口不滑动,没有删除节点的操作,所以
  105. // 节点可以在SortHeap 中连续分配
  106. struct STIDXNODE* SortHeap;
  107. int HeapPos; // 当前分配位置
  108. // 当前输出位置(字节偏移及位偏移)
  109. int CurByte, CurBit;
  110. protected:
  111. ////////////////////////////////////////
  112. // 输出压缩码
  113. // code - 要输出的数
  114. // bits - 要输出的位数(对isGamma=TRUE时无效)
  115. // isGamma - 是否输出为γ编码
  116. void _OutCode(BYTE* dest, DWORD code, int bits, BOOL isGamma);
  117. ///////////////////////////////////////////////////////////
  118. // 在滑动窗口中查找术语
  119. // nSeekStart - 从何处开始匹配
  120. // offset, len - 用于接收结果,表示在滑动窗口内的偏移和长度
  121. // 返回值- 是否查到长度为3或3以上的匹配字节串
  122. BOOL _SeekPhase(BYTE* src, int srclen, int nSeekStart, int* offset, int* len);
  123. ///////////////////////////////////////////////////////////
  124. // 得到已经匹配了3个字节的窗口位置offset
  125. // 共能匹配多少个字节
  126. inline int _GetSameLen(BYTE* src, int srclen, int nSeekStart, int offset);
  127. //////////////////////////////////////////
  128. // 将窗口向右滑动n个字节
  129. inline void _ScrollWindow(int n);
  130. // 向索引中添加一个2字节串
  131. inline void _InsertIndexItem(int off);
  132. // 初始化索引表,释放上次压缩用的空间
  133. void _InitSortTable();
  134. };
  135. #endif // _WIX_LZW_COMPRESS_HEADER_001_