Bcj2DecoderStream.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. namespace SharpCompress.Compressors.LZMA
  5. {
  6. internal class Bcj2DecoderStream : DecoderStream2
  7. {
  8. private const int K_NUM_TOP_BITS = 24;
  9. private const uint K_TOP_VALUE = (1 << K_NUM_TOP_BITS);
  10. private class RangeDecoder
  11. {
  12. internal readonly Stream _mStream;
  13. internal uint _range;
  14. internal uint _code;
  15. public RangeDecoder(Stream stream)
  16. {
  17. _mStream = stream;
  18. _range = 0xFFFFFFFF;
  19. for (int i = 0; i < 5; i++)
  20. {
  21. _code = (_code << 8) | ReadByte();
  22. }
  23. }
  24. public byte ReadByte()
  25. {
  26. int bt = _mStream.ReadByte();
  27. if (bt < 0)
  28. {
  29. throw new EndOfStreamException();
  30. }
  31. return (byte)bt;
  32. }
  33. public void Dispose()
  34. {
  35. _mStream.Dispose();
  36. }
  37. }
  38. private class StatusDecoder
  39. {
  40. private const int NUM_MOVE_BITS = 5;
  41. private const int K_NUM_BIT_MODEL_TOTAL_BITS = 11;
  42. private const uint K_BIT_MODEL_TOTAL = 1u << K_NUM_BIT_MODEL_TOTAL_BITS;
  43. private uint _prob;
  44. public StatusDecoder()
  45. {
  46. _prob = K_BIT_MODEL_TOTAL / 2;
  47. }
  48. private void UpdateModel(uint symbol)
  49. {
  50. /*
  51. Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;
  52. Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);
  53. */
  54. if (symbol == 0)
  55. {
  56. _prob += (K_BIT_MODEL_TOTAL - _prob) >> NUM_MOVE_BITS;
  57. }
  58. else
  59. {
  60. _prob -= (_prob) >> NUM_MOVE_BITS;
  61. }
  62. }
  63. public uint Decode(RangeDecoder decoder)
  64. {
  65. uint newBound = (decoder._range >> K_NUM_BIT_MODEL_TOTAL_BITS) * _prob;
  66. if (decoder._code < newBound)
  67. {
  68. decoder._range = newBound;
  69. _prob += (K_BIT_MODEL_TOTAL - _prob) >> NUM_MOVE_BITS;
  70. if (decoder._range < K_TOP_VALUE)
  71. {
  72. decoder._code = (decoder._code << 8) | decoder.ReadByte();
  73. decoder._range <<= 8;
  74. }
  75. return 0;
  76. }
  77. decoder._range -= newBound;
  78. decoder._code -= newBound;
  79. _prob -= _prob >> NUM_MOVE_BITS;
  80. if (decoder._range < K_TOP_VALUE)
  81. {
  82. decoder._code = (decoder._code << 8) | decoder.ReadByte();
  83. decoder._range <<= 8;
  84. }
  85. return 1;
  86. }
  87. }
  88. private readonly Stream _mMainStream;
  89. private readonly Stream _mCallStream;
  90. private readonly Stream _mJumpStream;
  91. private readonly RangeDecoder _mRangeDecoder;
  92. private readonly StatusDecoder[] _mStatusDecoder;
  93. private long _mWritten;
  94. private readonly IEnumerator<byte> _mIter;
  95. private bool _mFinished;
  96. private bool _isDisposed;
  97. public Bcj2DecoderStream(Stream[] streams, byte[] info, long limit)
  98. {
  99. if (info != null && info.Length > 0)
  100. {
  101. throw new NotSupportedException();
  102. }
  103. if (streams.Length != 4)
  104. {
  105. throw new NotSupportedException();
  106. }
  107. _mMainStream = streams[0];
  108. _mCallStream = streams[1];
  109. _mJumpStream = streams[2];
  110. _mRangeDecoder = new RangeDecoder(streams[3]);
  111. _mStatusDecoder = new StatusDecoder[256 + 2];
  112. for (int i = 0; i < _mStatusDecoder.Length; i++)
  113. {
  114. _mStatusDecoder[i] = new StatusDecoder();
  115. }
  116. _mIter = Run().GetEnumerator();
  117. }
  118. protected override void Dispose(bool disposing)
  119. {
  120. if (_isDisposed)
  121. {
  122. return;
  123. }
  124. _isDisposed = true;
  125. base.Dispose(disposing);
  126. _mMainStream.Dispose();
  127. _mCallStream.Dispose();
  128. _mJumpStream.Dispose();
  129. }
  130. private static bool IsJcc(byte b0, byte b1)
  131. {
  132. return b0 == 0x0F
  133. && (b1 & 0xF0) == 0x80;
  134. }
  135. private static bool IsJ(byte b0, byte b1)
  136. {
  137. return (b1 & 0xFE) == 0xE8
  138. || IsJcc(b0, b1);
  139. }
  140. private static int GetIndex(byte b0, byte b1)
  141. {
  142. if (b1 == 0xE8)
  143. {
  144. return b0;
  145. }
  146. if (b1 == 0xE9)
  147. {
  148. return 256;
  149. }
  150. return 257;
  151. }
  152. public override int Read(byte[] buffer, int offset, int count)
  153. {
  154. if (count == 0 || _mFinished)
  155. {
  156. return 0;
  157. }
  158. for (int i = 0; i < count; i++)
  159. {
  160. if (!_mIter.MoveNext())
  161. {
  162. _mFinished = true;
  163. return i;
  164. }
  165. buffer[offset + i] = _mIter.Current;
  166. }
  167. return count;
  168. }
  169. public override int ReadByte()
  170. {
  171. if (_mFinished)
  172. {
  173. return -1;
  174. }
  175. if (!_mIter.MoveNext())
  176. {
  177. _mFinished = true;
  178. return -1;
  179. }
  180. return _mIter.Current;
  181. }
  182. public IEnumerable<byte> Run()
  183. {
  184. const uint kBurstSize = (1u << 18);
  185. byte prevByte = 0;
  186. uint processedBytes = 0;
  187. for (;;)
  188. {
  189. byte b = 0;
  190. uint i;
  191. for (i = 0; i < kBurstSize; i++)
  192. {
  193. int tmp = _mMainStream.ReadByte();
  194. if (tmp < 0)
  195. {
  196. yield break;
  197. }
  198. b = (byte)tmp;
  199. _mWritten++;
  200. yield return b;
  201. if (IsJ(prevByte, b))
  202. {
  203. break;
  204. }
  205. prevByte = b;
  206. }
  207. processedBytes += i;
  208. if (i == kBurstSize)
  209. {
  210. continue;
  211. }
  212. if (_mStatusDecoder[GetIndex(prevByte, b)].Decode(_mRangeDecoder) == 1)
  213. {
  214. Stream s = (b == 0xE8) ? _mCallStream : _mJumpStream;
  215. uint src = 0;
  216. for (i = 0; i < 4; i++)
  217. {
  218. int b0 = s.ReadByte();
  219. if (b0 < 0)
  220. {
  221. throw new EndOfStreamException();
  222. }
  223. src <<= 8;
  224. src |= (uint)b0;
  225. }
  226. uint dest = src - (uint)(_mWritten + 4);
  227. _mWritten++;
  228. yield return (byte)dest;
  229. _mWritten++;
  230. yield return (byte)(dest >> 8);
  231. _mWritten++;
  232. yield return (byte)(dest >> 16);
  233. _mWritten++;
  234. yield return (byte)(dest >> 24);
  235. prevByte = (byte)(dest >> 24);
  236. processedBytes += 4;
  237. }
  238. else
  239. {
  240. prevByte = b;
  241. }
  242. }
  243. }
  244. }
  245. }