📄 shrinkdecoder.cpp
字号:
// ShrinkDecoder.cpp#include "StdAfx.h"#include "ShrinkDecoder.h"#include "../../../Common/Alloc.h"#include "../../Common/InBuffer.h"#include "../../Common/OutBuffer.h"#include "../../Common/LSBFDecoder.h"namespace NCompress {namespace NShrink {static const UInt32 kBufferSize = (1 << 20);static const int kNumMinBits = 9; STDMETHODIMP CDecoder ::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress){ NStream::NLSBF::CBaseDecoder<CInBuffer> inBuffer; COutBuffer outBuffer; if (!inBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; inBuffer.SetStream(inStream); inBuffer.Init(); if (!outBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; outBuffer.SetStream(outStream); outBuffer.Init(); UInt64 prevPos = 0; int numBits = kNumMinBits; UInt32 head = 257; bool needPrev = false; _parents[256] = 0; // virus protection _suffixes[256] = 0; int i; for (i = 0; i < 257; i++) _isFree[i] = false; for (; i < kNumItems; i++) _isFree[i] = true; UInt32 lastSymbol = 0; while (true) { outBuffer.Flush(); UInt32 symbol = inBuffer.ReadBits(numBits); if (inBuffer.ExtraBitsWereRead()) break; if (_isFree[symbol]) return S_FALSE; if (symbol == 256) { // fix it; UInt32 symbol = inBuffer.ReadBits(numBits); if (symbol == 1) { if (numBits < kNumMaxBits) numBits++; } else if (symbol == 2) { /* maybe need delete prev also ? if (needPrev) _isFree[head - 1] = true; */ for (i = 257; i < kNumItems; i++) _isParent[i] = false; for (i = 257; i < kNumItems; i++) if (!_isFree[i]) _isParent[_parents[i]] = true; for (i = 257; i < kNumItems; i++) if (!_isParent[i]) _isFree[i] = true; head = 257; while(head < ((UInt32)1 << numBits) && !_isFree[head]) head++; if (head < ((UInt32)1 << numBits)) { needPrev = true; _isFree[head] = false; _parents[head] = (UInt16)lastSymbol; head++; } } else return S_FALSE; continue; } UInt32 cur = symbol; i = 0; while (cur >= 256) { _stack[i++] = _suffixes[cur]; cur = _parents[cur]; } _stack[i++] = (Byte)cur; if (needPrev) { _suffixes[head - 1] = (Byte)cur; if (symbol == head - 1) _stack[0] = (Byte)cur; } while (i > 0) outBuffer.WriteByte((_stack[--i])); while(head < ((UInt32)1 << numBits) && !_isFree[head]) head++; if (head < ((UInt32)1 << numBits)) { needPrev = true; _isFree[head] = false; _parents[head] = (UInt16)symbol; head++; } else needPrev = false; lastSymbol = symbol; UInt64 nowPos = outBuffer.GetProcessedSize(); if (progress != NULL && nowPos - prevPos > (1 << 18)) { prevPos = nowPos; UInt64 packSize = inBuffer.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &nowPos)); } } return outBuffer.Flush();}STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress){ try { return CodeReal(inStream, outStream, inSize, outSize, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; }}}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -