BZip2InputStream.cs 20 KB

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