private bool FindLongestMatch()

in src/ICSharpCode.SharpZipLib/Zip/Compression/DeflaterEngine.cs [474:612]


		private bool FindLongestMatch(int curMatch)
		{
			int match;
			int scan = strstart;
			// scanMax is the highest position that we can look at
			int scanMax = scan + Math.Min(DeflaterConstants.MAX_MATCH, lookahead) - 1;
			int limit = Math.Max(scan - DeflaterConstants.MAX_DIST, 0);

			byte[] window = this.window;
			short[] prev = this.prev;
			int chainLength = this.max_chain;
			int niceLength = Math.Min(this.niceLength, lookahead);

			matchLen = Math.Max(matchLen, DeflaterConstants.MIN_MATCH - 1);

			if (scan + matchLen > scanMax) return false;

			byte scan_end1 = window[scan + matchLen - 1];
			byte scan_end = window[scan + matchLen];

			// Do not waste too much time if we already have a good match:
			if (matchLen >= this.goodLength) chainLength >>= 2;

			do
			{
				match = curMatch;
				scan = strstart;

				if (window[match + matchLen] != scan_end
				 || window[match + matchLen - 1] != scan_end1
				 || window[match] != window[scan]
				 || window[++match] != window[++scan])
				{
					continue;
				}

				// scan is set to strstart+1 and the comparison passed, so
				// scanMax - scan is the maximum number of bytes we can compare.
				// below we compare 8 bytes at a time, so first we compare
				// (scanMax - scan) % 8 bytes, so the remainder is a multiple of 8

				switch ((scanMax - scan) % 8)
				{
					case 1:
						if (window[++scan] == window[++match]) break;
						break;

					case 2:
						if (window[++scan] == window[++match]
				  && window[++scan] == window[++match]) break;
						break;

					case 3:
						if (window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]) break;
						break;

					case 4:
						if (window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]) break;
						break;

					case 5:
						if (window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]) break;
						break;

					case 6:
						if (window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]) break;
						break;

					case 7:
						if (window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]
				  && window[++scan] == window[++match]) break;
						break;
				}

				if (window[scan] == window[match])
				{
					/* We check for insufficient lookahead only every 8th comparison;
					 * the 256th check will be made at strstart + 258 unless lookahead is
					 * exhausted first.
					 */
					do
					{
						if (scan == scanMax)
						{
							++scan;     // advance to first position not matched
							++match;

							break;
						}
					}
					while (window[++scan] == window[++match]
						&& window[++scan] == window[++match]
						&& window[++scan] == window[++match]
						&& window[++scan] == window[++match]
						&& window[++scan] == window[++match]
						&& window[++scan] == window[++match]
						&& window[++scan] == window[++match]
						&& window[++scan] == window[++match]);
				}

				if (scan - strstart > matchLen)
				{
#if DebugDeflation
              if (DeflaterConstants.DEBUGGING && (ins_h == 0) )
              Console.Error.WriteLine("Found match: " + curMatch + "-" + (scan - strstart));
#endif

					matchStart = curMatch;
					matchLen = scan - strstart;

					if (matchLen >= niceLength)
						break;

					scan_end1 = window[scan - 1];
					scan_end = window[scan];
				}
			} while ((curMatch = (prev[curMatch & DeflaterConstants.WMASK] & 0xffff)) > limit && 0 != --chainLength);

			return matchLen >= DeflaterConstants.MIN_MATCH;
		}