/// <summary> /// Turns the patch list to the patch string /// </summary> /// <param name="list"></param> /// <param name="content"></param> /// <returns></returns> private static string GetStringPatch(IList <UpdatePanelShrinkerPatch> list, string content) { Debug.WriteLine("Patch fragments: " + list.Count); var sb = new StringBuilder(); int contentLength = content.Length; sb.AppendFormat("pat|{0}|", contentLength); for (int i = list.Count - 1; i >= 0; i--) { UpdatePanelShrinkerPatch p = list[i]; sb.AppendFormat("{0}|{1}|{2}|{3}|", p.IndexPrevious, p.LengthPrevious, p.LengthCurrent, (content.Substring(p.IndexCurrent, p.LengthCurrent))); } Debug.Write( string.Format("Shrinkage: from {0} to {1} = {2:P}\r\n", content.Length, sb.Length, ((double)sb.Length) / content.Length)); return(sb.ToString()); }
/// <summary> /// Tries to refine the patch list /// </summary> /// <param name="list"></param> /// <param name="prev"></param> /// <param name="content"></param> /// <returns></returns> private List <UpdatePanelShrinkerPatch> ProcessPatchList(IList <UpdatePanelShrinkerPatch> list, string prev, string content) { var newList = new List <UpdatePanelShrinkerPatch>(); foreach (UpdatePanelShrinkerPatch p in list) { int minLength = Math.Min(p.LengthPrevious, p.LengthCurrent); if (minLength < MinLength) { newList.Add(p); continue; } int searchIndexPrevious = -1; int searchIndexCurrent = 0; int length = SearchLength; for (int c = 0; (c < TryCount) && (searchIndexPrevious == -1); c++) { searchIndexCurrent = _rnd.Next(p.IndexCurrent, p.IndexCurrent + p.LengthCurrent - length); string search = content.Substring(searchIndexCurrent, length); searchIndexPrevious = prev.IndexOf(search, p.IndexPrevious, p.LengthPrevious - length, StringComparison.Ordinal); if (searchIndexPrevious <= -1) { continue; } while (searchIndexCurrent > searchIndexPrevious) { int f2 = prev.IndexOf(search, searchIndexPrevious + 1, Math.Min(2 * (searchIndexCurrent - searchIndexPrevious), p.LengthPrevious - length - (searchIndexPrevious - p.IndexPrevious)), StringComparison.Ordinal); if (f2 > -1) { searchIndexPrevious = f2; } else { break; } } } if (searchIndexPrevious == -1) { newList.Add(p); continue; } int len = Math.Min( Math.Min(p.LengthCurrent, p.LengthPrevious) / 10, Math.Min(p.IndexPrevious + p.LengthPrevious - searchIndexPrevious - length - 1, p.IndexCurrent + p.LengthCurrent - searchIndexCurrent - length - 1)); while (len > 10) { if (len > 0) { while ((searchIndexCurrent + length + len < p.IndexCurrent + p.LengthCurrent) && (searchIndexPrevious + length + len < p.IndexPrevious + p.LengthPrevious) && (string.CompareOrdinal(content, searchIndexCurrent + length, prev, searchIndexPrevious + length, len) == 0)) { length += len; } } len = len / 2; } len = Math.Min( Math.Min(p.LengthCurrent - length, p.LengthPrevious - length) / 10 , Math.Min(searchIndexPrevious - p.IndexPrevious, searchIndexCurrent - p.IndexCurrent) ); while (len > 10) { if (len > 0) { while ((searchIndexCurrent - len > p.IndexCurrent) && (searchIndexPrevious - len > p.IndexPrevious) && (string.CompareOrdinal(content, searchIndexCurrent - len, prev, searchIndexPrevious - len, len) == 0) ) { length += len; searchIndexPrevious -= len; searchIndexCurrent -= len; } } len = len / 2; } var p1 = new UpdatePanelShrinkerPatch(p.IndexPrevious, p.IndexCurrent, searchIndexPrevious - p.IndexPrevious, searchIndexCurrent - p.IndexCurrent); var p2 = new UpdatePanelShrinkerPatch(searchIndexPrevious + length, searchIndexCurrent + length, p.IndexPrevious + p.LengthPrevious - (searchIndexPrevious + length), p.IndexCurrent + p.LengthCurrent - (searchIndexCurrent + length)); if (p1.LengthPrevious + p1.LengthCurrent > 0) { newList.Add(p1); } if (p2.LengthPrevious + p2.LengthCurrent > 0) { newList.Add(p2); } } return(newList); }