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