Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Compress/LzhDecoder.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/LzhDecoder.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,220 @@ 1.4 +// LzhDecoder.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "LzhDecoder.h" 1.9 + 1.10 +#include "Windows/Defs.h" 1.11 + 1.12 +namespace NCompress{ 1.13 +namespace NLzh { 1.14 +namespace NDecoder { 1.15 + 1.16 +static const UInt32 kHistorySize = (1 << 16); 1.17 + 1.18 +static const int kBlockSizeBits = 16; 1.19 +static const int kNumCBits = 9; 1.20 +static const int kNumLevelBits = 5; // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/ 1.21 + 1.22 +UInt32 CCoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } 1.23 + 1.24 +HRESULT CCoder::ReadLevelTable() 1.25 +{ 1.26 + int n = ReadBits(kNumLevelBits); 1.27 + if (n == 0) 1.28 + { 1.29 + m_LevelHuffman.Symbol = ReadBits(kNumLevelBits); 1.30 + if (m_LevelHuffman.Symbol >= kNumLevelSymbols) 1.31 + return S_FALSE; 1.32 + } 1.33 + else 1.34 + { 1.35 + if (n > kNumLevelSymbols) 1.36 + return S_FALSE; 1.37 + m_LevelHuffman.Symbol = -1; 1.38 + Byte lens[kNumLevelSymbols]; 1.39 + int i = 0; 1.40 + while (i < n) 1.41 + { 1.42 + int c = m_InBitStream.ReadBits(3); 1.43 + if (c == 7) 1.44 + while (ReadBits(1)) 1.45 + if (c++ > kMaxHuffmanLen) 1.46 + return S_FALSE; 1.47 + lens[i++] = (Byte)c; 1.48 + if (i == kNumSpecLevelSymbols) 1.49 + { 1.50 + c = ReadBits(2); 1.51 + while (--c >= 0) 1.52 + lens[i++] = 0; 1.53 + } 1.54 + } 1.55 + while (i < kNumLevelSymbols) 1.56 + lens[i++] = 0; 1.57 + m_LevelHuffman.SetCodeLengths(lens); 1.58 + } 1.59 + return S_OK; 1.60 +} 1.61 + 1.62 +HRESULT CCoder::ReadPTable(int numBits) 1.63 +{ 1.64 + int n = ReadBits(numBits); 1.65 + if (n == 0) 1.66 + { 1.67 + m_PHuffmanDecoder.Symbol = ReadBits(numBits); 1.68 + if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols) 1.69 + return S_FALSE; 1.70 + } 1.71 + else 1.72 + { 1.73 + if (n > kNumDistanceSymbols) 1.74 + return S_FALSE; 1.75 + m_PHuffmanDecoder.Symbol = -1; 1.76 + Byte lens[kNumDistanceSymbols]; 1.77 + int i = 0; 1.78 + while (i < n) 1.79 + { 1.80 + int c = m_InBitStream.ReadBits(3); 1.81 + if (c == 7) 1.82 + while (ReadBits(1)) 1.83 + { 1.84 + if (c > kMaxHuffmanLen) 1.85 + return S_FALSE; 1.86 + c++; 1.87 + } 1.88 + lens[i++] = (Byte)c; 1.89 + } 1.90 + while (i < kNumDistanceSymbols) 1.91 + lens[i++] = 0; 1.92 + m_PHuffmanDecoder.SetCodeLengths(lens); 1.93 + } 1.94 + return S_OK; 1.95 +} 1.96 + 1.97 +HRESULT CCoder::ReadCTable() 1.98 +{ 1.99 + int n = ReadBits(kNumCBits); 1.100 + if (n == 0) 1.101 + { 1.102 + m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits); 1.103 + if (m_CHuffmanDecoder.Symbol >= kNumCSymbols) 1.104 + return S_FALSE; 1.105 + } 1.106 + else 1.107 + { 1.108 + if (n > kNumCSymbols) 1.109 + return S_FALSE; 1.110 + m_CHuffmanDecoder.Symbol = -1; 1.111 + Byte lens[kNumCSymbols]; 1.112 + int i = 0; 1.113 + while (i < n) 1.114 + { 1.115 + int c = m_LevelHuffman.Decode(&m_InBitStream); 1.116 + if (c < kNumSpecLevelSymbols) 1.117 + { 1.118 + if (c == 0) 1.119 + c = 1; 1.120 + else if (c == 1) 1.121 + c = ReadBits(4) + 3; 1.122 + else 1.123 + c = ReadBits(kNumCBits) + 20; 1.124 + while (--c >= 0) 1.125 + { 1.126 + if (i > kNumCSymbols) 1.127 + return S_FALSE; 1.128 + lens[i++] = 0; 1.129 + } 1.130 + } 1.131 + else 1.132 + lens[i++] = (Byte)(c - 2); 1.133 + } 1.134 + while (i < kNumCSymbols) 1.135 + lens[i++] = 0; 1.136 + m_CHuffmanDecoder.SetCodeLengths(lens); 1.137 + } 1.138 + return S_OK; 1.139 +} 1.140 + 1.141 +STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream, 1.142 + ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, 1.143 + ICompressProgressInfo *progress) 1.144 +{ 1.145 + if (outSize == NULL) 1.146 + return E_INVALIDARG; 1.147 + 1.148 + if (!m_OutWindowStream.Create(kHistorySize)) 1.149 + return E_OUTOFMEMORY; 1.150 + if (!m_InBitStream.Create(1 << 20)) 1.151 + return E_OUTOFMEMORY; 1.152 + 1.153 + UInt64 pos = 0; 1.154 + m_OutWindowStream.SetStream(outStream); 1.155 + m_OutWindowStream.Init(false); 1.156 + m_InBitStream.SetStream(inStream); 1.157 + m_InBitStream.Init(); 1.158 + 1.159 + CCoderReleaser coderReleaser(this); 1.160 + 1.161 + int pbit; 1.162 + if (m_NumDictBits <= 13) 1.163 + pbit = 4; 1.164 + else 1.165 + pbit = 5; 1.166 + 1.167 + UInt32 blockSize = 0; 1.168 + 1.169 + while(pos < *outSize) 1.170 + { 1.171 + // for (i = 0; i < dictSize; i++) dtext[i] = 0x20; 1.172 + 1.173 + if (blockSize == 0) 1.174 + { 1.175 + if (progress != NULL) 1.176 + { 1.177 + UInt64 packSize = m_InBitStream.GetProcessedSize(); 1.178 + RINOK(progress->SetRatioInfo(&packSize, &pos)); 1.179 + } 1.180 + blockSize = ReadBits(kBlockSizeBits); 1.181 + ReadLevelTable(); 1.182 + ReadCTable(); 1.183 + RINOK(ReadPTable(pbit)); 1.184 + } 1.185 + blockSize--; 1.186 + UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream); 1.187 + if (c < 256) 1.188 + { 1.189 + m_OutWindowStream.PutByte((Byte)c); 1.190 + pos++; 1.191 + } 1.192 + else if (c >= kNumCSymbols) 1.193 + return S_FALSE; 1.194 + else 1.195 + { 1.196 + // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3; 1.197 + UInt32 len = c - 256 + kMinMatch; 1.198 + UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream); 1.199 + if (distance != 0) 1.200 + distance = (1 << (distance - 1)) + ReadBits(distance - 1); 1.201 + if (distance >= pos) 1.202 + return S_FALSE; 1.203 + if (pos + len > *outSize) 1.204 + len = (UInt32)(*outSize - pos); 1.205 + pos += len; 1.206 + m_OutWindowStream.CopyBlock(distance, len); 1.207 + } 1.208 + } 1.209 + coderReleaser.NeedFlush = false; 1.210 + return m_OutWindowStream.Flush(); 1.211 +} 1.212 + 1.213 +STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, 1.214 + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, 1.215 + ICompressProgressInfo *progress) 1.216 +{ 1.217 + try { return CodeReal(inStream, outStream, inSize, outSize, progress);} 1.218 + catch(const CInBufferException &e) { return e.ErrorCode; } 1.219 + catch(const CLzOutWindowException &e) { return e.ErrorCode; } 1.220 + catch(...) { return S_FALSE; } 1.221 +} 1.222 + 1.223 +}}}