/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
- // Based on Mike Krueger's SharpZipLib, Copyright (C) 2001 (GNU license).
- // Authors of the original java version: Jochen Hoenicke, John Leuner
- // See http://www.ISeeSharpCode.com for more information.
-
- using System;
- using System.IO;
- using System.Security.Cryptography;
- using Delta.Utilities.Compression.Inflaters;
-
- namespace Delta.Utilities.Compression.Streams
- {
- /// <summary>
- /// An input buffer customized for use by <see cref="InflaterInputStream"/>
- /// </summary>
- /// <remarks>
- /// The buffer supports decryption of incoming data.
- /// </remarks>
- public class InflaterInputBuffer
- {
- #region RawLength (Public)
- /// <summary>
- /// Get the length of bytes bytes in the <see cref="GetRawData"/>
- /// </summary>
- public int RawLength
- {
- get
- {
- return rawLength;
- } // get
- }
- #endregion
-
- /*
- /// <summary>
- /// Get the contents of the raw data buffer.
- /// </summary>
- /// <remarks>This may contain encrypted data.</remarks>
- public byte[] RawData
- {
- get
- {
- return rawData;
- } // get
- } // RawData
- */
-
- #region ClearTextLength (Public)
- /// <summary>
- /// Get the number of useable bytes in <see cref="GetClearText"/>
- /// </summary>
- public int ClearTextLength
- {
- get
- {
- return clearTextLength;
- } // get
- }
- #endregion
-
- /*warning CA1819, use GetClearText instead
- /// <summary>
- /// Get the contents of the clear text buffer.
- /// </summary>
- public byte[] ClearText
- {
- get
- {
- return clearText;
- } // get
- } // ClearText
- */
-
- #region Available (Public)
- /// <summary>
- /// Get/set the number of bytes available
- /// </summary>
- public int Available
- {
- get
- {
- return available;
- } // get
- set
- {
- available = value;
- } // set
- }
- #endregion
-
- #region CryptoTransform (Public)
- /// <summary>
- /// Get/set the <see cref="ICryptoTransform"/> to apply to any data.
- /// </summary>
- /// <remarks>Set this value to null to have no transform applied.</remarks>
- public ICryptoTransform CryptoTransform
- {
- set
- {
- cryptoTransform = value;
- if (cryptoTransform != null)
- {
- if (rawData == clearText)
- {
- if (internalClearText == null)
- {
- internalClearText = new byte[4096];
- } // if (internalClearText)
- clearText = internalClearText;
- } // if (rawData)
- clearTextLength = rawLength;
- if (available > 0)
- {
- cryptoTransform.TransformBlock(rawData, rawLength - available,
- available, clearText, rawLength - available);
- } // if (available)
- } // if (cryptoTransform)
- else
- {
- clearText = rawData;
- clearTextLength = rawLength;
- } // else
- } // set
- }
- #endregion
-
- #region Private
-
- #region rawLength (Private)
- /// <remarks>
- /// The raw length
- /// </remarks>
- private int rawLength;
- #endregion
-
- #region rawData (Private)
- /// <remarks>
- /// The data inside the buffer
- /// </remarks>
- private readonly byte[] rawData;
- #endregion
-
- #region clearTextLength (Private)
- /// <remarks>
- /// Clear Text Length
- /// </remarks>
- private int clearTextLength;
- #endregion
-
- #region clearText (Private)
- /// <remarks>
- /// The clear Text
- /// </remarks>
- private byte[] clearText;
- #endregion
-
- #region internalClearText (Private)
- /// <remarks>
- /// Internal Clear Text
- /// </remarks>
- private byte[] internalClearText;
- #endregion
-
- #region available (Private)
- /// <remarks>
- /// Available
- /// </remarks>
- private int available;
- #endregion
-
- #region cryptoTransform (Private)
- /// <remarks>
- /// cryptoTransform
- /// </remarks>
- private ICryptoTransform cryptoTransform;
- #endregion
-
- #region inputStream (Private)
- /// <remarks>
- /// The input stream
- /// </remarks>
- private readonly Stream inputStream;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Initialise a new instance of <see cref="InflaterInputBuffer"/>
- /// </summary>
- /// <param name="stream">The stream to buffer.</param>
- public InflaterInputBuffer(Stream stream)
- {
- inputStream = stream;
- rawData = new byte[4096];
- clearText = rawData;
- }
- #endregion
-
- #region GetRawData (Public)
- /// <summary>
- /// Get the contents of the raw data buffer.
- /// </summary>
- /// <remarks>This may contain encrypted data.</remarks>
- public byte[] GetRawData()
- {
- return rawData;
- }
- #endregion
-
- #region GetClearText (Public)
- /// <summary>
- /// Get the contents of the clear text buffer.
- /// </summary>
- public byte[] GetClearText()
- {
- return clearText;
- }
- #endregion
-
- #region SetInflaterInput (Public)
- /// <summary>
- /// Call <see cref="Inflater.SetInput(byte[])"/> passing the current clear
- /// text buffer contents.
- /// </summary>
- /// <param name="inflater">The inflater to set input for.</param>
- public void SetInflaterInput(Inflater inflater)
- {
- if (available > 0)
- {
- inflater.SetInput(clearText, clearTextLength - available, available);
- available = 0;
- } // if (available)
- }
- #endregion
-
- #region Fill (Public)
- /// <summary>
- /// Fill the buffer from the underlying input stream.
- /// </summary>
- public void Fill()
- {
- rawLength = 0;
- int toRead = rawData.Length;
-
- while (toRead > 0)
- {
- int count = inputStream.Read(rawData, rawLength, toRead);
- if (count <= 0)
- {
- if (rawLength == 0)
- {
- throw new CompressionException("Unexpected EOF");
- } // if (rawLength)
- break;
- } // if (count)
- rawLength += count;
- toRead -= count;
- } // while (toRead)
-
- if (cryptoTransform != null)
- {
- clearTextLength = cryptoTransform.TransformBlock(
- rawData, 0, rawLength, clearText, 0);
- } // if (cryptoTransform)
- else
- {
- clearTextLength = rawLength;
- } // else
-
- available = clearTextLength;
- }
- #endregion
-
- #region ReadRawBuffer (Public)
- /// <summary>
- /// Read a buffer directly from the input stream
- /// </summary>
- /// <param name="buffer">The buffer to fill</param>
- /// <returns>Returns the number of bytes read.</returns>
- public int ReadRawBuffer(byte[] buffer)
- {
- return ReadRawBuffer(buffer, 0, buffer.Length);
- }
-
- // ReadRawBuffer(buffer)
-
- /// <summary>
- /// Read a buffer directly from the input stream
- /// </summary>
- /// <param name="outBuffer">The buffer to read into</param>
- /// <param name="offset">The offset to start reading data into.</param>
- /// <param name="length">The number of bytes to read.</param>
- /// <returns>Returns the number of bytes read.</returns>
- public int ReadRawBuffer(byte[] outBuffer, int offset, int length)
- {
- if (length <= 0)
- {
- throw new ArgumentOutOfRangeException("length");
- } // if (length)
-
- int currentOffset = offset;
- int currentLength = length;
-
- while (currentLength > 0)
- {
- if (available <= 0)
- {
- Fill();
- if (available <= 0)
- {
- return 0;
- } // if (available)
- } // if (available)
- int toCopy = Math.Min(currentLength, available);
- Array.Copy(rawData, rawLength - available,
- outBuffer, currentOffset, toCopy);
- currentOffset += toCopy;
- currentLength -= toCopy;
- available -= toCopy;
- } // while (currentLength)
- return length;
- }
- #endregion
-
- #region ReadClearTextBuffer (Public)
- /// <summary>
- /// Read clear text data from the input stream.
- /// </summary>
- /// <param name="outBuffer">The buffer to add data to.</param>
- /// <param name="offset">The offset to start adding data at.</param>
- /// <param name="length">The number of bytes to read.</param>
- /// <returns>Returns the number of bytes actually read.</returns>
- public int ReadClearTextBuffer(byte[] outBuffer, int offset, int length)
- {
- if (length <= 0)
- {
- throw new ArgumentOutOfRangeException("length");
- } // if (length)
-
- int currentOffset = offset;
- int currentLength = length;
-
- while (currentLength > 0)
- {
- if (available <= 0)
- {
- Fill();
- if (available <= 0)
- {
- return 0;
- } // if (available)
- } // if (available)
-
- int toCopy = Math.Min(currentLength, available);
- Array.Copy(clearText, clearTextLength - available,
- outBuffer, currentOffset, toCopy);
- currentOffset += toCopy;
- currentLength -= toCopy;
- available -= toCopy;
- } // while (currentLength)
- return length;
- }
- #endregion
-
- #region ReadLeByte (Public)
- /// <summary>
- /// Read a byte from the input stream.
- /// </summary>
- /// <returns>Returns the byte read.</returns>
- public int ReadLeByte()
- {
- if (available <= 0)
- {
- Fill();
- if (available <= 0)
- {
- throw new ZipException("EOF in header");
- } // if (available)
- } // if (available)
- byte result = (byte)(rawData[rawLength - available] & 0xff);
- available -= 1;
- return result;
- }
- #endregion
-
- #region ReadLeShort (Public)
- /// <summary>
- /// Read an unsigned short in little endian byte order.
- /// </summary>
- public int ReadLeShort()
- {
- return ReadLeByte() | (ReadLeByte() << 8);
- }
- #endregion
-
- #region ReadLeInt (Public)
- /// <summary>
- /// Read an int in little endian byte order.
- /// </summary>
- public int ReadLeInt()
- {
- return ReadLeShort() | (ReadLeShort() << 16);
- }
- #endregion
-
- #region ReadLeLong (Public)
- /// <summary>
- /// Read an int baseInputStream little endian byte order.
- /// </summary>
- public long ReadLeLong()
- {
- return ReadLeInt() | (ReadLeInt() << 32);
- }
- #endregion
- }
- }