HRESULT CDecoder::ReadCoderProperties(ISequentialInStream *anInStream) { UINT32 aNumPosStateBits; UINT32 aLiteralPosStateBits; UINT32 aLiteralContextBits; UINT32 aDictionarySize; UINT32 aProcessesedSize; BYTE aByte; RETURN_IF_NOT_S_OK(anInStream->Read(&aByte, sizeof(aByte), &aProcessesedSize)); if (aProcessesedSize != sizeof(aByte)) return E_INVALIDARG; aLiteralContextBits = aByte % 9; BYTE aRemainder = aByte / 9; aLiteralPosStateBits = aRemainder % 5; aNumPosStateBits = aRemainder / 5; UINT8 uint_buffer[UINT_SIZE]; RETURN_IF_NOT_S_OK(anInStream->Read(uint_buffer, sizeof(aDictionarySize), &aProcessesedSize)); aDictionarySize = charp_to_uint(uint_buffer); if (aProcessesedSize != sizeof(aDictionarySize)) return E_INVALIDARG; RETURN_IF_NOT_S_OK(SetDictionarySize(aDictionarySize)); RETURN_IF_NOT_S_OK(SetLiteralProperties(aLiteralPosStateBits, aLiteralContextBits)); RETURN_IF_NOT_S_OK(SetPosBitsProperties(aNumPosStateBits)); return S_OK; }
HRESULT CIn::ReadBlock() { if(m_StreamEndWasReached) return S_OK; while(true) { INT aSize = (m_BufferBase + m_BlockSize) - (m_Buffer + m_StreamPos); if(aSize == 0) return S_OK; INT aNumReadBytes; RETURN_IF_NOT_S_OK(m_Stream->Read(m_Buffer + m_StreamPos, aSize, &aNumReadBytes)); if(aNumReadBytes == 0) { m_PosLimit = m_StreamPos; const BYTE *aPointerToPostion = m_Buffer + m_PosLimit; if(aPointerToPostion > m_PointerToLastSafePosition) m_PosLimit = m_PointerToLastSafePosition - m_Buffer; m_StreamEndWasReached = true; return S_OK; } m_StreamPos += aNumReadBytes; if(m_StreamPos >= m_Pos + m_KeepSizeAfter) { m_PosLimit = m_StreamPos - m_KeepSizeAfter; return S_OK; } } }
HRESULT LzmaDecoderReadCoderProperties(LzmaDecoder *lzmaDecoder) { UINT32 aNumPosStateBits; UINT32 aLiteralPosStateBits; UINT32 aLiteralContextBits; UINT32 aDictionarySize; BYTE aRemainder; UINT32 aProcessesedSize; BYTE aByte; RETURN_IF_NOT_S_OK(InStreamRead(&aByte, sizeof(aByte), &aProcessesedSize)); if (aProcessesedSize != sizeof(aByte)) return E_INVALIDARG; aLiteralContextBits = aByte % 9; aRemainder = aByte / 9; aLiteralPosStateBits = aRemainder % 5; aNumPosStateBits = aRemainder / 5; RETURN_IF_NOT_S_OK(InStreamRead(&aDictionarySize, sizeof(aDictionarySize), &aProcessesedSize)); if (aProcessesedSize != sizeof(aDictionarySize)) return E_INVALIDARG; RETURN_IF_NOT_S_OK( LzmaDecoderSetDictionarySize(lzmaDecoder, aDictionarySize) ); RETURN_IF_NOT_S_OK( LzmaDecoderSetLiteralProperties(lzmaDecoder, aLiteralPosStateBits, aLiteralContextBits) ); RETURN_IF_NOT_S_OK( LzmaDecoderSetPosBitsProperties(lzmaDecoder, aNumPosStateBits) ); return S_OK; }
HRESULT CCoder::CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize) { if (!m_Created) { RETURN_IF_NOT_S_OK(Create()); m_Created = true; } UINT64 aNowPos = 0; m_FinderPos = 0; RETURN_IF_NOT_S_OK(m_MatchFinder.Init(anInStream)); m_OutStream.Init(anOutStream); m_ReverseOutStream.Init(&m_OutStream); InitStructures(); while(true) { int aCurrentPassIndex = 0; bool aNoMoreBytes; while (true) { while(true) { aNoMoreBytes = (m_AdditionalOffset == 0 && m_MatchFinder.GetNumAvailableBytes() == 0); if (((m_CurrentBlockUncompressedSize >= kBlockUncompressedSizeThreshold || m_ValueIndex >= kValueBlockSize) && (m_OptimumEndIndex == m_OptimumCurrentIndex)) || aNoMoreBytes) break; UINT32 aPos; UINT32 aLen = GetOptimal(aPos); if (aLen >= kMatchMinLen) { UINT32 aNewLen = aLen - kMatchMinLen; m_Values[m_ValueIndex].Flag = kFlagLenPos; m_Values[m_ValueIndex].Len = BYTE(aNewLen); UINT32 aLenSlot = g_LenSlots[aNewLen]; m_MainCoder.AddSymbol(kMatchNumber + aLenSlot); m_Values[m_ValueIndex].Pos = UINT16(aPos); UINT32 aPosSlot = GetPosSlot(aPos); m_DistCoder.AddSymbol(aPosSlot); } else if (aLen == 1) { BYTE aByte = m_MatchFinder.GetIndexByte(0 - m_AdditionalOffset); aLen = 1; m_MainCoder.AddSymbol(aByte); m_Values[m_ValueIndex].Flag = kFlagImm; m_Values[m_ValueIndex].Imm = aByte; } else throw E_INTERNAL_ERROR; m_ValueIndex++; m_AdditionalOffset -= aLen; aNowPos += aLen; m_CurrentBlockUncompressedSize += aLen; } aCurrentPassIndex++; bool aWriteMode = (aCurrentPassIndex == m_NumPasses); WriteBlockData(aWriteMode, aNoMoreBytes); if (aWriteMode) break; aNowPos = m_BlockStartPostion; m_AdditionalOffset = UINT32(m_FinderPos - m_BlockStartPostion); m_CurrentBlockUncompressedSize = 0; } m_BlockStartPostion += m_CurrentBlockUncompressedSize; m_CurrentBlockUncompressedSize = 0; if (aNoMoreBytes) break; } return m_OutStream.Flush(); }