annotate src/win32/7zip/7z/CPP/7zip/Compress/PpmdDecoder.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 // PpmdDecoder.cpp
rlm@1 2
rlm@1 3 #include "StdAfx.h"
rlm@1 4
rlm@1 5 #include "Common/Defs.h"
rlm@1 6 #include "Windows/Defs.h"
rlm@1 7
rlm@1 8 #include "PpmdDecoder.h"
rlm@1 9
rlm@1 10 namespace NCompress {
rlm@1 11 namespace NPpmd {
rlm@1 12
rlm@1 13 const int kLenIdFinished = -1;
rlm@1 14 const int kLenIdNeedInit = -2;
rlm@1 15
rlm@1 16 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
rlm@1 17 {
rlm@1 18 if (size < 5)
rlm@1 19 return E_INVALIDARG;
rlm@1 20 _order = properties[0];
rlm@1 21 _usedMemorySize = 0;
rlm@1 22 for (int i = 0; i < 4; i++)
rlm@1 23 _usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8);
rlm@1 24
rlm@1 25 if (_usedMemorySize > kMaxMemBlockSize)
rlm@1 26 return E_NOTIMPL;
rlm@1 27
rlm@1 28 if (!_rangeDecoder.Create(1 << 20))
rlm@1 29 return E_OUTOFMEMORY;
rlm@1 30 if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))
rlm@1 31 return E_OUTOFMEMORY;
rlm@1 32
rlm@1 33 return S_OK;
rlm@1 34 }
rlm@1 35
rlm@1 36 class CDecoderFlusher
rlm@1 37 {
rlm@1 38 CDecoder *_coder;
rlm@1 39 public:
rlm@1 40 bool NeedFlush;
rlm@1 41 CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {}
rlm@1 42 ~CDecoderFlusher()
rlm@1 43 {
rlm@1 44 if (NeedFlush)
rlm@1 45 _coder->Flush();
rlm@1 46 _coder->ReleaseStreams();
rlm@1 47 }
rlm@1 48 };
rlm@1 49
rlm@1 50 HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream)
rlm@1 51 {
rlm@1 52 if (_outSizeDefined)
rlm@1 53 {
rlm@1 54 const UInt64 rem = _outSize - _processedSize;
rlm@1 55 if (size > rem)
rlm@1 56 size = (UInt32)rem;
rlm@1 57 }
rlm@1 58 const UInt32 startSize = size;
rlm@1 59
rlm@1 60 if (_remainLen == kLenIdFinished)
rlm@1 61 return S_OK;
rlm@1 62 if (_remainLen == kLenIdNeedInit)
rlm@1 63 {
rlm@1 64 _rangeDecoder.Init();
rlm@1 65 _remainLen = 0;
rlm@1 66 _info.MaxOrder = 0;
rlm@1 67 _info.StartModelRare(_order);
rlm@1 68 }
rlm@1 69 while (size != 0)
rlm@1 70 {
rlm@1 71 int symbol = _info.DecodeSymbol(&_rangeDecoder);
rlm@1 72 if (symbol < 0)
rlm@1 73 {
rlm@1 74 _remainLen = kLenIdFinished;
rlm@1 75 break;
rlm@1 76 }
rlm@1 77 if (memStream != 0)
rlm@1 78 *memStream++ = (Byte)symbol;
rlm@1 79 else
rlm@1 80 _outStream.WriteByte((Byte)symbol);
rlm@1 81 size--;
rlm@1 82 }
rlm@1 83 _processedSize += startSize - size;
rlm@1 84 return S_OK;
rlm@1 85 }
rlm@1 86
rlm@1 87 STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
rlm@1 88 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
rlm@1 89 {
rlm@1 90 if (!_outStream.Create(1 << 20))
rlm@1 91 return E_OUTOFMEMORY;
rlm@1 92
rlm@1 93 SetInStream(inStream);
rlm@1 94 _outStream.SetStream(outStream);
rlm@1 95 SetOutStreamSize(outSize);
rlm@1 96 CDecoderFlusher flusher(this);
rlm@1 97
rlm@1 98 for (;;)
rlm@1 99 {
rlm@1 100 _processedSize = _outStream.GetProcessedSize();
rlm@1 101 UInt32 curSize = (1 << 18);
rlm@1 102 RINOK(CodeSpec(curSize, NULL));
rlm@1 103 if (_remainLen == kLenIdFinished)
rlm@1 104 break;
rlm@1 105 if (progress != NULL)
rlm@1 106 {
rlm@1 107 UInt64 inSize = _rangeDecoder.GetProcessedSize();
rlm@1 108 RINOK(progress->SetRatioInfo(&inSize, &_processedSize));
rlm@1 109 }
rlm@1 110 if (_outSizeDefined)
rlm@1 111 if (_outStream.GetProcessedSize() >= _outSize)
rlm@1 112 break;
rlm@1 113 }
rlm@1 114 flusher.NeedFlush = false;
rlm@1 115 return Flush();
rlm@1 116 }
rlm@1 117
rlm@1 118 #ifdef _NO_EXCEPTIONS
rlm@1 119
rlm@1 120 #define PPMD_TRY_BEGIN
rlm@1 121 #define PPMD_TRY_END
rlm@1 122
rlm@1 123 #else
rlm@1 124
rlm@1 125 #define PPMD_TRY_BEGIN try {
rlm@1 126 #define PPMD_TRY_END } \
rlm@1 127 catch(const CInBufferException &e) { return e.ErrorCode; } \
rlm@1 128 catch(const COutBufferException &e) { return e.ErrorCode; } \
rlm@1 129 catch(...) { return S_FALSE; }
rlm@1 130
rlm@1 131 #endif
rlm@1 132
rlm@1 133
rlm@1 134 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
rlm@1 135 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
rlm@1 136 {
rlm@1 137 PPMD_TRY_BEGIN
rlm@1 138 return CodeReal(inStream, outStream, inSize, outSize, progress);
rlm@1 139 PPMD_TRY_END
rlm@1 140 }
rlm@1 141
rlm@1 142 STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
rlm@1 143 {
rlm@1 144 _rangeDecoder.SetStream(inStream);
rlm@1 145 return S_OK;
rlm@1 146 }
rlm@1 147
rlm@1 148 STDMETHODIMP CDecoder::ReleaseInStream()
rlm@1 149 {
rlm@1 150 _rangeDecoder.ReleaseStream();
rlm@1 151 return S_OK;
rlm@1 152 }
rlm@1 153
rlm@1 154 STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
rlm@1 155 {
rlm@1 156 _outSizeDefined = (outSize != NULL);
rlm@1 157 if (_outSizeDefined)
rlm@1 158 _outSize = *outSize;
rlm@1 159 _processedSize = 0;
rlm@1 160 _remainLen = kLenIdNeedInit;
rlm@1 161 _outStream.Init();
rlm@1 162 return S_OK;
rlm@1 163 }
rlm@1 164
rlm@1 165 #ifndef NO_READ_FROM_CODER
rlm@1 166
rlm@1 167 STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
rlm@1 168 {
rlm@1 169 PPMD_TRY_BEGIN
rlm@1 170 if (processedSize)
rlm@1 171 *processedSize = 0;
rlm@1 172 const UInt64 startPos = _processedSize;
rlm@1 173 RINOK(CodeSpec(size, (Byte *)data));
rlm@1 174 if (processedSize)
rlm@1 175 *processedSize = (UInt32)(_processedSize - startPos);
rlm@1 176 return Flush();
rlm@1 177 PPMD_TRY_END
rlm@1 178 }
rlm@1 179
rlm@1 180 #endif
rlm@1 181
rlm@1 182 }}