PageRenderTime 242ms CodeModel.GetById 81ms app.highlight 91ms RepoModel.GetById 60ms app.codeStats 0ms

/Utilities/Compression/Deflaters/DeflaterHuffman.cs

#
C# | 1141 lines | 746 code | 126 blank | 269 comment | 100 complexity | 0160422a148c39304785d4d1ff431651 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;
   6
   7namespace Delta.Utilities.Compression.Deflaters
   8{
   9	/// <summary>
  10	/// This is the DeflaterHuffman class. This class is <i>not</i> thread safe.
  11	/// This is inherent in the API, due to the split of deflate and setInput.
  12	/// </summary>
  13	public class DeflaterHuffman
  14	{
  15		#region Tree Class
  16		/// <summary>
  17		/// Tree
  18		/// </summary>
  19		public class Tree
  20		{
  21			#region freqs (Public)
  22			/// <summary>
  23			/// Frequencies
  24			/// </summary>
  25			public short[] freqs;
  26			#endregion
  27
  28			#region length (Public)
  29			/// <summary>
  30			/// Length
  31			/// </summary>
  32			public byte[] length;
  33			#endregion
  34
  35			#region minNumCodes (Public)
  36			/// <summary>
  37			/// Number of codes.
  38			/// </summary>
  39			public int minNumCodes;
  40			#endregion
  41
  42			#region numCodes (Public)
  43			/// <summary>
  44			/// Number of codes.
  45			/// </summary>
  46			public int numCodes;
  47			#endregion
  48
  49			#region Private
  50
  51			#region codes (Private)
  52			private short[] codes;
  53			#endregion
  54
  55			#region bl_counts (Private)
  56			private readonly int[] bl_counts;
  57			#endregion
  58
  59			#region maxLength (Private)
  60			private readonly int maxLength;
  61			#endregion
  62
  63			#region dh (Private)
  64			private readonly DeflaterHuffman dh;
  65			#endregion
  66
  67			#endregion
  68
  69			#region Constructors
  70			/// <summary>
  71			/// Create tree
  72			/// </summary>
  73			/// <param name="dh">Dh</param>
  74			/// <param name="elems">Elems</param>
  75			/// <param name="minCodes">Min codes</param>
  76			/// <param name="maxLength">Max length</param>
  77			public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength)
  78			{
  79				this.dh = dh;
  80				minNumCodes = minCodes;
  81				this.maxLength = maxLength;
  82				freqs = new short[elems];
  83				bl_counts = new int[maxLength];
  84			}
  85			#endregion
  86
  87			// Tree(dh, elems, minCodes)
  88
  89			#region Reset (Public)
  90			/// <summary>
  91			/// Reset
  92			/// </summary>
  93			public void Reset()
  94			{
  95				for (int i = 0; i < freqs.Length; i++)
  96				{
  97					freqs[i] = 0;
  98				} // for (int)
  99				codes = null;
 100				length = null;
 101			}
 102			#endregion
 103
 104			// Reset()
 105
 106			#region WriteSymbol (Public)
 107			/// <summary>
 108			/// Write symbol
 109			/// </summary>
 110			/// <param name="code">code</param>
 111			public void WriteSymbol(int code)
 112			{
 113				//if (DeflaterConstants.DEBUGGING)
 114				//{
 115				//  freqs[code]--;
 116				//  //  	  Console.Write("writeSymbol("+freqs.length+","+code+"): ");
 117				//}
 118				dh.pending.WriteBits(codes[code] & 0xffff, length[code]);
 119			}
 120			#endregion
 121
 122			// WriteSymbol(code)
 123
 124			#region CheckEmpty (Public)
 125			/// <summary>
 126			/// Check empty
 127			/// </summary>
 128			public void CheckEmpty()
 129			{
 130				bool empty = true;
 131				for (int i = 0; i < freqs.Length; i++)
 132				{
 133					if (freqs[i] != 0)
 134					{
 135						//Console.WriteLine("freqs["+i+"] == "+freqs[i]);
 136						empty = false;
 137					} // if (freqs[i])
 138				} // for (int)
 139				if (!empty)
 140				{
 141					throw new Exception();
 142				} // if ()
 143				//Console.WriteLine("checkEmpty suceeded!");
 144			}
 145			#endregion
 146
 147			// CheckEmpty()
 148
 149			#region SetStaticCodes (Public)
 150			/// <summary>
 151			/// Set static codes
 152			/// </summary>
 153			/// <param name="stCodes">St codes</param>
 154			/// <param name="stLength">St length</param>
 155			public void SetStaticCodes(short[] stCodes, byte[] stLength)
 156			{
 157				codes = stCodes;
 158				length = stLength;
 159			}
 160			#endregion
 161
 162			// SetStaticCodes(stCodes, stLength)
 163
 164			#region BuildCodes (Public)
 165			/// <summary>
 166			/// Build codes
 167			/// </summary>
 168			public void BuildCodes()
 169			{
 170				//never used: int numSymbols = freqs.Length;
 171				int[] nextCode = new int[maxLength];
 172				int code = 0;
 173				codes = new short[freqs.Length];
 174
 175				//if (DeflaterConstants.DEBUGGING)
 176				//{
 177				//  //Console.WriteLine("buildCodes: "+freqs.Length);
 178				//}
 179
 180				for (int bits = 0; bits < maxLength; bits++)
 181				{
 182					nextCode[bits] = code;
 183					code += bl_counts[bits] << (15 - bits);
 184					//if (DeflaterConstants.DEBUGGING) {
 185					//  //Console.WriteLine("bits: "+(bits+1)+" count: "+bl_counts[bits]
 186					//                    +" nextCode: "+code);
 187					//}
 188				} // for (bits)
 189				//if (DeflaterConstants.DEBUGGING && code != 65536) {
 190				//	throw new Exception("Inconsistent bl_counts!");
 191				//}
 192
 193				for (int i = 0; i < numCodes; i++)
 194				{
 195					int bits = length[i];
 196					if (bits > 0)
 197					{
 198						//if (DeflaterConstants.DEBUGGING) {
 199						//                      +bits);
 200						//}
 201						codes[i] = BitReverse(nextCode[bits - 1]);
 202						nextCode[bits - 1] += 1 << (16 - bits);
 203					} // if (bits)
 204				} // for (int)
 205			}
 206			#endregion
 207
 208			// BuildCodes()
 209
 210			// BuildLength(childs)
 211
 212			#region BuildTree (Public)
 213			/// <summary>
 214			/// Build tree
 215			/// </summary>
 216			public void BuildTree()
 217			{
 218				int numSymbols = freqs.Length;
 219
 220				// heap is a priority queue, sorted by frequency, least frequent
 221				// nodes first.  The heap is a binary tree, with the property, that
 222				// the parent node is smaller than both child nodes.  This assures
 223				// that the smallest node is the first parent.
 224				//
 225				// The binary tree is encoded in an array:  0 is root node and
 226				// the nodes 2*n+1, 2*n+2 are the child nodes of node n.
 227				int[] heap = new int[numSymbols];
 228				int heapLen = 0;
 229				int maxCode = 0;
 230				for (int n = 0; n < numSymbols; n++)
 231				{
 232					int freq = freqs[n];
 233					if (freq != 0)
 234					{
 235						/* Insert n into heap */
 236						int pos = heapLen++;
 237						int ppos;
 238						while (pos > 0 &&
 239						       freqs[heap[ppos = (pos - 1) / 2]] > freq)
 240						{
 241							heap[pos] = heap[ppos];
 242							pos = ppos;
 243						} // while (pos)
 244						heap[pos] = n;
 245
 246						maxCode = n;
 247					} // if (freq)
 248				} // for (int)
 249
 250				// We could encode a single literal with 0 bits but then we
 251				// don't see the literals.  Therefore we force at least two
 252				// literals to avoid this case.  We don't care about order in
 253				// this case, both literals get a 1 bit code.
 254				while (heapLen < 2)
 255				{
 256					int node = maxCode < 2
 257					           	? ++maxCode
 258					           	: 0;
 259					heap[heapLen++] = node;
 260				} // while (heapLen)
 261
 262				numCodes = Math.Max(maxCode + 1, minNumCodes);
 263
 264				int numLeafs = heapLen;
 265				int[] childs = new int[4 * heapLen - 2];
 266				int[] values = new int[2 * heapLen - 1];
 267				int numNodes = numLeafs;
 268				for (int i = 0; i < heapLen; i++)
 269				{
 270					int node = heap[i];
 271					childs[2 * i] = node;
 272					childs[2 * i + 1] = -1;
 273					values[i] = freqs[node] << 8;
 274					heap[i] = i;
 275				} // for (int)
 276
 277				// Construct the Huffman tree by repeatedly combining the least two
 278				// frequent nodes.
 279				do
 280				{
 281					int first = heap[0];
 282					int last = heap[--heapLen];
 283
 284					// Propagate the hole to the leafs of the heap
 285					int ppos = 0;
 286					int path = 1;
 287
 288					while (path < heapLen)
 289					{
 290						if (path + 1 < heapLen && values[heap[path]] > values[heap[path + 1]])
 291						{
 292							path++;
 293						} // if (path)
 294
 295						heap[ppos] = heap[path];
 296						ppos = path;
 297						path = path * 2 + 1;
 298					} // while (path)
 299
 300					// Now propagate the last element down along path.  Normally
 301					// it shouldn't go too deep.
 302					int lastVal = values[last];
 303					while ((path = ppos) > 0 &&
 304					       values[heap[ppos = (path - 1) / 2]] > lastVal)
 305					{
 306						heap[path] = heap[ppos];
 307					} // while ()
 308					heap[path] = last;
 309
 310					int second = heap[0];
 311
 312					// Create a new node father of first and second
 313					last = numNodes++;
 314					childs[2 * last] = first;
 315					childs[2 * last + 1] = second;
 316					int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff);
 317					values[last] = lastVal = values[first] + values[second] - mindepth + 1;
 318
 319					// Again, propagate the hole to the leafs
 320					ppos = 0;
 321					path = 1;
 322
 323					while (path < heapLen)
 324					{
 325						if (path + 1 < heapLen && values[heap[path]] > values[heap[path + 1]])
 326						{
 327							path++;
 328						} // if (path)
 329
 330						heap[ppos] = heap[path];
 331						ppos = path;
 332						path = ppos * 2 + 1;
 333					} // while (path)
 334
 335					// Now propagate the new element down along path
 336					while ((path = ppos) > 0 &&
 337					       values[heap[ppos = (path - 1) / 2]] > lastVal)
 338					{
 339						heap[path] = heap[ppos];
 340					} // while ()
 341					heap[path] = last;
 342				} while (heapLen > 1);
 343
 344				if (heap[0] != childs.Length / 2 - 1)
 345				{
 346					throw new Exception("Weird!");
 347				} // if (heap[0])
 348				BuildLength(childs);
 349			}
 350			#endregion
 351
 352			// BuildTree()
 353
 354			#region GetEncodedLength (Public)
 355			/// <summary>
 356			/// Get encoded length
 357			/// </summary>
 358			/// <returns>Int</returns>
 359			public int GetEncodedLength()
 360			{
 361				int len = 0;
 362				for (int i = 0; i < freqs.Length; i++)
 363				{
 364					len += freqs[i] * length[i];
 365				} // for (int)
 366				return len;
 367			}
 368			#endregion
 369
 370			// GetEncodedLength()
 371
 372			#region CalcBLFreq (Public)
 373			/// <summary>
 374			/// Calc BL freq
 375			/// </summary>
 376			/// <param name="blTree">Bl tree</param>
 377			public void CalcBLFreq(Tree blTree)
 378			{
 379				// max repeat count
 380				int max_count;
 381				// min repeat count
 382				int min_count;
 383				// repeat count of the current code
 384				int count;
 385				// length of current code
 386				int curlen = -1;
 387
 388				int i = 0;
 389				while (i < numCodes)
 390				{
 391					count = 1;
 392					int nextlen = length[i];
 393					if (nextlen == 0)
 394					{
 395						max_count = 138;
 396						min_count = 3;
 397					} // if (nextlen)
 398					else
 399					{
 400						max_count = 6;
 401						min_count = 3;
 402						if (curlen != nextlen)
 403						{
 404							blTree.freqs[nextlen]++;
 405							count = 0;
 406						} // if (curlen)
 407					} // else
 408					curlen = nextlen;
 409					i++;
 410
 411					while (i < numCodes &&
 412					       curlen == length[i])
 413					{
 414						i++;
 415						if (++count >= max_count)
 416						{
 417							break;
 418						} // if (++count)
 419					} // while (i)
 420
 421					if (count < min_count)
 422					{
 423						blTree.freqs[curlen] += (short)count;
 424					} // if (count)
 425					else if (curlen != 0)
 426					{
 427						blTree.freqs[Rep3_6]++;
 428					} // else if
 429					else if (count <= 10)
 430					{
 431						blTree.freqs[Rep3_10]++;
 432					} // else if
 433					else
 434					{
 435						blTree.freqs[Rep11_138]++;
 436					} // else
 437				} // while (i)
 438			}
 439			#endregion
 440
 441			// CalcBLFreq(blTree)
 442
 443			#region WriteTree (Public)
 444			/// <summary>
 445			/// Write tree
 446			/// </summary>
 447			/// <param name="blTree">Bl tree</param>
 448			public void WriteTree(Tree blTree)
 449			{
 450				// max repeat count
 451				int max_count;
 452				// min repeat count
 453				int min_count;
 454				// repeat count of the current code
 455				int count;
 456				// length of current code
 457				int curlen = -1;
 458
 459				int i = 0;
 460				while (i < numCodes)
 461				{
 462					count = 1;
 463					int nextlen = length[i];
 464					if (nextlen == 0)
 465					{
 466						max_count = 138;
 467						min_count = 3;
 468					} // if (nextlen)
 469					else
 470					{
 471						max_count = 6;
 472						min_count = 3;
 473						if (curlen != nextlen)
 474						{
 475							blTree.WriteSymbol(nextlen);
 476							count = 0;
 477						} // if (curlen)
 478					} // else
 479					curlen = nextlen;
 480					i++;
 481
 482					while (i < numCodes &&
 483					       curlen == length[i])
 484					{
 485						i++;
 486						if (++count >= max_count)
 487						{
 488							break;
 489						} // if (++count)
 490					} // while (i)
 491
 492					if (count < min_count)
 493					{
 494						while (count-- > 0)
 495						{
 496							blTree.WriteSymbol(curlen);
 497						} // while (count--)
 498					} // if (count)
 499					else if (curlen != 0)
 500					{
 501						blTree.WriteSymbol(Rep3_6);
 502						dh.pending.WriteBits(count - 3, 2);
 503					} // else if
 504					else if (count <= 10)
 505					{
 506						blTree.WriteSymbol(Rep3_10);
 507						dh.pending.WriteBits(count - 3, 3);
 508					} // else if
 509					else
 510					{
 511						blTree.WriteSymbol(Rep11_138);
 512						dh.pending.WriteBits(count - 11, 7);
 513					} // else
 514				} // while (i)
 515			}
 516			#endregion
 517
 518			#region Methods (Private)
 519
 520			#region BuildLength
 521			/// <summary>
 522			/// Build length
 523			/// </summary>
 524			/// <param name="childs">Childs</param>
 525			private void BuildLength(int[] childs)
 526			{
 527				length = new byte[freqs.Length];
 528				int numNodes = childs.Length / 2;
 529				int numLeafs = (numNodes + 1) / 2;
 530				int overflow = 0;
 531
 532				for (int i = 0; i < maxLength; i++)
 533				{
 534					bl_counts[i] = 0;
 535				} // for (int)
 536
 537				// First calculate optimal bit lengths
 538				int[] lengths = new int[numNodes];
 539				lengths[numNodes - 1] = 0;
 540
 541				for (int i = numNodes - 1; i >= 0; i--)
 542				{
 543					if (childs[2 * i + 1] != -1)
 544					{
 545						int bitLength = lengths[i] + 1;
 546						if (bitLength > maxLength)
 547						{
 548							bitLength = maxLength;
 549							overflow++;
 550						} // if (bitLength)
 551						lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength;
 552					} // if (childs[2)
 553					else
 554					{
 555						// A leaf node
 556						int bitLength = lengths[i];
 557						bl_counts[bitLength - 1]++;
 558						length[childs[2 * i]] = (byte)lengths[i];
 559					} // else
 560				} // for (int)
 561
 562				//if (DeflaterConstants.DEBUGGING) {
 563				//  //Console.WriteLine("Tree "+freqs.Length+" lengths:");
 564				//  for (int i=0; i < numLeafs; i++) {
 565				//    //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
 566				//                      + " len: "+length[childs[2*i]]);
 567				//  }
 568				//}
 569
 570				if (overflow == 0)
 571				{
 572					return;
 573				} // if (overflow)
 574
 575				int incrBitLen = maxLength - 1;
 576				do
 577				{
 578					// Find the first bit length which could increase:
 579					while (bl_counts[--incrBitLen] == 0)
 580					{
 581						;
 582					}
 583
 584					// Move this node one down and remove a corresponding
 585					// amount of overflow nodes.
 586					do
 587					{
 588						bl_counts[incrBitLen]--;
 589						bl_counts[++incrBitLen]++;
 590						overflow -= 1 << (maxLength - 1 - incrBitLen);
 591					} while (overflow > 0 &&
 592					         incrBitLen < maxLength - 1);
 593				} while (overflow > 0);
 594
 595				// We may have overshot above.  Move some nodes from maxLength to
 596				// maxLength-1 in that case.
 597				bl_counts[maxLength - 1] += overflow;
 598				bl_counts[maxLength - 2] -= overflow;
 599
 600				// Now recompute all bit lengths, scanning in increasing
 601				// frequency.  It is simpler to reconstruct all lengths instead of
 602				// fixing only the wrong ones. This idea is taken from 'ar'
 603				// written by Haruhiko Okumura.
 604				//
 605				// The nodes were inserted with decreasing frequency into the childs
 606				// array.
 607				int nodePtr = 2 * numLeafs;
 608				for (int bits = maxLength; bits != 0; bits--)
 609				{
 610					int n = bl_counts[bits - 1];
 611					while (n > 0)
 612					{
 613						int childPtr = 2 * childs[nodePtr++];
 614						if (childs[childPtr + 1] == -1)
 615						{
 616							/* We found another leaf */
 617							length[childs[childPtr]] = (byte)bits;
 618							n--;
 619						} // if (childs[childPtr)
 620					} // while (n)
 621				} // for (bits)
 622				//if (DeflaterConstants.DEBUGGING) {
 623				//  //Console.WriteLine("*** After overflow elimination. ***");
 624				//  for (int i=0; i < numLeafs; i++) {
 625				//    //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
 626				//                      + " len: "+length[childs[2*i]]);
 627				//  }
 628				//}
 629			}
 630			#endregion
 631
 632			#endregion
 633
 634			// WriteTree(blTree)
 635		}
 636		#endregion
 637
 638		#region Constants
 639		/// <summary>
 640		/// Buffer size
 641		/// </summary>
 642		/// <returns>16384</returns>
 643		private const int BufferSize = 1 << (DeflaterConstants.DefaultMemoryLevel + 6);
 644
 645		/// <summary>
 646		/// Litteral number
 647		/// </summary>
 648		/// <returns>286</returns>
 649		private const int LiteralNum = 286;
 650
 651		/// <summary>
 652		/// Distance number
 653		/// </summary>
 654		/// <returns>30</returns>
 655		private const int DistanceNum = 30;
 656
 657		/// <summary>
 658		/// Bit length number
 659		/// </summary>
 660		/// <returns>19</returns>
 661		private const int BitLengthNum = 19;
 662
 663		/// <summary>
 664		/// REP 3_6
 665		/// </summary>
 666		/// <returns>16</returns>
 667		private const int Rep3_6 = 16;
 668
 669		/// <summary>
 670		/// REP 3_10
 671		/// </summary>
 672		/// <returns>18</returns>
 673		private const int Rep3_10 = 17;
 674
 675		/// <summary>
 676		/// REP 11_138
 677		/// </summary>
 678		/// <returns>18</returns>
 679		private const int Rep11_138 = 18;
 680
 681		/// <summary>
 682		/// EOF Symbol
 683		/// </summary>
 684		/// <returns>256</returns>
 685		private const int EofSymbol = 256;
 686
 687		/// <summary>
 688		/// BL Order
 689		/// </summary>
 690		private static readonly int[] BLOrder =
 691			{
 692				16,
 693				17,
 694				18,
 695				0,
 696				8,
 697				7,
 698				9,
 699				6,
 700				10,
 701				5,
 702				11,
 703				4,
 704				12,
 705				3,
 706				13,
 707				2,
 708				14,
 709				1,
 710				15
 711			};
 712
 713		/// <summary>
 714		/// Bit 4 reverse
 715		/// </summary>
 716		private static readonly byte[] Bit4Reverse =
 717			{
 718				0,
 719				8,
 720				4,
 721				12,
 722				2,
 723				10,
 724				6,
 725				14,
 726				1,
 727				9,
 728				5,
 729				13,
 730				3,
 731				11,
 732				7,
 733				15
 734			};
 735
 736		private static readonly short[] staticLCodes;
 737
 738		private static readonly byte[] staticLLength;
 739
 740		private static readonly short[] staticDCodes;
 741
 742		private static readonly byte[] staticDLength;
 743		#endregion
 744
 745		#region BitReverse (Static)
 746		/// <summary>
 747		/// Reverse the bits of a 16 bit value.
 748		/// </summary>
 749		/// <param name="toReverse">Value to reverse bits</param>
 750		/// <returns>Value with bits reversed</returns>
 751		public static short BitReverse(int toReverse)
 752		{
 753			return (short)(Bit4Reverse[toReverse & 0xF] << 12 |
 754			               Bit4Reverse[(toReverse >> 4) & 0xF] << 8 |
 755			               Bit4Reverse[(toReverse >> 8) & 0xF] << 4 |
 756			               Bit4Reverse[toReverse >> 12]);
 757		}
 758		#endregion
 759
 760		#region pending (Public)
 761		/// <summary>
 762		/// Pending buffer to use
 763		/// </summary>
 764		public DeflaterPending pending;
 765		#endregion
 766
 767		#region Private
 768
 769		#region literalTree (Private)
 770		private readonly Tree literalTree;
 771		#endregion
 772
 773		#region distTree (Private)
 774		private readonly Tree distTree;
 775		#endregion
 776
 777		#region blTree (Private)
 778		private readonly Tree blTree;
 779		#endregion
 780
 781		#region d_buf (Private)
 782		private readonly short[] d_buf;
 783		#endregion
 784
 785		#region l_buf (Private)
 786		private readonly byte[] l_buf;
 787		#endregion
 788
 789		#region last_lit (Private)
 790		private int last_lit;
 791		#endregion
 792
 793		#region extra_bits (Private)
 794		private int extra_bits;
 795		#endregion
 796
 797		#endregion
 798
 799		#region Constructors
 800		/// <summary>
 801		/// Create deflater huffman
 802		/// </summary>
 803		static DeflaterHuffman()
 804		{
 805			// See RFC 1951 3.2.6
 806			// Literal codes
 807			staticLCodes = new short[LiteralNum];
 808			staticLLength = new byte[LiteralNum];
 809			int i = 0;
 810			while (i < 144)
 811			{
 812				staticLCodes[i] = BitReverse((0x030 + i) << 8);
 813				staticLLength[i++] = 8;
 814			} // while (i)
 815			while (i < 256)
 816			{
 817				staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7);
 818				staticLLength[i++] = 9;
 819			} // while (i)
 820			while (i < 280)
 821			{
 822				staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9);
 823				staticLLength[i++] = 7;
 824			} // while (i)
 825			while (i < LiteralNum)
 826			{
 827				staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8);
 828				staticLLength[i++] = 8;
 829			} // while (i)
 830
 831			// Distant codes
 832			staticDCodes = new short[DistanceNum];
 833			staticDLength = new byte[DistanceNum];
 834			for (i = 0; i < DistanceNum; i++)
 835			{
 836				staticDCodes[i] = BitReverse(i << 11);
 837				staticDLength[i] = 5;
 838			} // for (i)
 839		}
 840
 841		// DeflaterHuffman()
 842
 843		/// <summary>
 844		/// Construct instance with pending buffer
 845		/// </summary>
 846		/// <param name="pending">Pending buffer to use</param>
 847		public DeflaterHuffman(DeflaterPending pending)
 848		{
 849			this.pending = pending;
 850
 851			literalTree = new Tree(this, LiteralNum, 257, 15);
 852			distTree = new Tree(this, DistanceNum, 1, 15);
 853			blTree = new Tree(this, BitLengthNum, 4, 7);
 854
 855			d_buf = new short[BufferSize];
 856			l_buf = new byte[BufferSize];
 857		}
 858		#endregion
 859
 860		#region Reset (Public)
 861		/// <summary>
 862		/// Reset internal state
 863		/// </summary>		
 864		public void Reset()
 865		{
 866			last_lit = 0;
 867			extra_bits = 0;
 868			literalTree.Reset();
 869			distTree.Reset();
 870			blTree.Reset();
 871		}
 872		#endregion
 873
 874		#region SendAllTrees (Public)
 875		/// <summary>
 876		/// Write all trees to pending buffer
 877		/// </summary>		
 878		public void SendAllTrees(int blTreeCodes)
 879		{
 880			blTree.BuildCodes();
 881			literalTree.BuildCodes();
 882			distTree.BuildCodes();
 883			pending.WriteBits(literalTree.numCodes - 257, 5);
 884			pending.WriteBits(distTree.numCodes - 1, 5);
 885			pending.WriteBits(blTreeCodes - 4, 4);
 886			for (int rank = 0; rank < blTreeCodes; rank++)
 887			{
 888				pending.WriteBits(blTree.length[BLOrder[rank]], 3);
 889			} // for (rank)
 890			literalTree.WriteTree(blTree);
 891			distTree.WriteTree(blTree);
 892		}
 893		#endregion
 894
 895		#region CompressBlock (Public)
 896		/// <summary>
 897		/// Compress current buffer writing data to pending buffer
 898		/// </summary>
 899		public void CompressBlock()
 900		{
 901			for (int i = 0; i < last_lit; i++)
 902			{
 903				int litlen = l_buf[i] & 0xff;
 904				int dist = d_buf[i];
 905				if (dist-- != 0)
 906				{
 907					int lc = Lcode(litlen);
 908					literalTree.WriteSymbol(lc);
 909
 910					int bits = (lc - 261) / 4;
 911					if (bits > 0 && bits <= 5)
 912					{
 913						pending.WriteBits(litlen & ((1 << bits) - 1), bits);
 914					} // if (bits)
 915
 916					int dc = Dcode(dist);
 917					distTree.WriteSymbol(dc);
 918
 919					bits = dc / 2 - 1;
 920					if (bits > 0)
 921					{
 922						pending.WriteBits(dist & ((1 << bits) - 1), bits);
 923					} // if (bits)
 924				} // if (dist--)
 925				else
 926				{
 927					literalTree.WriteSymbol(litlen);
 928				} // else
 929			} // for (int)
 930			literalTree.WriteSymbol(EofSymbol);
 931		}
 932		#endregion
 933
 934		#region FlushStoredBlock (Public)
 935		/// <summary>
 936		/// Flush block to output with no compression
 937		/// </summary>
 938		/// <param name="stored">Data to write</param>
 939		/// <param name="storedOffset">Index of first byte to write</param>
 940		/// <param name="storedLength">Count of bytes to write</param>
 941		/// <param name="lastBlock">True if this is the last block</param>
 942		public void FlushStoredBlock(byte[] stored, int storedOffset,
 943			int storedLength, bool lastBlock)
 944		{
 945			pending.WriteBits((DeflaterConstants.StoredBlock << 1) +
 946			                  (lastBlock
 947			                   	? 1
 948			                   	: 0), 3);
 949			pending.AlignToByte();
 950			pending.WriteShort(storedLength);
 951			pending.WriteShort(~storedLength);
 952			pending.WriteBlock(stored, storedOffset, storedLength);
 953			Reset();
 954		}
 955		#endregion
 956
 957		#region FlushBlock (Public)
 958		/// <summary>
 959		/// Flush block to output with compression
 960		/// </summary>		
 961		/// <param name="stored">Data to flush</param>
 962		/// <param name="storedOffset">Index of first byte to flush</param>
 963		/// <param name="storedLength">Count of bytes to flush</param>
 964		/// <param name="lastBlock">True if this is the last block</param>
 965		public void FlushBlock(byte[] stored, int storedOffset,
 966			int storedLength, bool lastBlock)
 967		{
 968			literalTree.freqs[EofSymbol]++;
 969
 970			// Build trees
 971			literalTree.BuildTree();
 972			distTree.BuildTree();
 973
 974			// Calculate bitlen frequency
 975			literalTree.CalcBLFreq(blTree);
 976			distTree.CalcBLFreq(blTree);
 977
 978			// Build bitlen tree
 979			blTree.BuildTree();
 980
 981			int blTreeCodes = 4;
 982			for (int i = 18; i > blTreeCodes; i--)
 983			{
 984				if (blTree.length[BLOrder[i]] > 0)
 985				{
 986					blTreeCodes = i + 1;
 987				} // if (blTree.length[BLOrder[i]])
 988			} // for (int)
 989			int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() +
 990			              literalTree.GetEncodedLength() + distTree.GetEncodedLength() +
 991			              extra_bits;
 992
 993			int static_len = extra_bits;
 994			for (int i = 0; i < LiteralNum; i++)
 995			{
 996				static_len += literalTree.freqs[i] * staticLLength[i];
 997			} // for (int)
 998			for (int i = 0; i < DistanceNum; i++)
 999			{
1000				static_len += distTree.freqs[i] * staticDLength[i];
1001			} // for (int)
1002			if (opt_len >= static_len)
1003			{
1004				// Force static trees
1005				opt_len = static_len;
1006			} // if (opt_len)
1007
1008			if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3)
1009			{
1010				// Store Block
1011				FlushStoredBlock(stored, storedOffset, storedLength, lastBlock);
1012			} // if (storedOffset)
1013			else if (opt_len == static_len)
1014			{
1015				// Encode with static tree
1016				pending.WriteBits((DeflaterConstants.StaticTrees << 1) +
1017				                  (lastBlock
1018				                   	? 1
1019				                   	: 0), 3);
1020				literalTree.SetStaticCodes(staticLCodes, staticLLength);
1021				distTree.SetStaticCodes(staticDCodes, staticDLength);
1022				CompressBlock();
1023				Reset();
1024			} // else if
1025			else
1026			{
1027				// Encode with dynamic tree
1028				pending.WriteBits((DeflaterConstants.DynamicTrees << 1) +
1029				                  (lastBlock
1030				                   	? 1
1031				                   	: 0), 3);
1032				SendAllTrees(blTreeCodes);
1033				CompressBlock();
1034				Reset();
1035			} // else
1036		}
1037		#endregion
1038
1039		#region IsFull (Public)
1040		/// <summary>
1041		/// Get value indicating if internal buffer is full
1042		/// </summary>
1043		/// <returns>true if buffer is full</returns>
1044		public bool IsFull()
1045		{
1046			return last_lit >= BufferSize;
1047		}
1048		#endregion
1049
1050		#region TallyLit (Public)
1051		/// <summary>
1052		/// Add literal to buffer
1053		/// </summary>
1054		/// <param name="lit"></param>
1055		/// <returns>Value indicating internal buffer is full</returns>
1056		public bool TallyLit(int lit)
1057		{
1058			d_buf[last_lit] = 0;
1059			l_buf[last_lit++] = (byte)lit;
1060			literalTree.freqs[lit]++;
1061			return IsFull();
1062		}
1063		#endregion
1064
1065		#region TallyDist (Public)
1066		/// <summary>
1067		/// Add distance code and length to literal and distance trees
1068		/// </summary>
1069		/// <param name="dist">Distance code</param>
1070		/// <param name="len">Length</param>
1071		/// <returns>Value indicating if internal buffer is full</returns>
1072		public bool TallyDist(int dist, int len)
1073		{
1074			d_buf[last_lit] = (short)dist;
1075			l_buf[last_lit++] = (byte)(len - 3);
1076
1077			int lc = Lcode(len - 3);
1078			literalTree.freqs[lc]++;
1079			if (lc >= 265 && lc < 285)
1080			{
1081				extra_bits += (lc - 261) / 4;
1082			} // if (lc)
1083
1084			int dc = Dcode(dist - 1);
1085			distTree.freqs[dc]++;
1086			if (dc >= 4)
1087			{
1088				extra_bits += dc / 2 - 1;
1089			} // if (dc)
1090			return IsFull();
1091		}
1092		#endregion
1093
1094		#region Methods (Private)
1095
1096		#region Lcode
1097		/// <summary>
1098		/// Lcode
1099		/// </summary>
1100		/// <param name="len">Len</param>
1101		/// <returns>Int</returns>
1102		private int Lcode(int len)
1103		{
1104			if (len == 255)
1105			{
1106				return 285;
1107			} // if (len)
1108
1109			int code = 257;
1110			while (len >= 8)
1111			{
1112				code += 4;
1113				len >>= 1;
1114			} // while (len)
1115			return code + len;
1116		}
1117		#endregion
1118
1119		// Lcode(len)
1120
1121		#region Dcode
1122		/// <summary>
1123		/// Dcode
1124		/// </summary>
1125		/// <param name="distance">Distance</param>
1126		/// <returns>Int</returns>
1127		private int Dcode(int distance)
1128		{
1129			int code = 0;
1130			while (distance >= 4)
1131			{
1132				code += 2;
1133				distance >>= 1;
1134			} // while (distance)
1135			return code + distance;
1136		}
1137		#endregion
1138
1139		#endregion
1140	}
1141}