Unpack.unpack20_cpp.cs 9.2 KB

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