patch_splitMax method
Look through the patches and break up any which are longer than the
maximum limit of the match algorithm.
Intended to be called only from within patch_apply.
patches
is a List of Patch objects.
Implementation
patch_splitMax(List<Patch> patches) {
final patch_size = Match_MaxBits;
for (var x = 0; x < patches.length; x++) {
if (patches[x].length1 <= patch_size) {
continue;
}
Patch bigpatch = patches[x];
// Remove the big old patch.
patches.removeAt(x--);
var start1 = bigpatch.start1,
start2 = bigpatch.start2;
String precontext = '';
while (bigpatch.diffs.isNotEmpty) {
// Create one of several smaller patches.
final patch = Patch();
bool empty = true;
patch.start1 = start1 - precontext.length;
patch.start2 = start2 - precontext.length;
if (precontext.isNotEmpty) {
patch.length1 = patch.length2 = precontext.length;
patch.diffs.add(Diff(Operation.equal, precontext));
}
while (bigpatch.diffs.isNotEmpty &&
patch.length1 < patch_size - Patch_Margin) {
Operation diff_type = bigpatch.diffs[0].operation;
var diff_text = bigpatch.diffs[0].text;
if (diff_type == Operation.insert) {
// Insertions are harmless.
patch.length2 += diff_text.length;
start2 += diff_text.length;
patch.diffs.add(bigpatch.diffs[0]);
bigpatch.diffs.removeAt(0);
empty = false;
} else if (diff_type == Operation.delete &&
patch.diffs.length == 1 &&
patch.diffs[0].operation == Operation.equal &&
diff_text.length > 2 * patch_size) {
// This is a large deletion. Let it pass in one chunk.
patch.length1 += diff_text.length;
start1 += diff_text.length;
empty = false;
patch.diffs.add(Diff(diff_type, diff_text));
bigpatch.diffs.removeAt(0);
} else {
// Deletion or equality. Only take as much as we can stomach.
diff_text = diff_text.substring(
0,
min(diff_text.length,
patch_size - patch.length1 - Patch_Margin));
patch.length1 += diff_text.length;
start1 += diff_text.length;
if (diff_type == Operation.equal) {
patch.length2 += diff_text.length;
start2 += diff_text.length;
} else {
empty = false;
}
patch.diffs.add(Diff(diff_type, diff_text));
if (diff_text == bigpatch.diffs[0].text) {
bigpatch.diffs.removeAt(0);
} else {
bigpatch.diffs[0].text =
bigpatch.diffs[0].text.substring(diff_text.length);
}
}
}
// Compute the head context for the next patch.
precontext = diff_text2(patch.diffs);
precontext =
precontext.substring(max(0, precontext.length - Patch_Margin));
// Append the end context for this patch.
String postcontext;
if (diff_text1(bigpatch.diffs).length > Patch_Margin) {
postcontext = diff_text1(bigpatch.diffs).substring(0, Patch_Margin);
} else {
postcontext = diff_text1(bigpatch.diffs);
}
if (postcontext.isNotEmpty) {
patch.length1 += postcontext.length;
patch.length2 += postcontext.length;
if (patch.diffs.isNotEmpty &&
patch.diffs.last.operation == Operation.equal) {
patch.diffs.last.text = patch.diffs.last.text + postcontext;
} else {
patch.diffs.add(Diff(Operation.equal, postcontext));
}
}
if (!empty) {
patches.insert(++x, patch);
}
}
}
}