UINT32 CLZMADecoder::Code(CLZMAStateP lzmaState) { m_RangeDecoder.Init(lzmaState); m_OutWindowStream.Init(lzmaState); int i; for (i = 0; i < sizeof(m_Decoders) / sizeof(CBitDecoder); i++) { ((CBitDecoder *) &m_Decoders)[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_PosDecoder.Init(); m_PosAlignDecoder.Init(); // m_LenDecoder.Init(m_PosStateMask + 1); // m_RepMatchLenDecoder.Init(m_PosStateMask + 1); m_LenDecoder.Init(); m_RepMatchLenDecoder.Init(); //////////////////////// // code CState state; state.Init(); bool peviousIsMatch = false; BYTE previousByte = 0; // kNumRepDistances == 4 UINT32 repDistances[kNumRepDistances] = {1, 1, 1, 1}; /*for(i = 0 ; i < kNumRepDistances; i++) repDistances[i] = 1;*/ UINT32 nowPos = 0; while(nowPos < 0xFFFFFFFF) { int posState = nowPos & m_PosStateMask; if (!m_Decoders.MainChoiceDecoders[state.Index][posState].Decode(&m_RangeDecoder)) { state.UpdateChar(); if(peviousIsMatch) { BYTE matchByte = m_OutWindowStream.GetOneByte(0 - repDistances[0]); previousByte = m_LiteralDecoder.DecodeWithMatchByte(&m_RangeDecoder, nowPos, previousByte, matchByte); peviousIsMatch = false; } else previousByte = m_LiteralDecoder.DecodeNormal(&m_RangeDecoder, nowPos, previousByte); m_OutWindowStream.PutOneByte(previousByte); nowPos++; } else { peviousIsMatch = true; UINT32 distance; int len; if(m_Decoders.MatchChoiceDecoders[state.Index].Decode(&m_RangeDecoder)) { if(!m_Decoders.MatchRepChoiceDecoders[state.Index].Decode(&m_RangeDecoder)) { if(!m_Decoders.MatchRepShortChoiceDecoders[state.Index][posState].Decode(&m_RangeDecoder)) { state.UpdateShortRep(); previousByte = m_OutWindowStream.GetOneByte(0 - repDistances[0]); m_OutWindowStream.PutOneByte(previousByte); nowPos++; continue; } distance = repDistances[0]; } else { if(!m_Decoders.MatchRep1ChoiceDecoders[state.Index].Decode(&m_RangeDecoder)) distance = repDistances[1]; else { if (!m_Decoders.MatchRep2ChoiceDecoders[state.Index].Decode(&m_RangeDecoder)) distance = repDistances[2]; else { distance = repDistances[3]; repDistances[3] = repDistances[2]; } repDistances[2] = repDistances[1]; } repDistances[1] = repDistances[0]; repDistances[0] = distance; } len = m_RepMatchLenDecoder.Decode(&m_RangeDecoder, posState); state.UpdateRep(); } else { len = m_LenDecoder.Decode(&m_RangeDecoder, posState); state.UpdateMatch(); int posSlot = m_PosSlotDecoder[GetLenToPosState2(len)].Decode(&m_RangeDecoder); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); distance = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) distance += m_PosDecoder.Decode(&m_RangeDecoder, posSlot); else { distance += (m_RangeDecoder.DecodeDirectBits( numDirectBits - kNumAlignBits) << kNumAlignBits); distance += m_PosAlignDecoder.Decode(&m_RangeDecoder); } } else distance = posSlot; distance++; repDistances[3] = repDistances[2]; repDistances[2] = repDistances[1]; repDistances[1] = repDistances[0]; repDistances[0] = distance; //LZMAMemCopy(repDistances, repDistances + 1, kNumRepDistances * sizeof(UINT32)); } // it's for stream version (without knowing uncompressed size) //if (distance >= _dictionarySizeCheck) if (!distance) break; if (distance > nowPos) return (-1); len += kMatchMinLen; nowPos += len; // CopyBackBlock { UINT32 fromPos = m_OutWindowStream._pos - distance; if (fromPos >= m_OutWindowStream._windowSize) fromPos += m_OutWindowStream._windowSize; while (len--) { m_OutWindowStream._buffer[m_OutWindowStream._pos++] = m_OutWindowStream._buffer[fromPos++]; if (fromPos >= m_OutWindowStream._windowSize) fromPos = 0; m_OutWindowStream.Flush(); } } previousByte = m_OutWindowStream.GetOneByte((UINT32)(-1)); }
HRESULT CDecoder::CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *, const UINT64 *anOutSize) { if (anOutSize == NULL) return E_INVALIDARG; Init(anInStream, anOutStream); CState aState; aState.Init(); bool aPeviousIsMatch = false; BYTE aPreviousByte = 0; UINT32 aRepDistances[kNumRepDistances]; for(UINT32 i = 0 ; i < kNumRepDistances; i++) aRepDistances[i] = 0; UINT64 aNowPos64 = 0; UINT64 aSize = *anOutSize; while(aNowPos64 < aSize) { UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize); while(aNowPos64 < aNext) { UINT32 aPosState = UINT32(aNowPos64) & m_PosStateMask; if (m_MainChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex) { // aCounts[0]++; aState.UpdateChar(); if(aPeviousIsMatch) { BYTE aMatchByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1); aPreviousByte = m_LiteralDecoder.DecodeWithMatchByte(&m_RangeDecoder, UINT32(aNowPos64), aPreviousByte, aMatchByte); aPeviousIsMatch = false; } else aPreviousByte = m_LiteralDecoder.DecodeNormal(&m_RangeDecoder, UINT32(aNowPos64), aPreviousByte); m_OutWindowStream.PutOneByte(aPreviousByte); aNowPos64++; } else { aPeviousIsMatch = true; UINT32 aDistance, aLen; if(m_MatchChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == (UINT32) kMatchChoiceRepetitionIndex) { if(m_MatchRepChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) { if(m_MatchRepShortChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == 0) { aState.UpdateShortRep(); aPreviousByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1); m_OutWindowStream.PutOneByte(aPreviousByte); aNowPos64++; // aCounts[3 + 4]++; continue; } // aCounts[3 + 0]++; aDistance = aRepDistances[0]; } else { if(m_MatchRep1ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) { aDistance = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; // aCounts[3 + 1]++; } else { if (m_MatchRep2ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) { // aCounts[3 + 2]++; aDistance = aRepDistances[2]; } else { // aCounts[3 + 3]++; aDistance = aRepDistances[3]; aRepDistances[3] = aRepDistances[2]; } aRepDistances[2] = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; } aRepDistances[0] = aDistance; } aLen = m_RepMatchLenDecoder.Decode(&m_RangeDecoder, aPosState) + kMatchMinLen; // aCounts[aLen]++; aState.UpdateRep(); } else { aLen = kMatchMinLen + m_LenDecoder.Decode(&m_RangeDecoder, aPosState); aState.UpdateMatch(); UINT32 aPosSlot = m_PosSlotDecoder[GetLenToPosState(aLen)].Decode(&m_RangeDecoder); // aCounts[aPosSlot]++; if (aPosSlot >= (UINT32) kStartPosModelIndex) { aDistance = kDistStart[aPosSlot]; if (aPosSlot < (UINT32) kEndPosModelIndex) aDistance += m_PosDecoders[aPosSlot - kStartPosModelIndex].Decode(&m_RangeDecoder); else { aDistance += (m_RangeDecoder.DecodeDirectBits(kDistDirectBits[aPosSlot] - kNumAlignBits) << kNumAlignBits); aDistance += m_PosAlignDecoder.Decode(&m_RangeDecoder); } } else aDistance = aPosSlot; aRepDistances[3] = aRepDistances[2]; aRepDistances[2] = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; aRepDistances[0] = aDistance; // UpdateStat(aLen, aPosSlot); } if (aDistance >= aNowPos64) throw E_INVALIDDATA; m_OutWindowStream.CopyBackBlock(aDistance, aLen); aNowPos64 += aLen; aPreviousByte = m_OutWindowStream.GetOneByte(0 - 1); } } } return Flush(); }