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

📄 unrarlib.c

📁 RAR的解压缩算法
💻 C
📖 第 1 页 / 共 4 页
字号:
  {
    UnpPtr &= MAXWINMASK;

    if (InAddr > sizeof (InBuf) - 30)
      UnpReadBuf (0);
    if (((WrPtr - UnpPtr) & MAXWINMASK) < 270 && WrPtr != UnpPtr)
    {
      if (FileFound)
      {
        if (UnpPtr < WrPtr)
        {
          if ((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
          {
            debug_log ("Fatal! Buffer overrun during decompression!");
            DestUnpSize = -1;

          }
          else
          {
            /* copy extracted data to output buffer                         */
            memcpy (temp_output_buffer + *temp_output_buffer_offset,
                    &UnpBuf[WrPtr], (0 - WrPtr) & MAXWINMASK);
            /* update offset within buffer                                  */
            *temp_output_buffer_offset += (0 - WrPtr) & MAXWINMASK;
            /* copy extracted data to output buffer                         */
            memcpy (temp_output_buffer + *temp_output_buffer_offset,
                    UnpBuf, UnpPtr);
            /* update offset within buffer                                  */
            *temp_output_buffer_offset += UnpPtr;
          }
        }
        else
        {
          if ((*temp_output_buffer_offset + (UnpPtr - WrPtr)) >
              NewLhd.UnpSize)
          {
            debug_log ("Fatal! Buffer overrun during decompression!");
            DestUnpSize = -1;
          }
          else
          {
            /* copy extracted data to output buffer                       */
            memcpy (temp_output_buffer + *temp_output_buffer_offset,
                    &UnpBuf[WrPtr], UnpPtr - WrPtr);
            *temp_output_buffer_offset += UnpPtr - WrPtr; /* update offset within buffer */
          }

        }
      }

      WrPtr = UnpPtr;
    }

    if (UnpAudioBlock)
    {
      DecodeNumber ((struct Decode *) MDPtr[CurChannel]);
      if (Number == 256)
      {
        ReadTables ();
        continue;
      }
      UnpBuf[UnpPtr++] = DecodeAudio (Number);
      if (++CurChannel == UnpChannels)
        CurChannel = 0;
      DestUnpSize--;
      continue;
    }

    DecodeNumber (LitDecode2Decode (&LD));
    if (Number < 256)
    {
      UnpBuf[UnpPtr++] = (UBYTE) Number;
      DestUnpSize--;
      continue;
    }
    if (Number > 269)
    {
      Length = LDecode[Number -= 270] + 3;
      if ((Bits = LBits[Number]) > 0)
      {
        GetBits ();
        Length += BitField >> (16 - Bits);
        AddBits (Bits);
      }

      DecodeNumber (DistDecode2Decode (&DD));
      Distance = DDecode[Number] + 1;
      if ((Bits = DBits[Number]) > 0)
      {
        GetBits ();
        Distance += BitField >> (16 - Bits);
        AddBits (Bits);
      }

      if (Distance >= 0x40000L)
        Length++;

      if (Distance >= 0x2000)
        Length++;

      LastDist = OldDist[OldDistPtr++ & 3] = Distance;
      DestUnpSize -= (LastLength = Length);
      while (Length--)
      {
        UnpBuf[UnpPtr] = UnpBuf[(UnpPtr - Distance) & MAXWINMASK];
        UnpPtr = (UnpPtr + 1) & MAXWINMASK;
      }

      continue;
    }
    if (Number == 269)
    {
      ReadTables ();
      continue;
    }
    if (Number == 256)
    {
      Length = LastLength;
      Distance = LastDist;
      LastDist = OldDist[OldDistPtr++ & 3] = Distance;
      DestUnpSize -= (LastLength = Length);
      while (Length--)
      {
        UnpBuf[UnpPtr] = UnpBuf[(UnpPtr - Distance) & MAXWINMASK];
        UnpPtr = (UnpPtr + 1) & MAXWINMASK;
      }
      continue;
    }
    if (Number < 261)
    {
      Distance = OldDist[(OldDistPtr - (Number - 256)) & 3];
      DecodeNumber (RepDecode2Decode (&RD));
      Length = LDecode[Number] + 2;
      if ((Bits = LBits[Number]) > 0)
      {
        GetBits ();
        Length += BitField >> (16 - Bits);
        AddBits (Bits);
      }
      if (Distance >= 0x40000)
        Length++;
      if (Distance >= 0x2000)
        Length++;
      if (Distance >= 0x101)
        Length++;
      LastDist = OldDist[OldDistPtr++ & 3] = Distance;
      DestUnpSize -= (LastLength = Length);
      while (Length--)
      {
        UnpBuf[UnpPtr] = UnpBuf[(UnpPtr - Distance) & MAXWINMASK];
        UnpPtr = (UnpPtr + 1) & MAXWINMASK;
      }
      continue;
    }
    if (Number < 270)
    {
      Distance = SDDecode[Number -= 261] + 1;
      if ((Bits = SDBits[Number]) > 0)
      {
        GetBits ();
        Distance += BitField >> (16 - Bits);
        AddBits (Bits);
      }
      Length = 2;
      LastDist = OldDist[OldDistPtr++ & 3] = Distance;
      DestUnpSize -= (LastLength = Length);
      while (Length--)
      {
        UnpBuf[UnpPtr] = UnpBuf[(UnpPtr - Distance) & MAXWINMASK];
        UnpPtr = (UnpPtr + 1) & MAXWINMASK;
      }
      continue;
    }
  }
  ReadLastTables ();

  if (FileFound)                /* flush buffer                 */
  {

    if (UnpPtr < WrPtr)
    {
      if ((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
      {
        debug_log ("Fatal! Buffer overrun during decompression!");
        DestUnpSize = -1;
      }
      else
      {
        /* copy extracted data to output buffer                             */
        memcpy (temp_output_buffer + *temp_output_buffer_offset,
                &UnpBuf[WrPtr], (0 - WrPtr) & MAXWINMASK);
        /* update offset within buffer                                      */
        *temp_output_buffer_offset += (0 - WrPtr) & MAXWINMASK;
        /* copy extracted data to output buffer                             */
        memcpy (temp_output_buffer + *temp_output_buffer_offset, UnpBuf,
                UnpPtr);
        /* update offset within buffer                                      */
        *temp_output_buffer_offset += UnpPtr;
      }
    }
    else
    {
      if ((*temp_output_buffer_offset + (UnpPtr - WrPtr)) > NewLhd.UnpSize)
      {
        debug_log ("Fatal! Buffer overrun during decompression!");
        DestUnpSize = -1;
      }
      else
      {
        /* copy extracted data to output buffer                             */
        memcpy (temp_output_buffer + *temp_output_buffer_offset,
                &UnpBuf[WrPtr], UnpPtr - WrPtr);
        /* update offset within buffer                                      */
        *temp_output_buffer_offset += UnpPtr - WrPtr;
      }
    }
  }

  WrPtr = UnpPtr;
}


unsigned int
UnpRead (unsigned char *Addr, unsigned int Count)
{
  int RetCode = 0;
  unsigned int I, ReadSize, TotalRead = 0;
  unsigned char *ReadAddr = Addr;

  if (Count > 0)
  {
    ReadSize = (unsigned int) ((Count > (unsigned long) UnpPackedSize) ?
                               (unsigned int) UnpPackedSize : Count);
    if (inputfile == NULL)
      return 0;

    RetCode = fread (ReadAddr, 1, ReadSize, inputfile);
    CurUnpRead += RetCode;
    ReadAddr += RetCode;
    TotalRead += RetCode;
    Count -= RetCode;
    UnpPackedSize -= RetCode;
  }

  if (RetCode != -1)
  {
    RetCode = TotalRead;
    if (Encryption)
    {
      if (Encryption < 20)
      {
        debug_log ("Old Crypt() not supported!");
      }
      else
      {
        for (I = 0; I < (unsigned int) RetCode; I += 16)
          DecryptBlock (&Addr[I]);
      }
    }
  }

  return RetCode;
}


void
UnpReadBuf (int FirstBuf)
{
  int RetCode;
  if (FirstBuf)
  {
    ReadTop = UnpRead (InBuf, sizeof (InBuf));
    InAddr = 0;
  }
  else
  {
    memcpy (InBuf, &InBuf[sizeof (InBuf) - 32], 32);
    InAddr &= 0x1f;
    RetCode = UnpRead (&InBuf[32], sizeof (InBuf) - 32);
    if (RetCode > 0)
      ReadTop = RetCode + 32;
    else
      ReadTop = InAddr;
  }
}


void
ReadTables (void)
{
  UBYTE BitLength[BC];
  unsigned char Table[MC * 4];
  int TableSize, N, I;
  if (InAddr > sizeof (InBuf) - 25)
    UnpReadBuf (0);
  GetBits ();
  UnpAudioBlock = (BitField & 0x8000);

  if (!(BitField & 0x4000))
    memset (UnpOldTable, 0, sizeof (UnpOldTable));
  AddBits (2);


  if (UnpAudioBlock)
  {
    UnpChannels = ((BitField >> 12) & 3) + 1;
    if (CurChannel >= UnpChannels)
      CurChannel = 0;
    AddBits (2);
    TableSize = MC * UnpChannels;
  }
  else
    TableSize = NC + DC + RC;


  for (I = 0; I < BC; I++)
  {
    GetBits ();
    BitLength[I] = (UBYTE) (BitField >> 12);
    AddBits (4);
  }
  MakeDecodeTables (BitLength, BitDecode2Decode (&BD), BC);
  Decode2BitDecode (&BD);
  I = 0;
  while (I < TableSize)
  {
    if (InAddr > sizeof (InBuf) - 5)
      UnpReadBuf (0);
    DecodeNumber (BitDecode2Decode (&BD));
    if (Number < 16)
    {
      Table[I] = (Number + UnpOldTable[I]) & 0xf;
      I++;
    }
    else if (Number == 16)
    {
      GetBits ();
      N = (BitField >> 14) + 3;
      AddBits (2);
      while (N-- > 0 && I < TableSize)
      {
        Table[I] = Table[I - 1];
        I++;
      }
    }
    else
    {
      if (Number == 17)
      {
        GetBits ();
        N = (BitField >> 13) + 3;
        AddBits (3);
      }
      else
      {
        GetBits ();
        N = (BitField >> 9) + 11;
        AddBits (7);
      }
      while (N-- > 0 && I < TableSize)
        Table[I++] = 0;
    }
  }
  if (UnpAudioBlock)
    for (I = 0; I < UnpChannels; I++)
    {
      MakeDecodeTables (&Table[I * MC], MultDecode2Decode (MDPtr[I]), MC);
      Decode2MultDecode (MDPtr[I]);
    }
  else
  {
    MakeDecodeTables (&Table[0], LitDecode2Decode (&LD), NC);
    Decode2LitDecode (&LD);
    MakeDecodeTables (&Table[NC], DistDecode2Decode (&DD), DC);
    Decode2DistDecode (&DD);
    MakeDecodeTables (&Table[NC + DC], RepDecode2Decode (&RD), RC);
    Decode2RepDecode (&RD);
  }
  memcpy (UnpOldTable, Table, sizeof (UnpOldTable));
}


static void
ReadLastTables (void)
{
  if (ReadTop >= InAddr + 5)
  {
    if (UnpAudioBlock)
    {
      DecodeNumber (MultDecode2Decode (MDPtr[CurChannel]));
      if (Number == 256)
        ReadTables ();
    }
    else
    {
      DecodeNumber (LitDecode2Decode (&LD));
      if (Number == 269)
        ReadTables ();
    }
  }
}


static void
MakeDecodeTables (unsigned char *LenTab, struct Decode *Dec, int Size)
{
  int LenCount[16], TmpPos[16], I;
  long M, N;
  memset (LenCount, 0, sizeof (LenCount));
  for (I = 0; I < Size; I++)
    LenCount[LenTab[I] & 0xF]++;

  LenCount[0] = 0;
  for (TmpPos[0] = Dec->DecodePos[0] = Dec->DecodeLen[0] = 0, N = 0, I = 1;
       I < 16; I++)
  {
    N = 2 * (N + LenCount[I]);
    M = N << (15 - I);
    if (M > 0xFFFF)
      M = 0xFFFF;
    Dec->DecodeLen[I] = (unsigned int) M;
    TmpPos[I] = Dec->DecodePos[I] = Dec->DecodePos[I - 1] + LenCount[I - 1];
  }

  for (I = 0; I < Size; I++)
    if (LenTab[I] != 0)
      Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++] = I;
  Dec->MaxNum = Size;
}


static void
DecodeNumber (struct Decode *Deco)
/* *** 52.6% of all CPU time is spent within this function!!!               */
{
  unsigned int I;
  register unsigned int N;
  GetBits ();

#ifdef _USE_ASM

  __asm__ __volatile__ ("andl $0xFFFFFFFE, %%eax\n"
                        "      movl %%eax, %1\n"
                        "          cmpl 8*4(%%edx), %%eax /* 5379 */\n"
                        "          jae  else_G\n"
                        "\n"
                        "             cmpl 4*4(%%edx), %%eax\n"
                        "             jae  else_F\n"
                        "\n"
                        "                cmpl 2*4(%%edx), %%eax\n"
                        "                jae  else_C\n"
                        "\n"
                        "                   cmpl 1*4(%%edx), %%eax\n"
                        "\n"
                        "                   jae  else_1\n"
                        "                   movl $1, %0\n"
                        "                   jmp  next_1\n"
                        "                 else_1:       \n"
                        "                   movl  $2, %0\n"
                        "                 next_1:\n"
                        "                \n"
                        "                jmp  next_C\n"
                        "              else_C:          \n"
                        "\n"
                        "                   cmpl 3*4(%%edx), %%eax \n"
                        "                   jae  else_2\n"
                        "                   movl  $3, %0\n"
                        "                   jmp  next_2\n"
                        "                 else_2:       \n"
                        "                   movl  $4, %0\n"
                        "                 next_2:\n"
                        "\n"
                        "              next_C:          \n"
                        "\n"
                        "             jmp  next_F\n"
                        "           else_F:\n"
                        "\n"
                        "             cmpl 6*4(%%edx), %%eax\n"
                        "             jae  else_E\n"
                        "\n"
                        "                cmpl 5*4(%%edx), %%eax\n"
                        "                jae  else_3\n"
                        "                movl  $5, %0   \n"
                        "                jmp  next_3\n"
                        "              else_3:          \n"
                        "                movl  $6, %0   \n"
                        "              next_3:\n"
                        "\n"
                        "             jmp  next_E\n"
                        "           else_E:             \n"
                        "\n"
                        "                cmpl 7*4(%%edx), %%eax\n"
                        "                jae  else_4\n"
                        "                movl  $7, %0   \n"
                        "                jmp  next_4\n"
                        "              else_4:          \n"
                        "                movl  $8, %0   \n"
                        "              next_4:\n"
                        "\n"
                        "           next_E:\n"
                        "\n"
                        "           next_F:\n"
                        "\n"
                        "          jmp  next_G\n"
                        "        else_G:\n"
                        "\n"
                        "          cmpl 12*4(%%edx), %%eax\n"
                        "          jae  else_D\n"
                        "\n"
                        "             cmpl 10*4(%%edx), %%eax\n"
                        "             jae  else_B\n"
                        "\n"
                        "                cmpl 9*4(%%edx), %%eax\n"
                        "                jae  else_5\n"
                        "                movl  $9, %0   \n"
                        "                jmp  next_5\n"
                        "              else_5:          \n"
                        "                movl  $10, %0  \n"
                        "              next_5:\n"
                        "\n"
                        "             jmp  next_B\n"
                        "           else_B:             \n"
                        "\n"
                        "                cmpl 11*4(%%edx), %%eax\n"
                        " \n"
                        "                jae  else_6\n"
                        "                movl  $11, %0  \n"
                        "                jmp  next_6\n"
                        "              else_6:          \n"
                        "                movl  $12, %0  \n"
                        "              next_6:\n"
                        "\n"
                        "           next_B:\n"
                        "      \n"
                        "        \n"
                        "          jmp  next_D\n"
                        "        else_D:                \n"
                        "\n"
                        "               cmpl 14*4(%%edx), %%eax\n"

⌨️ 快捷键说明

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