PageRenderTime 2148ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/3rdParty/unrar/unpack15.cpp

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