| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865 | 
							- using System;
 
- namespace ICSharpCode.SharpZipLib.Zip.Compression
 
- {
 
- 	/// <summary>
 
- 	/// This is the DeflaterHuffman class.
 
- 	/// 
 
- 	/// This class is <i>not</i> thread safe.  This is inherent in the API, due
 
- 	/// to the split of Deflate and SetInput.
 
- 	/// 
 
- 	/// author of the original java version : Jochen Hoenicke
 
- 	/// </summary>
 
- 	public class DeflaterHuffman
 
- 	{
 
- 		const int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6);
 
- 		const int LITERAL_NUM = 286;
 
- 		// Number of distance codes
 
- 		const int DIST_NUM = 30;
 
- 		// Number of codes used to transfer bit lengths
 
- 		const int BITLEN_NUM = 19;
 
- 		// repeat previous bit length 3-6 times (2 bits of repeat count)
 
- 		const int REP_3_6 = 16;
 
- 		// repeat a zero length 3-10 times  (3 bits of repeat count)
 
- 		const int REP_3_10 = 17;
 
- 		// repeat a zero length 11-138 times  (7 bits of repeat count)
 
- 		const int REP_11_138 = 18;
 
- 		const int EOF_SYMBOL = 256;
 
- 		// The lengths of the bit length codes are sent in order of decreasing
 
- 		// probability, to avoid transmitting the lengths for unused bit length codes.
 
- 		static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
 
- 		static readonly byte[] bit4Reverse = {
 
- 			0,
 
- 			8,
 
- 			4,
 
- 			12,
 
- 			2,
 
- 			10,
 
- 			6,
 
- 			14,
 
- 			1,
 
- 			9,
 
- 			5,
 
- 			13,
 
- 			3,
 
- 			11,
 
- 			7,
 
- 			15
 
- 		};
 
- 		static short[] staticLCodes;
 
- 		static byte[] staticLLength;
 
- 		static short[] staticDCodes;
 
- 		static byte[] staticDLength;
 
- 		class Tree
 
- 		{
 
- 			#region Instance Fields
 
- 			public short[] freqs;
 
- 			public byte[] length;
 
- 			public int minNumCodes;
 
- 			public int numCodes;
 
- 			short[] codes;
 
- 			readonly int[] bl_counts;
 
- 			readonly int maxLength;
 
- 			DeflaterHuffman dh;
 
- 			#endregion
 
- 			#region Constructors
 
- 			public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength)
 
- 			{
 
- 				this.dh = dh;
 
- 				this.minNumCodes = minCodes;
 
- 				this.maxLength = maxLength;
 
- 				freqs = new short[elems];
 
- 				bl_counts = new int[maxLength];
 
- 			}
 
- 			#endregion
 
- 			/// <summary>
 
- 			/// Resets the internal state of the tree
 
- 			/// </summary>
 
- 			public void Reset()
 
- 			{
 
- 				for (int i = 0; i < freqs.Length; i++) {
 
- 					freqs[i] = 0;
 
- 				}
 
- 				codes = null;
 
- 				length = null;
 
- 			}
 
- 			public void WriteSymbol(int code)
 
- 			{
 
- 				//				if (DeflaterConstants.DEBUGGING) {
 
- 				//					freqs[code]--;
 
- 				//					//  	  Console.Write("writeSymbol("+freqs.length+","+code+"): ");
 
- 				//				}
 
- 				dh.pending.WriteBits(codes[code] & 0xffff, length[code]);
 
- 			}
 
- 			/// <summary>
 
- 			/// Check that all frequencies are zero
 
- 			/// </summary>
 
- 			/// <exception cref="SharpZipBaseException">
 
- 			/// At least one frequency is non-zero
 
- 			/// </exception>
 
- 			public void CheckEmpty()
 
- 			{
 
- 				bool empty = true;
 
- 				for (int i = 0; i < freqs.Length; i++) {
 
- 					empty &= freqs[i] == 0;
 
- 				}
 
- 				if (!empty) {
 
- 					throw new SharpZipBaseException("!Empty");
 
- 				}
 
- 			}
 
- 			/// <summary>
 
- 			/// Set static codes and length
 
- 			/// </summary>
 
- 			/// <param name="staticCodes">new codes</param>
 
- 			/// <param name="staticLengths">length for new codes</param>
 
- 			public void SetStaticCodes(short[] staticCodes, byte[] staticLengths)
 
- 			{
 
- 				codes = staticCodes;
 
- 				length = staticLengths;
 
- 			}
 
- 			/// <summary>
 
- 			/// Build dynamic codes and lengths
 
- 			/// </summary>
 
- 			public void BuildCodes()
 
- 			{
 
- 				int numSymbols = freqs.Length;
 
- 				int[] nextCode = new int[maxLength];
 
- 				int code = 0;
 
- 				codes = new short[freqs.Length];
 
- 				//				if (DeflaterConstants.DEBUGGING) {
 
- 				//					//Console.WriteLine("buildCodes: "+freqs.Length);
 
- 				//				}
 
- 				for (int bits = 0; bits < maxLength; bits++) {
 
- 					nextCode[bits] = code;
 
- 					code += bl_counts[bits] << (15 - bits);
 
- 					//					if (DeflaterConstants.DEBUGGING) {
 
- 					//						//Console.WriteLine("bits: " + ( bits + 1) + " count: " + bl_counts[bits]
 
- 					//						                  +" nextCode: "+code);
 
- 					//					}
 
- 				}
 
- #if DebugDeflation
 
- 				if ( DeflaterConstants.DEBUGGING && (code != 65536) ) 
 
- 				{
 
- 					throw new SharpZipBaseException("Inconsistent bl_counts!");
 
- 				}
 
- #endif
 
- 				for (int i = 0; i < numCodes; i++) {
 
- 					int bits = length[i];
 
- 					if (bits > 0) {
 
- 						//						if (DeflaterConstants.DEBUGGING) {
 
- 						//								//Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+"),
 
- 						//								                  +bits);
 
- 						//						}
 
- 						codes[i] = BitReverse(nextCode[bits - 1]);
 
- 						nextCode[bits - 1] += 1 << (16 - bits);
 
- 					}
 
- 				}
 
- 			}
 
- 			public void BuildTree()
 
- 			{
 
- 				int numSymbols = freqs.Length;
 
- 				/* heap is a priority queue, sorted by frequency, least frequent
 
- 				* nodes first.  The heap is a binary tree, with the property, that
 
- 				* the parent node is smaller than both child nodes.  This assures
 
- 				* that the smallest node is the first parent.
 
- 				*
 
- 				* The binary tree is encoded in an array:  0 is root node and
 
- 				* the nodes 2*n+1, 2*n+2 are the child nodes of node n.
 
- 				*/
 
- 				int[] heap = new int[numSymbols];
 
- 				int heapLen = 0;
 
- 				int maxCode = 0;
 
- 				for (int n = 0; n < numSymbols; n++) {
 
- 					int freq = freqs[n];
 
- 					if (freq != 0) {
 
- 						// Insert n into heap
 
- 						int pos = heapLen++;
 
- 						int ppos;
 
- 						while (pos > 0 && freqs[heap[ppos = (pos - 1) / 2]] > freq) {
 
- 							heap[pos] = heap[ppos];
 
- 							pos = ppos;
 
- 						}
 
- 						heap[pos] = n;
 
- 						maxCode = n;
 
- 					}
 
- 				}
 
- 				/* We could encode a single literal with 0 bits but then we
 
- 				* don't see the literals.  Therefore we force at least two
 
- 				* literals to avoid this case.  We don't care about order in
 
- 				* this case, both literals get a 1 bit code.
 
- 				*/
 
- 				while (heapLen < 2) {
 
- 					int node = maxCode < 2 ? ++maxCode : 0;
 
- 					heap[heapLen++] = node;
 
- 				}
 
- 				numCodes = Math.Max(maxCode + 1, minNumCodes);
 
- 				int numLeafs = heapLen;
 
- 				int[] childs = new int[4 * heapLen - 2];
 
- 				int[] values = new int[2 * heapLen - 1];
 
- 				int numNodes = numLeafs;
 
- 				for (int i = 0; i < heapLen; i++) {
 
- 					int node = heap[i];
 
- 					childs[2 * i] = node;
 
- 					childs[2 * i + 1] = -1;
 
- 					values[i] = freqs[node] << 8;
 
- 					heap[i] = i;
 
- 				}
 
- 				/* Construct the Huffman tree by repeatedly combining the least two
 
- 				* frequent nodes.
 
- 				*/
 
- 				do {
 
- 					int first = heap[0];
 
- 					int last = heap[--heapLen];
 
- 					// Propagate the hole to the leafs of the heap
 
- 					int ppos = 0;
 
- 					int path = 1;
 
- 					while (path < heapLen) {
 
- 						if (path + 1 < heapLen && values[heap[path]] > values[heap[path + 1]]) {
 
- 							path++;
 
- 						}
 
- 						heap[ppos] = heap[path];
 
- 						ppos = path;
 
- 						path = path * 2 + 1;
 
- 					}
 
- 					/* Now propagate the last element down along path.  Normally
 
- 					* it shouldn't go too deep.
 
- 					*/
 
- 					int lastVal = values[last];
 
- 					while ((path = ppos) > 0 && values[heap[ppos = (path - 1) / 2]] > lastVal) {
 
- 						heap[path] = heap[ppos];
 
- 					}
 
- 					heap[path] = last;
 
- 					int second = heap[0];
 
- 					// Create a new node father of first and second
 
- 					last = numNodes++;
 
- 					childs[2 * last] = first;
 
- 					childs[2 * last + 1] = second;
 
- 					int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff);
 
- 					values[last] = lastVal = values[first] + values[second] - mindepth + 1;
 
- 					// Again, propagate the hole to the leafs
 
- 					ppos = 0;
 
- 					path = 1;
 
- 					while (path < heapLen) {
 
- 						if (path + 1 < heapLen && values[heap[path]] > values[heap[path + 1]]) {
 
- 							path++;
 
- 						}
 
- 						heap[ppos] = heap[path];
 
- 						ppos = path;
 
- 						path = ppos * 2 + 1;
 
- 					}
 
- 					// Now propagate the new element down along path
 
- 					while ((path = ppos) > 0 && values[heap[ppos = (path - 1) / 2]] > lastVal) {
 
- 						heap[path] = heap[ppos];
 
- 					}
 
- 					heap[path] = last;
 
- 				} while (heapLen > 1);
 
- 				if (heap[0] != childs.Length / 2 - 1) {
 
- 					throw new SharpZipBaseException("Heap invariant violated");
 
- 				}
 
- 				BuildLength(childs);
 
- 			}
 
- 			/// <summary>
 
- 			/// Get encoded length
 
- 			/// </summary>
 
- 			/// <returns>Encoded length, the sum of frequencies * lengths</returns>
 
- 			public int GetEncodedLength()
 
- 			{
 
- 				int len = 0;
 
- 				for (int i = 0; i < freqs.Length; i++) {
 
- 					len += freqs[i] * length[i];
 
- 				}
 
- 				return len;
 
- 			}
 
- 			/// <summary>
 
- 			/// Scan a literal or distance tree to determine the frequencies of the codes
 
- 			/// in the bit length tree.
 
- 			/// </summary>
 
- 			public void CalcBLFreq(Tree blTree)
 
- 			{
 
- 				int max_count;               /* max repeat count */
 
- 				int min_count;               /* min repeat count */
 
- 				int count;                   /* repeat count of the current code */
 
- 				int curlen = -1;             /* length of current code */
 
- 				int i = 0;
 
- 				while (i < numCodes) {
 
- 					count = 1;
 
- 					int nextlen = length[i];
 
- 					if (nextlen == 0) {
 
- 						max_count = 138;
 
- 						min_count = 3;
 
- 					} else {
 
- 						max_count = 6;
 
- 						min_count = 3;
 
- 						if (curlen != nextlen) {
 
- 							blTree.freqs[nextlen]++;
 
- 							count = 0;
 
- 						}
 
- 					}
 
- 					curlen = nextlen;
 
- 					i++;
 
- 					while (i < numCodes && curlen == length[i]) {
 
- 						i++;
 
- 						if (++count >= max_count) {
 
- 							break;
 
- 						}
 
- 					}
 
- 					if (count < min_count) {
 
- 						blTree.freqs[curlen] += (short)count;
 
- 					} else if (curlen != 0) {
 
- 						blTree.freqs[REP_3_6]++;
 
- 					} else if (count <= 10) {
 
- 						blTree.freqs[REP_3_10]++;
 
- 					} else {
 
- 						blTree.freqs[REP_11_138]++;
 
- 					}
 
- 				}
 
- 			}
 
- 			/// <summary>
 
- 			/// Write tree values
 
- 			/// </summary>
 
- 			/// <param name="blTree">Tree to write</param>
 
- 			public void WriteTree(Tree blTree)
 
- 			{
 
- 				int max_count;               // max repeat count
 
- 				int min_count;               // min repeat count
 
- 				int count;                   // repeat count of the current code
 
- 				int curlen = -1;             // length of current code
 
- 				int i = 0;
 
- 				while (i < numCodes) {
 
- 					count = 1;
 
- 					int nextlen = length[i];
 
- 					if (nextlen == 0) {
 
- 						max_count = 138;
 
- 						min_count = 3;
 
- 					} else {
 
- 						max_count = 6;
 
- 						min_count = 3;
 
- 						if (curlen != nextlen) {
 
- 							blTree.WriteSymbol(nextlen);
 
- 							count = 0;
 
- 						}
 
- 					}
 
- 					curlen = nextlen;
 
- 					i++;
 
- 					while (i < numCodes && curlen == length[i]) {
 
- 						i++;
 
- 						if (++count >= max_count) {
 
- 							break;
 
- 						}
 
- 					}
 
- 					if (count < min_count) {
 
- 						while (count-- > 0) {
 
- 							blTree.WriteSymbol(curlen);
 
- 						}
 
- 					} else if (curlen != 0) {
 
- 						blTree.WriteSymbol(REP_3_6);
 
- 						dh.pending.WriteBits(count - 3, 2);
 
- 					} else if (count <= 10) {
 
- 						blTree.WriteSymbol(REP_3_10);
 
- 						dh.pending.WriteBits(count - 3, 3);
 
- 					} else {
 
- 						blTree.WriteSymbol(REP_11_138);
 
- 						dh.pending.WriteBits(count - 11, 7);
 
- 					}
 
- 				}
 
- 			}
 
- 			void BuildLength(int[] childs)
 
- 			{
 
- 				this.length = new byte[freqs.Length];
 
- 				int numNodes = childs.Length / 2;
 
- 				int numLeafs = (numNodes + 1) / 2;
 
- 				int overflow = 0;
 
- 				for (int i = 0; i < maxLength; i++) {
 
- 					bl_counts[i] = 0;
 
- 				}
 
- 				// First calculate optimal bit lengths
 
- 				int[] lengths = new int[numNodes];
 
- 				lengths[numNodes - 1] = 0;
 
- 				for (int i = numNodes - 1; i >= 0; i--) {
 
- 					if (childs[2 * i + 1] != -1) {
 
- 						int bitLength = lengths[i] + 1;
 
- 						if (bitLength > maxLength) {
 
- 							bitLength = maxLength;
 
- 							overflow++;
 
- 						}
 
- 						lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength;
 
- 					} else {
 
- 						// A leaf node
 
- 						int bitLength = lengths[i];
 
- 						bl_counts[bitLength - 1]++;
 
- 						this.length[childs[2 * i]] = (byte)lengths[i];
 
- 					}
 
- 				}
 
- 				//				if (DeflaterConstants.DEBUGGING) {
 
- 				//					//Console.WriteLine("Tree "+freqs.Length+" lengths:");
 
- 				//					for (int i=0; i < numLeafs; i++) {
 
- 				//						//Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
 
- 				//						                  + " len: "+length[childs[2*i]]);
 
- 				//					}
 
- 				//				}
 
- 				if (overflow == 0) {
 
- 					return;
 
- 				}
 
- 				int incrBitLen = maxLength - 1;
 
- 				do {
 
- 					// Find the first bit length which could increase:
 
- 					while (bl_counts[--incrBitLen] == 0) {
 
- 					}
 
- 					// Move this node one down and remove a corresponding
 
- 					// number of overflow nodes.
 
- 					do {
 
- 						bl_counts[incrBitLen]--;
 
- 						bl_counts[++incrBitLen]++;
 
- 						overflow -= 1 << (maxLength - 1 - incrBitLen);
 
- 					} while (overflow > 0 && incrBitLen < maxLength - 1);
 
- 				} while (overflow > 0);
 
- 				/* We may have overshot above.  Move some nodes from maxLength to
 
- 				* maxLength-1 in that case.
 
- 				*/
 
- 				bl_counts[maxLength - 1] += overflow;
 
- 				bl_counts[maxLength - 2] -= overflow;
 
- 				/* Now recompute all bit lengths, scanning in increasing
 
- 				* frequency.  It is simpler to reconstruct all lengths instead of
 
- 				* fixing only the wrong ones. This idea is taken from 'ar'
 
- 				* written by Haruhiko Okumura.
 
- 				*
 
- 				* The nodes were inserted with decreasing frequency into the childs
 
- 				* array.
 
- 				*/
 
- 				int nodePtr = 2 * numLeafs;
 
- 				for (int bits = maxLength; bits != 0; bits--) {
 
- 					int n = bl_counts[bits - 1];
 
- 					while (n > 0) {
 
- 						int childPtr = 2 * childs[nodePtr++];
 
- 						if (childs[childPtr + 1] == -1) {
 
- 							// We found another leaf
 
- 							length[childs[childPtr]] = (byte)bits;
 
- 							n--;
 
- 						}
 
- 					}
 
- 				}
 
- 				//				if (DeflaterConstants.DEBUGGING) {
 
- 				//					//Console.WriteLine("*** After overflow elimination. ***");
 
- 				//					for (int i=0; i < numLeafs; i++) {
 
- 				//						//Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
 
- 				//						                  + " len: "+length[childs[2*i]]);
 
- 				//					}
 
- 				//				}
 
- 			}
 
- 		}
 
- 		#region Instance Fields
 
- 		/// <summary>
 
- 		/// Pending buffer to use
 
- 		/// </summary>
 
- 		public DeflaterPending pending;
 
- 		Tree literalTree;
 
- 		Tree distTree;
 
- 		Tree blTree;
 
- 		// Buffer for distances
 
- 		short[] d_buf;
 
- 		byte[] l_buf;
 
- 		int last_lit;
 
- 		int extra_bits;
 
- 		#endregion
 
- 		static DeflaterHuffman()
 
- 		{
 
- 			// See RFC 1951 3.2.6
 
- 			// Literal codes
 
- 			staticLCodes = new short[LITERAL_NUM];
 
- 			staticLLength = new byte[LITERAL_NUM];
 
- 			int i = 0;
 
- 			while (i < 144) {
 
- 				staticLCodes[i] = BitReverse((0x030 + i) << 8);
 
- 				staticLLength[i++] = 8;
 
- 			}
 
- 			while (i < 256) {
 
- 				staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7);
 
- 				staticLLength[i++] = 9;
 
- 			}
 
- 			while (i < 280) {
 
- 				staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9);
 
- 				staticLLength[i++] = 7;
 
- 			}
 
- 			while (i < LITERAL_NUM) {
 
- 				staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8);
 
- 				staticLLength[i++] = 8;
 
- 			}
 
- 			// Distance codes
 
- 			staticDCodes = new short[DIST_NUM];
 
- 			staticDLength = new byte[DIST_NUM];
 
- 			for (i = 0; i < DIST_NUM; i++) {
 
- 				staticDCodes[i] = BitReverse(i << 11);
 
- 				staticDLength[i] = 5;
 
- 			}
 
- 		}
 
- 		/// <summary>
 
- 		/// Construct instance with pending buffer
 
- 		/// </summary>
 
- 		/// <param name="pending">Pending buffer to use</param>
 
- 		public DeflaterHuffman(DeflaterPending pending)
 
- 		{
 
- 			this.pending = pending;
 
- 			literalTree = new Tree(this, LITERAL_NUM, 257, 15);
 
- 			distTree = new Tree(this, DIST_NUM, 1, 15);
 
- 			blTree = new Tree(this, BITLEN_NUM, 4, 7);
 
- 			d_buf = new short[BUFSIZE];
 
- 			l_buf = new byte[BUFSIZE];
 
- 		}
 
- 		/// <summary>
 
- 		/// Reset internal state
 
- 		/// </summary>		
 
- 		public void Reset()
 
- 		{
 
- 			last_lit = 0;
 
- 			extra_bits = 0;
 
- 			literalTree.Reset();
 
- 			distTree.Reset();
 
- 			blTree.Reset();
 
- 		}
 
- 		/// <summary>
 
- 		/// Write all trees to pending buffer
 
- 		/// </summary>
 
- 		/// <param name="blTreeCodes">The number/rank of treecodes to send.</param>
 
- 		public void SendAllTrees(int blTreeCodes)
 
- 		{
 
- 			blTree.BuildCodes();
 
- 			literalTree.BuildCodes();
 
- 			distTree.BuildCodes();
 
- 			pending.WriteBits(literalTree.numCodes - 257, 5);
 
- 			pending.WriteBits(distTree.numCodes - 1, 5);
 
- 			pending.WriteBits(blTreeCodes - 4, 4);
 
- 			for (int rank = 0; rank < blTreeCodes; rank++) {
 
- 				pending.WriteBits(blTree.length[BL_ORDER[rank]], 3);
 
- 			}
 
- 			literalTree.WriteTree(blTree);
 
- 			distTree.WriteTree(blTree);
 
- #if DebugDeflation
 
- 			if (DeflaterConstants.DEBUGGING) {
 
- 				blTree.CheckEmpty();
 
- 			}
 
- #endif
 
- 		}
 
- 		/// <summary>
 
- 		/// Compress current buffer writing data to pending buffer
 
- 		/// </summary>
 
- 		public void CompressBlock()
 
- 		{
 
- 			for (int i = 0; i < last_lit; i++) {
 
- 				int litlen = l_buf[i] & 0xff;
 
- 				int dist = d_buf[i];
 
- 				if (dist-- != 0) {
 
- 					//					if (DeflaterConstants.DEBUGGING) {
 
- 					//						Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");
 
- 					//					}
 
- 					int lc = Lcode(litlen);
 
- 					literalTree.WriteSymbol(lc);
 
- 					int bits = (lc - 261) / 4;
 
- 					if (bits > 0 && bits <= 5) {
 
- 						pending.WriteBits(litlen & ((1 << bits) - 1), bits);
 
- 					}
 
- 					int dc = Dcode(dist);
 
- 					distTree.WriteSymbol(dc);
 
- 					bits = dc / 2 - 1;
 
- 					if (bits > 0) {
 
- 						pending.WriteBits(dist & ((1 << bits) - 1), bits);
 
- 					}
 
- 				} else {
 
- 					//					if (DeflaterConstants.DEBUGGING) {
 
- 					//						if (litlen > 32 && litlen < 127) {
 
- 					//							Console.Write("("+(char)litlen+"): ");
 
- 					//						} else {
 
- 					//							Console.Write("{"+litlen+"}: ");
 
- 					//						}
 
- 					//					}
 
- 					literalTree.WriteSymbol(litlen);
 
- 				}
 
- 			}
 
- #if DebugDeflation
 
- 			if (DeflaterConstants.DEBUGGING) {
 
- 				Console.Write("EOF: ");
 
- 			}
 
- #endif
 
- 			literalTree.WriteSymbol(EOF_SYMBOL);
 
- #if DebugDeflation
 
- 			if (DeflaterConstants.DEBUGGING) {
 
- 				literalTree.CheckEmpty();
 
- 				distTree.CheckEmpty();
 
- 			}
 
- #endif
 
- 		}
 
- 		/// <summary>
 
- 		/// Flush block to output with no compression
 
- 		/// </summary>
 
- 		/// <param name="stored">Data to write</param>
 
- 		/// <param name="storedOffset">Index of first byte to write</param>
 
- 		/// <param name="storedLength">Count of bytes to write</param>
 
- 		/// <param name="lastBlock">True if this is the last block</param>
 
- 		public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
 
- 		{
 
- #if DebugDeflation
 
- 			//			if (DeflaterConstants.DEBUGGING) {
 
- 			//				//Console.WriteLine("Flushing stored block "+ storedLength);
 
- 			//			}
 
- #endif
 
- 			pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3);
 
- 			pending.AlignToByte();
 
- 			pending.WriteShort(storedLength);
 
- 			pending.WriteShort(~storedLength);
 
- 			pending.WriteBlock(stored, storedOffset, storedLength);
 
- 			Reset();
 
- 		}
 
- 		/// <summary>
 
- 		/// Flush block to output with compression
 
- 		/// </summary>		
 
- 		/// <param name="stored">Data to flush</param>
 
- 		/// <param name="storedOffset">Index of first byte to flush</param>
 
- 		/// <param name="storedLength">Count of bytes to flush</param>
 
- 		/// <param name="lastBlock">True if this is the last block</param>
 
- 		public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
 
- 		{
 
- 			literalTree.freqs[EOF_SYMBOL]++;
 
- 			// Build trees
 
- 			literalTree.BuildTree();
 
- 			distTree.BuildTree();
 
- 			// Calculate bitlen frequency
 
- 			literalTree.CalcBLFreq(blTree);
 
- 			distTree.CalcBLFreq(blTree);
 
- 			// Build bitlen tree
 
- 			blTree.BuildTree();
 
- 			int blTreeCodes = 4;
 
- 			for (int i = 18; i > blTreeCodes; i--) {
 
- 				if (blTree.length[BL_ORDER[i]] > 0) {
 
- 					blTreeCodes = i + 1;
 
- 				}
 
- 			}
 
- 			int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() +
 
- 				literalTree.GetEncodedLength() + distTree.GetEncodedLength() +
 
- 				extra_bits;
 
- 			int static_len = extra_bits;
 
- 			for (int i = 0; i < LITERAL_NUM; i++) {
 
- 				static_len += literalTree.freqs[i] * staticLLength[i];
 
- 			}
 
- 			for (int i = 0; i < DIST_NUM; i++) {
 
- 				static_len += distTree.freqs[i] * staticDLength[i];
 
- 			}
 
- 			if (opt_len >= static_len) {
 
- 				// Force static trees
 
- 				opt_len = static_len;
 
- 			}
 
- 			if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3) {
 
- 				// Store Block
 
- 				//				if (DeflaterConstants.DEBUGGING) {
 
- 				//					//Console.WriteLine("Storing, since " + storedLength + " < " + opt_len
 
- 				//					                  + " <= " + static_len);
 
- 				//				}
 
- 				FlushStoredBlock(stored, storedOffset, storedLength, lastBlock);
 
- 			} else if (opt_len == static_len) {
 
- 				// Encode with static tree
 
- 				pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3);
 
- 				literalTree.SetStaticCodes(staticLCodes, staticLLength);
 
- 				distTree.SetStaticCodes(staticDCodes, staticDLength);
 
- 				CompressBlock();
 
- 				Reset();
 
- 			} else {
 
- 				// Encode with dynamic tree
 
- 				pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3);
 
- 				SendAllTrees(blTreeCodes);
 
- 				CompressBlock();
 
- 				Reset();
 
- 			}
 
- 		}
 
- 		/// <summary>
 
- 		/// Get value indicating if internal buffer is full
 
- 		/// </summary>
 
- 		/// <returns>true if buffer is full</returns>
 
- 		public bool IsFull()
 
- 		{
 
- 			return last_lit >= BUFSIZE;
 
- 		}
 
- 		/// <summary>
 
- 		/// Add literal to buffer
 
- 		/// </summary>
 
- 		/// <param name="literal">Literal value to add to buffer.</param>
 
- 		/// <returns>Value indicating internal buffer is full</returns>
 
- 		public bool TallyLit(int literal)
 
- 		{
 
- 			//			if (DeflaterConstants.DEBUGGING) {
 
- 			//				if (lit > 32 && lit < 127) {
 
- 			//					//Console.WriteLine("("+(char)lit+")");
 
- 			//				} else {
 
- 			//					//Console.WriteLine("{"+lit+"}");
 
- 			//				}
 
- 			//			}
 
- 			d_buf[last_lit] = 0;
 
- 			l_buf[last_lit++] = (byte)literal;
 
- 			literalTree.freqs[literal]++;
 
- 			return IsFull();
 
- 		}
 
- 		/// <summary>
 
- 		/// Add distance code and length to literal and distance trees
 
- 		/// </summary>
 
- 		/// <param name="distance">Distance code</param>
 
- 		/// <param name="length">Length</param>
 
- 		/// <returns>Value indicating if internal buffer is full</returns>
 
- 		public bool TallyDist(int distance, int length)
 
- 		{
 
- 			//			if (DeflaterConstants.DEBUGGING) {
 
- 			//				//Console.WriteLine("[" + distance + "," + length + "]");
 
- 			//			}
 
- 			d_buf[last_lit] = (short)distance;
 
- 			l_buf[last_lit++] = (byte)(length - 3);
 
- 			int lc = Lcode(length - 3);
 
- 			literalTree.freqs[lc]++;
 
- 			if (lc >= 265 && lc < 285) {
 
- 				extra_bits += (lc - 261) / 4;
 
- 			}
 
- 			int dc = Dcode(distance - 1);
 
- 			distTree.freqs[dc]++;
 
- 			if (dc >= 4) {
 
- 				extra_bits += dc / 2 - 1;
 
- 			}
 
- 			return IsFull();
 
- 		}
 
- 		/// <summary>
 
- 		/// Reverse the bits of a 16 bit value.
 
- 		/// </summary>
 
- 		/// <param name="toReverse">Value to reverse bits</param>
 
- 		/// <returns>Value with bits reversed</returns>
 
- 		public static short BitReverse(int toReverse)
 
- 		{
 
- 			return (short)(bit4Reverse[toReverse & 0xF] << 12 |
 
- 							bit4Reverse[(toReverse >> 4) & 0xF] << 8 |
 
- 							bit4Reverse[(toReverse >> 8) & 0xF] << 4 |
 
- 							bit4Reverse[toReverse >> 12]);
 
- 		}
 
- 		static int Lcode(int length)
 
- 		{
 
- 			if (length == 255) {
 
- 				return 285;
 
- 			}
 
- 			int code = 257;
 
- 			while (length >= 8) {
 
- 				code += 4;
 
- 				length >>= 1;
 
- 			}
 
- 			return code + length;
 
- 		}
 
- 		static int Dcode(int distance)
 
- 		{
 
- 			int code = 0;
 
- 			while (distance >= 4) {
 
- 				code += 2;
 
- 				distance >>= 1;
 
- 			}
 
- 			return code + distance;
 
- 		}
 
- 	}
 
- }
 
 
  |