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.cpp
3 #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 else
93 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 else
125 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 }}