Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Compress/ShrinkDecoder.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 // ShrinkDecoder.cpp3 #include "StdAfx.h"5 extern "C"6 {7 #include "../../../C/Alloc.h"8 }10 #include "../Common/InBuffer.h"11 #include "../Common/OutBuffer.h"13 #include "BitlDecoder.h"14 #include "ShrinkDecoder.h"16 namespace NCompress {17 namespace NShrink {19 static const UInt32 kBufferSize = (1 << 20);20 static const int kNumMinBits = 9;22 HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,23 const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)24 {25 NBitl::CBaseDecoder<CInBuffer> inBuffer;26 COutBuffer outBuffer;28 if (!inBuffer.Create(kBufferSize))29 return E_OUTOFMEMORY;30 inBuffer.SetStream(inStream);31 inBuffer.Init();33 if (!outBuffer.Create(kBufferSize))34 return E_OUTOFMEMORY;35 outBuffer.SetStream(outStream);36 outBuffer.Init();38 UInt64 prevPos = 0;39 int numBits = kNumMinBits;40 UInt32 head = 257;41 bool needPrev = false;42 UInt32 lastSymbol = 0;44 int i;45 for (i = 0; i < kNumItems; i++)46 _parents[i] = 0;47 for (i = 0; i < kNumItems; i++)48 _suffixes[i] = 0;49 for (i = 0; i < 257; i++)50 _isFree[i] = false;51 for (; i < kNumItems; i++)52 _isFree[i] = true;54 for (;;)55 {56 UInt32 symbol = inBuffer.ReadBits(numBits);57 if (inBuffer.ExtraBitsWereRead())58 break;59 if (_isFree[symbol])60 return S_FALSE;61 if (symbol == 256)62 {63 UInt32 symbol = inBuffer.ReadBits(numBits);64 if (symbol == 1)65 {66 if (numBits < kNumMaxBits)67 numBits++;68 }69 else if (symbol == 2)70 {71 if (needPrev)72 _isFree[head - 1] = true;73 for (i = 257; i < kNumItems; i++)74 _isParent[i] = false;75 for (i = 257; i < kNumItems; i++)76 if (!_isFree[i])77 _isParent[_parents[i]] = true;78 for (i = 257; i < kNumItems; i++)79 if (!_isParent[i])80 _isFree[i] = true;81 head = 257;82 while (head < kNumItems && !_isFree[head])83 head++;84 if (head < kNumItems)85 {86 needPrev = true;87 _isFree[head] = false;88 _parents[head] = (UInt16)lastSymbol;89 head++;90 }91 }92 else93 return S_FALSE;94 continue;95 }96 UInt32 cur = symbol;97 i = 0;98 int corectionIndex = -1;99 while (cur >= 256)100 {101 if (cur == head - 1)102 corectionIndex = i;103 _stack[i++] = _suffixes[cur];104 cur = _parents[cur];105 }106 _stack[i++] = (Byte)cur;107 if (needPrev)108 {109 _suffixes[head - 1] = (Byte)cur;110 if (corectionIndex >= 0)111 _stack[corectionIndex] = (Byte)cur;112 }113 while (i > 0)114 outBuffer.WriteByte((_stack[--i]));115 while (head < kNumItems && !_isFree[head])116 head++;117 if (head < kNumItems)118 {119 needPrev = true;120 _isFree[head] = false;121 _parents[head] = (UInt16)symbol;122 head++;123 }124 else125 needPrev = false;126 lastSymbol = symbol;128 UInt64 nowPos = outBuffer.GetProcessedSize();129 if (progress != NULL && nowPos - prevPos > (1 << 18))130 {131 prevPos = nowPos;132 UInt64 packSize = inBuffer.GetProcessedSize();133 RINOK(progress->SetRatioInfo(&packSize, &nowPos));134 }135 }136 return outBuffer.Flush();137 }139 STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,140 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)141 {142 try { return CodeReal(inStream, outStream, inSize, outSize, progress); }143 catch(const CInBufferException &e) { return e.ErrorCode; }144 catch(const COutBufferException &e) { return e.ErrorCode; }145 catch(...) { return S_FALSE; }146 }148 }}