BZip2InputStream.cs 21 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  1. using ICSharpCode.SharpZipLib.Checksum;
  2. using System;
  3. using System.IO;
  4. namespace ICSharpCode.SharpZipLib.BZip2
  5. {
  6. /// <summary>
  7. /// An input stream that decompresses files in the BZip2 format
  8. /// </summary>
  9. public class BZip2InputStream : Stream
  10. {
  11. #region Constants
  12. private const int START_BLOCK_STATE = 1;
  13. private const int RAND_PART_A_STATE = 2;
  14. private const int RAND_PART_B_STATE = 3;
  15. private const int RAND_PART_C_STATE = 4;
  16. private const int NO_RAND_PART_A_STATE = 5;
  17. private const int NO_RAND_PART_B_STATE = 6;
  18. private const int NO_RAND_PART_C_STATE = 7;
  19. #endregion Constants
  20. #region Instance Fields
  21. /*--
  22. index of the last char in the block, so
  23. the block size == last + 1.
  24. --*/
  25. private int last;
  26. /*--
  27. index in zptr[] of original string after sorting.
  28. --*/
  29. private int origPtr;
  30. /*--
  31. always: in the range 0 .. 9.
  32. The current block size is 100000 * this number.
  33. --*/
  34. private int blockSize100k;
  35. private bool blockRandomised;
  36. private int bsBuff;
  37. private int bsLive;
  38. private IChecksum mCrc = new BZip2Crc();
  39. private bool[] inUse = new bool[256];
  40. private int nInUse;
  41. private byte[] seqToUnseq = new byte[256];
  42. private byte[] unseqToSeq = new byte[256];
  43. private byte[] selector = new byte[BZip2Constants.MaximumSelectors];
  44. private byte[] selectorMtf = new byte[BZip2Constants.MaximumSelectors];
  45. private int[] tt;
  46. private byte[] ll8;
  47. /*--
  48. freq table collected to save a pass over the data
  49. during decompression.
  50. --*/
  51. private int[] unzftab = new int[256];
  52. private int[][] limit = new int[BZip2Constants.GroupCount][];
  53. private int[][] baseArray = new int[BZip2Constants.GroupCount][];
  54. private int[][] perm = new int[BZip2Constants.GroupCount][];
  55. private int[] minLens = new int[BZip2Constants.GroupCount];
  56. private readonly Stream baseStream;
  57. private bool streamEnd;
  58. private int currentChar = -1;
  59. private int currentState = START_BLOCK_STATE;
  60. private int storedBlockCRC, storedCombinedCRC;
  61. private int computedBlockCRC;
  62. private uint computedCombinedCRC;
  63. private int count, chPrev, ch2;
  64. private int tPos;
  65. private int rNToGo;
  66. private int rTPos;
  67. private int i2, j2;
  68. private byte z;
  69. #endregion Instance Fields
  70. /// <summary>
  71. /// Construct instance for reading from stream
  72. /// </summary>
  73. /// <param name="stream">Data source</param>
  74. public BZip2InputStream(Stream stream)
  75. {
  76. if (stream == null)
  77. throw new ArgumentNullException(nameof(stream));
  78. // init arrays
  79. for (int i = 0; i < BZip2Constants.GroupCount; ++i)
  80. {
  81. limit[i] = new int[BZip2Constants.MaximumAlphaSize];
  82. baseArray[i] = new int[BZip2Constants.MaximumAlphaSize];
  83. perm[i] = new int[BZip2Constants.MaximumAlphaSize];
  84. }
  85. baseStream = stream;
  86. bsLive = 0;
  87. bsBuff = 0;
  88. Initialize();
  89. InitBlock();
  90. SetupBlock();
  91. }
  92. /// <summary>
  93. /// Get/set flag indicating ownership of underlying stream.
  94. /// When the flag is true <see cref="Stream.Dispose()" /> will close the underlying stream also.
  95. /// </summary>
  96. public bool IsStreamOwner { get; set; } = true;
  97. #region Stream Overrides
  98. /// <summary>
  99. /// Gets a value indicating if the stream supports reading
  100. /// </summary>
  101. public override bool CanRead
  102. {
  103. get
  104. {
  105. return baseStream.CanRead;
  106. }
  107. }
  108. /// <summary>
  109. /// Gets a value indicating whether the current stream supports seeking.
  110. /// </summary>
  111. public override bool CanSeek
  112. {
  113. get
  114. {
  115. return false;
  116. }
  117. }
  118. /// <summary>
  119. /// Gets a value indicating whether the current stream supports writing.
  120. /// This property always returns false
  121. /// </summary>
  122. public override bool CanWrite
  123. {
  124. get
  125. {
  126. return false;
  127. }
  128. }
  129. /// <summary>
  130. /// Gets the length in bytes of the stream.
  131. /// </summary>
  132. public override long Length
  133. {
  134. get
  135. {
  136. return baseStream.Length;
  137. }
  138. }
  139. /// <summary>
  140. /// Gets the current position of the stream.
  141. /// Setting the position is not supported and will throw a NotSupportException.
  142. /// </summary>
  143. /// <exception cref="NotSupportedException">Any attempt to set the position.</exception>
  144. public override long Position
  145. {
  146. get
  147. {
  148. return baseStream.Position;
  149. }
  150. set
  151. {
  152. throw new NotSupportedException("BZip2InputStream position cannot be set");
  153. }
  154. }
  155. /// <summary>
  156. /// Flushes the stream.
  157. /// </summary>
  158. public override void Flush()
  159. {
  160. baseStream.Flush();
  161. }
  162. /// <summary>
  163. /// Set the streams position. This operation is not supported and will throw a NotSupportedException
  164. /// </summary>
  165. /// <param name="offset">A byte offset relative to the <paramref name="origin"/> parameter.</param>
  166. /// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the reference point used to obtain the new position.</param>
  167. /// <returns>The new position of the stream.</returns>
  168. /// <exception cref="NotSupportedException">Any access</exception>
  169. public override long Seek(long offset, SeekOrigin origin)
  170. {
  171. throw new NotSupportedException("BZip2InputStream Seek not supported");
  172. }
  173. /// <summary>
  174. /// Sets the length of this stream to the given value.
  175. /// This operation is not supported and will throw a NotSupportedExceptionortedException
  176. /// </summary>
  177. /// <param name="value">The new length for the stream.</param>
  178. /// <exception cref="NotSupportedException">Any access</exception>
  179. public override void SetLength(long value)
  180. {
  181. throw new NotSupportedException("BZip2InputStream SetLength not supported");
  182. }
  183. /// <summary>
  184. /// Writes a block of bytes to this stream using data from a buffer.
  185. /// This operation is not supported and will throw a NotSupportedException
  186. /// </summary>
  187. /// <param name="buffer">The buffer to source data from.</param>
  188. /// <param name="offset">The offset to start obtaining data from.</param>
  189. /// <param name="count">The number of bytes of data to write.</param>
  190. /// <exception cref="NotSupportedException">Any access</exception>
  191. public override void Write(byte[] buffer, int offset, int count)
  192. {
  193. throw new NotSupportedException("BZip2InputStream Write not supported");
  194. }
  195. /// <summary>
  196. /// Writes a byte to the current position in the file stream.
  197. /// This operation is not supported and will throw a NotSupportedException
  198. /// </summary>
  199. /// <param name="value">The value to write.</param>
  200. /// <exception cref="NotSupportedException">Any access</exception>
  201. public override void WriteByte(byte value)
  202. {
  203. throw new NotSupportedException("BZip2InputStream WriteByte not supported");
  204. }
  205. /// <summary>
  206. /// Read a sequence of bytes and advances the read position by one byte.
  207. /// </summary>
  208. /// <param name="buffer">Array of bytes to store values in</param>
  209. /// <param name="offset">Offset in array to begin storing data</param>
  210. /// <param name="count">The maximum number of bytes to read</param>
  211. /// <returns>The total number of bytes read into the buffer. This might be less
  212. /// than the number of bytes requested if that number of bytes are not
  213. /// currently available or zero if the end of the stream is reached.
  214. /// </returns>
  215. public override int Read(byte[] buffer, int offset, int count)
  216. {
  217. if (buffer == null)
  218. {
  219. throw new ArgumentNullException(nameof(buffer));
  220. }
  221. for (int i = 0; i < count; ++i)
  222. {
  223. int rb = ReadByte();
  224. if (rb == -1)
  225. {
  226. return i;
  227. }
  228. buffer[offset + i] = (byte)rb;
  229. }
  230. return count;
  231. }
  232. /// <summary>
  233. /// Closes the stream, releasing any associated resources.
  234. /// </summary>
  235. protected override void Dispose(bool disposing)
  236. {
  237. if (disposing && IsStreamOwner)
  238. {
  239. baseStream.Dispose();
  240. }
  241. }
  242. /// <summary>
  243. /// Read a byte from stream advancing position
  244. /// </summary>
  245. /// <returns>byte read or -1 on end of stream</returns>
  246. public override int ReadByte()
  247. {
  248. if (streamEnd)
  249. {
  250. return -1; // ok
  251. }
  252. int retChar = currentChar;
  253. switch (currentState)
  254. {
  255. case RAND_PART_B_STATE:
  256. SetupRandPartB();
  257. break;
  258. case RAND_PART_C_STATE:
  259. SetupRandPartC();
  260. break;
  261. case NO_RAND_PART_B_STATE:
  262. SetupNoRandPartB();
  263. break;
  264. case NO_RAND_PART_C_STATE:
  265. SetupNoRandPartC();
  266. break;
  267. case START_BLOCK_STATE:
  268. case NO_RAND_PART_A_STATE:
  269. case RAND_PART_A_STATE:
  270. break;
  271. }
  272. return retChar;
  273. }
  274. #endregion Stream Overrides
  275. private void MakeMaps()
  276. {
  277. nInUse = 0;
  278. for (int i = 0; i < 256; ++i)
  279. {
  280. if (inUse[i])
  281. {
  282. seqToUnseq[nInUse] = (byte)i;
  283. unseqToSeq[i] = (byte)nInUse;
  284. nInUse++;
  285. }
  286. }
  287. }
  288. private void Initialize()
  289. {
  290. char magic1 = BsGetUChar();
  291. char magic2 = BsGetUChar();
  292. char magic3 = BsGetUChar();
  293. char magic4 = BsGetUChar();
  294. if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9')
  295. {
  296. streamEnd = true;
  297. return;
  298. }
  299. SetDecompressStructureSizes(magic4 - '0');
  300. computedCombinedCRC = 0;
  301. }
  302. private void InitBlock()
  303. {
  304. char magic1 = BsGetUChar();
  305. char magic2 = BsGetUChar();
  306. char magic3 = BsGetUChar();
  307. char magic4 = BsGetUChar();
  308. char magic5 = BsGetUChar();
  309. char magic6 = BsGetUChar();
  310. if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90)
  311. {
  312. Complete();
  313. return;
  314. }
  315. if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59)
  316. {
  317. BadBlockHeader();
  318. streamEnd = true;
  319. return;
  320. }
  321. storedBlockCRC = BsGetInt32();
  322. blockRandomised = (BsR(1) == 1);
  323. GetAndMoveToFrontDecode();
  324. mCrc.Reset();
  325. currentState = START_BLOCK_STATE;
  326. }
  327. private void EndBlock()
  328. {
  329. computedBlockCRC = (int)mCrc.Value;
  330. // -- A bad CRC is considered a fatal error. --
  331. if (storedBlockCRC != computedBlockCRC)
  332. {
  333. CrcError();
  334. }
  335. // 1528150659
  336. computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31);
  337. computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC;
  338. }
  339. private void Complete()
  340. {
  341. storedCombinedCRC = BsGetInt32();
  342. if (storedCombinedCRC != (int)computedCombinedCRC)
  343. {
  344. CrcError();
  345. }
  346. streamEnd = true;
  347. }
  348. private void FillBuffer()
  349. {
  350. int thech = 0;
  351. try
  352. {
  353. thech = baseStream.ReadByte();
  354. }
  355. catch (Exception)
  356. {
  357. CompressedStreamEOF();
  358. }
  359. if (thech == -1)
  360. {
  361. CompressedStreamEOF();
  362. }
  363. bsBuff = (bsBuff << 8) | (thech & 0xFF);
  364. bsLive += 8;
  365. }
  366. private int BsR(int n)
  367. {
  368. while (bsLive < n)
  369. {
  370. FillBuffer();
  371. }
  372. int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
  373. bsLive -= n;
  374. return v;
  375. }
  376. private char BsGetUChar()
  377. {
  378. return (char)BsR(8);
  379. }
  380. private int BsGetIntVS(int numBits)
  381. {
  382. return BsR(numBits);
  383. }
  384. private int BsGetInt32()
  385. {
  386. int result = BsR(8);
  387. result = (result << 8) | BsR(8);
  388. result = (result << 8) | BsR(8);
  389. result = (result << 8) | BsR(8);
  390. return result;
  391. }
  392. private void RecvDecodingTables()
  393. {
  394. char[][] len = new char[BZip2Constants.GroupCount][];
  395. for (int i = 0; i < BZip2Constants.GroupCount; ++i)
  396. {
  397. len[i] = new char[BZip2Constants.MaximumAlphaSize];
  398. }
  399. bool[] inUse16 = new bool[16];
  400. //--- Receive the mapping table ---
  401. for (int i = 0; i < 16; i++)
  402. {
  403. inUse16[i] = (BsR(1) == 1);
  404. }
  405. for (int i = 0; i < 16; i++)
  406. {
  407. if (inUse16[i])
  408. {
  409. for (int j = 0; j < 16; j++)
  410. {
  411. inUse[i * 16 + j] = (BsR(1) == 1);
  412. }
  413. }
  414. else
  415. {
  416. for (int j = 0; j < 16; j++)
  417. {
  418. inUse[i * 16 + j] = false;
  419. }
  420. }
  421. }
  422. MakeMaps();
  423. int alphaSize = nInUse + 2;
  424. //--- Now the selectors ---
  425. int nGroups = BsR(3);
  426. int nSelectors = BsR(15);
  427. for (int i = 0; i < nSelectors; i++)
  428. {
  429. int j = 0;
  430. while (BsR(1) == 1)
  431. {
  432. j++;
  433. }
  434. selectorMtf[i] = (byte)j;
  435. }
  436. //--- Undo the MTF values for the selectors. ---
  437. byte[] pos = new byte[BZip2Constants.GroupCount];
  438. for (int v = 0; v < nGroups; v++)
  439. {
  440. pos[v] = (byte)v;
  441. }
  442. for (int i = 0; i < nSelectors; i++)
  443. {
  444. int v = selectorMtf[i];
  445. byte tmp = pos[v];
  446. while (v > 0)
  447. {
  448. pos[v] = pos[v - 1];
  449. v--;
  450. }
  451. pos[0] = tmp;
  452. selector[i] = tmp;
  453. }
  454. //--- Now the coding tables ---
  455. for (int t = 0; t < nGroups; t++)
  456. {
  457. int curr = BsR(5);
  458. for (int i = 0; i < alphaSize; i++)
  459. {
  460. while (BsR(1) == 1)
  461. {
  462. if (BsR(1) == 0)
  463. {
  464. curr++;
  465. }
  466. else
  467. {
  468. curr--;
  469. }
  470. }
  471. len[t][i] = (char)curr;
  472. }
  473. }
  474. //--- Create the Huffman decoding tables ---
  475. for (int t = 0; t < nGroups; t++)
  476. {
  477. int minLen = 32;
  478. int maxLen = 0;
  479. for (int i = 0; i < alphaSize; i++)
  480. {
  481. maxLen = Math.Max(maxLen, len[t][i]);
  482. minLen = Math.Min(minLen, len[t][i]);
  483. }
  484. HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize);
  485. minLens[t] = minLen;
  486. }
  487. }
  488. private void GetAndMoveToFrontDecode()
  489. {
  490. byte[] yy = new byte[256];
  491. int nextSym;
  492. int limitLast = BZip2Constants.BaseBlockSize * blockSize100k;
  493. origPtr = BsGetIntVS(24);
  494. RecvDecodingTables();
  495. int EOB = nInUse + 1;
  496. int groupNo = -1;
  497. int groupPos = 0;
  498. /*--
  499. Setting up the unzftab entries here is not strictly
  500. necessary, but it does save having to do it later
  501. in a separate pass, and so saves a block's worth of
  502. cache misses.
  503. --*/
  504. for (int i = 0; i <= 255; i++)
  505. {
  506. unzftab[i] = 0;
  507. }
  508. for (int i = 0; i <= 255; i++)
  509. {
  510. yy[i] = (byte)i;
  511. }
  512. last = -1;
  513. if (groupPos == 0)
  514. {
  515. groupNo++;
  516. groupPos = BZip2Constants.GroupSize;
  517. }
  518. groupPos--;
  519. int zt = selector[groupNo];
  520. int zn = minLens[zt];
  521. int zvec = BsR(zn);
  522. int zj;
  523. while (zvec > limit[zt][zn])
  524. {
  525. if (zn > 20)
  526. { // the longest code
  527. throw new BZip2Exception("Bzip data error");
  528. }
  529. zn++;
  530. while (bsLive < 1)
  531. {
  532. FillBuffer();
  533. }
  534. zj = (bsBuff >> (bsLive - 1)) & 1;
  535. bsLive--;
  536. zvec = (zvec << 1) | zj;
  537. }
  538. if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize)
  539. {
  540. throw new BZip2Exception("Bzip data error");
  541. }
  542. nextSym = perm[zt][zvec - baseArray[zt][zn]];
  543. while (true)
  544. {
  545. if (nextSym == EOB)
  546. {
  547. break;
  548. }
  549. if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB)
  550. {
  551. int s = -1;
  552. int n = 1;
  553. do
  554. {
  555. if (nextSym == BZip2Constants.RunA)
  556. {
  557. s += (0 + 1) * n;
  558. }
  559. else if (nextSym == BZip2Constants.RunB)
  560. {
  561. s += (1 + 1) * n;
  562. }
  563. n <<= 1;
  564. if (groupPos == 0)
  565. {
  566. groupNo++;
  567. groupPos = BZip2Constants.GroupSize;
  568. }
  569. groupPos--;
  570. zt = selector[groupNo];
  571. zn = minLens[zt];
  572. zvec = BsR(zn);
  573. while (zvec > limit[zt][zn])
  574. {
  575. zn++;
  576. while (bsLive < 1)
  577. {
  578. FillBuffer();
  579. }
  580. zj = (bsBuff >> (bsLive - 1)) & 1;
  581. bsLive--;
  582. zvec = (zvec << 1) | zj;
  583. }
  584. nextSym = perm[zt][zvec - baseArray[zt][zn]];
  585. } while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB);
  586. s++;
  587. byte ch = seqToUnseq[yy[0]];
  588. unzftab[ch] += s;
  589. while (s > 0)
  590. {
  591. last++;
  592. ll8[last] = ch;
  593. s--;
  594. }
  595. if (last >= limitLast)
  596. {
  597. BlockOverrun();
  598. }
  599. continue;
  600. }
  601. else
  602. {
  603. last++;
  604. if (last >= limitLast)
  605. {
  606. BlockOverrun();
  607. }
  608. byte tmp = yy[nextSym - 1];
  609. unzftab[seqToUnseq[tmp]]++;
  610. ll8[last] = seqToUnseq[tmp];
  611. for (int j = nextSym - 1; j > 0; --j)
  612. {
  613. yy[j] = yy[j - 1];
  614. }
  615. yy[0] = tmp;
  616. if (groupPos == 0)
  617. {
  618. groupNo++;
  619. groupPos = BZip2Constants.GroupSize;
  620. }
  621. groupPos--;
  622. zt = selector[groupNo];
  623. zn = minLens[zt];
  624. zvec = BsR(zn);
  625. while (zvec > limit[zt][zn])
  626. {
  627. zn++;
  628. while (bsLive < 1)
  629. {
  630. FillBuffer();
  631. }
  632. zj = (bsBuff >> (bsLive - 1)) & 1;
  633. bsLive--;
  634. zvec = (zvec << 1) | zj;
  635. }
  636. nextSym = perm[zt][zvec - baseArray[zt][zn]];
  637. continue;
  638. }
  639. }
  640. }
  641. private void SetupBlock()
  642. {
  643. int[] cftab = new int[257];
  644. cftab[0] = 0;
  645. Array.Copy(unzftab, 0, cftab, 1, 256);
  646. for (int i = 1; i <= 256; i++)
  647. {
  648. cftab[i] += cftab[i - 1];
  649. }
  650. for (int i = 0; i <= last; i++)
  651. {
  652. byte ch = ll8[i];
  653. tt[cftab[ch]] = i;
  654. cftab[ch]++;
  655. }
  656. cftab = null;
  657. tPos = tt[origPtr];
  658. count = 0;
  659. i2 = 0;
  660. ch2 = 256; /*-- not a char and not EOF --*/
  661. if (blockRandomised)
  662. {
  663. rNToGo = 0;
  664. rTPos = 0;
  665. SetupRandPartA();
  666. }
  667. else
  668. {
  669. SetupNoRandPartA();
  670. }
  671. }
  672. private void SetupRandPartA()
  673. {
  674. if (i2 <= last)
  675. {
  676. chPrev = ch2;
  677. ch2 = ll8[tPos];
  678. tPos = tt[tPos];
  679. if (rNToGo == 0)
  680. {
  681. rNToGo = BZip2Constants.RandomNumbers[rTPos];
  682. rTPos++;
  683. if (rTPos == 512)
  684. {
  685. rTPos = 0;
  686. }
  687. }
  688. rNToGo--;
  689. ch2 ^= (int)((rNToGo == 1) ? 1 : 0);
  690. i2++;
  691. currentChar = ch2;
  692. currentState = RAND_PART_B_STATE;
  693. mCrc.Update(ch2);
  694. }
  695. else
  696. {
  697. EndBlock();
  698. InitBlock();
  699. SetupBlock();
  700. }
  701. }
  702. private void SetupNoRandPartA()
  703. {
  704. if (i2 <= last)
  705. {
  706. chPrev = ch2;
  707. ch2 = ll8[tPos];
  708. tPos = tt[tPos];
  709. i2++;
  710. currentChar = ch2;
  711. currentState = NO_RAND_PART_B_STATE;
  712. mCrc.Update(ch2);
  713. }
  714. else
  715. {
  716. EndBlock();
  717. InitBlock();
  718. SetupBlock();
  719. }
  720. }
  721. private void SetupRandPartB()
  722. {
  723. if (ch2 != chPrev)
  724. {
  725. currentState = RAND_PART_A_STATE;
  726. count = 1;
  727. SetupRandPartA();
  728. }
  729. else
  730. {
  731. count++;
  732. if (count >= 4)
  733. {
  734. z = ll8[tPos];
  735. tPos = tt[tPos];
  736. if (rNToGo == 0)
  737. {
  738. rNToGo = BZip2Constants.RandomNumbers[rTPos];
  739. rTPos++;
  740. if (rTPos == 512)
  741. {
  742. rTPos = 0;
  743. }
  744. }
  745. rNToGo--;
  746. z ^= (byte)((rNToGo == 1) ? 1 : 0);
  747. j2 = 0;
  748. currentState = RAND_PART_C_STATE;
  749. SetupRandPartC();
  750. }
  751. else
  752. {
  753. currentState = RAND_PART_A_STATE;
  754. SetupRandPartA();
  755. }
  756. }
  757. }
  758. private void SetupRandPartC()
  759. {
  760. if (j2 < (int)z)
  761. {
  762. currentChar = ch2;
  763. mCrc.Update(ch2);
  764. j2++;
  765. }
  766. else
  767. {
  768. currentState = RAND_PART_A_STATE;
  769. i2++;
  770. count = 0;
  771. SetupRandPartA();
  772. }
  773. }
  774. private void SetupNoRandPartB()
  775. {
  776. if (ch2 != chPrev)
  777. {
  778. currentState = NO_RAND_PART_A_STATE;
  779. count = 1;
  780. SetupNoRandPartA();
  781. }
  782. else
  783. {
  784. count++;
  785. if (count >= 4)
  786. {
  787. z = ll8[tPos];
  788. tPos = tt[tPos];
  789. currentState = NO_RAND_PART_C_STATE;
  790. j2 = 0;
  791. SetupNoRandPartC();
  792. }
  793. else
  794. {
  795. currentState = NO_RAND_PART_A_STATE;
  796. SetupNoRandPartA();
  797. }
  798. }
  799. }
  800. private void SetupNoRandPartC()
  801. {
  802. if (j2 < (int)z)
  803. {
  804. currentChar = ch2;
  805. mCrc.Update(ch2);
  806. j2++;
  807. }
  808. else
  809. {
  810. currentState = NO_RAND_PART_A_STATE;
  811. i2++;
  812. count = 0;
  813. SetupNoRandPartA();
  814. }
  815. }
  816. private void SetDecompressStructureSizes(int newSize100k)
  817. {
  818. if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9))
  819. {
  820. throw new BZip2Exception("Invalid block size");
  821. }
  822. blockSize100k = newSize100k;
  823. if (newSize100k == 0)
  824. {
  825. return;
  826. }
  827. int n = BZip2Constants.BaseBlockSize * newSize100k;
  828. ll8 = new byte[n];
  829. tt = new int[n];
  830. }
  831. private static void CompressedStreamEOF()
  832. {
  833. throw new EndOfStreamException("BZip2 input stream end of compressed stream");
  834. }
  835. private static void BlockOverrun()
  836. {
  837. throw new BZip2Exception("BZip2 input stream block overrun");
  838. }
  839. private static void BadBlockHeader()
  840. {
  841. throw new BZip2Exception("BZip2 input stream bad block header");
  842. }
  843. private static void CrcError()
  844. {
  845. throw new BZip2Exception("BZip2 input stream crc error");
  846. }
  847. private static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize)
  848. {
  849. int pp = 0;
  850. for (int i = minLen; i <= maxLen; ++i)
  851. {
  852. for (int j = 0; j < alphaSize; ++j)
  853. {
  854. if (length[j] == i)
  855. {
  856. perm[pp] = j;
  857. ++pp;
  858. }
  859. }
  860. }
  861. for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++)
  862. {
  863. baseArray[i] = 0;
  864. }
  865. for (int i = 0; i < alphaSize; i++)
  866. {
  867. ++baseArray[length[i] + 1];
  868. }
  869. for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++)
  870. {
  871. baseArray[i] += baseArray[i - 1];
  872. }
  873. for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++)
  874. {
  875. limit[i] = 0;
  876. }
  877. int vec = 0;
  878. for (int i = minLen; i <= maxLen; i++)
  879. {
  880. vec += (baseArray[i + 1] - baseArray[i]);
  881. limit[i] = vec - 1;
  882. vec <<= 1;
  883. }
  884. for (int i = minLen + 1; i <= maxLen; i++)
  885. {
  886. baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i];
  887. }
  888. }
  889. }
  890. }