BZip2InputStream.cs 24 KB

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