CBZip2InputStream.cs 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  1. using System.IO;
  2. /*
  3. * Copyright 2001,2004-2005 The Apache Software Foundation
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /*
  18. * This package is based on the work done by Keiron Liddle, Aftex Software
  19. * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
  20. * great code.
  21. */
  22. namespace SharpCompress.Compressors.BZip2
  23. {
  24. /**
  25. * An input stream that decompresses from the BZip2 format (with the file
  26. * header chars) to be read as any other stream.
  27. *
  28. * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
  29. *
  30. * <b>NB:</b> note this class has been modified to read the leading BZ from the
  31. * start of the BZIP2 stream to make it compatible with other PGP programs.
  32. */
  33. internal class CBZip2InputStream : Stream
  34. {
  35. private static void Cadvise()
  36. {
  37. //System.out.Println("CRC Error");
  38. //throw new CCoruptionError();
  39. }
  40. private static void BadBGLengths()
  41. {
  42. Cadvise();
  43. }
  44. private static void BitStreamEOF()
  45. {
  46. Cadvise();
  47. }
  48. private static void CompressedStreamEOF()
  49. {
  50. Cadvise();
  51. }
  52. private void MakeMaps()
  53. {
  54. int i;
  55. nInUse = 0;
  56. for (i = 0; i < 256; i++)
  57. {
  58. if (inUse[i])
  59. {
  60. seqToUnseq[nInUse] = (char)i;
  61. unseqToSeq[i] = (char)nInUse;
  62. nInUse++;
  63. }
  64. }
  65. }
  66. /*
  67. index of the last char in the block, so
  68. the block size == last + 1.
  69. */
  70. private int last;
  71. /*
  72. index in zptr[] of original string after sorting.
  73. */
  74. private int origPtr;
  75. /*
  76. always: in the range 0 .. 9.
  77. The current block size is 100000 * this number.
  78. */
  79. private int blockSize100k;
  80. private bool blockRandomised;
  81. private int bsBuff;
  82. private int bsLive;
  83. private readonly CRC mCrc = new CRC();
  84. private readonly bool[] inUse = new bool[256];
  85. private int nInUse;
  86. private readonly char[] seqToUnseq = new char[256];
  87. private readonly char[] unseqToSeq = new char[256];
  88. private readonly char[] selector = new char[BZip2Constants.MAX_SELECTORS];
  89. private readonly char[] selectorMtf = new char[BZip2Constants.MAX_SELECTORS];
  90. private int[] tt;
  91. private char[] ll8;
  92. /*
  93. freq table collected to save a pass over the data
  94. during decompression.
  95. */
  96. private readonly int[] unzftab = new int[256];
  97. private readonly int[][] limit = InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
  98. private readonly int[][] basev = InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
  99. private readonly int[][] perm = InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
  100. private readonly int[] minLens = new int[BZip2Constants.N_GROUPS];
  101. private Stream bsStream;
  102. private bool streamEnd;
  103. private int currentChar = -1;
  104. private const int START_BLOCK_STATE = 1;
  105. private const int RAND_PART_A_STATE = 2;
  106. private const int RAND_PART_B_STATE = 3;
  107. private const int RAND_PART_C_STATE = 4;
  108. private const int NO_RAND_PART_A_STATE = 5;
  109. private const int NO_RAND_PART_B_STATE = 6;
  110. private const int NO_RAND_PART_C_STATE = 7;
  111. private int currentState = START_BLOCK_STATE;
  112. private int storedBlockCRC, storedCombinedCRC;
  113. private int computedBlockCRC, computedCombinedCRC;
  114. private readonly bool decompressConcatenated;
  115. private int i2, count, chPrev, ch2;
  116. private int i, tPos;
  117. private int rNToGo;
  118. private int rTPos;
  119. private int j2;
  120. private char z;
  121. private bool isDisposed;
  122. public CBZip2InputStream(Stream zStream, bool decompressConcatenated)
  123. {
  124. this.decompressConcatenated = decompressConcatenated;
  125. ll8 = null;
  126. tt = null;
  127. BsSetStream(zStream);
  128. Initialize(true);
  129. InitBlock();
  130. SetupBlock();
  131. }
  132. protected override void Dispose(bool disposing)
  133. {
  134. if (isDisposed)
  135. {
  136. return;
  137. }
  138. isDisposed = true;
  139. base.Dispose(disposing);
  140. if (bsStream != null)
  141. {
  142. bsStream.Dispose();
  143. }
  144. }
  145. internal static int[][] InitIntArray(int n1, int n2)
  146. {
  147. int[][] a = new int[n1][];
  148. for (int k = 0; k < n1; ++k)
  149. {
  150. a[k] = new int[n2];
  151. }
  152. return a;
  153. }
  154. internal static char[][] InitCharArray(int n1, int n2)
  155. {
  156. char[][] a = new char[n1][];
  157. for (int k = 0; k < n1; ++k)
  158. {
  159. a[k] = new char[n2];
  160. }
  161. return a;
  162. }
  163. public override int ReadByte()
  164. {
  165. if (streamEnd)
  166. {
  167. return -1;
  168. }
  169. int retChar = currentChar;
  170. switch (currentState)
  171. {
  172. case START_BLOCK_STATE:
  173. break;
  174. case RAND_PART_A_STATE:
  175. break;
  176. case RAND_PART_B_STATE:
  177. SetupRandPartB();
  178. break;
  179. case RAND_PART_C_STATE:
  180. SetupRandPartC();
  181. break;
  182. case NO_RAND_PART_A_STATE:
  183. break;
  184. case NO_RAND_PART_B_STATE:
  185. SetupNoRandPartB();
  186. break;
  187. case NO_RAND_PART_C_STATE:
  188. SetupNoRandPartC();
  189. break;
  190. default:
  191. break;
  192. }
  193. return retChar;
  194. }
  195. private bool Initialize(bool isFirstStream)
  196. {
  197. int magic0 = bsStream.ReadByte();
  198. int magic1 = bsStream.ReadByte();
  199. int magic2 = bsStream.ReadByte();
  200. if (magic0 == -1 && !isFirstStream)
  201. {
  202. return false;
  203. }
  204. if (magic0 != 'B' || magic1 != 'Z' || magic2 != 'h')
  205. {
  206. throw new IOException("Not a BZIP2 marked stream");
  207. }
  208. int magic3 = bsStream.ReadByte();
  209. if (magic3 < '1' || magic3 > '9')
  210. {
  211. BsFinishedWithStream();
  212. streamEnd = true;
  213. return false;
  214. }
  215. SetDecompressStructureSizes(magic3 - '0');
  216. bsLive = 0;
  217. computedCombinedCRC = 0;
  218. return true;
  219. }
  220. private void InitBlock()
  221. {
  222. char magic1, magic2, magic3, magic4;
  223. char magic5, magic6;
  224. while (true)
  225. {
  226. magic1 = BsGetUChar();
  227. magic2 = BsGetUChar();
  228. magic3 = BsGetUChar();
  229. magic4 = BsGetUChar();
  230. magic5 = BsGetUChar();
  231. magic6 = BsGetUChar();
  232. if (magic1 != 0x17 || magic2 != 0x72 || magic3 != 0x45
  233. || magic4 != 0x38 || magic5 != 0x50 || magic6 != 0x90)
  234. {
  235. break;
  236. }
  237. if (Complete())
  238. {
  239. return;
  240. }
  241. }
  242. if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59
  243. || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59)
  244. {
  245. BadBlockHeader();
  246. streamEnd = true;
  247. return;
  248. }
  249. storedBlockCRC = BsGetInt32();
  250. if (BsR(1) == 1)
  251. {
  252. blockRandomised = true;
  253. }
  254. else
  255. {
  256. blockRandomised = false;
  257. }
  258. // currBlockNo++;
  259. GetAndMoveToFrontDecode();
  260. mCrc.InitialiseCRC();
  261. currentState = START_BLOCK_STATE;
  262. }
  263. private void EndBlock()
  264. {
  265. computedBlockCRC = mCrc.GetFinalCRC();
  266. /* A bad CRC is considered a fatal error. */
  267. if (storedBlockCRC != computedBlockCRC)
  268. {
  269. CrcError();
  270. }
  271. computedCombinedCRC = (computedCombinedCRC << 1)
  272. | (int)(((uint)computedCombinedCRC) >> 31);
  273. computedCombinedCRC ^= computedBlockCRC;
  274. }
  275. private bool Complete()
  276. {
  277. storedCombinedCRC = BsGetInt32();
  278. if (storedCombinedCRC != computedCombinedCRC)
  279. {
  280. CrcError();
  281. }
  282. bool complete = !decompressConcatenated || !Initialize(false);
  283. if (complete)
  284. {
  285. BsFinishedWithStream();
  286. streamEnd = true;
  287. }
  288. // Look for the next .bz2 stream if decompressing
  289. // concatenated files.
  290. return complete;
  291. }
  292. private static void BlockOverrun()
  293. {
  294. Cadvise();
  295. }
  296. private static void BadBlockHeader()
  297. {
  298. Cadvise();
  299. }
  300. private static void CrcError()
  301. {
  302. Cadvise();
  303. }
  304. private void BsFinishedWithStream()
  305. {
  306. bsStream?.Dispose();
  307. bsStream = null;
  308. }
  309. private void BsSetStream(Stream f)
  310. {
  311. bsStream = f;
  312. bsLive = 0;
  313. bsBuff = 0;
  314. }
  315. private int BsR(int n)
  316. {
  317. int v;
  318. while (bsLive < n)
  319. {
  320. int zzi;
  321. int thech = '\0';
  322. try
  323. {
  324. thech = (char)bsStream.ReadByte();
  325. }
  326. catch (IOException)
  327. {
  328. CompressedStreamEOF();
  329. }
  330. if (thech == '\uffff')
  331. {
  332. CompressedStreamEOF();
  333. }
  334. zzi = thech;
  335. bsBuff = (bsBuff << 8) | (zzi & 0xff);
  336. bsLive += 8;
  337. }
  338. v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
  339. bsLive -= n;
  340. return v;
  341. }
  342. private char BsGetUChar()
  343. {
  344. return (char)BsR(8);
  345. }
  346. private int BsGetint()
  347. {
  348. int u = 0;
  349. u = (u << 8) | BsR(8);
  350. u = (u << 8) | BsR(8);
  351. u = (u << 8) | BsR(8);
  352. u = (u << 8) | BsR(8);
  353. return u;
  354. }
  355. private int BsGetIntVS(int numBits)
  356. {
  357. return BsR(numBits);
  358. }
  359. private int BsGetInt32()
  360. {
  361. return BsGetint();
  362. }
  363. private void HbCreateDecodeTables(int[] limit, int[] basev,
  364. int[] perm, char[] length,
  365. int minLen, int maxLen, int alphaSize)
  366. {
  367. int pp, i, j, vec;
  368. pp = 0;
  369. for (i = minLen; i <= maxLen; i++)
  370. {
  371. for (j = 0; j < alphaSize; j++)
  372. {
  373. if (length[j] == i)
  374. {
  375. perm[pp] = j;
  376. pp++;
  377. }
  378. }
  379. }
  380. for (i = 0; i < BZip2Constants.MAX_CODE_LEN; i++)
  381. {
  382. basev[i] = 0;
  383. }
  384. for (i = 0; i < alphaSize; i++)
  385. {
  386. basev[length[i] + 1]++;
  387. }
  388. for (i = 1; i < BZip2Constants.MAX_CODE_LEN; i++)
  389. {
  390. basev[i] += basev[i - 1];
  391. }
  392. for (i = 0; i < BZip2Constants.MAX_CODE_LEN; i++)
  393. {
  394. limit[i] = 0;
  395. }
  396. vec = 0;
  397. for (i = minLen; i <= maxLen; i++)
  398. {
  399. vec += (basev[i + 1] - basev[i]);
  400. limit[i] = vec - 1;
  401. vec <<= 1;
  402. }
  403. for (i = minLen + 1; i <= maxLen; i++)
  404. {
  405. basev[i] = ((limit[i - 1] + 1) << 1) - basev[i];
  406. }
  407. }
  408. private void RecvDecodingTables()
  409. {
  410. char[][] len = InitCharArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
  411. int i, j, t, nGroups, nSelectors, alphaSize;
  412. int minLen, maxLen;
  413. bool[] inUse16 = new bool[16];
  414. /* Receive the mapping table */
  415. for (i = 0; i < 16; i++)
  416. {
  417. if (BsR(1) == 1)
  418. {
  419. inUse16[i] = true;
  420. }
  421. else
  422. {
  423. inUse16[i] = false;
  424. }
  425. }
  426. for (i = 0; i < 256; i++)
  427. {
  428. inUse[i] = false;
  429. }
  430. for (i = 0; i < 16; i++)
  431. {
  432. if (inUse16[i])
  433. {
  434. for (j = 0; j < 16; j++)
  435. {
  436. if (BsR(1) == 1)
  437. {
  438. inUse[i * 16 + j] = true;
  439. }
  440. }
  441. }
  442. }
  443. MakeMaps();
  444. alphaSize = nInUse + 2;
  445. /* Now the selectors */
  446. nGroups = BsR(3);
  447. nSelectors = BsR(15);
  448. for (i = 0; i < nSelectors; i++)
  449. {
  450. j = 0;
  451. while (BsR(1) == 1)
  452. {
  453. j++;
  454. }
  455. selectorMtf[i] = (char)j;
  456. }
  457. /* Undo the MTF values for the selectors. */
  458. {
  459. char[] pos = new char[BZip2Constants.N_GROUPS];
  460. char tmp, v;
  461. for (v = '\0'; v < nGroups; v++)
  462. {
  463. pos[v] = v;
  464. }
  465. for (i = 0; i < nSelectors; i++)
  466. {
  467. v = selectorMtf[i];
  468. tmp = pos[v];
  469. while (v > 0)
  470. {
  471. pos[v] = pos[v - 1];
  472. v--;
  473. }
  474. pos[0] = tmp;
  475. selector[i] = tmp;
  476. }
  477. }
  478. /* Now the coding tables */
  479. for (t = 0; t < nGroups; t++)
  480. {
  481. int curr = BsR(5);
  482. for (i = 0; i < alphaSize; i++)
  483. {
  484. while (BsR(1) == 1)
  485. {
  486. if (BsR(1) == 0)
  487. {
  488. curr++;
  489. }
  490. else
  491. {
  492. curr--;
  493. }
  494. }
  495. len[t][i] = (char)curr;
  496. }
  497. }
  498. /* Create the Huffman decoding tables */
  499. for (t = 0; t < nGroups; t++)
  500. {
  501. minLen = 32;
  502. maxLen = 0;
  503. for (i = 0; i < alphaSize; i++)
  504. {
  505. if (len[t][i] > maxLen)
  506. {
  507. maxLen = len[t][i];
  508. }
  509. if (len[t][i] < minLen)
  510. {
  511. minLen = len[t][i];
  512. }
  513. }
  514. HbCreateDecodeTables(limit[t], basev[t], perm[t], len[t], minLen,
  515. maxLen, alphaSize);
  516. minLens[t] = minLen;
  517. }
  518. }
  519. private void GetAndMoveToFrontDecode()
  520. {
  521. char[] yy = new char[256];
  522. int i, j, nextSym, limitLast;
  523. int EOB, groupNo, groupPos;
  524. limitLast = BZip2Constants.baseBlockSize * blockSize100k;
  525. origPtr = BsGetIntVS(24);
  526. RecvDecodingTables();
  527. EOB = nInUse + 1;
  528. groupNo = -1;
  529. groupPos = 0;
  530. /*
  531. Setting up the unzftab entries here is not strictly
  532. necessary, but it does save having to do it later
  533. in a separate pass, and so saves a block's worth of
  534. cache misses.
  535. */
  536. for (i = 0; i <= 255; i++)
  537. {
  538. unzftab[i] = 0;
  539. }
  540. for (i = 0; i <= 255; i++)
  541. {
  542. yy[i] = (char)i;
  543. }
  544. last = -1;
  545. {
  546. int zt, zn, zvec, zj;
  547. if (groupPos == 0)
  548. {
  549. groupNo++;
  550. groupPos = BZip2Constants.G_SIZE;
  551. }
  552. groupPos--;
  553. zt = selector[groupNo];
  554. zn = minLens[zt];
  555. zvec = BsR(zn);
  556. while (zvec > limit[zt][zn])
  557. {
  558. zn++;
  559. {
  560. {
  561. while (bsLive < 1)
  562. {
  563. int zzi;
  564. char thech = '\0';
  565. try
  566. {
  567. thech = (char)bsStream.ReadByte();
  568. }
  569. catch (IOException)
  570. {
  571. CompressedStreamEOF();
  572. }
  573. if (thech == '\uffff')
  574. {
  575. CompressedStreamEOF();
  576. }
  577. zzi = thech;
  578. bsBuff = (bsBuff << 8) | (zzi & 0xff);
  579. bsLive += 8;
  580. }
  581. }
  582. zj = (bsBuff >> (bsLive - 1)) & 1;
  583. bsLive--;
  584. }
  585. zvec = (zvec << 1) | zj;
  586. }
  587. nextSym = perm[zt][zvec - basev[zt][zn]];
  588. }
  589. while (true)
  590. {
  591. if (nextSym == EOB)
  592. {
  593. break;
  594. }
  595. if (nextSym == BZip2Constants.RUNA || nextSym == BZip2Constants.RUNB)
  596. {
  597. char ch;
  598. int s = -1;
  599. int N = 1;
  600. do
  601. {
  602. if (nextSym == BZip2Constants.RUNA)
  603. {
  604. s = s + (0 + 1) * N;
  605. }
  606. else if (nextSym == BZip2Constants.RUNB)
  607. {
  608. s = s + (1 + 1) * N;
  609. }
  610. N = N * 2;
  611. {
  612. int zt, zn, zvec, zj;
  613. if (groupPos == 0)
  614. {
  615. groupNo++;
  616. groupPos = BZip2Constants.G_SIZE;
  617. }
  618. groupPos--;
  619. zt = selector[groupNo];
  620. zn = minLens[zt];
  621. zvec = BsR(zn);
  622. while (zvec > limit[zt][zn])
  623. {
  624. zn++;
  625. {
  626. {
  627. while (bsLive < 1)
  628. {
  629. int zzi;
  630. char thech = '\0';
  631. try
  632. {
  633. thech = (char)bsStream.ReadByte();
  634. }
  635. catch (IOException)
  636. {
  637. CompressedStreamEOF();
  638. }
  639. if (thech == '\uffff')
  640. {
  641. CompressedStreamEOF();
  642. }
  643. zzi = thech;
  644. bsBuff = (bsBuff << 8) | (zzi & 0xff);
  645. bsLive += 8;
  646. }
  647. }
  648. zj = (bsBuff >> (bsLive - 1)) & 1;
  649. bsLive--;
  650. }
  651. zvec = (zvec << 1) | zj;
  652. }
  653. nextSym = perm[zt][zvec - basev[zt][zn]];
  654. }
  655. }
  656. while (nextSym == BZip2Constants.RUNA || nextSym == BZip2Constants.RUNB);
  657. s++;
  658. ch = seqToUnseq[yy[0]];
  659. unzftab[ch] += s;
  660. while (s > 0)
  661. {
  662. last++;
  663. ll8[last] = ch;
  664. s--;
  665. }
  666. if (last >= limitLast)
  667. {
  668. BlockOverrun();
  669. }
  670. }
  671. else
  672. {
  673. char tmp;
  674. last++;
  675. if (last >= limitLast)
  676. {
  677. BlockOverrun();
  678. }
  679. tmp = yy[nextSym - 1];
  680. unzftab[seqToUnseq[tmp]]++;
  681. ll8[last] = seqToUnseq[tmp];
  682. /*
  683. This loop is hammered during decompression,
  684. hence the unrolling.
  685. for (j = nextSym-1; j > 0; j--) yy[j] = yy[j-1];
  686. */
  687. j = nextSym - 1;
  688. for (; j > 3; j -= 4)
  689. {
  690. yy[j] = yy[j - 1];
  691. yy[j - 1] = yy[j - 2];
  692. yy[j - 2] = yy[j - 3];
  693. yy[j - 3] = yy[j - 4];
  694. }
  695. for (; j > 0; j--)
  696. {
  697. yy[j] = yy[j - 1];
  698. }
  699. yy[0] = tmp;
  700. {
  701. int zt, zn, zvec, zj;
  702. if (groupPos == 0)
  703. {
  704. groupNo++;
  705. groupPos = BZip2Constants.G_SIZE;
  706. }
  707. groupPos--;
  708. zt = selector[groupNo];
  709. zn = minLens[zt];
  710. zvec = BsR(zn);
  711. while (zvec > limit[zt][zn])
  712. {
  713. zn++;
  714. {
  715. {
  716. while (bsLive < 1)
  717. {
  718. int zzi;
  719. char thech = '\0';
  720. try
  721. {
  722. thech = (char)bsStream.ReadByte();
  723. }
  724. catch (IOException)
  725. {
  726. CompressedStreamEOF();
  727. }
  728. zzi = thech;
  729. bsBuff = (bsBuff << 8) | (zzi & 0xff);
  730. bsLive += 8;
  731. }
  732. }
  733. zj = (bsBuff >> (bsLive - 1)) & 1;
  734. bsLive--;
  735. }
  736. zvec = (zvec << 1) | zj;
  737. }
  738. nextSym = perm[zt][zvec - basev[zt][zn]];
  739. }
  740. }
  741. }
  742. }
  743. private void SetupBlock()
  744. {
  745. int[] cftab = new int[257];
  746. char ch;
  747. cftab[0] = 0;
  748. for (i = 1; i <= 256; i++)
  749. {
  750. cftab[i] = unzftab[i - 1];
  751. }
  752. for (i = 1; i <= 256; i++)
  753. {
  754. cftab[i] += cftab[i - 1];
  755. }
  756. for (i = 0; i <= last; i++)
  757. {
  758. ch = ll8[i];
  759. tt[cftab[ch]] = i;
  760. cftab[ch]++;
  761. }
  762. cftab = null;
  763. tPos = tt[origPtr];
  764. count = 0;
  765. i2 = 0;
  766. ch2 = 256; /* not a char and not EOF */
  767. if (blockRandomised)
  768. {
  769. rNToGo = 0;
  770. rTPos = 0;
  771. SetupRandPartA();
  772. }
  773. else
  774. {
  775. SetupNoRandPartA();
  776. }
  777. }
  778. private void SetupRandPartA()
  779. {
  780. if (i2 <= last)
  781. {
  782. chPrev = ch2;
  783. ch2 = ll8[tPos];
  784. tPos = tt[tPos];
  785. if (rNToGo == 0)
  786. {
  787. rNToGo = BZip2Constants.rNums[rTPos];
  788. rTPos++;
  789. if (rTPos == 512)
  790. {
  791. rTPos = 0;
  792. }
  793. }
  794. rNToGo--;
  795. ch2 ^= (rNToGo == 1) ? 1 : 0;
  796. i2++;
  797. currentChar = ch2;
  798. currentState = RAND_PART_B_STATE;
  799. mCrc.UpdateCRC(ch2);
  800. }
  801. else
  802. {
  803. EndBlock();
  804. InitBlock();
  805. SetupBlock();
  806. }
  807. }
  808. private void SetupNoRandPartA()
  809. {
  810. if (i2 <= last)
  811. {
  812. chPrev = ch2;
  813. ch2 = ll8[tPos];
  814. tPos = tt[tPos];
  815. i2++;
  816. currentChar = ch2;
  817. currentState = NO_RAND_PART_B_STATE;
  818. mCrc.UpdateCRC(ch2);
  819. }
  820. else
  821. {
  822. EndBlock();
  823. InitBlock();
  824. SetupBlock();
  825. }
  826. }
  827. private void SetupRandPartB()
  828. {
  829. if (ch2 != chPrev)
  830. {
  831. currentState = RAND_PART_A_STATE;
  832. count = 1;
  833. SetupRandPartA();
  834. }
  835. else
  836. {
  837. count++;
  838. if (count >= 4)
  839. {
  840. z = ll8[tPos];
  841. tPos = tt[tPos];
  842. if (rNToGo == 0)
  843. {
  844. rNToGo = BZip2Constants.rNums[rTPos];
  845. rTPos++;
  846. if (rTPos == 512)
  847. {
  848. rTPos = 0;
  849. }
  850. }
  851. rNToGo--;
  852. z ^= (char)((rNToGo == 1) ? 1 : 0);
  853. j2 = 0;
  854. currentState = RAND_PART_C_STATE;
  855. SetupRandPartC();
  856. }
  857. else
  858. {
  859. currentState = RAND_PART_A_STATE;
  860. SetupRandPartA();
  861. }
  862. }
  863. }
  864. private void SetupRandPartC()
  865. {
  866. if (j2 < z)
  867. {
  868. currentChar = ch2;
  869. mCrc.UpdateCRC(ch2);
  870. j2++;
  871. }
  872. else
  873. {
  874. currentState = RAND_PART_A_STATE;
  875. i2++;
  876. count = 0;
  877. SetupRandPartA();
  878. }
  879. }
  880. private void SetupNoRandPartB()
  881. {
  882. if (ch2 != chPrev)
  883. {
  884. currentState = NO_RAND_PART_A_STATE;
  885. count = 1;
  886. SetupNoRandPartA();
  887. }
  888. else
  889. {
  890. count++;
  891. if (count >= 4)
  892. {
  893. z = ll8[tPos];
  894. tPos = tt[tPos];
  895. currentState = NO_RAND_PART_C_STATE;
  896. j2 = 0;
  897. SetupNoRandPartC();
  898. }
  899. else
  900. {
  901. currentState = NO_RAND_PART_A_STATE;
  902. SetupNoRandPartA();
  903. }
  904. }
  905. }
  906. private void SetupNoRandPartC()
  907. {
  908. if (j2 < z)
  909. {
  910. currentChar = ch2;
  911. mCrc.UpdateCRC(ch2);
  912. j2++;
  913. }
  914. else
  915. {
  916. currentState = NO_RAND_PART_A_STATE;
  917. i2++;
  918. count = 0;
  919. SetupNoRandPartA();
  920. }
  921. }
  922. private void SetDecompressStructureSizes(int newSize100k)
  923. {
  924. if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k
  925. && blockSize100k <= 9))
  926. {
  927. // throw new IOException("Invalid block size");
  928. }
  929. blockSize100k = newSize100k;
  930. if (newSize100k == 0)
  931. {
  932. return;
  933. }
  934. int n = BZip2Constants.baseBlockSize * newSize100k;
  935. ll8 = new char[n];
  936. tt = new int[n];
  937. }
  938. public override void Flush()
  939. {
  940. }
  941. public override int Read(byte[] buffer, int offset, int count)
  942. {
  943. int c = -1;
  944. int k;
  945. for (k = 0; k < count; ++k)
  946. {
  947. c = ReadByte();
  948. if (c == -1)
  949. {
  950. break;
  951. }
  952. buffer[k + offset] = (byte)c;
  953. }
  954. return k;
  955. }
  956. public override long Seek(long offset, SeekOrigin origin)
  957. {
  958. return 0;
  959. }
  960. public override void SetLength(long value)
  961. {
  962. }
  963. public override void Write(byte[] buffer, int offset, int count)
  964. {
  965. }
  966. public override void WriteByte(byte value)
  967. {
  968. }
  969. public override bool CanRead => true;
  970. public override bool CanSeek => false;
  971. public override bool CanWrite => false;
  972. public override long Length => 0;
  973. public override long Position { get { return 0; } set { } }
  974. }
  975. }