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::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (!m_InBitStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!m_OutWindowStream.Create(kHistorySize)) return E_OUTOFMEMORY; if (outSize == NULL) return E_INVALIDARG; UInt64 pos = 0, unPackSize = *outSize; m_OutWindowStream.SetStream(outStream); m_OutWindowStream.Init(false); m_InBitStream.SetStream(inStream); m_InBitStream.Init(); CCoderReleaser coderReleaser(this); if (!ReadTables()) return S_FALSE; while(pos < unPackSize) { if (progress != NULL && pos % (1 << 16) == 0) { UInt64 packSize = m_InBitStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &pos)); } if(m_InBitStream.ReadBits(1) == kMatchId) // match { UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits); UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream); if (distance >= kDistanceTableSize) return S_FALSE; distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits; UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream); if (lengthSymbol >= kLengthTableSize) return S_FALSE; UInt32 length = lengthSymbol + m_MinMatchLength; if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63 length += m_InBitStream.ReadBits(kNumAdditionalLengthBits); while(distance >= pos && length > 0) { m_OutWindowStream.PutByte(0); pos++; length--; } if (length > 0) m_OutWindowStream.CopyBlock(distance, length); pos += length; } else { Byte b; if (m_LiteralsOn) { UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream); if (temp >= kLiteralTableSize) return S_FALSE; b = (Byte)temp; } else b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte); m_OutWindowStream.PutByte(b); pos++; } } if (pos > unPackSize) return S_FALSE; return m_OutWindowStream.Flush(); }
STDMETHODIMP 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); int pbit; if (m_NumDictBits <= 13) pbit = 4; else pbit = 5; UInt32 blockSize = 0; while (pos < *outSize) { // for (i = 0; i < dictSize; i++) dtext[i] = 0x20; if (blockSize == 0) { if (progress != NULL) { UInt64 packSize = m_InBitStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &pos)); } blockSize = ReadBits(kBlockSizeBits); ReadLevelTable(); ReadCTable(); RINOK(ReadPTable(pbit)); } blockSize--; UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream); if (c < 256) { m_OutWindowStream.PutByte((Byte)c); pos++; } else if (c >= kNumCSymbols) return S_FALSE; else { // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3; UInt32 len = c - 256 + kMinMatch; UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream); if (distance != 0) distance = (1 << (distance - 1)) + ReadBits(distance - 1); if (distance >= pos) return S_FALSE; if (pos + len > *outSize) len = (UInt32)(*outSize - pos); pos += len; m_OutWindowStream.CopyBlock(distance, len); } } coderReleaser.NeedFlush = false; return m_OutWindowStream.Flush(); }