Algorithm-Diff-XS
view release on metacpan or search on metacpan
SV *lcs__CREATE_(char *class)
IV lcs_DESTROY(SV *sv)
void lcs__core_loop_(obj, a, a_min, a_max, h)
SV *obj
AV *a
IV a_min
IV a_max
HV *h
PREINIT:
struct CTX *ctx = (struct CTX *)SvIVX(SvRV(obj));
IV i, j;
PPCODE:
ctx->links.max = ctx->thresh.max = -1;
ctx->current = *ctx->avail.arr;
for (i = a_min; i <= a_max; ++i) {
SV *line = *av_fetch(a, i, 0);
STRLEN klen;
char *key = SvPVbyte(line, klen);
SV **lines = hv_fetch(h, key, klen, 0);
if (lines != NULL) {
register IV k = 0, idx;
AV *matches = (AV *)SvRV(*lines); /* line_map() value */
for (idx = av_len(matches); idx >= 0; --idx) {
/* We know (via sub line_map) "matches" holds
* valid SvIV's, in increasing order, so we can use
* (quicker) SvIVX instead of (safer) SvIV here.
*/
j = SvIVX(*av_fetch(matches, idx, 0));
if (k > 0 && ctx->thresh.arr[k] > j &&
ctx->thresh.arr[k-1] < j) {
ctx->thresh.arr[k] = j;
}
else
k = rnlw(&ctx->thresh, j, k);
if (k >= 0) {
struct LK *lk = make_link(ctx, (k>0) ?
ctx->links.arr[k-1] :
NULL, i, j);
if (ctx->links.max < k) {
*la_push(&ctx->links) = lk;
}
else
ctx->links.arr[k] = lk;
}
}
}
}
if (ctx->thresh.max >= 0) {
struct LK *lk;
if (GIMME_V == G_ARRAY) {
SV **start, **end;
XSprePUSH;
start = SP+1;
for (lk = ctx->links.arr[ctx->thresh.max]; lk; lk = lk->link) {
AV *arr;
/* only count transitions */
if (lk->link && lk->link->i == lk->i)
continue;
arr = newAV();
av_push(arr, newSViv(lk->i));
av_push(arr, newSViv(lk->j));
XPUSHs(sv_2mortal(newRV_noinc((SV *)arr)));
}
/* reverse the stack */
end = SP;
while (start < end) {
SV *tmp = *start;
*start++ = *end;
*end-- = tmp;
}
}
else {
j = 0;
for (lk = ctx->links.arr[ctx->thresh.max]; lk; lk = lk->link) {
if (lk->link && lk->link->i == lk->i)
continue;
++j;
}
XSRETURN_IV(j);
}
}
else if (GIMME_V == G_SCALAR)
XSRETURN_IV(0);
( run in 0.892 second using v1.01-cache-2.11-cpan-3c2a17b8caa )