PageRenderTime 245ms CodeModel.GetById 131ms app.highlight 9ms RepoModel.GetById 61ms app.codeStats 0ms

/Utilities/Compression/Inflaters/InflaterDynHeader.cs

#
C# | 300 lines | 195 code | 31 blank | 74 comment | 20 complexity | 6f46816e7ff09a4c97bffd279739bdfb MD5 | raw file
  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
  5using System;
  6using Delta.Utilities.Compression.Streams;
  7
  8namespace Delta.Utilities.Compression.Inflaters
  9{
 10	/// <summary>
 11	/// Inflater dyn header
 12	/// </summary>
 13	internal class InflaterDynHeader
 14	{
 15		#region Constants
 16		private const int LNUM = 0;
 17
 18		private const int DNUM = 1;
 19
 20		private const int BLNUM = 2;
 21
 22		private const int BLLENS = 3;
 23
 24		private const int LENS = 4;
 25
 26		private const int REPS = 5;
 27
 28		/// <summary>
 29		/// Rep minimum
 30		/// </summary>
 31		private static readonly int[] repMin = {
 32			3, 3, 11
 33		};
 34
 35		/// <summary>
 36		/// Rep bits
 37		/// </summary>
 38		private static readonly int[] repBits = {
 39			2, 3, 7
 40		};
 41
 42		/// <summary>
 43		/// BL_ ORDER
 44		/// </summary>
 45		private static readonly int[] BL_ORDER =
 46			{
 47				16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
 48			};
 49		#endregion
 50
 51		#region Private
 52
 53		#region blLens (Private)
 54		/// <summary>
 55		/// Bl lens
 56		/// </summary>
 57		private byte[] blLens;
 58		#endregion
 59
 60		#region litdistLens (Private)
 61		/// <summary>
 62		/// Litdist lens
 63		/// </summary>
 64		private byte[] litdistLens;
 65		#endregion
 66
 67		#region blTree (Private)
 68		/// <summary>
 69		/// Bl tree
 70		/// </summary>
 71		private InflaterHuffmanTree blTree;
 72		#endregion
 73
 74		#region mode (Private)
 75		/// <summary>
 76		/// Mode
 77		/// </summary>
 78		private int mode;
 79		#endregion
 80
 81		#region lnum (Private)
 82		/// <summary>
 83		/// Lnum
 84		/// </summary>
 85		private int lnum;
 86		#endregion
 87
 88		#region dnum (Private)
 89		/// <summary>
 90		/// Lnum
 91		/// </summary>
 92		private int dnum;
 93		#endregion
 94
 95		#region blnum (Private)
 96		/// <summary>
 97		/// Lnum
 98		/// </summary>
 99		private int blnum;
100		#endregion
101
102		#region num (Private)
103		/// <summary>
104		/// Lnum
105		/// </summary>
106		private int num;
107		#endregion
108
109		#region repSymbol (Private)
110		/// <summary>
111		/// Rep symbol
112		/// </summary>
113		private int repSymbol;
114		#endregion
115
116		#region lastLen (Private)
117		/// <summary>
118		/// Last len
119		/// </summary>
120		private byte lastLen;
121		#endregion
122
123		#region ptr (Private)
124		/// <summary>
125		/// Ptr
126		/// </summary>
127		private int ptr;
128		#endregion
129
130		#endregion
131
132		#region Decode (Public)
133		/// <summary>
134		/// Decode
135		/// </summary>
136		/// <param name="input">Input</param>
137		/// <returns>True if we are done decoding.</returns>
138		public bool Decode(StreamManipulator input)
139		{
140			decode_loop:
141			for (;;)
142			{
143				switch (mode)
144				{
145					case LNUM:
146						lnum = input.PeekBits(5);
147						if (lnum < 0)
148						{
149							return false;
150						} // if (lnum)
151						lnum += 257;
152						input.DropBits(5);
153						//Console.WriteLine("LNUM: "+lnum);
154						mode = DNUM;
155						goto case DNUM; // fall through
156					case DNUM:
157						dnum = input.PeekBits(5);
158						if (dnum < 0)
159						{
160							return false;
161						} // if (dnum)
162						dnum++;
163						input.DropBits(5);
164						//Console.WriteLine("DNUM: "+dnum);
165						num = lnum + dnum;
166						litdistLens = new byte[num];
167						mode = BLNUM;
168						goto case BLNUM; // fall through
169					case BLNUM:
170						blnum = input.PeekBits(4);
171						if (blnum < 0)
172						{
173							return false;
174						} // if (blnum)
175						blnum += 4;
176						input.DropBits(4);
177						blLens = new byte[19];
178						ptr = 0;
179						//Console.WriteLine("BLNUM: "+blnum);
180						mode = BLLENS;
181						goto case BLLENS; // fall through
182					case BLLENS:
183						while (ptr < blnum)
184						{
185							int len = input.PeekBits(3);
186							if (len < 0)
187							{
188								return false;
189							} // if (len)
190							input.DropBits(3);
191							//Console.WriteLine("blLens["+BLOrder[ptr]+"]: "+len);
192							blLens[BL_ORDER[ptr]] = (byte)len;
193							ptr++;
194						} // while (ptr)
195						blTree = new InflaterHuffmanTree(blLens);
196						blLens = null;
197						ptr = 0;
198						mode = LENS;
199						goto case LENS; // fall through
200					case LENS:
201					{
202						int symbol;
203						while (((symbol = blTree.GetSymbol(input)) & ~15) == 0)
204						{
205							// Normal case: symbol in [0..15]
206							//Console.WriteLine("litdistLens["+ptr+"]: "+symbol);
207							litdistLens[ptr++] = lastLen = (byte)symbol;
208
209							if (ptr == num)
210							{
211								// Finished
212								return true;
213							} // if (ptr)
214						} // while ()
215
216						// Need more input?
217						if (symbol < 0)
218						{
219							return false;
220						} // if (symbol)
221
222						// Otherwise repeat code
223						if (symbol >= 17)
224						{
225							// Repeat zero
226							//Console.WriteLine("repeating zero");
227							lastLen = 0;
228						} // if (symbol)
229						else
230						{
231							if (ptr == 0)
232							{
233								throw new CompressionException();
234							} // if (ptr)
235						} // else
236						repSymbol = symbol - 16;
237					} // block
238						mode = REPS;
239						goto case REPS; // fall through
240					case REPS:
241					{
242						int bits = repBits[repSymbol];
243						int count = input.PeekBits(bits);
244						if (count < 0)
245						{
246							return false;
247						} // if (count)
248						input.DropBits(bits);
249						count += repMin[repSymbol];
250						//Console.WriteLine("litdistLens repeated: "+count);
251
252						if (ptr + count > num)
253						{
254							throw new CompressionException();
255						} // if (ptr)
256						while (count-- > 0)
257						{
258							litdistLens[ptr++] = lastLen;
259						} // while (count--)
260
261						if (ptr == num)
262						{
263							// Finished
264							return true;
265						} // if (ptr)
266					} // block
267						mode = LENS;
268						goto decode_loop;
269				} // switch
270			} // for
271		}
272		#endregion
273
274		#region BuildLitLenTree (Public)
275		/// <summary>
276		/// Build lit len tree
277		/// </summary>
278		/// <returns>Inflater huffman tree</returns>
279		public InflaterHuffmanTree BuildLitLenTree()
280		{
281			byte[] litlenLens = new byte[lnum];
282			Array.Copy(litdistLens, 0, litlenLens, 0, lnum);
283			return new InflaterHuffmanTree(litlenLens);
284		}
285		#endregion
286
287		#region BuildDistTree (Public)
288		/// <summary>
289		/// Build dist tree
290		/// </summary>
291		/// <returns>Inflater huffman tree</returns>
292		public InflaterHuffmanTree BuildDistTree()
293		{
294			byte[] distLens = new byte[dnum];
295			Array.Copy(litdistLens, lnum, distLens, 0, dnum);
296			return new InflaterHuffmanTree(distLens);
297		}
298		#endregion
299	}
300}