"Fossies" - the Fresh Open Source Software Archive

Member "unrar/unpack50frag.cpp" (4 May 2022, 2454 Bytes) of package /linux/misc/unrarsrc-6.1.7.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "unpack50frag.cpp" see the Fossies "Dox" file reference documentation.

    1 FragmentedWindow::FragmentedWindow()
    2 {
    3   memset(Mem,0,sizeof(Mem));
    4   memset(MemSize,0,sizeof(MemSize));
    5 }
    6 
    7 
    8 FragmentedWindow::~FragmentedWindow()
    9 {
   10   Reset();
   11 }
   12 
   13 
   14 void FragmentedWindow::Reset()
   15 {
   16   for (uint I=0;I<ASIZE(Mem);I++)
   17     if (Mem[I]!=NULL)
   18     {
   19       free(Mem[I]);
   20       Mem[I]=NULL;
   21     }
   22 }
   23 
   24 
   25 void FragmentedWindow::Init(size_t WinSize)
   26 {
   27   Reset();
   28 
   29   uint BlockNum=0;
   30   size_t TotalSize=0; // Already allocated.
   31   while (TotalSize<WinSize && BlockNum<ASIZE(Mem))
   32   {
   33     size_t Size=WinSize-TotalSize; // Size needed to allocate.
   34 
   35     // Minimum still acceptable block size. Next allocations cannot be larger
   36     // than current, so we do not need blocks if they are smaller than
   37     // "size left / attempts left". Also we do not waste time to blocks
   38     // smaller than some arbitrary constant.
   39     size_t MinSize=Max(Size/(ASIZE(Mem)-BlockNum), 0x400000);
   40 
   41     byte *NewMem=NULL;
   42     while (Size>=MinSize)
   43     {
   44       NewMem=(byte *)malloc(Size);
   45       if (NewMem!=NULL)
   46         break;
   47       Size-=Size/32;
   48     }
   49     if (NewMem==NULL)
   50       throw std::bad_alloc();
   51 
   52     // Clean the window to generate the same output when unpacking corrupt
   53     // RAR files, which may access to unused areas of sliding dictionary.
   54     memset(NewMem,0,Size);
   55 
   56     Mem[BlockNum]=NewMem;
   57     TotalSize+=Size;
   58     MemSize[BlockNum]=TotalSize;
   59     BlockNum++;
   60   }
   61   if (TotalSize<WinSize) // Not found enough free blocks.
   62     throw std::bad_alloc();
   63 }
   64 
   65 
   66 byte& FragmentedWindow::operator [](size_t Item)
   67 {
   68   if (Item<MemSize[0])
   69     return Mem[0][Item];
   70   for (uint I=1;I<ASIZE(MemSize);I++)
   71     if (Item<MemSize[I])
   72       return Mem[I][Item-MemSize[I-1]];
   73   return Mem[0][0]; // Must never happen;
   74 }
   75 
   76 
   77 void FragmentedWindow::CopyString(uint Length,uint Distance,size_t &UnpPtr,size_t MaxWinMask)
   78 {
   79   size_t SrcPtr=UnpPtr-Distance;
   80   while (Length-- > 0)
   81   {
   82     (*this)[UnpPtr]=(*this)[SrcPtr++ & MaxWinMask];
   83     // We need to have masked UnpPtr after quit from loop, so it must not
   84     // be replaced with '(*this)[UnpPtr++ & MaxWinMask]'
   85     UnpPtr=(UnpPtr+1) & MaxWinMask;
   86   }
   87 }
   88 
   89 
   90 void FragmentedWindow::CopyData(byte *Dest,size_t WinPos,size_t Size)
   91 {
   92   for (size_t I=0;I<Size;I++)
   93     Dest[I]=(*this)[WinPos+I];
   94 }
   95 
   96 
   97 size_t FragmentedWindow::GetBlockSize(size_t StartPos,size_t RequiredSize)
   98 {
   99   for (uint I=0;I<ASIZE(MemSize);I++)
  100     if (StartPos<MemSize[I])
  101       return Min(MemSize[I]-StartPos,RequiredSize);
  102   return 0; // Must never be here.
  103 }