⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lzmadecode.c

📁 lzma的压缩算法再嵌入式系统上的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
  UInt32 Reps[4];
  int lc;
  int lp;
  int pb;
  int State;
  int PreviousIsMatch;
  int RemainLen;
} LzmaVarState;

int LzmaDecoderInit(
    unsigned char *buffer, UInt32 bufferSize,
    int lc, int lp, int pb,
    unsigned char *dictionary, UInt32 dictionarySize,
    #ifdef _LZMA_IN_CB
    ILzmaInCallback *inCallback
    #else
    unsigned char *inStream, UInt32 inSize
    #endif
    )
{
  LzmaVarState *vs = (LzmaVarState *)buffer;
  CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
  UInt32 i;
  if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
    return LZMA_RESULT_NOT_ENOUGH_MEM;
  vs->Dictionary = dictionary;
  vs->DictionarySize = dictionarySize;
  vs->DictionaryPos = 0;
  vs->GlobalPos = 0;
  vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
  vs->lc = lc;
  vs->lp = lp;
  vs->pb = pb;
  vs->State = 0;
  vs->PreviousIsMatch = 0;
  vs->RemainLen = 0;
  dictionary[dictionarySize - 1] = 0;
  for (i = 0; i < numProbs; i++)
    p[i] = kBitModelTotal >> 1; 
  RangeDecoderInit(&vs->RangeDecoder, 
      #ifdef _LZMA_IN_CB
      inCallback
      #else
      inStream, inSize
      #endif
  );
  return LZMA_RESULT_OK;
}

int LzmaDecode(unsigned char *buffer, 
    unsigned char *outStream, UInt32 outSize,
    UInt32 *outSizeProcessed)
{
  LzmaVarState *vs = (LzmaVarState *)buffer;
  CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
  CRangeDecoder rd = vs->RangeDecoder;
  int state = vs->State;
  int previousIsMatch = vs->PreviousIsMatch;
  Byte previousByte;
  UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
  UInt32 nowPos = 0;
  UInt32 posStateMask = (1 << (vs->pb)) - 1;
  UInt32 literalPosMask = (1 << (vs->lp)) - 1;
  int lc = vs->lc;
  int len = vs->RemainLen;
  UInt32 globalPos = vs->GlobalPos;

  Byte *dictionary = vs->Dictionary;
  UInt32 dictionarySize = vs->DictionarySize;
  UInt32 dictionaryPos = vs->DictionaryPos;

  if (len == -1)
  {
    *outSizeProcessed = 0;
    return LZMA_RESULT_OK;
  }

  while(len > 0 && nowPos < outSize)
  {
    UInt32 pos = dictionaryPos - rep0;
    if (pos >= dictionarySize)
      pos += dictionarySize;
    outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
    if (++dictionaryPos == dictionarySize)
      dictionaryPos = 0;
    len--;
  }
  if (dictionaryPos == 0)
    previousByte = dictionary[dictionarySize - 1];
  else
    previousByte = dictionary[dictionaryPos - 1];
#else

int LzmaDecode(
    Byte *buffer, UInt32 bufferSize,
    int lc, int lp, int pb,
    #ifdef _LZMA_IN_CB
    ILzmaInCallback *inCallback,
    #else
    unsigned char *inStream, UInt32 inSize,
    #endif
    unsigned char *outStream, UInt32 outSize,
    UInt32 *outSizeProcessed)
{
  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
  CProb *p = (CProb *)buffer;
  CRangeDecoder rd;
  UInt32 i;
  int state = 0;
  int previousIsMatch = 0;
  Byte previousByte = 0;
  UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
  UInt32 nowPos = 0;
  UInt32 posStateMask = (1 << pb) - 1;
  UInt32 literalPosMask = (1 << lp) - 1;
  int len = 0;
  if (bufferSize < numProbs * sizeof(CProb))
    return LZMA_RESULT_NOT_ENOUGH_MEM;
  for (i = 0; i < numProbs; i++)
    p[i] = kBitModelTotal >> 1; 
  RangeDecoderInit(&rd, 
      #ifdef _LZMA_IN_CB
      inCallback
      #else
      inStream, inSize
      #endif
      );
#endif

  *outSizeProcessed = 0;
  while(nowPos < outSize)
  {
    int posState = (int)(
        (nowPos 
        #ifdef _LZMA_OUT_READ
        + globalPos
        #endif
        )
        & posStateMask);
    #ifdef _LZMA_IN_CB
    if (rd.Result != LZMA_RESULT_OK)
      return rd.Result;
    #endif
    if (rd.ExtraBytes != 0)
      return LZMA_RESULT_DATA_ERROR;
    if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
    {
      CProb *probs = p + Literal + (LZMA_LIT_SIZE * 
        (((
        (nowPos 
        #ifdef _LZMA_OUT_READ
        + globalPos
        #endif
        )
        & literalPosMask) << lc) + (previousByte >> (8 - lc))));

      if (state < 4) state = 0;
      else if (state < 10) state -= 3;
      else state -= 6;
      if (previousIsMatch)
      {
        Byte matchByte;
        #ifdef _LZMA_OUT_READ
        UInt32 pos = dictionaryPos - rep0;
        if (pos >= dictionarySize)
          pos += dictionarySize;
        matchByte = dictionary[pos];
        #else
        matchByte = outStream[nowPos - rep0];
        #endif
        previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
        previousIsMatch = 0;
      }
      else
        previousByte = LzmaLiteralDecode(probs, &rd);
      outStream[nowPos++] = previousByte;
      #ifdef _LZMA_OUT_READ
      dictionary[dictionaryPos] = previousByte;
      if (++dictionaryPos == dictionarySize)
        dictionaryPos = 0;
      #endif
    }
    else             
    {
      previousIsMatch = 1;
      if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
      {
        if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
        {
          if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
          {
            #ifdef _LZMA_OUT_READ
            UInt32 pos;
            #endif
            if (
               (nowPos 
                #ifdef _LZMA_OUT_READ
                + globalPos
                #endif
               )
               == 0)
              return LZMA_RESULT_DATA_ERROR;
            state = state < 7 ? 9 : 11;
            #ifdef _LZMA_OUT_READ
            pos = dictionaryPos - rep0;
            if (pos >= dictionarySize)
              pos += dictionarySize;
            previousByte = dictionary[pos];
            dictionary[dictionaryPos] = previousByte;
            if (++dictionaryPos == dictionarySize)
              dictionaryPos = 0;
            #else
            previousByte = outStream[nowPos - rep0];
            #endif
            outStream[nowPos++] = previousByte;
            continue;
          }
        }
        else
        {
          UInt32 distance;
          if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
            distance = rep1;
          else 
          {
            if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
              distance = rep2;
            else
            {
              distance = rep3;
              rep3 = rep2;
            }
            rep2 = rep1;
          }
          rep1 = rep0;
          rep0 = distance;
        }
        len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
        state = state < 7 ? 8 : 11;
      }
      else
      {
        int posSlot;
        rep3 = rep2;
        rep2 = rep1;
        rep1 = rep0;
        state = state < 7 ? 7 : 10;
        len = LzmaLenDecode(p + LenCoder, &rd, posState);
        posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 
            kNumPosSlotBits), kNumPosSlotBits, &rd);
        if (posSlot >= kStartPosModelIndex)
        {
          int numDirectBits = ((posSlot >> 1) - 1);
          rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
          if (posSlot < kEndPosModelIndex)
          {
            rep0 += RangeDecoderReverseBitTreeDecode(
                p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
          }
          else
          {
            rep0 += RangeDecoderDecodeDirectBits(&rd, 
                numDirectBits - kNumAlignBits) << kNumAlignBits;
            rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
          }
        }
        else
          rep0 = posSlot;
        rep0++;
      }
      if (rep0 == (UInt32)(0))
      {
        /* it's for stream version */
        len = -1;
        break;
      }
      if (rep0 > nowPos 
        #ifdef _LZMA_OUT_READ
        + globalPos
        #endif
        )
      {
        return LZMA_RESULT_DATA_ERROR;
      }
      len += kMatchMinLen;
      do
      {
        #ifdef _LZMA_OUT_READ
        UInt32 pos = dictionaryPos - rep0;
        if (pos >= dictionarySize)
          pos += dictionarySize;
        previousByte = dictionary[pos];
        dictionary[dictionaryPos] = previousByte;
        if (++dictionaryPos == dictionarySize)
          dictionaryPos = 0;
        #else
        previousByte = outStream[nowPos - rep0];
        #endif
        outStream[nowPos++] = previousByte;
        len--;
      }
      while(len > 0 && nowPos < outSize);
    }
  }

  #ifdef _LZMA_OUT_READ
  vs->RangeDecoder = rd;
  vs->DictionaryPos = dictionaryPos;
  vs->GlobalPos = globalPos + nowPos;
  vs->Reps[0] = rep0;
  vs->Reps[1] = rep1;
  vs->Reps[2] = rep2;
  vs->Reps[3] = rep3;
  vs->State = state;
  vs->PreviousIsMatch = previousIsMatch;
  vs->RemainLen = len;
  #endif

  *outSizeProcessed = nowPos;
  return LZMA_RESULT_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -