"Fossies" - the Fresh Open Source Software Archive

Member "unrar/unpack20.cpp" (4 May 2022, 8604 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 "unpack20.cpp" see the Fossies "Dox" file reference documentation.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 #include "rar.hpp"
    2 
    3 void Unpack::CopyString20(uint Length,uint Distance)
    4 {
    5   LastDist=OldDist[OldDistPtr++]=Distance;
    6   OldDistPtr = OldDistPtr & 3; // Needed if RAR 1.5 file is called after RAR 2.0.
    7   LastLength=Length;
    8   DestUnpSize-=Length;
    9   CopyString(Length,Distance);
   10 }
   11 
   12 
   13 void Unpack::Unpack20(bool Solid)
   14 {
   15   static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
   16   static unsigned char LBits[]=  {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,  4,  5,  5,  5,  5};
   17   static uint DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
   18   static unsigned char DBits[]=  {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5,  6,  6,  7,  7,  8,  8,   9,   9,  10,  10,  11,  11,  12,   12,   13,   13,    14,    14,   15,   15,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16};
   19   static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
   20   static unsigned char SDBits[]=  {2,2,3, 4, 5, 6,  6,  6};
   21   uint Bits;
   22 
   23   if (Suspended)
   24     UnpPtr=WrPtr;
   25   else
   26   {
   27     UnpInitData(Solid);
   28     if (!UnpReadBuf())
   29       return;
   30     if ((!Solid || !TablesRead2) && !ReadTables20())
   31       return;
   32     --DestUnpSize;
   33   }
   34 
   35   while (DestUnpSize>=0)
   36   {
   37     UnpPtr&=MaxWinMask;
   38 
   39     if (Inp.InAddr>ReadTop-30)
   40       if (!UnpReadBuf())
   41         break;
   42     if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr)
   43     {
   44       UnpWriteBuf20();
   45       if (Suspended)
   46         return;
   47     }
   48     if (UnpAudioBlock)
   49     {
   50       uint AudioNumber=DecodeNumber(Inp,&MD[UnpCurChannel]);
   51 
   52       if (AudioNumber==256)
   53       {
   54         if (!ReadTables20())
   55           break;
   56         continue;
   57       }
   58       Window[UnpPtr++]=DecodeAudio((int)AudioNumber);
   59       if (++UnpCurChannel==UnpChannels)
   60         UnpCurChannel=0;
   61       --DestUnpSize;
   62       continue;
   63     }
   64 
   65     uint Number=DecodeNumber(Inp,&BlockTables.LD);
   66     if (Number<256)
   67     {
   68       Window[UnpPtr++]=(byte)Number;
   69       --DestUnpSize;
   70       continue;
   71     }
   72     if (Number>269)
   73     {
   74       uint Length=LDecode[Number-=270]+3;
   75       if ((Bits=LBits[Number])>0)
   76       {
   77         Length+=Inp.getbits()>>(16-Bits);
   78         Inp.addbits(Bits);
   79       }
   80 
   81       uint DistNumber=DecodeNumber(Inp,&BlockTables.DD);
   82       uint Distance=DDecode[DistNumber]+1;
   83       if ((Bits=DBits[DistNumber])>0)
   84       {
   85         Distance+=Inp.getbits()>>(16-Bits);
   86         Inp.addbits(Bits);
   87       }
   88 
   89       if (Distance>=0x2000)
   90       {
   91         Length++;
   92         if (Distance>=0x40000L)
   93           Length++;
   94       }
   95 
   96       CopyString20(Length,Distance);
   97       continue;
   98     }
   99     if (Number==269)
  100     {
  101       if (!ReadTables20())
  102         break;
  103       continue;
  104     }
  105     if (Number==256)
  106     {
  107       CopyString20(LastLength,LastDist);
  108       continue;
  109     }
  110     if (Number<261)
  111     {
  112       uint Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
  113       uint LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
  114       uint Length=LDecode[LengthNumber]+2;
  115       if ((Bits=LBits[LengthNumber])>0)
  116       {
  117         Length+=Inp.getbits()>>(16-Bits);
  118         Inp.addbits(Bits);
  119       }
  120       if (Distance>=0x101)
  121       {
  122         Length++;
  123         if (Distance>=0x2000)
  124         {
  125           Length++;
  126           if (Distance>=0x40000)
  127             Length++;
  128         }
  129       }
  130       CopyString20(Length,Distance);
  131       continue;
  132     }
  133     if (Number<270)
  134     {
  135       uint Distance=SDDecode[Number-=261]+1;
  136       if ((Bits=SDBits[Number])>0)
  137       {
  138         Distance+=Inp.getbits()>>(16-Bits);
  139         Inp.addbits(Bits);
  140       }
  141       CopyString20(2,Distance);
  142       continue;
  143    }
  144   }
  145   ReadLastTables();
  146   UnpWriteBuf20();
  147 }
  148 
  149 
  150 void Unpack::UnpWriteBuf20()
  151 {
  152   if (UnpPtr!=WrPtr)
  153     UnpSomeRead=true;
  154   if (UnpPtr<WrPtr)
  155   {
  156     UnpIO->UnpWrite(&Window[WrPtr],-(int)WrPtr & MaxWinMask);
  157     UnpIO->UnpWrite(Window,UnpPtr);
  158     UnpAllBuf=true;
  159   }
  160   else
  161     UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr);
  162   WrPtr=UnpPtr;
  163 }
  164 
  165 
  166 bool Unpack::ReadTables20()
  167 {
  168   byte BitLength[BC20];
  169   byte Table[MC20*4];
  170   if (Inp.InAddr>ReadTop-25)
  171     if (!UnpReadBuf())
  172       return false;
  173   uint BitField=Inp.getbits();
  174   UnpAudioBlock=(BitField & 0x8000)!=0;
  175 
  176   if (!(BitField & 0x4000))
  177     memset(UnpOldTable20,0,sizeof(UnpOldTable20));
  178   Inp.addbits(2);
  179 
  180   uint TableSize;
  181   if (UnpAudioBlock)
  182   {
  183     UnpChannels=((BitField>>12) & 3)+1;
  184     if (UnpCurChannel>=UnpChannels)
  185       UnpCurChannel=0;
  186     Inp.addbits(2);
  187     TableSize=MC20*UnpChannels;
  188   }
  189   else
  190     TableSize=NC20+DC20+RC20;
  191 
  192   for (uint I=0;I<BC20;I++)
  193   {
  194     BitLength[I]=(byte)(Inp.getbits() >> 12);
  195     Inp.addbits(4);
  196   }
  197   MakeDecodeTables(BitLength,&BlockTables.BD,BC20);
  198   for (uint I=0;I<TableSize;)
  199   {
  200     if (Inp.InAddr>ReadTop-5)
  201       if (!UnpReadBuf())
  202         return false;
  203     uint Number=DecodeNumber(Inp,&BlockTables.BD);
  204     if (Number<16)
  205     {
  206       Table[I]=(Number+UnpOldTable20[I]) & 0xf;
  207       I++;
  208     }
  209     else
  210       if (Number==16)
  211       {
  212         uint N=(Inp.getbits() >> 14)+3;
  213         Inp.addbits(2);
  214         if (I==0)
  215           return false; // We cannot have "repeat previous" code at the first position.
  216         else
  217           while (N-- > 0 && I<TableSize)
  218           {
  219             Table[I]=Table[I-1];
  220             I++;
  221           }
  222       }
  223       else
  224       {
  225         uint N;
  226         if (Number==17)
  227         {
  228           N=(Inp.getbits() >> 13)+3;
  229           Inp.addbits(3);
  230         }
  231         else
  232         {
  233           N=(Inp.getbits() >> 9)+11;
  234           Inp.addbits(7);
  235         }
  236         while (N-- > 0 && I<TableSize)
  237           Table[I++]=0;
  238       }
  239   }
  240   TablesRead2=true;
  241   if (Inp.InAddr>ReadTop)
  242     return true;
  243   if (UnpAudioBlock)
  244     for (uint I=0;I<UnpChannels;I++)
  245       MakeDecodeTables(&Table[I*MC20],&MD[I],MC20);
  246   else
  247   {
  248     MakeDecodeTables(&Table[0],&BlockTables.LD,NC20);
  249     MakeDecodeTables(&Table[NC20],&BlockTables.DD,DC20);
  250     MakeDecodeTables(&Table[NC20+DC20],&BlockTables.RD,RC20);
  251   }
  252   memcpy(UnpOldTable20,Table,TableSize);
  253   return true;
  254 }
  255 
  256 
  257 void Unpack::ReadLastTables()
  258 {
  259   if (ReadTop>=Inp.InAddr+5)
  260     if (UnpAudioBlock)
  261     {
  262       if (DecodeNumber(Inp,&MD[UnpCurChannel])==256)
  263         ReadTables20();
  264     }
  265     else
  266       if (DecodeNumber(Inp,&BlockTables.LD)==269)
  267         ReadTables20();
  268 }
  269 
  270 
  271 void Unpack::UnpInitData20(int Solid)
  272 {
  273   if (!Solid)
  274   {
  275     TablesRead2=false;
  276     UnpAudioBlock=false;
  277     UnpChannelDelta=0;
  278     UnpCurChannel=0;
  279     UnpChannels=1;
  280 
  281     memset(AudV,0,sizeof(AudV));
  282     memset(UnpOldTable20,0,sizeof(UnpOldTable20));
  283     memset(MD,0,sizeof(MD));
  284   }
  285 }
  286 
  287 
  288 byte Unpack::DecodeAudio(int Delta)
  289 {
  290   struct AudioVariables *V=&AudV[UnpCurChannel];
  291   V->ByteCount++;
  292   V->D4=V->D3;
  293   V->D3=V->D2;
  294   V->D2=V->LastDelta-V->D1;
  295   V->D1=V->LastDelta;
  296   int PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+V->K3*V->D3+V->K4*V->D4+V->K5*UnpChannelDelta;
  297   PCh=(PCh>>3) & 0xFF;
  298 
  299   uint Ch=PCh-Delta;
  300 
  301   int D=(signed char)Delta;
  302   // Left shift of negative value is undefined behavior in C++,
  303   // so we cast it to unsigned to follow the standard.
  304   D=(uint)D<<3;
  305 
  306   V->Dif[0]+=abs(D);
  307   V->Dif[1]+=abs(D-V->D1);
  308   V->Dif[2]+=abs(D+V->D1);
  309   V->Dif[3]+=abs(D-V->D2);
  310   V->Dif[4]+=abs(D+V->D2);
  311   V->Dif[5]+=abs(D-V->D3);
  312   V->Dif[6]+=abs(D+V->D3);
  313   V->Dif[7]+=abs(D-V->D4);
  314   V->Dif[8]+=abs(D+V->D4);
  315   V->Dif[9]+=abs(D-UnpChannelDelta);
  316   V->Dif[10]+=abs(D+UnpChannelDelta);
  317 
  318   UnpChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
  319   V->LastChar=Ch;
  320 
  321   if ((V->ByteCount & 0x1F)==0)
  322   {
  323     uint MinDif=V->Dif[0],NumMinDif=0;
  324     V->Dif[0]=0;
  325     for (uint I=1;I<ASIZE(V->Dif);I++)
  326     {
  327       if (V->Dif[I]<MinDif)
  328       {
  329         MinDif=V->Dif[I];
  330         NumMinDif=I;
  331       }
  332       V->Dif[I]=0;
  333     }
  334     switch(NumMinDif)
  335     {
  336       case 1:
  337         if (V->K1>=-16)
  338           V->K1--;
  339         break;
  340       case 2:
  341         if (V->K1<16)
  342           V->K1++;
  343         break;
  344       case 3:
  345         if (V->K2>=-16)
  346           V->K2--;
  347         break;
  348       case 4:
  349         if (V->K2<16)
  350           V->K2++;
  351         break;
  352       case 5:
  353         if (V->K3>=-16)
  354           V->K3--;
  355         break;
  356       case 6:
  357         if (V->K3<16)
  358           V->K3++;
  359         break;
  360       case 7:
  361         if (V->K4>=-16)
  362           V->K4--;
  363         break;
  364       case 8:
  365         if (V->K4<16)
  366           V->K4++;
  367         break;
  368       case 9:
  369         if (V->K5>=-16)
  370           V->K5--;
  371         break;
  372       case 10:
  373         if (V->K5<16)
  374           V->K5++;
  375         break;
  376     }
  377   }
  378   return (byte)Ch;
  379 }