Mercurial > vba-linux
view 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 source
1 // LzhDecoder.cpp3 #include "StdAfx.h"5 #include "LzhDecoder.h"7 #include "Windows/Defs.h"9 namespace NCompress{10 namespace NLzh {11 namespace NDecoder {13 static const UInt32 kHistorySize = (1 << 16);15 static const int kBlockSizeBits = 16;16 static const int kNumCBits = 9;17 static const int kNumLevelBits = 5; // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/19 UInt32 CCoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }21 HRESULT CCoder::ReadLevelTable()22 {23 int n = ReadBits(kNumLevelBits);24 if (n == 0)25 {26 m_LevelHuffman.Symbol = ReadBits(kNumLevelBits);27 if (m_LevelHuffman.Symbol >= kNumLevelSymbols)28 return S_FALSE;29 }30 else31 {32 if (n > kNumLevelSymbols)33 return S_FALSE;34 m_LevelHuffman.Symbol = -1;35 Byte lens[kNumLevelSymbols];36 int i = 0;37 while (i < n)38 {39 int c = m_InBitStream.ReadBits(3);40 if (c == 7)41 while (ReadBits(1))42 if (c++ > kMaxHuffmanLen)43 return S_FALSE;44 lens[i++] = (Byte)c;45 if (i == kNumSpecLevelSymbols)46 {47 c = ReadBits(2);48 while (--c >= 0)49 lens[i++] = 0;50 }51 }52 while (i < kNumLevelSymbols)53 lens[i++] = 0;54 m_LevelHuffman.SetCodeLengths(lens);55 }56 return S_OK;57 }59 HRESULT CCoder::ReadPTable(int numBits)60 {61 int n = ReadBits(numBits);62 if (n == 0)63 {64 m_PHuffmanDecoder.Symbol = ReadBits(numBits);65 if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols)66 return S_FALSE;67 }68 else69 {70 if (n > kNumDistanceSymbols)71 return S_FALSE;72 m_PHuffmanDecoder.Symbol = -1;73 Byte lens[kNumDistanceSymbols];74 int i = 0;75 while (i < n)76 {77 int c = m_InBitStream.ReadBits(3);78 if (c == 7)79 while (ReadBits(1))80 {81 if (c > kMaxHuffmanLen)82 return S_FALSE;83 c++;84 }85 lens[i++] = (Byte)c;86 }87 while (i < kNumDistanceSymbols)88 lens[i++] = 0;89 m_PHuffmanDecoder.SetCodeLengths(lens);90 }91 return S_OK;92 }94 HRESULT CCoder::ReadCTable()95 {96 int n = ReadBits(kNumCBits);97 if (n == 0)98 {99 m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits);100 if (m_CHuffmanDecoder.Symbol >= kNumCSymbols)101 return S_FALSE;102 }103 else104 {105 if (n > kNumCSymbols)106 return S_FALSE;107 m_CHuffmanDecoder.Symbol = -1;108 Byte lens[kNumCSymbols];109 int i = 0;110 while (i < n)111 {112 int c = m_LevelHuffman.Decode(&m_InBitStream);113 if (c < kNumSpecLevelSymbols)114 {115 if (c == 0)116 c = 1;117 else if (c == 1)118 c = ReadBits(4) + 3;119 else120 c = ReadBits(kNumCBits) + 20;121 while (--c >= 0)122 {123 if (i > kNumCSymbols)124 return S_FALSE;125 lens[i++] = 0;126 }127 }128 else129 lens[i++] = (Byte)(c - 2);130 }131 while (i < kNumCSymbols)132 lens[i++] = 0;133 m_CHuffmanDecoder.SetCodeLengths(lens);134 }135 return S_OK;136 }138 STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,139 ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,140 ICompressProgressInfo *progress)141 {142 if (outSize == NULL)143 return E_INVALIDARG;145 if (!m_OutWindowStream.Create(kHistorySize))146 return E_OUTOFMEMORY;147 if (!m_InBitStream.Create(1 << 20))148 return E_OUTOFMEMORY;150 UInt64 pos = 0;151 m_OutWindowStream.SetStream(outStream);152 m_OutWindowStream.Init(false);153 m_InBitStream.SetStream(inStream);154 m_InBitStream.Init();156 CCoderReleaser coderReleaser(this);158 int pbit;159 if (m_NumDictBits <= 13)160 pbit = 4;161 else162 pbit = 5;164 UInt32 blockSize = 0;166 while(pos < *outSize)167 {168 // for (i = 0; i < dictSize; i++) dtext[i] = 0x20;170 if (blockSize == 0)171 {172 if (progress != NULL)173 {174 UInt64 packSize = m_InBitStream.GetProcessedSize();175 RINOK(progress->SetRatioInfo(&packSize, &pos));176 }177 blockSize = ReadBits(kBlockSizeBits);178 ReadLevelTable();179 ReadCTable();180 RINOK(ReadPTable(pbit));181 }182 blockSize--;183 UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream);184 if (c < 256)185 {186 m_OutWindowStream.PutByte((Byte)c);187 pos++;188 }189 else if (c >= kNumCSymbols)190 return S_FALSE;191 else192 {193 // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3;194 UInt32 len = c - 256 + kMinMatch;195 UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream);196 if (distance != 0)197 distance = (1 << (distance - 1)) + ReadBits(distance - 1);198 if (distance >= pos)199 return S_FALSE;200 if (pos + len > *outSize)201 len = (UInt32)(*outSize - pos);202 pos += len;203 m_OutWindowStream.CopyBlock(distance, len);204 }205 }206 coderReleaser.NeedFlush = false;207 return m_OutWindowStream.Flush();208 }210 STDMETHODIMP CCoder::Code(ISequentialInStream *inStream,211 ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,212 ICompressProgressInfo *progress)213 {214 try { return CodeReal(inStream, outStream, inSize, outSize, progress);}215 catch(const CInBufferException &e) { return e.ErrorCode; }216 catch(const CLzOutWindowException &e) { return e.ErrorCode; }217 catch(...) { return S_FALSE; }218 }220 }}}