PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Utilities/Compression/Streams/InflaterInputBuffer.cs

#
C# | 416 lines | 255 code | 38 blank | 123 comment | 24 complexity | c2767bc60c923d23e6ca6e7b8c9a204b MD5 | raw file
Possible License(s): Apache-2.0
  1. // Based on Mike Krueger's SharpZipLib, Copyright (C) 2001 (GNU license).
  2. // Authors of the original java version: Jochen Hoenicke, John Leuner
  3. // See http://www.ISeeSharpCode.com for more information.
  4. using System;
  5. using System.IO;
  6. using System.Security.Cryptography;
  7. using Delta.Utilities.Compression.Inflaters;
  8. namespace Delta.Utilities.Compression.Streams
  9. {
  10. /// <summary>
  11. /// An input buffer customized for use by <see cref="InflaterInputStream"/>
  12. /// </summary>
  13. /// <remarks>
  14. /// The buffer supports decryption of incoming data.
  15. /// </remarks>
  16. public class InflaterInputBuffer
  17. {
  18. #region RawLength (Public)
  19. /// <summary>
  20. /// Get the length of bytes bytes in the <see cref="GetRawData"/>
  21. /// </summary>
  22. public int RawLength
  23. {
  24. get
  25. {
  26. return rawLength;
  27. } // get
  28. }
  29. #endregion
  30. /*
  31. /// <summary>
  32. /// Get the contents of the raw data buffer.
  33. /// </summary>
  34. /// <remarks>This may contain encrypted data.</remarks>
  35. public byte[] RawData
  36. {
  37. get
  38. {
  39. return rawData;
  40. } // get
  41. } // RawData
  42. */
  43. #region ClearTextLength (Public)
  44. /// <summary>
  45. /// Get the number of useable bytes in <see cref="GetClearText"/>
  46. /// </summary>
  47. public int ClearTextLength
  48. {
  49. get
  50. {
  51. return clearTextLength;
  52. } // get
  53. }
  54. #endregion
  55. /*warning CA1819, use GetClearText instead
  56. /// <summary>
  57. /// Get the contents of the clear text buffer.
  58. /// </summary>
  59. public byte[] ClearText
  60. {
  61. get
  62. {
  63. return clearText;
  64. } // get
  65. } // ClearText
  66. */
  67. #region Available (Public)
  68. /// <summary>
  69. /// Get/set the number of bytes available
  70. /// </summary>
  71. public int Available
  72. {
  73. get
  74. {
  75. return available;
  76. } // get
  77. set
  78. {
  79. available = value;
  80. } // set
  81. }
  82. #endregion
  83. #region CryptoTransform (Public)
  84. /// <summary>
  85. /// Get/set the <see cref="ICryptoTransform"/> to apply to any data.
  86. /// </summary>
  87. /// <remarks>Set this value to null to have no transform applied.</remarks>
  88. public ICryptoTransform CryptoTransform
  89. {
  90. set
  91. {
  92. cryptoTransform = value;
  93. if (cryptoTransform != null)
  94. {
  95. if (rawData == clearText)
  96. {
  97. if (internalClearText == null)
  98. {
  99. internalClearText = new byte[4096];
  100. } // if (internalClearText)
  101. clearText = internalClearText;
  102. } // if (rawData)
  103. clearTextLength = rawLength;
  104. if (available > 0)
  105. {
  106. cryptoTransform.TransformBlock(rawData, rawLength - available,
  107. available, clearText, rawLength - available);
  108. } // if (available)
  109. } // if (cryptoTransform)
  110. else
  111. {
  112. clearText = rawData;
  113. clearTextLength = rawLength;
  114. } // else
  115. } // set
  116. }
  117. #endregion
  118. #region Private
  119. #region rawLength (Private)
  120. /// <remarks>
  121. /// The raw length
  122. /// </remarks>
  123. private int rawLength;
  124. #endregion
  125. #region rawData (Private)
  126. /// <remarks>
  127. /// The data inside the buffer
  128. /// </remarks>
  129. private readonly byte[] rawData;
  130. #endregion
  131. #region clearTextLength (Private)
  132. /// <remarks>
  133. /// Clear Text Length
  134. /// </remarks>
  135. private int clearTextLength;
  136. #endregion
  137. #region clearText (Private)
  138. /// <remarks>
  139. /// The clear Text
  140. /// </remarks>
  141. private byte[] clearText;
  142. #endregion
  143. #region internalClearText (Private)
  144. /// <remarks>
  145. /// Internal Clear Text
  146. /// </remarks>
  147. private byte[] internalClearText;
  148. #endregion
  149. #region available (Private)
  150. /// <remarks>
  151. /// Available
  152. /// </remarks>
  153. private int available;
  154. #endregion
  155. #region cryptoTransform (Private)
  156. /// <remarks>
  157. /// cryptoTransform
  158. /// </remarks>
  159. private ICryptoTransform cryptoTransform;
  160. #endregion
  161. #region inputStream (Private)
  162. /// <remarks>
  163. /// The input stream
  164. /// </remarks>
  165. private readonly Stream inputStream;
  166. #endregion
  167. #endregion
  168. #region Constructors
  169. /// <summary>
  170. /// Initialise a new instance of <see cref="InflaterInputBuffer"/>
  171. /// </summary>
  172. /// <param name="stream">The stream to buffer.</param>
  173. public InflaterInputBuffer(Stream stream)
  174. {
  175. inputStream = stream;
  176. rawData = new byte[4096];
  177. clearText = rawData;
  178. }
  179. #endregion
  180. #region GetRawData (Public)
  181. /// <summary>
  182. /// Get the contents of the raw data buffer.
  183. /// </summary>
  184. /// <remarks>This may contain encrypted data.</remarks>
  185. public byte[] GetRawData()
  186. {
  187. return rawData;
  188. }
  189. #endregion
  190. #region GetClearText (Public)
  191. /// <summary>
  192. /// Get the contents of the clear text buffer.
  193. /// </summary>
  194. public byte[] GetClearText()
  195. {
  196. return clearText;
  197. }
  198. #endregion
  199. #region SetInflaterInput (Public)
  200. /// <summary>
  201. /// Call <see cref="Inflater.SetInput(byte[])"/> passing the current clear
  202. /// text buffer contents.
  203. /// </summary>
  204. /// <param name="inflater">The inflater to set input for.</param>
  205. public void SetInflaterInput(Inflater inflater)
  206. {
  207. if (available > 0)
  208. {
  209. inflater.SetInput(clearText, clearTextLength - available, available);
  210. available = 0;
  211. } // if (available)
  212. }
  213. #endregion
  214. #region Fill (Public)
  215. /// <summary>
  216. /// Fill the buffer from the underlying input stream.
  217. /// </summary>
  218. public void Fill()
  219. {
  220. rawLength = 0;
  221. int toRead = rawData.Length;
  222. while (toRead > 0)
  223. {
  224. int count = inputStream.Read(rawData, rawLength, toRead);
  225. if (count <= 0)
  226. {
  227. if (rawLength == 0)
  228. {
  229. throw new CompressionException("Unexpected EOF");
  230. } // if (rawLength)
  231. break;
  232. } // if (count)
  233. rawLength += count;
  234. toRead -= count;
  235. } // while (toRead)
  236. if (cryptoTransform != null)
  237. {
  238. clearTextLength = cryptoTransform.TransformBlock(
  239. rawData, 0, rawLength, clearText, 0);
  240. } // if (cryptoTransform)
  241. else
  242. {
  243. clearTextLength = rawLength;
  244. } // else
  245. available = clearTextLength;
  246. }
  247. #endregion
  248. #region ReadRawBuffer (Public)
  249. /// <summary>
  250. /// Read a buffer directly from the input stream
  251. /// </summary>
  252. /// <param name="buffer">The buffer to fill</param>
  253. /// <returns>Returns the number of bytes read.</returns>
  254. public int ReadRawBuffer(byte[] buffer)
  255. {
  256. return ReadRawBuffer(buffer, 0, buffer.Length);
  257. }
  258. // ReadRawBuffer(buffer)
  259. /// <summary>
  260. /// Read a buffer directly from the input stream
  261. /// </summary>
  262. /// <param name="outBuffer">The buffer to read into</param>
  263. /// <param name="offset">The offset to start reading data into.</param>
  264. /// <param name="length">The number of bytes to read.</param>
  265. /// <returns>Returns the number of bytes read.</returns>
  266. public int ReadRawBuffer(byte[] outBuffer, int offset, int length)
  267. {
  268. if (length <= 0)
  269. {
  270. throw new ArgumentOutOfRangeException("length");
  271. } // if (length)
  272. int currentOffset = offset;
  273. int currentLength = length;
  274. while (currentLength > 0)
  275. {
  276. if (available <= 0)
  277. {
  278. Fill();
  279. if (available <= 0)
  280. {
  281. return 0;
  282. } // if (available)
  283. } // if (available)
  284. int toCopy = Math.Min(currentLength, available);
  285. Array.Copy(rawData, rawLength - available,
  286. outBuffer, currentOffset, toCopy);
  287. currentOffset += toCopy;
  288. currentLength -= toCopy;
  289. available -= toCopy;
  290. } // while (currentLength)
  291. return length;
  292. }
  293. #endregion
  294. #region ReadClearTextBuffer (Public)
  295. /// <summary>
  296. /// Read clear text data from the input stream.
  297. /// </summary>
  298. /// <param name="outBuffer">The buffer to add data to.</param>
  299. /// <param name="offset">The offset to start adding data at.</param>
  300. /// <param name="length">The number of bytes to read.</param>
  301. /// <returns>Returns the number of bytes actually read.</returns>
  302. public int ReadClearTextBuffer(byte[] outBuffer, int offset, int length)
  303. {
  304. if (length <= 0)
  305. {
  306. throw new ArgumentOutOfRangeException("length");
  307. } // if (length)
  308. int currentOffset = offset;
  309. int currentLength = length;
  310. while (currentLength > 0)
  311. {
  312. if (available <= 0)
  313. {
  314. Fill();
  315. if (available <= 0)
  316. {
  317. return 0;
  318. } // if (available)
  319. } // if (available)
  320. int toCopy = Math.Min(currentLength, available);
  321. Array.Copy(clearText, clearTextLength - available,
  322. outBuffer, currentOffset, toCopy);
  323. currentOffset += toCopy;
  324. currentLength -= toCopy;
  325. available -= toCopy;
  326. } // while (currentLength)
  327. return length;
  328. }
  329. #endregion
  330. #region ReadLeByte (Public)
  331. /// <summary>
  332. /// Read a byte from the input stream.
  333. /// </summary>
  334. /// <returns>Returns the byte read.</returns>
  335. public int ReadLeByte()
  336. {
  337. if (available <= 0)
  338. {
  339. Fill();
  340. if (available <= 0)
  341. {
  342. throw new ZipException("EOF in header");
  343. } // if (available)
  344. } // if (available)
  345. byte result = (byte)(rawData[rawLength - available] & 0xff);
  346. available -= 1;
  347. return result;
  348. }
  349. #endregion
  350. #region ReadLeShort (Public)
  351. /// <summary>
  352. /// Read an unsigned short in little endian byte order.
  353. /// </summary>
  354. public int ReadLeShort()
  355. {
  356. return ReadLeByte() | (ReadLeByte() << 8);
  357. }
  358. #endregion
  359. #region ReadLeInt (Public)
  360. /// <summary>
  361. /// Read an int in little endian byte order.
  362. /// </summary>
  363. public int ReadLeInt()
  364. {
  365. return ReadLeShort() | (ReadLeShort() << 16);
  366. }
  367. #endregion
  368. #region ReadLeLong (Public)
  369. /// <summary>
  370. /// Read an int baseInputStream little endian byte order.
  371. /// </summary>
  372. public long ReadLeLong()
  373. {
  374. return ReadLeInt() | (ReadLeInt() << 32);
  375. }
  376. #endregion
  377. }
  378. }