Unpack.unpack50_cpp.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  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.UnpackGlobal;
  14. namespace SharpCompress.Compressors.Rar.UnpackV2017
  15. {
  16. internal partial class Unpack
  17. {
  18. private void Unpack5(bool Solid)
  19. {
  20. FileExtracted=true;
  21. if (!Suspended)
  22. {
  23. UnpInitData(Solid);
  24. if (!UnpReadBuf())
  25. return;
  26. // Check TablesRead5 to be sure that we read tables at least once
  27. // regardless of current block header TablePresent flag.
  28. // So we can safefly use these tables below.
  29. if (!ReadBlockHeader(Inp,ref BlockHeader) ||
  30. !ReadTables(Inp,ref BlockHeader, ref BlockTables) || !TablesRead5)
  31. return;
  32. }
  33. while (true)
  34. {
  35. UnpPtr&=MaxWinMask;
  36. if (Inp.InAddr>=ReadBorder)
  37. {
  38. bool FileDone=false;
  39. // We use 'while', because for empty block containing only Huffman table,
  40. // we'll be on the block border once again just after reading the table.
  41. while (Inp.InAddr>BlockHeader.BlockStart+BlockHeader.BlockSize-1 ||
  42. Inp.InAddr==BlockHeader.BlockStart+BlockHeader.BlockSize-1 &&
  43. Inp.InBit>=BlockHeader.BlockBitSize)
  44. {
  45. if (BlockHeader.LastBlockInFile)
  46. {
  47. FileDone=true;
  48. break;
  49. }
  50. if (!ReadBlockHeader(Inp,ref BlockHeader) || !ReadTables(Inp, ref BlockHeader, ref BlockTables))
  51. return;
  52. }
  53. if (FileDone || !UnpReadBuf())
  54. break;
  55. }
  56. if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr)
  57. {
  58. UnpWriteBuf();
  59. if (WrittenFileSize>DestUnpSize)
  60. return;
  61. if (Suspended)
  62. {
  63. FileExtracted=false;
  64. return;
  65. }
  66. }
  67. uint MainSlot=DecodeNumber(Inp,BlockTables.LD);
  68. if (MainSlot<256)
  69. {
  70. if (Fragmented)
  71. FragWindow[UnpPtr++]=(byte)MainSlot;
  72. else
  73. Window[UnpPtr++]=(byte)MainSlot;
  74. continue;
  75. }
  76. if (MainSlot>=262)
  77. {
  78. uint Length=SlotToLength(Inp,MainSlot-262);
  79. uint DBits,Distance=1,DistSlot=DecodeNumber(Inp,BlockTables.DD);
  80. if (DistSlot<4)
  81. {
  82. DBits=0;
  83. Distance+=DistSlot;
  84. }
  85. else
  86. {
  87. DBits=DistSlot/2 - 1;
  88. Distance+=(2 | (DistSlot & 1)) << (int)DBits;
  89. }
  90. if (DBits>0)
  91. {
  92. if (DBits>=4)
  93. {
  94. if (DBits>4)
  95. {
  96. Distance+=((Inp.getbits32()>>(int)(36-DBits))<<4);
  97. Inp.addbits(DBits-4);
  98. }
  99. uint LowDist=DecodeNumber(Inp,BlockTables.LDD);
  100. Distance+=LowDist;
  101. }
  102. else
  103. {
  104. Distance+=Inp.getbits32()>>(int)(32-DBits);
  105. Inp.addbits(DBits);
  106. }
  107. }
  108. if (Distance>0x100)
  109. {
  110. Length++;
  111. if (Distance>0x2000)
  112. {
  113. Length++;
  114. if (Distance>0x40000)
  115. Length++;
  116. }
  117. }
  118. InsertOldDist(Distance);
  119. LastLength=Length;
  120. if (Fragmented)
  121. FragWindow.CopyString(Length,Distance,ref UnpPtr,MaxWinMask);
  122. else
  123. CopyString(Length,Distance);
  124. continue;
  125. }
  126. if (MainSlot==256)
  127. {
  128. UnpackFilter Filter = new UnpackFilter();
  129. if (!ReadFilter(Inp,Filter) || !AddFilter(Filter))
  130. break;
  131. continue;
  132. }
  133. if (MainSlot==257)
  134. {
  135. if (LastLength!=0)
  136. if (Fragmented)
  137. FragWindow.CopyString(LastLength,OldDist[0],ref UnpPtr,MaxWinMask);
  138. else
  139. CopyString(LastLength,OldDist[0]);
  140. continue;
  141. }
  142. if (MainSlot<262)
  143. {
  144. uint DistNum=MainSlot-258;
  145. uint Distance=OldDist[DistNum];
  146. for (uint I=DistNum;I>0;I--)
  147. OldDist[I]=OldDist[I-1];
  148. OldDist[0]=Distance;
  149. uint LengthSlot=DecodeNumber(Inp,BlockTables.RD);
  150. uint Length=SlotToLength(Inp,LengthSlot);
  151. LastLength=Length;
  152. if (Fragmented)
  153. FragWindow.CopyString(Length,Distance,ref UnpPtr,MaxWinMask);
  154. else
  155. CopyString(Length,Distance);
  156. continue;
  157. }
  158. }
  159. UnpWriteBuf();
  160. }
  161. private uint ReadFilterData(BitInput Inp)
  162. {
  163. uint ByteCount=(Inp.fgetbits()>>14)+1;
  164. Inp.addbits(2);
  165. uint Data=0;
  166. for (uint I=0;I<ByteCount;I++)
  167. {
  168. Data+=(Inp.fgetbits()>>8)<<(int)(I*8);
  169. Inp.addbits(8);
  170. }
  171. return Data;
  172. }
  173. private bool ReadFilter(BitInput Inp,UnpackFilter Filter)
  174. {
  175. if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-16)
  176. if (!UnpReadBuf())
  177. return false;
  178. Filter.BlockStart=ReadFilterData(Inp);
  179. Filter.BlockLength=ReadFilterData(Inp);
  180. if (Filter.BlockLength>MAX_FILTER_BLOCK_SIZE)
  181. Filter.BlockLength=0;
  182. Filter.Type=(byte)(Inp.fgetbits()>>13);
  183. Inp.faddbits(3);
  184. if (Filter.Type==FILTER_DELTA)
  185. {
  186. Filter.Channels=(byte)((Inp.fgetbits()>>11)+1);
  187. Inp.faddbits(5);
  188. }
  189. return true;
  190. }
  191. private bool AddFilter(UnpackFilter Filter)
  192. {
  193. if (Filters.Count>=MAX_UNPACK_FILTERS)
  194. {
  195. UnpWriteBuf(); // Write data, apply and flush filters.
  196. if (Filters.Count>=MAX_UNPACK_FILTERS)
  197. InitFilters(); // Still too many filters, prevent excessive memory use.
  198. }
  199. // If distance to filter start is that large that due to circular dictionary
  200. // mode now it points to old not written yet data, then we set 'NextWindow'
  201. // flag and process this filter only after processing that older data.
  202. Filter.NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=Filter.BlockStart;
  203. Filter.BlockStart=(uint)((Filter.BlockStart+UnpPtr)&MaxWinMask);
  204. Filters.Add(Filter);
  205. return true;
  206. }
  207. private bool UnpReadBuf()
  208. {
  209. int DataSize=ReadTop-Inp.InAddr; // Data left to process.
  210. if (DataSize<0)
  211. return false;
  212. BlockHeader.BlockSize-=Inp.InAddr-BlockHeader.BlockStart;
  213. if (Inp.InAddr>MAX_SIZE/2)
  214. {
  215. // If we already processed more than half of buffer, let's move
  216. // remaining data into beginning to free more space for new data
  217. // and ensure that calling function does not cross the buffer border
  218. // even if we did not read anything here. Also it ensures that read size
  219. // is not less than CRYPT_BLOCK_SIZE, so we can align it without risk
  220. // to make it zero.
  221. if (DataSize>0)
  222. //x memmove(Inp.InBuf,Inp.InBuf+Inp.InAddr,DataSize);
  223. Buffer.BlockCopy(Inp.InBuf, Inp.InAddr, Inp.InBuf, 0, DataSize);
  224. Inp.InAddr=0;
  225. ReadTop=DataSize;
  226. }
  227. else
  228. DataSize=ReadTop;
  229. int ReadCode=0;
  230. if (MAX_SIZE!=DataSize)
  231. ReadCode=UnpIO_UnpRead(Inp.InBuf,DataSize,MAX_SIZE-DataSize);
  232. if (ReadCode>0) // Can be also -1.
  233. ReadTop+=ReadCode;
  234. ReadBorder=ReadTop-30;
  235. BlockHeader.BlockStart=Inp.InAddr;
  236. if (BlockHeader.BlockSize!=-1) // '-1' means not defined yet.
  237. {
  238. // We may need to quit from main extraction loop and read new block header
  239. // and trees earlier than data in input buffer ends.
  240. ReadBorder=Math.Min(ReadBorder,BlockHeader.BlockStart+BlockHeader.BlockSize-1);
  241. }
  242. return ReadCode!=-1;
  243. }
  244. private void UnpWriteBuf()
  245. {
  246. size_t WrittenBorder=WrPtr;
  247. size_t FullWriteSize=(UnpPtr-WrittenBorder)&MaxWinMask;
  248. size_t WriteSizeLeft=FullWriteSize;
  249. bool NotAllFiltersProcessed=false;
  250. //for (size_t I=0;I<Filters.Count;I++)
  251. // sharpcompress: size_t -> int
  252. for (int I=0;I<Filters.Count;I++)
  253. {
  254. // Here we apply filters to data which we need to write.
  255. // We always copy data to another memory block before processing.
  256. // We cannot process them just in place in Window buffer, because
  257. // these data can be used for future string matches, so we must
  258. // preserve them in original form.
  259. UnpackFilter flt=Filters[I];
  260. if (flt.Type==FILTER_NONE)
  261. continue;
  262. if (flt.NextWindow)
  263. {
  264. // Here we skip filters which have block start in current data range
  265. // due to address wrap around in circular dictionary, but actually
  266. // belong to next dictionary block. If such filter start position
  267. // is included to current write range, then we reset 'NextWindow' flag.
  268. // In fact we can reset it even without such check, because current
  269. // implementation seems to guarantee 'NextWindow' flag reset after
  270. // buffer writing for all existing filters. But let's keep this check
  271. // just in case. Compressor guarantees that distance between
  272. // filter block start and filter storing position cannot exceed
  273. // the dictionary size. So if we covered the filter block start with
  274. // our write here, we can safely assume that filter is applicable
  275. // to next block on no further wrap arounds is possible.
  276. if (((flt.BlockStart-WrPtr)&MaxWinMask)<=FullWriteSize)
  277. flt.NextWindow=false;
  278. continue;
  279. }
  280. uint BlockStart=flt.BlockStart;
  281. uint BlockLength=flt.BlockLength;
  282. if (((BlockStart-WrittenBorder)&MaxWinMask)<WriteSizeLeft)
  283. {
  284. if (WrittenBorder!=BlockStart)
  285. {
  286. UnpWriteArea(WrittenBorder,BlockStart);
  287. WrittenBorder=BlockStart;
  288. WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
  289. }
  290. if (BlockLength<=WriteSizeLeft)
  291. {
  292. if (BlockLength>0) // We set it to 0 also for invalid filters.
  293. {
  294. uint BlockEnd=(BlockStart+BlockLength)&MaxWinMask;
  295. //x FilterSrcMemory.Alloc(BlockLength);
  296. FilterSrcMemory = EnsureCapacity(FilterSrcMemory, checked((int)BlockLength));
  297. byte[] Mem= FilterSrcMemory;
  298. if (BlockStart<BlockEnd || BlockEnd==0)
  299. {
  300. if (Fragmented)
  301. FragWindow.CopyData(Mem,0,BlockStart,BlockLength);
  302. else
  303. //x memcpy(Mem,Window+BlockStart,BlockLength);
  304. Utility.Copy(Window, BlockStart, Mem, 0, BlockLength);
  305. }
  306. else
  307. {
  308. size_t FirstPartLength=(size_t)(MaxWinSize-BlockStart);
  309. if (Fragmented)
  310. {
  311. FragWindow.CopyData(Mem,0,BlockStart,FirstPartLength);
  312. FragWindow.CopyData(Mem,FirstPartLength,0,BlockEnd);
  313. }
  314. else
  315. {
  316. //x memcpy(Mem,Window+BlockStart,FirstPartLength);
  317. Utility.Copy(Window, BlockStart, Mem, 0, FirstPartLength);
  318. //x memcpy(Mem+FirstPartLength,Window,BlockEnd);
  319. Utility.Copy(Window, 0, Mem, FirstPartLength,BlockEnd);
  320. }
  321. }
  322. byte[] OutMem=ApplyFilter(Mem,BlockLength,flt);
  323. Filters[I].Type=FILTER_NONE;
  324. if (OutMem!=null)
  325. UnpIO_UnpWrite(OutMem,0,BlockLength);
  326. UnpSomeRead=true;
  327. WrittenFileSize+=BlockLength;
  328. WrittenBorder=BlockEnd;
  329. WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
  330. }
  331. }
  332. else
  333. {
  334. // Current filter intersects the window write border, so we adjust
  335. // the window border to process this filter next time, not now.
  336. WrPtr=WrittenBorder;
  337. // Since Filter start position can only increase, we quit processing
  338. // all following filters for this data block and reset 'NextWindow'
  339. // flag for them.
  340. //for (size_t J=I;J<Filters.Count;J++)
  341. // sharpcompress: size_t -> int
  342. for (int J=I;J<Filters.Count;J++)
  343. {
  344. UnpackFilter _flt=Filters[J];
  345. if (_flt.Type!=FILTER_NONE)
  346. _flt.NextWindow=false;
  347. }
  348. // Do not write data left after current filter now.
  349. NotAllFiltersProcessed=true;
  350. break;
  351. }
  352. }
  353. }
  354. // Remove processed filters from queue.
  355. // sharpcompress: size_t -> int
  356. int EmptyCount=0;
  357. // sharpcompress: size_t -> int
  358. for (int I=0;I<Filters.Count;I++)
  359. {
  360. if (EmptyCount>0)
  361. Filters[I-EmptyCount]=Filters[I];
  362. if (Filters[I].Type==FILTER_NONE)
  363. EmptyCount++;
  364. }
  365. if (EmptyCount>0)
  366. //Filters.Alloc(Filters.Count-EmptyCount);
  367. Filters.RemoveRange(Filters.Count-EmptyCount, EmptyCount);
  368. if (!NotAllFiltersProcessed) // Only if all filters are processed.
  369. {
  370. // Write data left after last filter.
  371. UnpWriteArea(WrittenBorder,UnpPtr);
  372. WrPtr=UnpPtr;
  373. }
  374. // We prefer to write data in blocks not exceeding UNPACK_MAX_WRITE
  375. // instead of potentially huge MaxWinSize blocks. It also allows us
  376. // to keep the size of Filters array reasonable.
  377. WriteBorder=(UnpPtr+Math.Min(MaxWinSize,UNPACK_MAX_WRITE))&MaxWinMask;
  378. // Choose the nearest among WriteBorder and WrPtr actual written border.
  379. // If border is equal to UnpPtr, it means that we have MaxWinSize data ahead.
  380. if (WriteBorder==UnpPtr ||
  381. WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<((WriteBorder-UnpPtr)&MaxWinMask))
  382. WriteBorder=WrPtr;
  383. }
  384. private byte[] ApplyFilter(byte[] __d,uint DataSize,UnpackFilter Flt)
  385. {
  386. int Data = 0;
  387. byte[] SrcData=__d;
  388. switch(Flt.Type)
  389. {
  390. case FILTER_E8:
  391. case FILTER_E8E9:
  392. {
  393. uint FileOffset=(uint)WrittenFileSize;
  394. const uint FileSize=0x1000000;
  395. byte CmpByte2=Flt.Type==FILTER_E8E9 ? (byte)0xe9 : (byte)0xe8;
  396. // DataSize is unsigned, so we use "CurPos+4" and not "DataSize-4"
  397. // to avoid overflow for DataSize<4.
  398. for (uint CurPos=0;CurPos+4<DataSize;)
  399. {
  400. //x byte CurByte=*(Data++);
  401. byte CurByte=__d[Data++];
  402. CurPos++;
  403. if (CurByte==0xe8 || CurByte==CmpByte2)
  404. {
  405. uint Offset=(CurPos+FileOffset)%FileSize;
  406. uint Addr=RawGet4(__d,Data);
  407. // We check 0x80000000 bit instead of '< 0' comparison
  408. // not assuming int32 presence or uint size and endianness.
  409. if ((Addr & 0x80000000)!=0) // Addr<0
  410. {
  411. if (((Addr+Offset) & 0x80000000)==0) // Addr+Offset>=0
  412. RawPut4(Addr+FileSize,__d,Data);
  413. }
  414. else
  415. if (((Addr-FileSize) & 0x80000000)!=0) // Addr<FileSize
  416. RawPut4(Addr-Offset,__d,Data);
  417. Data+=4;
  418. CurPos+=4;
  419. }
  420. }
  421. }
  422. return SrcData;
  423. case FILTER_ARM:
  424. {
  425. uint FileOffset=(uint)WrittenFileSize;
  426. // DataSize is unsigned, so we use "CurPos+3" and not "DataSize-3"
  427. // to avoid overflow for DataSize<3.
  428. for (uint CurPos=0;CurPos+3<DataSize;CurPos+=4)
  429. {
  430. var D=Data+CurPos;
  431. if (__d[D+3]==0xeb) // BL command with '1110' (Always) condition.
  432. {
  433. uint Offset=__d[D]+(uint)(__d[D+1])*0x100+(uint)(__d[D+2])*0x10000;
  434. Offset-=(FileOffset+CurPos)/4;
  435. __d[D]=(byte)Offset;
  436. __d[D+1]=(byte)(Offset>>8);
  437. __d[D+2]=(byte)(Offset>>16);
  438. }
  439. }
  440. }
  441. return SrcData;
  442. case FILTER_DELTA:
  443. {
  444. // Unlike RAR3, we do not need to reject excessive channel
  445. // values here, since RAR5 uses only 5 bits to store channel.
  446. uint Channels=Flt.Channels,SrcPos=0;
  447. //x FilterDstMemory.Alloc(DataSize);
  448. FilterDstMemory = EnsureCapacity(FilterDstMemory, checked((int)DataSize));
  449. byte[] DstData=FilterDstMemory;
  450. // Bytes from same channels are grouped to continual data blocks,
  451. // so we need to place them back to their interleaving positions.
  452. for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
  453. {
  454. byte PrevByte=0;
  455. for (uint DestPos=CurChannel;DestPos<DataSize;DestPos+=Channels)
  456. DstData[DestPos]=(PrevByte-=__d[Data+SrcPos++]);
  457. }
  458. return DstData;
  459. }
  460. }
  461. return null;
  462. }
  463. private void UnpWriteArea(size_t StartPtr,size_t EndPtr)
  464. {
  465. if (EndPtr!=StartPtr)
  466. UnpSomeRead=true;
  467. if (EndPtr<StartPtr)
  468. UnpAllBuf=true;
  469. if (Fragmented)
  470. {
  471. size_t SizeToWrite=(EndPtr-StartPtr) & MaxWinMask;
  472. while (SizeToWrite>0)
  473. {
  474. size_t BlockSize=FragWindow.GetBlockSize(StartPtr,SizeToWrite);
  475. //UnpWriteData(&FragWindow[StartPtr],BlockSize);
  476. FragWindow.GetBuffer(StartPtr, out var __buffer, out var __offset);
  477. UnpWriteData(__buffer, __offset, BlockSize);
  478. SizeToWrite-=BlockSize;
  479. StartPtr=(StartPtr+BlockSize) & MaxWinMask;
  480. }
  481. }
  482. else
  483. if (EndPtr<StartPtr)
  484. {
  485. UnpWriteData(Window,StartPtr,MaxWinSize-StartPtr);
  486. UnpWriteData(Window,0,EndPtr);
  487. }
  488. else
  489. UnpWriteData(Window,StartPtr,EndPtr-StartPtr);
  490. }
  491. private void UnpWriteData(byte[] Data, size_t offset, size_t Size)
  492. {
  493. if (WrittenFileSize>=DestUnpSize)
  494. return;
  495. size_t WriteSize=Size;
  496. int64 LeftToWrite=DestUnpSize-WrittenFileSize;
  497. if ((int64)WriteSize>LeftToWrite)
  498. WriteSize=(size_t)LeftToWrite;
  499. UnpIO_UnpWrite(Data, offset, WriteSize);
  500. WrittenFileSize+=Size;
  501. }
  502. private void UnpInitData50(bool Solid)
  503. {
  504. if (!Solid)
  505. TablesRead5=false;
  506. }
  507. private bool ReadBlockHeader(BitInput Inp,ref UnpackBlockHeader Header)
  508. {
  509. Header.HeaderSize=0;
  510. if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-7)
  511. if (!UnpReadBuf())
  512. return false;
  513. Inp.faddbits((uint)((8-Inp.InBit)&7));
  514. byte BlockFlags=(byte)(Inp.fgetbits()>>8);
  515. Inp.faddbits(8);
  516. uint ByteCount=(uint)(((BlockFlags>>3)&3)+1); // Block size byte count.
  517. if (ByteCount==4)
  518. return false;
  519. Header.HeaderSize=(int)(2+ByteCount);
  520. Header.BlockBitSize=(BlockFlags&7)+1;
  521. byte SavedCheckSum=(byte)(Inp.fgetbits()>>8);
  522. Inp.faddbits(8);
  523. int BlockSize=0;
  524. for (uint I=0;I<ByteCount;I++)
  525. {
  526. BlockSize+=(int)((Inp.fgetbits()>>8)<<(int)(I*8));
  527. Inp.addbits(8);
  528. }
  529. Header.BlockSize=BlockSize;
  530. byte CheckSum=(byte)(0x5a^BlockFlags^BlockSize^(BlockSize>>8)^(BlockSize>>16));
  531. if (CheckSum!=SavedCheckSum)
  532. return false;
  533. Header.BlockStart=Inp.InAddr;
  534. ReadBorder=Math.Min(ReadBorder,Header.BlockStart+Header.BlockSize-1);
  535. Header.LastBlockInFile=(BlockFlags & 0x40)!=0;
  536. Header.TablePresent=(BlockFlags & 0x80)!=0;
  537. return true;
  538. }
  539. private bool ReadTables(BitInput Inp,ref UnpackBlockHeader Header, ref UnpackBlockTables Tables)
  540. {
  541. if (!Header.TablePresent)
  542. return true;
  543. if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-25)
  544. if (!UnpReadBuf())
  545. return false;
  546. byte[] BitLength = new byte[BC];
  547. for (uint I=0;I<BC;I++)
  548. {
  549. uint Length=(byte)(Inp.fgetbits() >> 12);
  550. Inp.faddbits(4);
  551. if (Length==15)
  552. {
  553. uint ZeroCount=(byte)(Inp.fgetbits() >> 12);
  554. Inp.faddbits(4);
  555. if (ZeroCount==0)
  556. BitLength[I]=15;
  557. else
  558. {
  559. ZeroCount+=2;
  560. while (ZeroCount-- > 0 && I<BitLength.Length)
  561. BitLength[I++]=0;
  562. I--;
  563. }
  564. }
  565. else
  566. BitLength[I]=(byte)Length;
  567. }
  568. MakeDecodeTables(BitLength,0,Tables.BD,BC);
  569. byte[] Table = new byte[HUFF_TABLE_SIZE];
  570. const uint TableSize=HUFF_TABLE_SIZE;
  571. for (uint I=0;I<TableSize;)
  572. {
  573. if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-5)
  574. if (!UnpReadBuf())
  575. return false;
  576. uint Number=DecodeNumber(Inp,Tables.BD);
  577. if (Number<16)
  578. {
  579. Table[I]=(byte)Number;
  580. I++;
  581. }
  582. else
  583. if (Number<18)
  584. {
  585. uint N;
  586. if (Number==16)
  587. {
  588. N=(Inp.fgetbits() >> 13)+3;
  589. Inp.faddbits(3);
  590. }
  591. else
  592. {
  593. N=(Inp.fgetbits() >> 9)+11;
  594. Inp.faddbits(7);
  595. }
  596. if (I==0)
  597. {
  598. // We cannot have "repeat previous" code at the first position.
  599. // Multiple such codes would shift Inp position without changing I,
  600. // which can lead to reading beyond of Inp boundary in mutithreading
  601. // mode, where Inp.ExternalBuffer disables bounds check and we just
  602. // reserve a lot of buffer space to not need such check normally.
  603. return false;
  604. }
  605. else
  606. while (N-- > 0 && I<TableSize)
  607. {
  608. Table[I]=Table[I-1];
  609. I++;
  610. }
  611. }
  612. else
  613. {
  614. uint N;
  615. if (Number==18)
  616. {
  617. N=(Inp.fgetbits() >> 13)+3;
  618. Inp.faddbits(3);
  619. }
  620. else
  621. {
  622. N=(Inp.fgetbits() >> 9)+11;
  623. Inp.faddbits(7);
  624. }
  625. while (N-- > 0 && I<TableSize)
  626. Table[I++]=0;
  627. }
  628. }
  629. TablesRead5=true;
  630. if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop)
  631. return false;
  632. MakeDecodeTables(Table, 0, Tables.LD,NC);
  633. MakeDecodeTables(Table, (int)NC,Tables.DD,DC);
  634. MakeDecodeTables(Table, (int)(NC+DC),Tables.LDD,LDC);
  635. MakeDecodeTables(Table, (int)(NC+DC+LDC),Tables.RD,RC);
  636. return true;
  637. }
  638. private void InitFilters()
  639. {
  640. //Filters.SoftReset();
  641. Filters.Clear();
  642. }
  643. }
  644. }