Exemple #1
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();
}
HRESULT LzmaDecoderCodeReal(
    LzmaDecoder     *lzmaDecoder,
    UINT64          *anInSize,
    UINT64          *anOutSize)
{
    BOOL                  aPeviousIsMatch         = FALSE;
    BYTE                  aPreviousByte           = 0;
    UINT32                aRepDistances[kNumRepDistances];
    int                   i;
    UINT64                aNowPos64               = 0;
    UINT64                aSize                   = *anOutSize;
    ISequentialInStream   my_in_stream;
//  WindowOut             out_window;
    CState                aState;

    CStateInit(&aState);

    if (anOutSize == NULL)
    {
        printf("CodeReal: invalid argument %x\n", (UINT32) anOutSize );
        return E_INVALIDARG;
    }


    LzmaDecoderInit(lzmaDecoder);

    my_in_stream.data           = in_stream.data;
    my_in_stream.remainingBytes = in_stream.remainingBytes;

    for(i = 0 ; i < (int) kNumRepDistances; i++)
        aRepDistances[i] = 0;

    //while(aNowPos64 < aSize)
    while(my_in_stream.remainingBytes > 0)
    {
        UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize);
        while(aNowPos64 < aNext)
        {
            UINT32 aPosState = (UINT32)(aNowPos64) & lzmaDecoder->m_PosStateMask;
            if (BitDecode(&my_in_stream,
                          &lzmaDecoder->m_MainChoiceDecoders[aState][aPosState],
                          &lzmaDecoder->m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex)
            {
                CStateUpdateChar(&aState);
                if(aPeviousIsMatch)
                {
                    BYTE aMatchByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1);
                    aPreviousByte = LitDecodeWithMatchByte(&my_in_stream,
                                                           &lzmaDecoder->m_LiteralDecoder,
                                                           &lzmaDecoder->m_RangeDecoder,
                                                           (UINT32)(aNowPos64),
                                                           aPreviousByte,
                                                           aMatchByte);
                    aPeviousIsMatch = FALSE;
                }
                else
                    aPreviousByte = LitDecodeNormal(&my_in_stream,
                                                    &lzmaDecoder->m_LiteralDecoder,
                                                    &lzmaDecoder->m_RangeDecoder,
                                                    (UINT32)(aNowPos64),
                                                    aPreviousByte);
                OutWindowPutOneByte(aPreviousByte);
                aNowPos64++;
            }
            else
            {
                UINT32 aDistance, aLen;
                aPeviousIsMatch = TRUE;
                if(BitDecode(&my_in_stream,
                             &lzmaDecoder->m_MatchChoiceDecoders[aState],
                             &lzmaDecoder->m_RangeDecoder) == (UINT32) kMatchChoiceRepetitionIndex)
                {
                    if(BitDecode(&my_in_stream,
                                 &lzmaDecoder->m_MatchRepChoiceDecoders[aState],
                                 &lzmaDecoder->m_RangeDecoder) == 0)
                    {
                        if(BitDecode(&my_in_stream,
                                     &lzmaDecoder->m_MatchRepShortChoiceDecoders[aState][aPosState],
                                     &lzmaDecoder->m_RangeDecoder) == 0)
                        {
                            CStateUpdateShortRep(&aState);
                            aPreviousByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1);
                            OutWindowPutOneByte(aPreviousByte);
                            aNowPos64++;
                            continue;
                        }
                        aDistance = aRepDistances[0];
                    }
                    else
                    {
                        if(BitDecode(&my_in_stream,
                                     &lzmaDecoder->m_MatchRep1ChoiceDecoders[aState],
                                     &lzmaDecoder->m_RangeDecoder) == 0)
                        {
                            aDistance = aRepDistances[1];
                            aRepDistances[1] = aRepDistances[0];
                        }
                        else
                        {
                            if (BitDecode(&my_in_stream,
                                          &lzmaDecoder->m_MatchRep2ChoiceDecoders[aState],
                                          &lzmaDecoder->m_RangeDecoder) == 0)
                            {
                                aDistance = aRepDistances[2];
                            }
                            else
                            {
                                aDistance = aRepDistances[3];
                                aRepDistances[3] = aRepDistances[2];
                            }
                            aRepDistances[2] = aRepDistances[1];
                            aRepDistances[1] = aRepDistances[0];
                        }
                        aRepDistances[0] = aDistance;
                    }
                    aLen = LenDecode(&my_in_stream,
                                     &lzmaDecoder->m_RepMatchLenDecoder,
                                     &lzmaDecoder->m_RangeDecoder,
                                     aPosState) + kMatchMinLen;
                    CStateUpdateRep(&aState);
                }
                else
                {
                    UINT32 aPosSlot;
                    aLen = kMatchMinLen + LenDecode(&my_in_stream,
                                                    &lzmaDecoder->m_LenDecoder,
                                                    &lzmaDecoder->m_RangeDecoder,
                                                    aPosState);
                    CStateUpdateMatch(&aState);
                    aPosSlot = BitTreeDecode(&my_in_stream,
                                             &lzmaDecoder->m_PosSlotDecoder[GetLenToPosState(aLen)],
                                             &lzmaDecoder->m_RangeDecoder);
                    if (aPosSlot >= (UINT32) kStartPosModelIndex)
                    {
                        aDistance = kDistStart[aPosSlot];
                        if (aPosSlot < (UINT32) kEndPosModelIndex)
                            aDistance += ReverseBitTreeDecoder2Decode(&my_in_stream,
                                         &lzmaDecoder->m_PosDecoders[aPosSlot - kStartPosModelIndex],
                                         &lzmaDecoder->m_RangeDecoder);
                        else
                        {
                            aDistance += (RangeDecodeDirectBits(&my_in_stream,
                                                                &lzmaDecoder->m_RangeDecoder,
                                                                kDistDirectBits[aPosSlot] - kNumAlignBits) << kNumAlignBits);
                            aDistance += ReverseBitTreeDecoderDecode(&my_in_stream,
                                         &lzmaDecoder->m_PosAlignDecoder,
                                         &lzmaDecoder->m_RangeDecoder);
                        }
                    }
                    else
                        aDistance = aPosSlot;


                    aRepDistances[3] = aRepDistances[2];
                    aRepDistances[2] = aRepDistances[1];
                    aRepDistances[1] = aRepDistances[0];

                    aRepDistances[0] = aDistance;
                }
                if (aDistance >= aNowPos64)
                {
                    printf("CodeReal: invalid data\n" );
                    return E_INVALIDDATA;
                }
                OutWindowCopyBackBlock(aDistance, aLen);
                aNowPos64 += aLen;
                aPreviousByte = OutWindowGetOneByte(0 - 1);
            }
        }
    }

    //BRCM modification
    LzmaDecoderFreeBuffer(lzmaDecoder);

    OutWindowFlush();
    return S_OK;
}