diff options
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/Compress/ArjDecoder2.cpp')
-rw-r--r-- | src/libs/7zip/unix/CPP/7zip/Compress/ArjDecoder2.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/ArjDecoder2.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/ArjDecoder2.cpp new file mode 100644 index 000000000..365993bc5 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Compress/ArjDecoder2.cpp @@ -0,0 +1,90 @@ +// ArjDecoder2.cpp + +#include "StdAfx.h" + +#include "ArjDecoder2.h" + +namespace NCompress{ +namespace NArj { +namespace NDecoder2 { + +static const UInt32 kHistorySize = 26624; +static const UInt32 kMatchMinLen = 3; + +HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo * /* progress */) +{ + if (outSize == NULL) + return E_INVALIDARG; + + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 20)) + return E_OUTOFMEMORY; + + UInt64 pos = 0; + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(false); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + CCoderReleaser coderReleaser(this); + + while(pos < *outSize) + { + const UInt32 kStartWidth = 0; + const UInt32 kStopWidth = 7; + UInt32 power = 1 << kStartWidth; + UInt32 width; + UInt32 len = 0; + for (width = kStartWidth; width < kStopWidth; width++) + { + if (m_InBitStream.ReadBits(1) == 0) + break; + len += power; + power <<= 1; + } + if (width != 0) + len += m_InBitStream.ReadBits(width); + if (len == 0) + { + m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8)); + pos++; + continue; + } + else + { + len = len - 1 + kMatchMinLen; + const UInt32 kStartWidth = 9; + const UInt32 kStopWidth = 13; + UInt32 power = 1 << kStartWidth; + UInt32 width; + UInt32 distance = 0; + for (width = kStartWidth; width < kStopWidth; width++) + { + if (m_InBitStream.ReadBits(1) == 0) + break; + distance += power; + power <<= 1; + } + if (width != 0) + distance += m_InBitStream.ReadBits(width); + if (distance >= pos) + return S_FALSE; + m_OutWindowStream.CopyBlock(distance, len); + pos += len; + } + } + coderReleaser.NeedFlush = false; + return m_OutWindowStream.Flush(); +} + +STDMETHODIMP CCoder::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 CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +}}} |