public static NPatch Diff(NElement oldE, ref NElement newE) { var oldSet = oldE != null; var newSet = newE != null; if (oldSet == newSet) { if (!oldSet) { return(null); } if (NPatch.ElementEquals(oldE, newE)) { var oldC = oldE as NClass; if (oldC != null) { var newC = (NClass)newE; newE = oldE; return(oldC.Upgrade(newC)); } return(new NPropDiffer(oldE, newE).Diff()); } } return(NPatch.AssignNewValue); }
NPatch Diff() { var cOld = _source.Length; var cNew = _target.Length; if (cOld == 0 || cNew == 0) { return(NPatch.AssignNewValue); } var iOld = 0; var iNew = 0; var iFix = 0; for (;;) { var oldH = iOld < cOld; var oldE = oldH ? _source[iOld] : null; var newH = iNew < cNew; var newE = newH ? _target[iNew] : null; if (oldH) { if (newH && NPatch.ElementEquals(oldE, newE)) { Update(iOld + iFix, newE, oldE); iNew++; } else { Remove(iOld + iFix, oldE); iFix--; } iOld++; } else { if (newH) { Insert(iOld + iFix, newE); iOld++; iNew++; } else { break; } } } Optimize(); TransferClasses(); return(_head != null ? new NListPatch(_head) : null); }
void OptimizeRemove(NListPatchEntry e) { var delta = 0; var oldE = e.Finalizer; var last = e; for (var i = e.Next; i != null; i = i.Next) { switch (i.Op) { case NListPatchOp.Insert: { var newE = i.Value; if (NPatch.ElementEquals(newE, oldE)) { e.Op = NListPatchOp.Move; // transform to move e.Finalizer = null; // remove finalizer e.iInsert = i.iInsert + delta; // correct insert index at the time of move e.iFinal = i.iFinal; // preserve final index e.Patch = NPropDiffer.Diff(oldE, ref newE); // make patch e.Value = oldE; // preserve moved value last.Next = i.Next; // delete insertion return; } delta--; } break; case NListPatchOp.Remove: delta++; break; } last = i; } }