diff --git a/diff.js b/diff.js index 8f54fe1..2dba092 100644 --- a/diff.js +++ b/diff.js @@ -224,8 +224,10 @@ var getDiffSections = function(A, B, cmp, min_chunk){ // store the gap... ;(a != e.A || b != e.B) && gaps.push([ - [a, A.slice(a, e.A)], - [b, B.slice(b, e.B)], + [a, + A.slice(a, e.A)], + [b, + B.slice(b, e.B)], ]) // go to next gap... a = e.A + e.length diff --git a/diff2.js b/diff2.js index 011c211..5f6e34c 100644 --- a/diff2.js +++ b/diff2.js @@ -33,6 +33,36 @@ var types = require('ig-types') // - reconstruct protocol // // +// XXX proposed diff format: +// [ +// // change... +// [ +// // pre-context... +// // XXX should '=' here be optional??? +// ['=', , ], +// ... +// ['=', , ], +// +// // changes... +// // addition... +// ['+', , ], +// // removal... +// ['-', , ], +// // unchanged context line.... +// ['=', , ], +// ... +// +// // post-context... +// ['=', , ], +// ... +// ['=', , ], +// ], +// +// ... +// ] +// +// +// /*********************************************************************/ var STOP = @@ -601,6 +631,83 @@ function(root, spec){ +//--------------------------------------------------------------------- + +// Get common chunks (LCS)... +// +// Format: +// [ +// , +// +// // XXX should this be an obj??? +// [ +// , +// , +// , +// ], +// ... +// ] +// +var commonSections = +module.commonSections = +function(A, B, cmp){ + cmp = cmp + || function(a, b){ + return a === b || a == b } + + var LCS = function(a, b){ + // calculate length of chunk... + var l = 0 + while(a+l < A.length && b+l < B.length + && a+l in A && b+l in B + && cmp(A[a+l], B[b+l])){ + l++ } + // get next chunks... + var L = A.length > a+l ? + LCS(a+l+1, b+l) + : [0] + var R = B.length > b+l ? + LCS(a+l, b+l+1) + : [0] + // select the best chunk-set... + // NOTE: we maximize the number of elements in a chunk set then + // minimize the number of chunks per set... + var next = L[0] == R[0] ? + (L.length < R.length ? L : R) + : L[0] > R[0] ? + L + : R + return ( + // non-empty chunk and next... + next[0] > 0 && l > 0 ? + [l + next[0], [a, b, l]].concat(next.slice(1)) + // non-empty chunk and empty next... + : l > 0 ? + [l, [a, b, l]] + // empty chunk... + : next ) } + + return LCS(0, 0) } + + +var diffSections = +function(A, B, cmp){ + var pa = 0 + var pb = 0 + return commonSections(A, B, cmp) + .slice(1) + .concat([[A.length, B.length, 0]]) + .reduce(function(gaps, [a, b, l]){ + ;(pa == a && pb == b) + || gaps.push([ + pa, + A.slice(pa, a), + pb, + B.slice(pb, b), + ]) + pa = a + l + pb = b + l + return gaps }, []) } @@ -701,6 +808,16 @@ console.log('\n\n---\n', )]) +var A = [1,2,3,1,2,3,4,5,,,4] +var B = [1,2,3,4,5,6] +console.log(A) +console.log(B) +console.log( + commonSections(A, B)) +console.log( + diffSections(A, B)) + + /********************************************************************** * vim:set ts=4 sw=4 : */ return module })