| |
| |
| |
| |
| |
| 'use strict'; |
| exports.__esModule = true; |
| |
| |
| |
| var DiffChange = (function() { |
| |
| |
| |
| |
| function DiffChange( |
| originalStart, |
| originalLength, |
| modifiedStart, |
| modifiedLength |
| ) { |
| |
| this.originalStart = originalStart; |
| this.originalLength = originalLength; |
| this.modifiedStart = modifiedStart; |
| this.modifiedLength = modifiedLength; |
| } |
| |
| |
| |
| DiffChange.prototype.getOriginalEnd = function() { |
| return this.originalStart + this.originalLength; |
| }; |
| |
| |
| |
| DiffChange.prototype.getModifiedEnd = function() { |
| return this.modifiedStart + this.modifiedLength; |
| }; |
| return DiffChange; |
| })(); |
| function createStringSequence(a) { |
| return { |
| getLength: function() { |
| return a.length; |
| }, |
| getElementAtIndex: function(pos) { |
| return a.charCodeAt(pos); |
| }, |
| }; |
| } |
| function stringDiff(original, modified, pretty) { |
| return new LcsDiff( |
| createStringSequence(original), |
| createStringSequence(modified) |
| ).ComputeDiff(pretty); |
| } |
| exports.stringDiff = stringDiff; |
| |
| |
| |
| var Debug = (function() { |
| function Debug() {} |
| Debug.Assert = function(condition, message) { |
| if (!condition) { |
| throw new Error(message); |
| } |
| }; |
| return Debug; |
| })(); |
| exports.Debug = Debug; |
| var MyArray = (function() { |
| function MyArray() {} |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| MyArray.Copy = function( |
| sourceArray, |
| sourceIndex, |
| destinationArray, |
| destinationIndex, |
| length |
| ) { |
| for (var i = 0; i < length; i++) { |
| destinationArray[destinationIndex + i] = sourceArray[sourceIndex + i]; |
| } |
| }; |
| return MyArray; |
| })(); |
| exports.MyArray = MyArray; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var MaxDifferencesHistory = 1447; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var DiffChangeHelper = (function() { |
| |
| |
| |
| function DiffChangeHelper() { |
| this.m_changes = []; |
| this.m_originalStart = Number.MAX_VALUE; |
| this.m_modifiedStart = Number.MAX_VALUE; |
| this.m_originalCount = 0; |
| this.m_modifiedCount = 0; |
| } |
| |
| |
| |
| DiffChangeHelper.prototype.MarkNextChange = function() { |
| |
| if (this.m_originalCount > 0 || this.m_modifiedCount > 0) { |
| |
| this.m_changes.push( |
| new DiffChange( |
| this.m_originalStart, |
| this.m_originalCount, |
| this.m_modifiedStart, |
| this.m_modifiedCount |
| ) |
| ); |
| } |
| |
| this.m_originalCount = 0; |
| this.m_modifiedCount = 0; |
| this.m_originalStart = Number.MAX_VALUE; |
| this.m_modifiedStart = Number.MAX_VALUE; |
| }; |
| |
| |
| |
| |
| |
| |
| |
| DiffChangeHelper.prototype.AddOriginalElement = function( |
| originalIndex, |
| modifiedIndex |
| ) { |
| |
| this.m_originalStart = Math.min(this.m_originalStart, originalIndex); |
| this.m_modifiedStart = Math.min(this.m_modifiedStart, modifiedIndex); |
| this.m_originalCount++; |
| }; |
| |
| |
| |
| |
| |
| |
| |
| DiffChangeHelper.prototype.AddModifiedElement = function( |
| originalIndex, |
| modifiedIndex |
| ) { |
| |
| this.m_originalStart = Math.min(this.m_originalStart, originalIndex); |
| this.m_modifiedStart = Math.min(this.m_modifiedStart, modifiedIndex); |
| this.m_modifiedCount++; |
| }; |
| |
| |
| |
| DiffChangeHelper.prototype.getChanges = function() { |
| if (this.m_originalCount > 0 || this.m_modifiedCount > 0) { |
| |
| this.MarkNextChange(); |
| } |
| return this.m_changes; |
| }; |
| |
| |
| |
| DiffChangeHelper.prototype.getReverseChanges = function() { |
| if (this.m_originalCount > 0 || this.m_modifiedCount > 0) { |
| |
| this.MarkNextChange(); |
| } |
| this.m_changes.reverse(); |
| return this.m_changes; |
| }; |
| return DiffChangeHelper; |
| })(); |
| |
| |
| |
| |
| var LcsDiff = (function() { |
| |
| |
| |
| function LcsDiff(originalSequence, newSequence, continueProcessingPredicate) { |
| if (continueProcessingPredicate === void 0) { |
| continueProcessingPredicate = null; |
| } |
| this.OriginalSequence = originalSequence; |
| this.ModifiedSequence = newSequence; |
| this.ContinueProcessingPredicate = continueProcessingPredicate; |
| this.m_forwardHistory = []; |
| this.m_reverseHistory = []; |
| } |
| LcsDiff.prototype.ElementsAreEqual = function(originalIndex, newIndex) { |
| return ( |
| this.OriginalSequence.getElementAtIndex(originalIndex) === |
| this.ModifiedSequence.getElementAtIndex(newIndex) |
| ); |
| }; |
| LcsDiff.prototype.OriginalElementsAreEqual = function(index1, index2) { |
| return ( |
| this.OriginalSequence.getElementAtIndex(index1) === |
| this.OriginalSequence.getElementAtIndex(index2) |
| ); |
| }; |
| LcsDiff.prototype.ModifiedElementsAreEqual = function(index1, index2) { |
| return ( |
| this.ModifiedSequence.getElementAtIndex(index1) === |
| this.ModifiedSequence.getElementAtIndex(index2) |
| ); |
| }; |
| LcsDiff.prototype.ComputeDiff = function(pretty) { |
| return this._ComputeDiff( |
| 0, |
| this.OriginalSequence.getLength() - 1, |
| 0, |
| this.ModifiedSequence.getLength() - 1, |
| pretty |
| ); |
| }; |
| |
| |
| |
| |
| |
| LcsDiff.prototype._ComputeDiff = function( |
| originalStart, |
| originalEnd, |
| modifiedStart, |
| modifiedEnd, |
| pretty |
| ) { |
| var quitEarlyArr = [false]; |
| var changes = this.ComputeDiffRecursive( |
| originalStart, |
| originalEnd, |
| modifiedStart, |
| modifiedEnd, |
| quitEarlyArr |
| ); |
| if (pretty) { |
| |
| |
| |
| return this.ShiftChanges(changes); |
| } |
| return changes; |
| }; |
| |
| |
| |
| |
| |
| LcsDiff.prototype.ComputeDiffRecursive = function( |
| originalStart, |
| originalEnd, |
| modifiedStart, |
| modifiedEnd, |
| quitEarlyArr |
| ) { |
| quitEarlyArr[0] = false; |
| |
| while ( |
| originalStart <= originalEnd && |
| modifiedStart <= modifiedEnd && |
| this.ElementsAreEqual(originalStart, modifiedStart) |
| ) { |
| originalStart++; |
| modifiedStart++; |
| } |
| |
| while ( |
| originalEnd >= originalStart && |
| modifiedEnd >= modifiedStart && |
| this.ElementsAreEqual(originalEnd, modifiedEnd) |
| ) { |
| originalEnd--; |
| modifiedEnd--; |
| } |
| |
| if (originalStart > originalEnd || modifiedStart > modifiedEnd) { |
| var changes = void 0; |
| if (modifiedStart <= modifiedEnd) { |
| Debug.Assert( |
| originalStart === originalEnd + 1, |
| 'originalStart should only be one more than originalEnd' |
| ); |
| |
| changes = [ |
| new DiffChange( |
| originalStart, |
| 0, |
| modifiedStart, |
| modifiedEnd - modifiedStart + 1 |
| ), |
| ]; |
| } else if (originalStart <= originalEnd) { |
| Debug.Assert( |
| modifiedStart === modifiedEnd + 1, |
| 'modifiedStart should only be one more than modifiedEnd' |
| ); |
| |
| changes = [ |
| new DiffChange( |
| originalStart, |
| originalEnd - originalStart + 1, |
| modifiedStart, |
| 0 |
| ), |
| ]; |
| } else { |
| Debug.Assert( |
| originalStart === originalEnd + 1, |
| 'originalStart should only be one more than originalEnd' |
| ); |
| Debug.Assert( |
| modifiedStart === modifiedEnd + 1, |
| 'modifiedStart should only be one more than modifiedEnd' |
| ); |
| |
| changes = []; |
| } |
| return changes; |
| } |
| |
| var midOriginalArr = [0], |
| midModifiedArr = [0]; |
| var result = this.ComputeRecursionPoint( |
| originalStart, |
| originalEnd, |
| modifiedStart, |
| modifiedEnd, |
| midOriginalArr, |
| midModifiedArr, |
| quitEarlyArr |
| ); |
| var midOriginal = midOriginalArr[0]; |
| var midModified = midModifiedArr[0]; |
| if (result !== null) { |
| |
| |
| return result; |
| } else if (!quitEarlyArr[0]) { |
| |
| |
| |
| |
| var leftChanges = this.ComputeDiffRecursive( |
| originalStart, |
| midOriginal, |
| modifiedStart, |
| midModified, |
| quitEarlyArr |
| ); |
| var rightChanges = []; |
| if (!quitEarlyArr[0]) { |
| rightChanges = this.ComputeDiffRecursive( |
| midOriginal + 1, |
| originalEnd, |
| midModified + 1, |
| modifiedEnd, |
| quitEarlyArr |
| ); |
| } else { |
| |
| |
| rightChanges = [ |
| new DiffChange( |
| midOriginal + 1, |
| originalEnd - (midOriginal + 1) + 1, |
| midModified + 1, |
| modifiedEnd - (midModified + 1) + 1 |
| ), |
| ]; |
| } |
| return this.ConcatenateChanges(leftChanges, rightChanges); |
| } |
| |
| return [ |
| new DiffChange( |
| originalStart, |
| originalEnd - originalStart + 1, |
| modifiedStart, |
| modifiedEnd - modifiedStart + 1 |
| ), |
| ]; |
| }; |
| LcsDiff.prototype.WALKTRACE = function( |
| diagonalForwardBase, |
| diagonalForwardStart, |
| diagonalForwardEnd, |
| diagonalForwardOffset, |
| diagonalReverseBase, |
| diagonalReverseStart, |
| diagonalReverseEnd, |
| diagonalReverseOffset, |
| forwardPoints, |
| reversePoints, |
| originalIndex, |
| originalEnd, |
| midOriginalArr, |
| modifiedIndex, |
| modifiedEnd, |
| midModifiedArr, |
| deltaIsEven, |
| quitEarlyArr |
| ) { |
| var forwardChanges = null, |
| reverseChanges = null; |
| |
| var changeHelper = new DiffChangeHelper(); |
| var diagonalMin = diagonalForwardStart; |
| var diagonalMax = diagonalForwardEnd; |
| var diagonalRelative = |
| midOriginalArr[0] - midModifiedArr[0] - diagonalForwardOffset; |
| var lastOriginalIndex = Number.MIN_VALUE; |
| var historyIndex = this.m_forwardHistory.length - 1; |
| var diagonal; |
| do { |
| |
| diagonal = diagonalRelative + diagonalForwardBase; |
| |
| if ( |
| diagonal === diagonalMin || |
| (diagonal < diagonalMax && |
| forwardPoints[diagonal - 1] < forwardPoints[diagonal + 1]) |
| ) { |
| |
| originalIndex = forwardPoints[diagonal + 1]; |
| modifiedIndex = |
| originalIndex - diagonalRelative - diagonalForwardOffset; |
| if (originalIndex < lastOriginalIndex) { |
| changeHelper.MarkNextChange(); |
| } |
| lastOriginalIndex = originalIndex; |
| changeHelper.AddModifiedElement(originalIndex + 1, modifiedIndex); |
| diagonalRelative = diagonal + 1 - diagonalForwardBase; |
| } else { |
| |
| originalIndex = forwardPoints[diagonal - 1] + 1; |
| modifiedIndex = |
| originalIndex - diagonalRelative - diagonalForwardOffset; |
| if (originalIndex < lastOriginalIndex) { |
| changeHelper.MarkNextChange(); |
| } |
| lastOriginalIndex = originalIndex - 1; |
| changeHelper.AddOriginalElement(originalIndex, modifiedIndex + 1); |
| diagonalRelative = diagonal - 1 - diagonalForwardBase; |
| } |
| if (historyIndex >= 0) { |
| forwardPoints = this.m_forwardHistory[historyIndex]; |
| diagonalForwardBase = forwardPoints[0]; |
| diagonalMin = 1; |
| diagonalMax = forwardPoints.length - 1; |
| } |
| } while (--historyIndex >= -1); |
| |
| |
| forwardChanges = changeHelper.getReverseChanges(); |
| if (quitEarlyArr[0]) { |
| |
| |
| var originalStartPoint = midOriginalArr[0] + 1; |
| var modifiedStartPoint = midModifiedArr[0] + 1; |
| if (forwardChanges !== null && forwardChanges.length > 0) { |
| var lastForwardChange = forwardChanges[forwardChanges.length - 1]; |
| originalStartPoint = Math.max( |
| originalStartPoint, |
| lastForwardChange.getOriginalEnd() |
| ); |
| modifiedStartPoint = Math.max( |
| modifiedStartPoint, |
| lastForwardChange.getModifiedEnd() |
| ); |
| } |
| reverseChanges = [ |
| new DiffChange( |
| originalStartPoint, |
| originalEnd - originalStartPoint + 1, |
| modifiedStartPoint, |
| modifiedEnd - modifiedStartPoint + 1 |
| ), |
| ]; |
| } else { |
| |
| changeHelper = new DiffChangeHelper(); |
| diagonalMin = diagonalReverseStart; |
| diagonalMax = diagonalReverseEnd; |
| diagonalRelative = |
| midOriginalArr[0] - midModifiedArr[0] - diagonalReverseOffset; |
| lastOriginalIndex = Number.MAX_VALUE; |
| historyIndex = deltaIsEven |
| ? this.m_reverseHistory.length - 1 |
| : this.m_reverseHistory.length - 2; |
| do { |
| |
| diagonal = diagonalRelative + diagonalReverseBase; |
| |
| if ( |
| diagonal === diagonalMin || |
| (diagonal < diagonalMax && |
| reversePoints[diagonal - 1] >= reversePoints[diagonal + 1]) |
| ) { |
| |
| originalIndex = reversePoints[diagonal + 1] - 1; |
| modifiedIndex = |
| originalIndex - diagonalRelative - diagonalReverseOffset; |
| if (originalIndex > lastOriginalIndex) { |
| changeHelper.MarkNextChange(); |
| } |
| lastOriginalIndex = originalIndex + 1; |
| changeHelper.AddOriginalElement(originalIndex + 1, modifiedIndex + 1); |
| diagonalRelative = diagonal + 1 - diagonalReverseBase; |
| } else { |
| |
| originalIndex = reversePoints[diagonal - 1]; |
| modifiedIndex = |
| originalIndex - diagonalRelative - diagonalReverseOffset; |
| if (originalIndex > lastOriginalIndex) { |
| changeHelper.MarkNextChange(); |
| } |
| lastOriginalIndex = originalIndex; |
| changeHelper.AddModifiedElement(originalIndex + 1, modifiedIndex + 1); |
| diagonalRelative = diagonal - 1 - diagonalReverseBase; |
| } |
| if (historyIndex >= 0) { |
| reversePoints = this.m_reverseHistory[historyIndex]; |
| diagonalReverseBase = reversePoints[0]; |
| diagonalMin = 1; |
| diagonalMax = reversePoints.length - 1; |
| } |
| } while (--historyIndex >= -1); |
| |
| |
| reverseChanges = changeHelper.getChanges(); |
| } |
| return this.ConcatenateChanges(forwardChanges, reverseChanges); |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| LcsDiff.prototype.ComputeRecursionPoint = function( |
| originalStart, |
| originalEnd, |
| modifiedStart, |
| modifiedEnd, |
| midOriginalArr, |
| midModifiedArr, |
| quitEarlyArr |
| ) { |
| var originalIndex, modifiedIndex; |
| var diagonalForwardStart = 0, |
| diagonalForwardEnd = 0; |
| var diagonalReverseStart = 0, |
| diagonalReverseEnd = 0; |
| var numDifferences; |
| |
| |
| originalStart--; |
| modifiedStart--; |
| |
| |
| midOriginalArr[0] = 0; |
| midModifiedArr[0] = 0; |
| |
| this.m_forwardHistory = []; |
| this.m_reverseHistory = []; |
| |
| |
| |
| |
| var maxDifferences = |
| originalEnd - originalStart + (modifiedEnd - modifiedStart); |
| var numDiagonals = maxDifferences + 1; |
| var forwardPoints = new Array(numDiagonals); |
| var reversePoints = new Array(numDiagonals); |
| |
| |
| var diagonalForwardBase = modifiedEnd - modifiedStart; |
| var diagonalReverseBase = originalEnd - originalStart; |
| |
| |
| |
| |
| var diagonalForwardOffset = originalStart - modifiedStart; |
| var diagonalReverseOffset = originalEnd - modifiedEnd; |
| |
| |
| |
| var delta = diagonalReverseBase - diagonalForwardBase; |
| var deltaIsEven = delta % 2 === 0; |
| |
| |
| forwardPoints[diagonalForwardBase] = originalStart; |
| reversePoints[diagonalReverseBase] = originalEnd; |
| |
| quitEarlyArr[0] = false; |
| |
| |
| |
| |
| |
| |
| |
| var diagonal, tempOriginalIndex; |
| for ( |
| numDifferences = 1; |
| numDifferences <= maxDifferences / 2 + 1; |
| numDifferences++ |
| ) { |
| var furthestOriginalIndex = 0; |
| var furthestModifiedIndex = 0; |
| |
| diagonalForwardStart = this.ClipDiagonalBound( |
| diagonalForwardBase - numDifferences, |
| numDifferences, |
| diagonalForwardBase, |
| numDiagonals |
| ); |
| diagonalForwardEnd = this.ClipDiagonalBound( |
| diagonalForwardBase + numDifferences, |
| numDifferences, |
| diagonalForwardBase, |
| numDiagonals |
| ); |
| for ( |
| diagonal = diagonalForwardStart; |
| diagonal <= diagonalForwardEnd; |
| diagonal += 2 |
| ) { |
| |
| |
| |
| if ( |
| diagonal === diagonalForwardStart || |
| (diagonal < diagonalForwardEnd && |
| forwardPoints[diagonal - 1] < forwardPoints[diagonal + 1]) |
| ) { |
| originalIndex = forwardPoints[diagonal + 1]; |
| } else { |
| originalIndex = forwardPoints[diagonal - 1] + 1; |
| } |
| modifiedIndex = |
| originalIndex - |
| (diagonal - diagonalForwardBase) - |
| diagonalForwardOffset; |
| |
| tempOriginalIndex = originalIndex; |
| |
| |
| while ( |
| originalIndex < originalEnd && |
| modifiedIndex < modifiedEnd && |
| this.ElementsAreEqual(originalIndex + 1, modifiedIndex + 1) |
| ) { |
| originalIndex++; |
| modifiedIndex++; |
| } |
| forwardPoints[diagonal] = originalIndex; |
| if ( |
| originalIndex + modifiedIndex > |
| furthestOriginalIndex + furthestModifiedIndex |
| ) { |
| furthestOriginalIndex = originalIndex; |
| furthestModifiedIndex = modifiedIndex; |
| } |
| |
| |
| |
| |
| if ( |
| !deltaIsEven && |
| Math.abs(diagonal - diagonalReverseBase) <= numDifferences - 1 |
| ) { |
| if (originalIndex >= reversePoints[diagonal]) { |
| midOriginalArr[0] = originalIndex; |
| midModifiedArr[0] = modifiedIndex; |
| if ( |
| tempOriginalIndex <= reversePoints[diagonal] && |
| MaxDifferencesHistory > 0 && |
| numDifferences <= MaxDifferencesHistory + 1 |
| ) { |
| |
| return this.WALKTRACE( |
| diagonalForwardBase, |
| diagonalForwardStart, |
| diagonalForwardEnd, |
| diagonalForwardOffset, |
| diagonalReverseBase, |
| diagonalReverseStart, |
| diagonalReverseEnd, |
| diagonalReverseOffset, |
| forwardPoints, |
| reversePoints, |
| originalIndex, |
| originalEnd, |
| midOriginalArr, |
| modifiedIndex, |
| modifiedEnd, |
| midModifiedArr, |
| deltaIsEven, |
| quitEarlyArr |
| ); |
| } else { |
| |
| |
| return null; |
| } |
| } |
| } |
| } |
| |
| var matchLengthOfLongest = |
| (furthestOriginalIndex - |
| originalStart + |
| (furthestModifiedIndex - modifiedStart) - |
| numDifferences) / |
| 2; |
| if ( |
| this.ContinueProcessingPredicate !== null && |
| !this.ContinueProcessingPredicate( |
| furthestOriginalIndex, |
| this.OriginalSequence, |
| matchLengthOfLongest |
| ) |
| ) { |
| |
| quitEarlyArr[0] = true; |
| |
| midOriginalArr[0] = furthestOriginalIndex; |
| midModifiedArr[0] = furthestModifiedIndex; |
| if ( |
| matchLengthOfLongest > 0 && |
| MaxDifferencesHistory > 0 && |
| numDifferences <= MaxDifferencesHistory + 1 |
| ) { |
| |
| return this.WALKTRACE( |
| diagonalForwardBase, |
| diagonalForwardStart, |
| diagonalForwardEnd, |
| diagonalForwardOffset, |
| diagonalReverseBase, |
| diagonalReverseStart, |
| diagonalReverseEnd, |
| diagonalReverseOffset, |
| forwardPoints, |
| reversePoints, |
| originalIndex, |
| originalEnd, |
| midOriginalArr, |
| modifiedIndex, |
| modifiedEnd, |
| midModifiedArr, |
| deltaIsEven, |
| quitEarlyArr |
| ); |
| } else { |
| |
| |
| |
| originalStart++; |
| modifiedStart++; |
| return [ |
| new DiffChange( |
| originalStart, |
| originalEnd - originalStart + 1, |
| modifiedStart, |
| modifiedEnd - modifiedStart + 1 |
| ), |
| ]; |
| } |
| } |
| |
| diagonalReverseStart = this.ClipDiagonalBound( |
| diagonalReverseBase - numDifferences, |
| numDifferences, |
| diagonalReverseBase, |
| numDiagonals |
| ); |
| diagonalReverseEnd = this.ClipDiagonalBound( |
| diagonalReverseBase + numDifferences, |
| numDifferences, |
| diagonalReverseBase, |
| numDiagonals |
| ); |
| for ( |
| diagonal = diagonalReverseStart; |
| diagonal <= diagonalReverseEnd; |
| diagonal += 2 |
| ) { |
| |
| |
| |
| if ( |
| diagonal === diagonalReverseStart || |
| (diagonal < diagonalReverseEnd && |
| reversePoints[diagonal - 1] >= reversePoints[diagonal + 1]) |
| ) { |
| originalIndex = reversePoints[diagonal + 1] - 1; |
| } else { |
| originalIndex = reversePoints[diagonal - 1]; |
| } |
| modifiedIndex = |
| originalIndex - |
| (diagonal - diagonalReverseBase) - |
| diagonalReverseOffset; |
| |
| tempOriginalIndex = originalIndex; |
| |
| |
| while ( |
| originalIndex > originalStart && |
| modifiedIndex > modifiedStart && |
| this.ElementsAreEqual(originalIndex, modifiedIndex) |
| ) { |
| originalIndex--; |
| modifiedIndex--; |
| } |
| reversePoints[diagonal] = originalIndex; |
| |
| |
| |
| if ( |
| deltaIsEven && |
| Math.abs(diagonal - diagonalForwardBase) <= numDifferences |
| ) { |
| if (originalIndex <= forwardPoints[diagonal]) { |
| midOriginalArr[0] = originalIndex; |
| midModifiedArr[0] = modifiedIndex; |
| if ( |
| tempOriginalIndex >= forwardPoints[diagonal] && |
| MaxDifferencesHistory > 0 && |
| numDifferences <= MaxDifferencesHistory + 1 |
| ) { |
| |
| return this.WALKTRACE( |
| diagonalForwardBase, |
| diagonalForwardStart, |
| diagonalForwardEnd, |
| diagonalForwardOffset, |
| diagonalReverseBase, |
| diagonalReverseStart, |
| diagonalReverseEnd, |
| diagonalReverseOffset, |
| forwardPoints, |
| reversePoints, |
| originalIndex, |
| originalEnd, |
| midOriginalArr, |
| modifiedIndex, |
| modifiedEnd, |
| midModifiedArr, |
| deltaIsEven, |
| quitEarlyArr |
| ); |
| } else { |
| |
| |
| return null; |
| } |
| } |
| } |
| } |
| |
| if (numDifferences <= MaxDifferencesHistory) { |
| |
| |
| var temp = new Array(diagonalForwardEnd - diagonalForwardStart + 2); |
| temp[0] = diagonalForwardBase - diagonalForwardStart + 1; |
| MyArray.Copy( |
| forwardPoints, |
| diagonalForwardStart, |
| temp, |
| 1, |
| diagonalForwardEnd - diagonalForwardStart + 1 |
| ); |
| this.m_forwardHistory.push(temp); |
| temp = new Array(diagonalReverseEnd - diagonalReverseStart + 2); |
| temp[0] = diagonalReverseBase - diagonalReverseStart + 1; |
| MyArray.Copy( |
| reversePoints, |
| diagonalReverseStart, |
| temp, |
| 1, |
| diagonalReverseEnd - diagonalReverseStart + 1 |
| ); |
| this.m_reverseHistory.push(temp); |
| } |
| } |
| |
| |
| return this.WALKTRACE( |
| diagonalForwardBase, |
| diagonalForwardStart, |
| diagonalForwardEnd, |
| diagonalForwardOffset, |
| diagonalReverseBase, |
| diagonalReverseStart, |
| diagonalReverseEnd, |
| diagonalReverseOffset, |
| forwardPoints, |
| reversePoints, |
| originalIndex, |
| originalEnd, |
| midOriginalArr, |
| modifiedIndex, |
| modifiedEnd, |
| midModifiedArr, |
| deltaIsEven, |
| quitEarlyArr |
| ); |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| LcsDiff.prototype.ShiftChanges = function(changes) { |
| var mergedDiffs; |
| do { |
| mergedDiffs = false; |
| |
| for (var i = 0; i < changes.length; i++) { |
| var change = changes[i]; |
| var originalStop = |
| i < changes.length - 1 |
| ? changes[i + 1].originalStart |
| : this.OriginalSequence.getLength(); |
| var modifiedStop = |
| i < changes.length - 1 |
| ? changes[i + 1].modifiedStart |
| : this.ModifiedSequence.getLength(); |
| var checkOriginal = change.originalLength > 0; |
| var checkModified = change.modifiedLength > 0; |
| while ( |
| change.originalStart + change.originalLength < originalStop && |
| change.modifiedStart + change.modifiedLength < modifiedStop && |
| (!checkOriginal || |
| this.OriginalElementsAreEqual( |
| change.originalStart, |
| change.originalStart + change.originalLength |
| )) && |
| (!checkModified || |
| this.ModifiedElementsAreEqual( |
| change.modifiedStart, |
| change.modifiedStart + change.modifiedLength |
| )) |
| ) { |
| change.originalStart++; |
| change.modifiedStart++; |
| } |
| } |
| |
| |
| var result = new Array(); |
| var mergedChangeArr = [null]; |
| for (var i = 0; i < changes.length; i++) { |
| if ( |
| i < changes.length - 1 && |
| this.ChangesOverlap(changes[i], changes[i + 1], mergedChangeArr) |
| ) { |
| mergedDiffs = true; |
| result.push(mergedChangeArr[0]); |
| i++; |
| } else { |
| result.push(changes[i]); |
| } |
| } |
| changes = result; |
| } while (mergedDiffs); |
| |
| for (var i = changes.length - 1; i >= 0; i--) { |
| var change = changes[i]; |
| var originalStop = 0; |
| var modifiedStop = 0; |
| if (i > 0) { |
| var prevChange = changes[i - 1]; |
| if (prevChange.originalLength > 0) { |
| originalStop = prevChange.originalStart + prevChange.originalLength; |
| } |
| if (prevChange.modifiedLength > 0) { |
| modifiedStop = prevChange.modifiedStart + prevChange.modifiedLength; |
| } |
| } |
| var checkOriginal = change.originalLength > 0; |
| var checkModified = change.modifiedLength > 0; |
| var bestDelta = 0; |
| var bestScore = this._boundaryScore( |
| change.originalStart, |
| change.originalLength, |
| change.modifiedStart, |
| change.modifiedLength |
| ); |
| for (var delta = 1; ; delta++) { |
| var originalStart = change.originalStart - delta; |
| var modifiedStart = change.modifiedStart - delta; |
| if (originalStart < originalStop || modifiedStart < modifiedStop) { |
| break; |
| } |
| if ( |
| checkOriginal && |
| !this.OriginalElementsAreEqual( |
| originalStart, |
| originalStart + change.originalLength |
| ) |
| ) { |
| break; |
| } |
| if ( |
| checkModified && |
| !this.ModifiedElementsAreEqual( |
| modifiedStart, |
| modifiedStart + change.modifiedLength |
| ) |
| ) { |
| break; |
| } |
| var score = this._boundaryScore( |
| originalStart, |
| change.originalLength, |
| modifiedStart, |
| change.modifiedLength |
| ); |
| if (score > bestScore) { |
| bestScore = score; |
| bestDelta = delta; |
| } |
| } |
| change.originalStart -= bestDelta; |
| change.modifiedStart -= bestDelta; |
| } |
| return changes; |
| }; |
| LcsDiff.prototype._OriginalIsBoundary = function(index) { |
| if (index <= 0 || index >= this.OriginalSequence.getLength() - 1) { |
| return true; |
| } |
| var element = this.OriginalSequence.getElementAtIndex(index); |
| return typeof element === 'string' && /^\s*$/.test(element); |
| }; |
| LcsDiff.prototype._OriginalRegionIsBoundary = function( |
| originalStart, |
| originalLength |
| ) { |
| if ( |
| this._OriginalIsBoundary(originalStart) || |
| this._OriginalIsBoundary(originalStart - 1) |
| ) { |
| return true; |
| } |
| if (originalLength > 0) { |
| var originalEnd = originalStart + originalLength; |
| if ( |
| this._OriginalIsBoundary(originalEnd - 1) || |
| this._OriginalIsBoundary(originalEnd) |
| ) { |
| return true; |
| } |
| } |
| return false; |
| }; |
| LcsDiff.prototype._ModifiedIsBoundary = function(index) { |
| if (index <= 0 || index >= this.ModifiedSequence.getLength() - 1) { |
| return true; |
| } |
| var element = this.ModifiedSequence.getElementAtIndex(index); |
| return typeof element === 'string' && /^\s*$/.test(element); |
| }; |
| LcsDiff.prototype._ModifiedRegionIsBoundary = function( |
| modifiedStart, |
| modifiedLength |
| ) { |
| if ( |
| this._ModifiedIsBoundary(modifiedStart) || |
| this._ModifiedIsBoundary(modifiedStart - 1) |
| ) { |
| return true; |
| } |
| if (modifiedLength > 0) { |
| var modifiedEnd = modifiedStart + modifiedLength; |
| if ( |
| this._ModifiedIsBoundary(modifiedEnd - 1) || |
| this._ModifiedIsBoundary(modifiedEnd) |
| ) { |
| return true; |
| } |
| } |
| return false; |
| }; |
| LcsDiff.prototype._boundaryScore = function( |
| originalStart, |
| originalLength, |
| modifiedStart, |
| modifiedLength |
| ) { |
| var originalScore = this._OriginalRegionIsBoundary( |
| originalStart, |
| originalLength |
| ) |
| ? 1 |
| : 0; |
| var modifiedScore = this._ModifiedRegionIsBoundary( |
| modifiedStart, |
| modifiedLength |
| ) |
| ? 1 |
| : 0; |
| return originalScore + modifiedScore; |
| }; |
| |
| |
| |
| |
| |
| |
| |
| LcsDiff.prototype.ConcatenateChanges = function(left, right) { |
| var mergedChangeArr = []; |
| var result = null; |
| if (left.length === 0 || right.length === 0) { |
| return right.length > 0 ? right : left; |
| } else if ( |
| this.ChangesOverlap(left[left.length - 1], right[0], mergedChangeArr) |
| ) { |
| |
| |
| |
| |
| result = new Array(left.length + right.length - 1); |
| MyArray.Copy(left, 0, result, 0, left.length - 1); |
| result[left.length - 1] = mergedChangeArr[0]; |
| MyArray.Copy(right, 1, result, left.length, right.length - 1); |
| return result; |
| } else { |
| result = new Array(left.length + right.length); |
| MyArray.Copy(left, 0, result, 0, left.length); |
| MyArray.Copy(right, 0, result, left.length, right.length); |
| return result; |
| } |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| LcsDiff.prototype.ChangesOverlap = function(left, right, mergedChangeArr) { |
| Debug.Assert( |
| left.originalStart <= right.originalStart, |
| 'Left change is not less than or equal to right change' |
| ); |
| Debug.Assert( |
| left.modifiedStart <= right.modifiedStart, |
| 'Left change is not less than or equal to right change' |
| ); |
| if ( |
| left.originalStart + left.originalLength >= right.originalStart || |
| left.modifiedStart + left.modifiedLength >= right.modifiedStart |
| ) { |
| var originalStart = left.originalStart; |
| var originalLength = left.originalLength; |
| var modifiedStart = left.modifiedStart; |
| var modifiedLength = left.modifiedLength; |
| if (left.originalStart + left.originalLength >= right.originalStart) { |
| originalLength = |
| right.originalStart + right.originalLength - left.originalStart; |
| } |
| if (left.modifiedStart + left.modifiedLength >= right.modifiedStart) { |
| modifiedLength = |
| right.modifiedStart + right.modifiedLength - left.modifiedStart; |
| } |
| mergedChangeArr[0] = new DiffChange( |
| originalStart, |
| originalLength, |
| modifiedStart, |
| modifiedLength |
| ); |
| return true; |
| } else { |
| mergedChangeArr[0] = null; |
| return false; |
| } |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| LcsDiff.prototype.ClipDiagonalBound = function( |
| diagonal, |
| numDifferences, |
| diagonalBaseIndex, |
| numDiagonals |
| ) { |
| if (diagonal >= 0 && diagonal < numDiagonals) { |
| |
| return diagonal; |
| } |
| |
| |
| var diagonalsBelow = diagonalBaseIndex; |
| var diagonalsAbove = numDiagonals - diagonalBaseIndex - 1; |
| var diffEven = numDifferences % 2 === 0; |
| if (diagonal < 0) { |
| var lowerBoundEven = diagonalsBelow % 2 === 0; |
| return diffEven === lowerBoundEven ? 0 : 1; |
| } else { |
| var upperBoundEven = diagonalsAbove % 2 === 0; |
| return diffEven === upperBoundEven ? numDiagonals - 1 : numDiagonals - 2; |
| } |
| }; |
| return LcsDiff; |
| })(); |
| exports.LcsDiff = LcsDiff; |
|
|