securityos/node_modules/diff3/onp.js

179 lines
5.3 KiB
JavaScript

/*
* URL: https://github.com/cubicdaiya/onp
*
* Copyright (c) 2013 Tatsuhiko Kubo <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* The algorithm implemented here is based on "An O(NP) Sequence Comparison Algorithm"
* by described by Sun Wu, Udi Manber and Gene Myers
*/
module.exports = function (a_, b_) {
var a = a_,
b = b_,
m = a.length,
n = b.length,
reverse = false,
ed = null,
offset = m + 1,
path = [],
pathposi = [],
ses = [],
lcs = "",
SES_DELETE = -1,
SES_COMMON = 0,
SES_ADD = 1;
var tmp1,
tmp2;
var init = function () {
if (m >= n) {
tmp1 = a;
tmp2 = m;
a = b;
b = tmp1;
m = n;
n = tmp2;
reverse = true;
offset = m + 1;
}
};
var P = function (x, y, k) {
return {
'x' : x,
'y' : y,
'k' : k,
};
};
var seselem = function (elem, t) {
return {
'elem' : elem,
't' : t,
};
};
var snake = function (k, p, pp) {
var r, x, y;
if (p > pp) {
r = path[k-1+offset];
} else {
r = path[k+1+offset];
}
y = Math.max(p, pp);
x = y - k;
while (x < m && y < n && a[x] === b[y]) {
++x;
++y;
}
path[k+offset] = pathposi.length;
pathposi[pathposi.length] = new P(x, y, r);
return y;
};
var recordseq = function (epc) {
var x_idx, y_idx, px_idx, py_idx, i;
x_idx = y_idx = 1;
px_idx = py_idx = 0;
for (i=epc.length-1;i>=0;--i) {
while(px_idx < epc[i].x || py_idx < epc[i].y) {
if (epc[i].y - epc[i].x > py_idx - px_idx) {
if (reverse) {
ses[ses.length] = new seselem(b[py_idx], SES_DELETE);
} else {
ses[ses.length] = new seselem(b[py_idx], SES_ADD);
}
++y_idx;
++py_idx;
} else if (epc[i].y - epc[i].x < py_idx - px_idx) {
if (reverse) {
ses[ses.length] = new seselem(a[px_idx], SES_ADD);
} else {
ses[ses.length] = new seselem(a[px_idx], SES_DELETE);
}
++x_idx;
++px_idx;
} else {
ses[ses.length] = new seselem(a[px_idx], SES_COMMON);
lcs += a[px_idx];
++x_idx;
++y_idx;
++px_idx;
++py_idx;
}
}
}
};
init();
return {
SES_DELETE : -1,
SES_COMMON : 0,
SES_ADD : 1,
editdistance : function () {
return ed;
},
getlcs : function () {
return lcs;
},
getses : function () {
return ses;
},
compose : function () {
var delta, size, fp, p, r, epc, i, k;
delta = n - m;
size = m + n + 3;
fp = {};
for (i=0;i<size;++i) {
fp[i] = -1;
path[i] = -1;
}
p = -1;
do {
++p;
for (k=-p;k<=delta-1;++k) {
fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]);
}
for (k=delta+p;k>=delta+1;--k) {
fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]);
}
fp[delta+offset] = snake(delta, fp[delta-1+offset]+1, fp[delta+1+offset]);
} while (fp[delta+offset] !== n);
ed = delta + 2 * p;
r = path[delta+offset];
epc = [];
while (r !== -1) {
epc[epc.length] = new P(pathposi[r].x, pathposi[r].y, null);
r = pathposi[r].k;
}
recordseq(epc);
}
};
};