summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/7zip/Compress/ArjDecoder2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/Compress/ArjDecoder2.cpp')
-rw-r--r--src/libs/7zip/win/CPP/7zip/Compress/ArjDecoder2.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/ArjDecoder2.cpp b/src/libs/7zip/win/CPP/7zip/Compress/ArjDecoder2.cpp
new file mode 100644
index 000000000..365993bc5
--- /dev/null
+++ b/src/libs/7zip/win/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; }
+}
+
+}}}