void DiffChildren(RuntimeAttribute a, RuntimeAttribute b, PatchGroup group) { var aChildren = a.Children; var bChildren = b.Children; var aLen = aChildren.Count; var bLen = bChildren.Count; var len = aLen > bLen ? aLen : bLen; var leftIter = aChildren.GetEnumerator(); var rightIter = bChildren.GetEnumerator(); for (int i = 0; i < len; i++) { var leftNode = leftIter.MoveNext() ? leftIter.Current : null; var rightNode = rightIter.MoveNext() ? rightIter.Current : null; if (leftNode == null) { if (rightNode != null) { // Excess nodes in b need to be added group.Append(new PatchOperateInsert(a, rightNode)); //// execute once function //group.Append(new PatchOperateOnceFunc(rightNode, rightNode.template.onceExpressList, rightNode.onceExecuteFunc)); } } else { Walk(leftNode, rightNode); // change it or remove it. } } }
void Walk(RuntimeAttribute a, RuntimeAttribute b) { if (a == b) { return; } var group = new PatchGroup(); if (a != null && a.IsThunk && b != null && b.IsThunk) // diff thunk { // TODO: .... //var patchDiff = Diff(a, b); //if (patchDiff.HasPatch) //{ // group.Append(new PatchOperateThunk(patchDiff)); //} } else if (b == null) { group.Append(new PatchOperateRemove(a)); } else if (a.template.TagName == b.template.TagName && a.template.Key == b.template.Key) { //// diff once function //var needToExecute = DiffOnceExpresstion(a.onceExecuteFunc, b.onceExecuteFunc); //if (needToExecute != null) //{ // group.Append(new PatchOperateOnceFunc(a, needToExecute, b.onceExecuteFunc)); //} // diff properties var propsPatch = DiffProperties(a.attributes, b.attributes); if (propsPatch != null && propsPatch.Count > 0) { group.Append(new PatchOperateProperties(a, propsPatch)); } if (a.textDataBindExpressCurrentValue != b.textDataBindExpressCurrentValue) { group.Append(new PatchOperateText(a, b.textDataBindExpressCurrentValue)); } DiffChildren(a, b, group); } else { group.Append(new PatchOperateChange(a, b)); //// change the a & b //// execute once function //group.Append(new PatchOperateOnceFunc(b, b.template.onceExpressList, b.onceExecuteFunc)); } if (group.HasChange) { groupList.AddLast(group); } }
public static List <PatchGroup> Patches = Reader(); // See Write() for tmp overrides /// <summary> /// Reads PatchGroups from patches.crk to this instance. /// </summary> /// <returns>A list of PatchGroups read from the patches.crk file resource.</returns> /// <remarks>This is only used for Patches list initialization.</remarks> public static List <PatchGroup> Reader() { /* Get patches.crk resource from assembly resources */ /* Read strings from memory to...array? */ var nl = new string[] { "\r\n" }; var byteSep = new string[] { ": ", " " }; var list = new List <PatchGroup>(); var patchGroup = new PatchGroup(); var file = Properties.Resources.patches.Split(nl, StringSplitOptions.RemoveEmptyEntries).ToList(); file.RemoveAt(0); /* Remove comments from list */ { var file2 = new List <string>(); foreach (var line in file) { if (!line.StartsWith(";")) { file2.Add(line); } } file = file2; } /* Add Name, exe, and patch data to list */ for (var index = 0; index < file.Count; index++) { /// If the first char in the line is a letter... */ while (index < file.Count && char.IsLetter(file.ElementAt(index).ToCharArray().First())) { /** ...skip Name and Executable. Go to patch data. */ index += 2; /** Then, if the line is patch data... */ /** ...assign patch name, */ /** ...assign filename, */ /** ...and then read patch data. */ while (index < file.Count && char.IsDigit(file.ElementAt(index).ToCharArray().First())) { patchGroup = new PatchGroup() { DataSets = new List <DataSet>(), Name = file.ElementAt(index - 2), Executable = file.ElementAt(index - 1) }; while (index < file.Count && char.IsDigit(file.ElementAt(index).ToCharArray().First())) { /** Read Patch Data to List, ... * Assign values{offset, original, patch} * proceed to next Patch Data, * then check if line is Patch Data */ List <string> values = file. ElementAt(index).Split(byteSep, StringSplitOptions.RemoveEmptyEntries). ToList(); patchGroup.DataSets.Add(new DataSet { Offset = int.Parse(values[0], System.Globalization.NumberStyles.HexNumber), Original = byte.Parse(values[1], System.Globalization.NumberStyles.HexNumber), Patch = byte.Parse(values[2], System.Globalization.NumberStyles.HexNumber) }); index++; } } list.Add(patchGroup); } } /* Parse the data to members "PatchGroup" of list "Patches" */ /* return list */ return(list); }
/// <exception cref="T:PatchworkLauncher.PatchingProcessException">Cannot patch manifest during the patching process</exception> public static void TryPatchManifest(this AssemblyPatcher patcher, PatchInstruction patch, PatchGroup patchGroup, ProgressObject patchProgress) { try { patcher.PatchManifest(patch.Patch, patchProgress.ToMonitor()); } catch (PatchException patchException) { throw new PatchingProcessException(patchException) { AssociatedInstruction = patch, AssociatedPatchGroup = patchGroup, Step = PatchProcessingStep.ApplyingSpecificPatch }; } }
/// <exception cref="T:PatchworkLauncher.PatchingProcessException">Cannot write to backup to <paramref name="targetFilePath"/> during the patching process</exception> public static void TryBackup(this AssemblyPatcher patcher, string targetFilePath, PatchGroup associatedPatchGroup) { try { patcher.WriteTo(targetFilePath); } catch (Exception exception) { throw new PatchingProcessException(exception) { AssociatedInstruction = null, AssociatedPatchGroup = associatedPatchGroup, Step = PatchProcessingStep.WritingToFile }; } }