Lzss.cpp
上传用户:deer201011
上传日期:2022-06-24
资源大小:10k
文件大小:7k
源码类别:

压缩解压

开发平台:

Visual C++

  1. // Lzss.cpp
  2. #include "CompressedFile.h"
  3. #define END_OF_STREAM 0
  4. #ifdef UNUSED
  5. #undef UNUSED
  6. #endif
  7. #define UNUSED 0
  8. BOOL CLzssFile::Open( const char *pszFileName, unsigned int nOpenFlags, CFileException *pError )
  9. {
  10. memset( ucWindow, 0, WINDOW_SIZE );
  11. m_pExtraBuffer = (unsigned char *) new unsigned char [16000];
  12. m_dwExtra = 0;
  13. m_nCompressionType = LZSS;
  14. m_bInitialized = FALSE;
  15. m_nStoreLookAhead = 0;
  16. m_dwPointer = 0L;
  17. m_nCurrentPosition = 1;
  18. return( CCompressedFile::Open( pszFileName, nOpenFlags, pError ) );
  19. }
  20. void CLzssFile::Close( void )
  21. {
  22. if( m_pExtraBuffer != NULL ) delete [] m_pExtraBuffer;
  23. m_pExtraBuffer = NULL;
  24. if( m_nFlags != CFile::modeRead ){
  25. OutputBit( 0 );
  26. OutputBits( (DWORD) END_OF_STREAM, INDEX_BIT_COUNT );
  27. }
  28. CCompressedFile::Close();
  29. if( m_nFlags == ( CFile::modeCreate | CFile::modeWrite ) || m_nFlags == CFile::modeWrite ){
  30. CFile cf;
  31. cf.Open( m_szFilename, CFile::modeWrite );
  32. cf.Seek( m_dwSeekTo, CFile::begin );
  33. cf.Write( &m_dwUncompressedSize, sizeof( DWORD ) );
  34. cf.Write( &m_dwCompressedSize, sizeof( DWORD ) );
  35. cf.Close();
  36. }
  37. }
  38. unsigned int CLzssFile::Read( void far *lpBuf, unsigned int nCount )
  39. {
  40. unsigned char *pTransfer;
  41. unsigned int nBytesRead = 0;
  42. int c;
  43. pTransfer = (unsigned char *) lpBuf;
  44. m_dwPointer = 0L;
  45. m_nCurrentPosition = 1;
  46. while( m_dwExtra && m_dwPointer < (DWORD) nCount ){
  47. pTransfer[m_dwPointer++] = m_pExtraBuffer[m_dwExtraPointer];
  48. m_dwExtraPointer++;
  49. m_dwExtra--;
  50. nBytesRead++;
  51. }
  52. for ( ; ; ){
  53. if( InputBit() ){
  54. c = (int) InputBits( 8 );
  55. pTransfer[m_dwPointer++] = (unsigned char) c;
  56. ucWindow[m_nCurrentPosition] = (unsigned char) c;
  57. m_nCurrentPosition = MOD_WINDOW( m_nCurrentPosition + 1 );
  58. nBytesRead++;
  59. }
  60. else{
  61. m_nMatchPosition = (int) InputBits( INDEX_BIT_COUNT );
  62. if( m_nMatchPosition == END_OF_STREAM ) break;
  63. m_nMatchLength = (int) InputBits( LENGTH_BIT_COUNT );
  64. m_nMatchLength += BREAK_EVEN;
  65. m_dwExtraPointer = 0L;
  66. for( int i=0; i<=m_nMatchLength; i++ ){
  67. c = (int) ucWindow[MOD_WINDOW(m_nMatchPosition+i)];
  68. if( m_dwPointer < (DWORD) nCount ){
  69. nBytesRead++;
  70. pTransfer[m_dwPointer++] = (unsigned char) c;
  71. }
  72. else if( m_pExtraBuffer ){
  73. m_pExtraBuffer[m_dwExtra++] = (unsigned char) c;
  74. }
  75. ucWindow[m_nCurrentPosition] = (unsigned char) c;
  76. m_nCurrentPosition = MOD_WINDOW( m_nCurrentPosition + 1 );
  77. }
  78. }
  79. if( m_dwPointer >= (DWORD) nCount ) break;
  80. }
  81. return( nBytesRead );
  82. }
  83. void CLzssFile::Write( void *lpBuf, unsigned int nCount )
  84. {
  85. m_dwBytesToEncode = (DWORD) nCount;
  86. m_dwPointer = 0L;
  87. EncodeSymbols( (unsigned char *) lpBuf );
  88. m_dwUncompressedSize += (DWORD) nCount;
  89. }
  90. void CLzssFile::EncodeSymbols( unsigned char *lpBuf, BOOL bEndFlag )
  91. {
  92. int i, c;
  93. if( !m_bInitialized ){
  94. while( m_nStoreLookAhead < LOOK_AHEAD_SIZE && !bEndFlag && m_dwBytesToEncode ){
  95. ucWindow[++m_nStoreLookAhead] = lpBuf[m_dwPointer++];
  96. m_dwBytesToEncode--;
  97. }
  98. if( !bEndFlag && m_nStoreLookAhead < LOOK_AHEAD_SIZE ) return;
  99. m_nLookAheadBytes = m_nStoreLookAhead;
  100. InitializeTree();
  101. m_nMatchLength = m_nMatchPosition = 0;
  102. m_bInitialized = 1;
  103. }
  104. if( m_bInitialized == 2 ) goto LZSSEntry;
  105. m_bInitialized = 2;
  106. while( m_nLookAheadBytes > 0 ){
  107. if( m_nMatchLength > m_nLookAheadBytes ) m_nMatchLength = m_nLookAheadBytes;
  108. if( m_nMatchLength <= BREAK_EVEN ){
  109. m_nReplaceCount = 1;
  110. OutputBit( 1 );
  111. OutputBits( (DWORD) ucWindow[m_nCurrentPosition], 8 );
  112. }
  113. else{
  114. OutputBit( 0 );
  115. OutputBits( (DWORD) m_nMatchPosition, INDEX_BIT_COUNT );
  116. OutputBits( (DWORD) ( m_nMatchLength - ( BREAK_EVEN + 1 ) ), LENGTH_BIT_COUNT );
  117. m_nReplaceCount = m_nMatchLength;
  118. }
  119. for( i=0; i<m_nReplaceCount; i++ ){
  120. DeleteString( MOD_WINDOW( m_nCurrentPosition + LOOK_AHEAD_SIZE ) );
  121. LZSSEntry:
  122. if( m_dwBytesToEncode ){
  123. c = (int) lpBuf[m_dwPointer++], m_dwBytesToEncode--;
  124. ucWindow[MOD_WINDOW(m_nCurrentPosition+LOOK_AHEAD_SIZE)] = (unsigned char) c;
  125. }
  126. else m_nLookAheadBytes--;
  127. m_nCurrentPosition = MOD_WINDOW( m_nCurrentPosition + 1 );
  128. if( m_nLookAheadBytes ) m_nMatchLength = AddString( m_nCurrentPosition, &m_nMatchPosition );
  129. }
  130. }
  131. }
  132. void CLzssFile::InitializeTree( void )
  133. {
  134. for( int i=0; i<WINDOW_SIZE+1; i++ ) memset ( &Tree[i], 0, sizeof( LZSS_TREE ) );
  135. Tree[TREE_ROOT].nLargerChild = 1;
  136. Tree[1].nParent = TREE_ROOT;
  137. Tree[1].nLargerChild = UNUSED;
  138. Tree[1].nSmallerChild = UNUSED;
  139. }
  140. void CLzssFile::ContractNode( int nOldNode, int nNewNode )
  141. {
  142. Tree[nNewNode].nParent = Tree[nOldNode].nParent;
  143. if( Tree[Tree[nOldNode].nParent].nLargerChild == nOldNode ) Tree[Tree[nOldNode].nParent].nLargerChild = nNewNode;
  144. else Tree[Tree[nOldNode].nParent].nSmallerChild = nNewNode;
  145. Tree[nOldNode].nParent = UNUSED;
  146. }
  147. void CLzssFile::ReplaceNode( int nOldNode, int nNewNode )
  148. {
  149. int nParent;
  150. nParent = Tree[nOldNode].nParent;
  151. if( Tree[nParent].nSmallerChild == nOldNode ) Tree[nParent].nSmallerChild = nNewNode;
  152. else Tree[nParent].nLargerChild = nNewNode;
  153. Tree[nNewNode] = Tree[nOldNode];
  154. Tree[Tree[nNewNode].nSmallerChild].nParent = nNewNode;
  155. Tree[Tree[nNewNode].nLargerChild].nParent = nNewNode;
  156. Tree[nOldNode].nParent = UNUSED;
  157. }
  158. int CLzssFile::FindNextNode( int nNode )
  159. {
  160. int nNext;
  161. nNext = Tree[nNode].nSmallerChild;
  162. while( Tree[nNext].nLargerChild != UNUSED ) nNext = Tree[nNext].nLargerChild;
  163. return( nNext );
  164. }
  165. void CLzssFile::DeleteString( int p )
  166. {
  167. int nReplacement;
  168. if( Tree[p].nParent == UNUSED ) return;
  169. if( Tree[p].nLargerChild == UNUSED ) ContractNode( p, Tree[p].nSmallerChild );
  170. else if( Tree[p].nSmallerChild == UNUSED ) ContractNode( p, Tree[p].nLargerChild );
  171. else{
  172. nReplacement = FindNextNode( p );
  173. DeleteString( nReplacement );
  174. ReplaceNode( p, nReplacement );
  175. }
  176. }
  177. int CLzssFile::AddString( int nNewNode, int *pnMatchPosition )
  178. {
  179. int i;
  180. int nDelta;
  181. int nMatchLength;
  182. int *pnChild;
  183. int nTestNode;
  184. if( nNewNode == END_OF_STREAM ) return( 0 );
  185. nTestNode = Tree[TREE_ROOT].nLargerChild;
  186. nMatchLength = 0;
  187. for( ; ; ){
  188. for( i=0; i<LOOK_AHEAD_SIZE; i++ ){
  189. nDelta = ucWindow[MOD_WINDOW(nNewNode+i)] - ucWindow[MOD_WINDOW(nTestNode+i)];
  190. if( nDelta ) break;
  191. }
  192. if( i >= nMatchLength ){
  193. nMatchLength = i;
  194. *pnMatchPosition = nTestNode;
  195. if( nMatchLength >= LOOK_AHEAD_SIZE ){
  196. ReplaceNode( nTestNode, nNewNode );
  197. return( nMatchLength );
  198. }
  199. }
  200. if( nDelta >= 0 ) pnChild = &Tree[nTestNode].nLargerChild;
  201. else pnChild = &Tree[nTestNode].nSmallerChild;
  202. if( *pnChild == UNUSED ){
  203. *pnChild = nNewNode;
  204. Tree[nNewNode].nParent = nTestNode;
  205. Tree[nNewNode].nLargerChild = UNUSED;
  206. Tree[nNewNode].nSmallerChild = UNUSED;
  207. return( nMatchLength );
  208. }
  209. nTestNode = *pnChild;
  210. }
  211. return( 0 );
  212. }