Unpack.unpack15_cpp.cs 12 KB

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