"Fossies" - the Fresh Open Source Software Archive

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

    1 #define STARTL1  2
    2 static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
    3                              0xee00,0xf000,0xf200,0xf200,0xffff};
    4 static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32};
    5 
    6 #define STARTL2  3
    7 static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00,
    8                              0xf000,0xf200,0xf240,0xffff};
    9 static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36};
   10 
   11 #define STARTHF0  4
   12 static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200,
   13                               0xf200,0xf200,0xffff};
   14 static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33};
   15 
   16 
   17 #define STARTHF1  5
   18 static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200,
   19                               0xf7e0,0xffff};
   20 static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127};
   21 
   22 
   23 #define STARTHF2  5
   24 static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff,
   25                               0xffff,0xffff};
   26 static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0};
   27 
   28 
   29 #define STARTHF3  6
   30 static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff,
   31                               0xffff};
   32 static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0};
   33 
   34 
   35 #define STARTHF4  8
   36 static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff};
   37 static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0};
   38 
   39 
   40 void Unpack::Unpack15(bool Solid)
   41 {
   42   UnpInitData(Solid);
   43   UnpInitData15(Solid);
   44   UnpReadBuf();
   45   if (!Solid)
   46   {
   47     InitHuff();
   48     UnpPtr=0;
   49   }
   50   else
   51     UnpPtr=WrPtr;
   52   --DestUnpSize;
   53   if (DestUnpSize>=0)
   54   {
   55     GetFlagsBuf();
   56     FlagsCnt=8;
   57   }
   58 
   59   while (DestUnpSize>=0)
   60   {
   61     UnpPtr&=MaxWinMask;
   62 
   63     if (Inp.InAddr>ReadTop-30 && !UnpReadBuf())
   64       break;
   65     if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr)
   66       UnpWriteBuf20();
   67     if (StMode)
   68     {
   69       HuffDecode();
   70       continue;
   71     }
   72 
   73     if (--FlagsCnt < 0)
   74     {
   75       GetFlagsBuf();
   76       FlagsCnt=7;
   77     }
   78 
   79     if (FlagBuf & 0x80)
   80     {
   81       FlagBuf<<=1;
   82       if (Nlzb > Nhfb)
   83         LongLZ();
   84       else
   85         HuffDecode();
   86     }
   87     else
   88     {
   89       FlagBuf<<=1;
   90       if (--FlagsCnt < 0)
   91       {
   92         GetFlagsBuf();
   93         FlagsCnt=7;
   94       }
   95       if (FlagBuf & 0x80)
   96       {
   97         FlagBuf<<=1;
   98         if (Nlzb > Nhfb)
   99           HuffDecode();
  100         else
  101           LongLZ();
  102       }
  103       else
  104       {
  105         FlagBuf<<=1;
  106         ShortLZ();
  107       }
  108     }
  109   }
  110   UnpWriteBuf20();
  111 }
  112 
  113 
  114 #define GetShortLen1(pos) ((pos)==1 ? Buf60+3:ShortLen1[pos])
  115 #define GetShortLen2(pos) ((pos)==3 ? Buf60+3:ShortLen2[pos])
  116 
  117 void Unpack::ShortLZ()
  118 {
  119   static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
  120   static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,
  121                                    0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
  122   static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0};
  123   static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,
  124                                    0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
  125 
  126 
  127   unsigned int Length,SaveLength;
  128   unsigned int LastDistance;
  129   unsigned int Distance;
  130   int DistancePlace;
  131   NumHuf=0;
  132 
  133   unsigned int BitField=Inp.fgetbits();
  134   if (LCount==2)
  135   {
  136     Inp.faddbits(1);
  137     if (BitField >= 0x8000)
  138     {
  139       CopyString15((unsigned int)LastDist,LastLength);
  140       return;
  141     }
  142     BitField <<= 1;
  143     LCount=0;
  144   }
  145 
  146   BitField>>=8;
  147 
  148 //  not thread safe, replaced by GetShortLen1 and GetShortLen2 macro
  149 //  ShortLen1[1]=ShortLen2[3]=Buf60+3;
  150 
  151   if (AvrLn1<37)
  152   {
  153     for (Length=0;;Length++)
  154       if (((BitField^ShortXor1[Length]) & (~(0xff>>GetShortLen1(Length))))==0)
  155         break;
  156     Inp.faddbits(GetShortLen1(Length));
  157   }
  158   else
  159   {
  160     for (Length=0;;Length++)
  161       if (((BitField^ShortXor2[Length]) & (~(0xff>>GetShortLen2(Length))))==0)
  162         break;
  163     Inp.faddbits(GetShortLen2(Length));
  164   }
  165 
  166   if (Length >= 9)
  167   {
  168     if (Length == 9)
  169     {
  170       LCount++;
  171       CopyString15((unsigned int)LastDist,LastLength);
  172       return;
  173     }
  174     if (Length == 14)
  175     {
  176       LCount=0;
  177       Length=DecodeNum(Inp.fgetbits(),STARTL2,DecL2,PosL2)+5;
  178       Distance=(Inp.fgetbits()>>1) | 0x8000;
  179       Inp.faddbits(15);
  180       LastLength=Length;
  181       LastDist=Distance;
  182       CopyString15(Distance,Length);
  183       return;
  184     }
  185 
  186     LCount=0;
  187     SaveLength=Length;
  188     Distance=OldDist[(OldDistPtr-(Length-9)) & 3];
  189     Length=DecodeNum(Inp.fgetbits(),STARTL1,DecL1,PosL1)+2;
  190     if (Length==0x101 && SaveLength==10)
  191     {
  192       Buf60 ^= 1;
  193       return;
  194     }
  195     if (Distance > 256)
  196       Length++;
  197     if (Distance >= MaxDist3)
  198       Length++;
  199 
  200     OldDist[OldDistPtr++]=Distance;
  201     OldDistPtr = OldDistPtr & 3;
  202     LastLength=Length;
  203     LastDist=Distance;
  204     CopyString15(Distance,Length);
  205     return;
  206   }
  207 
  208   LCount=0;
  209   AvrLn1 += Length;
  210   AvrLn1 -= AvrLn1 >> 4;
  211 
  212   DistancePlace=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2) & 0xff;
  213   Distance=ChSetA[DistancePlace];
  214   if (--DistancePlace != -1)
  215   {
  216     LastDistance=ChSetA[DistancePlace];
  217     ChSetA[DistancePlace+1]=LastDistance;
  218     ChSetA[DistancePlace]=Distance;
  219   }
  220   Length+=2;
  221   OldDist[OldDistPtr++] = ++Distance;
  222   OldDistPtr = OldDistPtr & 3;
  223   LastLength=Length;
  224   LastDist=Distance;
  225   CopyString15(Distance,Length);
  226 }
  227 
  228 
  229 void Unpack::LongLZ()
  230 {
  231   unsigned int Length;
  232   unsigned int Distance;
  233   unsigned int DistancePlace,NewDistancePlace;
  234   unsigned int OldAvr2,OldAvr3;
  235 
  236   NumHuf=0;
  237   Nlzb+=16;
  238   if (Nlzb > 0xff)
  239   {
  240     Nlzb=0x90;
  241     Nhfb >>= 1;
  242   }
  243   OldAvr2=AvrLn2;
  244 
  245   unsigned int BitField=Inp.fgetbits();
  246   if (AvrLn2 >= 122)
  247     Length=DecodeNum(BitField,STARTL2,DecL2,PosL2);
  248   else
  249     if (AvrLn2 >= 64)
  250       Length=DecodeNum(BitField,STARTL1,DecL1,PosL1);
  251     else
  252       if (BitField < 0x100)
  253       {
  254         Length=BitField;
  255         Inp.faddbits(16);
  256       }
  257       else
  258       {
  259         for (Length=0;((BitField<<Length)&0x8000)==0;Length++)
  260           ;
  261         Inp.faddbits(Length+1);
  262       }
  263 
  264   AvrLn2 += Length;
  265   AvrLn2 -= AvrLn2 >> 5;
  266 
  267   BitField=Inp.fgetbits();
  268   if (AvrPlcB > 0x28ff)
  269     DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
  270   else
  271     if (AvrPlcB > 0x6ff)
  272       DistancePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
  273     else
  274       DistancePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
  275 
  276   AvrPlcB += DistancePlace;
  277   AvrPlcB -= AvrPlcB >> 8;
  278   while (1)
  279   {
  280     Distance = ChSetB[DistancePlace & 0xff];
  281     NewDistancePlace = NToPlB[Distance++ & 0xff]++;
  282     if (!(Distance & 0xff))
  283       CorrHuff(ChSetB,NToPlB);
  284     else
  285       break;
  286   }
  287 
  288   ChSetB[DistancePlace & 0xff]=ChSetB[NewDistancePlace];
  289   ChSetB[NewDistancePlace]=Distance;
  290 
  291   Distance=((Distance & 0xff00) | (Inp.fgetbits() >> 8)) >> 1;
  292   Inp.faddbits(7);
  293 
  294   OldAvr3=AvrLn3;
  295   if (Length!=1 && Length!=4)
  296     if (Length==0 && Distance <= MaxDist3)
  297     {
  298       AvrLn3++;
  299       AvrLn3 -= AvrLn3 >> 8;
  300     }
  301     else
  302       if (AvrLn3 > 0)
  303         AvrLn3--;
  304   Length+=3;
  305   if (Distance >= MaxDist3)
  306     Length++;
  307   if (Distance <= 256)
  308     Length+=8;
  309   if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40)
  310     MaxDist3=0x7f00;
  311   else
  312     MaxDist3=0x2001;
  313   OldDist[OldDistPtr++]=Distance;
  314   OldDistPtr = OldDistPtr & 3;
  315   LastLength=Length;
  316   LastDist=Distance;
  317   CopyString15(Distance,Length);
  318 }
  319 
  320 
  321 void Unpack::HuffDecode()
  322 {
  323   unsigned int CurByte,NewBytePlace;
  324   unsigned int Length;
  325   unsigned int Distance;
  326   int BytePlace;
  327 
  328   unsigned int BitField=Inp.fgetbits();
  329 
  330   if (AvrPlc > 0x75ff)
  331     BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4);
  332   else
  333     if (AvrPlc > 0x5dff)
  334       BytePlace=DecodeNum(BitField,STARTHF3,DecHf3,PosHf3);
  335     else
  336       if (AvrPlc > 0x35ff)
  337         BytePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
  338       else
  339         if (AvrPlc > 0x0dff)
  340           BytePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
  341         else
  342           BytePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
  343   BytePlace&=0xff;
  344   if (StMode)
  345   {
  346     if (BytePlace==0 && BitField > 0xfff)
  347       BytePlace=0x100;
  348     if (--BytePlace==-1)
  349     {
  350       BitField=Inp.fgetbits();
  351       Inp.faddbits(1);
  352       if (BitField & 0x8000)
  353       {
  354         NumHuf=StMode=0;
  355         return;
  356       }
  357       else
  358       {
  359         Length = (BitField & 0x4000) ? 4 : 3;
  360         Inp.faddbits(1);
  361         Distance=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2);
  362         Distance = (Distance << 5) | (Inp.fgetbits() >> 11);
  363         Inp.faddbits(5);
  364         CopyString15(Distance,Length);
  365         return;
  366       }
  367     }
  368   }
  369   else
  370     if (NumHuf++ >= 16 && FlagsCnt==0)
  371       StMode=1;
  372   AvrPlc += BytePlace;
  373   AvrPlc -= AvrPlc >> 8;
  374   Nhfb+=16;
  375   if (Nhfb > 0xff)
  376   {
  377     Nhfb=0x90;
  378     Nlzb >>= 1;
  379   }
  380 
  381   Window[UnpPtr++]=(byte)(ChSet[BytePlace]>>8);
  382   --DestUnpSize;
  383 
  384   while (1)
  385   {
  386     CurByte=ChSet[BytePlace];
  387     NewBytePlace=NToPl[CurByte++ & 0xff]++;
  388     if ((CurByte & 0xff) > 0xa1)
  389       CorrHuff(ChSet,NToPl);
  390     else
  391       break;
  392   }
  393 
  394   ChSet[BytePlace]=ChSet[NewBytePlace];
  395   ChSet[NewBytePlace]=CurByte;
  396 }
  397 
  398 
  399 void Unpack::GetFlagsBuf()
  400 {
  401   unsigned int Flags,NewFlagsPlace;
  402   unsigned int FlagsPlace=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2);
  403 
  404   // Our Huffman table stores 257 items and needs all them in other parts
  405   // of code such as when StMode is on, so the first item is control item.
  406   // While normally we do not use the last item to code the flags byte here,
  407   // we need to check for value 256 when unpacking in case we unpack
  408   // a corrupt archive.
  409   if (FlagsPlace>=sizeof(ChSetC)/sizeof(ChSetC[0]))
  410     return;
  411 
  412   while (1)
  413   {
  414     Flags=ChSetC[FlagsPlace];
  415     FlagBuf=Flags>>8;
  416     NewFlagsPlace=NToPlC[Flags++ & 0xff]++;
  417     if ((Flags & 0xff) != 0)
  418       break;
  419     CorrHuff(ChSetC,NToPlC);
  420   }
  421 
  422   ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace];
  423   ChSetC[NewFlagsPlace]=Flags;
  424 }
  425 
  426 
  427 void Unpack::UnpInitData15(int Solid)
  428 {
  429   if (!Solid)
  430   {
  431     AvrPlcB=AvrLn1=AvrLn2=AvrLn3=NumHuf=Buf60=0;
  432     AvrPlc=0x3500;
  433     MaxDist3=0x2001;
  434     Nhfb=Nlzb=0x80;
  435   }
  436   FlagsCnt=0;
  437   FlagBuf=0;
  438   StMode=0;
  439   LCount=0;
  440   ReadTop=0;
  441 }
  442 
  443 
  444 void Unpack::InitHuff()
  445 {
  446   for (unsigned int I=0;I<256;I++)
  447   {
  448     ChSet[I]=ChSetB[I]=I<<8;
  449     ChSetA[I]=I;
  450     ChSetC[I]=((~I+1) & 0xff)<<8;
  451   }
  452   memset(NToPl,0,sizeof(NToPl));
  453   memset(NToPlB,0,sizeof(NToPlB));
  454   memset(NToPlC,0,sizeof(NToPlC));
  455   CorrHuff(ChSetB,NToPlB);
  456 }
  457 
  458 
  459 void Unpack::CorrHuff(ushort *CharSet,byte *NumToPlace)
  460 {
  461   int I,J;
  462   for (I=7;I>=0;I--)
  463     for (J=0;J<32;J++,CharSet++)
  464       *CharSet=(*CharSet & ~0xff) | I;
  465   memset(NumToPlace,0,sizeof(NToPl));
  466   for (I=6;I>=0;I--)
  467     NumToPlace[I]=(7-I)*32;
  468 }
  469 
  470 
  471 void Unpack::CopyString15(uint Distance,uint Length)
  472 {
  473   DestUnpSize-=Length;
  474   while (Length--)
  475   {
  476     Window[UnpPtr]=Window[(UnpPtr-Distance) & MaxWinMask];
  477     UnpPtr=(UnpPtr+1) & MaxWinMask;
  478   }
  479 }
  480 
  481 
  482 uint Unpack::DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab)
  483 {
  484   int I;
  485   for (Num&=0xfff0,I=0;DecTab[I]<=Num;I++)
  486     StartPos++;
  487   Inp.faddbits(StartPos);
  488   return(((Num-(I ? DecTab[I-1]:0))>>(16-StartPos))+PosTab[StartPos]);
  489 }