patch_splitMax method

dynamic patch_splitMax(
  1. List<Patch> patches
)

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);
      }
    }
  }
}