diff_cleanupEfficiency method
Reduce the number of edits by eliminating operationally trivial equalities.
diffs
is a List of Diff objects.
Implementation
void diff_cleanupEfficiency(List<Diff> diffs) {
bool changes = false;
// Stack of indices where equalities are found.
final equalities = <int>[];
// Always equal to diffs[equalities.last()].text
String? lastEquality;
int pointer = 0; // Index of current position.
// Is there an insertion operation before the last equality.
bool pre_ins = false;
// Is there a deletion operation before the last equality.
bool pre_del = false;
// Is there an insertion operation after the last equality.
bool post_ins = false;
// Is there a deletion operation after the last equality.
bool post_del = false;
while (pointer < diffs.length) {
if (diffs[pointer].operation == Operation.equal) {
// Equality found.
if (diffs[pointer].text.length < Diff_EditCost &&
(post_ins || post_del)) {
// Candidate found.
equalities.add(pointer);
pre_ins = post_ins;
pre_del = post_del;
lastEquality = diffs[pointer].text;
} else {
// Not a candidate, and can never become one.
equalities.clear();
lastEquality = null;
}
post_ins = post_del = false;
} else {
// An insertion or deletion.
if (diffs[pointer].operation == Operation.delete) {
post_del = true;
} else {
post_ins = true;
}
/*
* Five types to be split:
* <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
* <ins>A</ins>X<ins>C</ins><del>D</del>
* <ins>A</ins><del>B</del>X<ins>C</ins>
* <ins>A</del>X<ins>C</ins><del>D</del>
* <ins>A</ins><del>B</del>X<del>C</del>
*/
if (lastEquality != null &&
((pre_ins && pre_del && post_ins && post_del) ||
((lastEquality.length < Diff_EditCost / 2) &&
((pre_ins ? 1 : 0) +
(pre_del ? 1 : 0) +
(post_ins ? 1 : 0) +
(post_del ? 1 : 0)) ==
3))) {
// Duplicate record.
diffs.insert(
equalities.last, Diff(Operation.delete, lastEquality));
// Change second copy to insert.
diffs[equalities.last + 1].operation = Operation.insert;
equalities.removeLast(); // Throw away the equality we just deleted.
lastEquality = null;
if (pre_ins && pre_del) {
// No changes made which could affect previous entry, keep going.
post_ins = post_del = true;
equalities.clear();
} else {
if (equalities.isNotEmpty) {
equalities.removeLast();
}
pointer = equalities.isEmpty ? -1 : equalities.last;
post_ins = post_del = false;
}
changes = true;
}
}
pointer++;
}
if (changes) {
diff_cleanupMerge(diffs);
}
}