cleanupEfficiency function
Reduce the number of edits by eliminating operationally trivial equalities.
diffs
is a List of Diff objects.
Implementation
void cleanupEfficiency(List<Diff> diffs, int diffEditCost) {
bool changes = false;
// Stack of indices where equalities are found.
final equalities = <int>[];
// Always equal to diffs[equalities.last()].text
String? lastequality = null;
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 == DIFF_EQUAL) { // Equality found.
if (diffs[pointer].text.length < diffEditCost
&& (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 == DIFF_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 < diffEditCost / 2)
&& ((pre_ins ? 1 : 0) + (pre_del ? 1 : 0) + (post_ins ? 1 : 0)
+ (post_del ? 1 : 0)) == 3))) {
// Duplicate record.
diffs.insert(equalities.last, new Diff(DIFF_DELETE, lastequality));
// Change second copy to insert.
diffs[equalities.last + 1].operation = DIFF_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.isEmpty) {
equalities.removeLast();
}
pointer = equalities.isEmpty ? -1 : equalities.last;
post_ins = post_del = false;
}
changes = true;
}
}
pointer++;
}
if (changes) {
cleanupMerge(diffs);
}
}