示例#1
0
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));
    }
示例#2
0
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();
}