Change diff Implementation to use end indices instead of length
Having absolute begin and relative lenght was a bit strange to work with. Rename middle_snake to snake.
This commit is contained in:
parent
793c2ed9cf
commit
50fec86749
42
src/diff.hh
42
src/diff.hh
|
@ -108,53 +108,55 @@ inline void append_diff(Vector<Diff>& diffs, Diff diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Iterator, typename Equal>
|
template<typename Iterator, typename Equal>
|
||||||
void find_diff_rec(Iterator a, int offA, int lenA,
|
void find_diff_rec(Iterator a, int begA, int endA,
|
||||||
Iterator b, int offB, int lenB,
|
Iterator b, int begB, int endB,
|
||||||
int* V1, int* V2, Equal eq, Vector<Diff>& diffs)
|
int* V1, int* V2, Equal eq, Vector<Diff>& diffs)
|
||||||
{
|
{
|
||||||
int prefix_len = 0;
|
int prefix_len = 0;
|
||||||
while (lenA > 0 and lenB > 0 and a[offA] == b[offB])
|
while (begA != endA and begB != endB and a[begA] == b[begB])
|
||||||
++offA, ++offB, --lenA, --lenB, ++prefix_len;
|
++begA, ++begB, ++prefix_len;
|
||||||
|
|
||||||
int suffix_len = 0;
|
int suffix_len = 0;
|
||||||
while (lenA != 0 and lenB != 0 and a[offA + lenA - 1] == b[offB + lenB - 1])
|
while (begA != endA and begB != endB and a[endA-1] == b[endB-1])
|
||||||
--lenA, --lenB, ++suffix_len;
|
--endA, --endB, ++suffix_len;
|
||||||
|
|
||||||
append_diff(diffs, {Diff::Keep, prefix_len, 0});
|
append_diff(diffs, {Diff::Keep, prefix_len, 0});
|
||||||
|
|
||||||
|
const auto lenA = endA - begA, lenB = endB - begB;
|
||||||
|
|
||||||
if (lenA == 0)
|
if (lenA == 0)
|
||||||
append_diff(diffs, {Diff::Add, lenB, offB});
|
append_diff(diffs, {Diff::Add, lenB, begB});
|
||||||
else if (lenB == 0)
|
else if (lenB == 0)
|
||||||
append_diff(diffs, {Diff::Remove, lenA, 0});
|
append_diff(diffs, {Diff::Remove, lenA, 0});
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto middle_snake = find_middle_snake(a + offA, lenA, b + offB, lenB, V1, V2, eq);
|
auto snake = find_middle_snake(a + begA, lenA, b + begB, lenB, V1, V2, eq);
|
||||||
kak_assert(middle_snake.u <= lenA and middle_snake.v <= lenB);
|
kak_assert(snake.u <= lenA and snake.v <= lenB);
|
||||||
if (middle_snake.d > 1)
|
if (snake.d > 1)
|
||||||
{
|
{
|
||||||
find_diff_rec(a, offA, middle_snake.x,
|
find_diff_rec(a, begA, begA + snake.x,
|
||||||
b, offB, middle_snake.y,
|
b, begB, begB + snake.y,
|
||||||
V1, V2, eq, diffs);
|
V1, V2, eq, diffs);
|
||||||
|
|
||||||
append_diff(diffs, {Diff::Keep, middle_snake.u - middle_snake.x, 0});
|
append_diff(diffs, {Diff::Keep, snake.u - snake.x, 0});
|
||||||
|
|
||||||
find_diff_rec(a, offA + middle_snake.u, lenA - middle_snake.u,
|
find_diff_rec(a, begA + snake.u, endA,
|
||||||
b, offB + middle_snake.v, lenB - middle_snake.v,
|
b, begB + snake.v, endB,
|
||||||
V1, V2, eq, diffs);
|
V1, V2, eq, diffs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (middle_snake.d == 1)
|
if (snake.d == 1)
|
||||||
{
|
{
|
||||||
const int diag = middle_snake.x - (middle_snake.add ? 0 : 1);
|
const int diag = snake.x - (snake.add ? 0 : 1);
|
||||||
append_diff(diffs, {Diff::Keep, diag, 0});
|
append_diff(diffs, {Diff::Keep, diag, 0});
|
||||||
|
|
||||||
if (middle_snake.add)
|
if (snake.add)
|
||||||
append_diff(diffs, {Diff::Add, 1, offB + diag});
|
append_diff(diffs, {Diff::Add, 1, begB + diag});
|
||||||
else
|
else
|
||||||
append_diff(diffs, {Diff::Remove, 1, 0});
|
append_diff(diffs, {Diff::Remove, 1, 0});
|
||||||
}
|
}
|
||||||
append_diff(diffs, {Diff::Keep, middle_snake.u - middle_snake.x, 0});
|
append_diff(diffs, {Diff::Keep, snake.u - snake.x, 0});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,28 @@ UnitTest test_diff{[]()
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
StringView s1 = "a?";
|
auto diff = find_diff("a?", 2, "!", 1);
|
||||||
StringView s2 = "!";
|
|
||||||
|
|
||||||
auto diff = find_diff(s1.begin(), (int)s1.length(), s2.begin(), (int)s2.length());
|
|
||||||
|
|
||||||
kak_assert(diff.size() == 3 and
|
kak_assert(diff.size() == 3 and
|
||||||
eq(diff[0], {Diff::Remove, 1, 0}) and
|
eq(diff[0], {Diff::Remove, 1, 0}) and
|
||||||
eq(diff[1], {Diff::Add, 1, 0}) and
|
eq(diff[1], {Diff::Add, 1, 0}) and
|
||||||
eq(diff[2], {Diff::Remove, 1, 0}));
|
eq(diff[2], {Diff::Remove, 1, 0}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto diff = find_diff("abcd", 4, "c", 1);
|
||||||
|
kak_assert(diff.size() == 3 and
|
||||||
|
eq(diff[0], {Diff::Remove, 2, 0}) and
|
||||||
|
eq(diff[1], {Diff::Keep, 1, 0}) and
|
||||||
|
eq(diff[2], {Diff::Remove, 1, 0}));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto diff = find_diff("abcd", 4, "cdef", 4);
|
||||||
|
kak_assert(diff.size() == 3 and
|
||||||
|
eq(diff[0], {Diff::Remove, 2, 0}) and
|
||||||
|
eq(diff[1], {Diff::Keep, 2, 0}) and
|
||||||
|
eq(diff[2], {Diff::Add, 2, 2}));
|
||||||
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
UnitTest* UnitTest::list = nullptr;
|
UnitTest* UnitTest::list = nullptr;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user