+ create(BiPredicate < T, T > equalizer) {
+ return new MyersDiffWithLinearSpace<>(equalizer);
+ }
+ };
+ }
+}
diff --git a/src/com/github/difflib/algorithm/myers/PathNode.java b/src/com/github/difflib/algorithm/myers/PathNode.java
new file mode 100644
index 00000000..fe8fd03a
--- /dev/null
+++ b/src/com/github/difflib/algorithm/myers/PathNode.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2009-2017 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.algorithm.myers;
+
+/**
+ * A node in a diffpath.
+ *
+ * @author Juanco Anez
+ */
+public final class PathNode {
+
+ /**
+ * Position in the original sequence.
+ */
+ public final int i;
+ /**
+ * Position in the revised sequence.
+ */
+ public final int j;
+ /**
+ * The previous node in the path.
+ */
+ public final PathNode prev;
+
+ public final boolean snake;
+
+ public final boolean bootstrap;
+
+ /**
+ * Concatenates a new path node with an existing diffpath.
+ *
+ * @param i The position in the original sequence for the new node.
+ * @param j The position in the revised sequence for the new node.
+ * @param prev The previous node in the path.
+ */
+ public PathNode(int i, int j, boolean snake, boolean bootstrap, PathNode prev) {
+ this.i = i;
+ this.j = j;
+ this.bootstrap = bootstrap;
+ if (snake) {
+ this.prev = prev;
+ } else {
+ this.prev = prev == null ? null : prev.previousSnake();
+ }
+ this.snake = snake;
+ }
+
+ public boolean isSnake() {
+ return snake;
+ }
+
+ /**
+ * Is this a bootstrap node?
+ *
+ * In bottstrap nodes one of the two corrdinates is less than zero.
+ *
+ * @return tru if this is a bootstrap node.
+ */
+ public boolean isBootstrap() {
+ return bootstrap;
+ }
+
+ /**
+ * Skips sequences of {@link PathNode PathNodes} until a snake or bootstrap node is found, or the end of the
+ * path is reached.
+ *
+ * @return The next first {@link PathNode} or bootstrap node in the path, or null if none found.
+ */
+ public final PathNode previousSnake() {
+ if (isBootstrap()) {
+ return null;
+ }
+ if (!isSnake() && prev != null) {
+ return prev.previousSnake();
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder("[");
+ PathNode node = this;
+ while (node != null) {
+ buf.append("(");
+ buf.append(node.i);
+ buf.append(",");
+ buf.append(node.j);
+ buf.append(")");
+ node = node.prev;
+ }
+ buf.append("]");
+ return buf.toString();
+ }
+}
diff --git a/src/com/github/difflib/patch/AbstractDelta.java b/src/com/github/difflib/patch/AbstractDelta.java
new file mode 100644
index 00000000..f74f62ca
--- /dev/null
+++ b/src/com/github/difflib/patch/AbstractDelta.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2018 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.patch;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Abstract delta between a source and a target.
+ * @author Tobias Warneke (t.warneke@gmx.net)
+ */
+public abstract class AbstractDelta implements Serializable {
+ private final Chunk source;
+ private final Chunk target;
+ private final DeltaType type;
+
+ public AbstractDelta(DeltaType type, Chunk source, Chunk target) {
+ Objects.requireNonNull(source);
+ Objects.requireNonNull(target);
+ Objects.requireNonNull(type);
+ this.type = type;
+ this.source = source;
+ this.target = target;
+ }
+
+ public Chunk getSource() {
+ return source;
+ }
+
+ public Chunk getTarget() {
+ return target;
+ }
+
+ public DeltaType getType() {
+ return type;
+ }
+
+ /**
+ * Verify the chunk of this delta, to fit the target.
+ * @param target
+ * @throws PatchFailedException
+ */
+ protected VerifyChunk verifyChunkToFitTarget(List target) throws PatchFailedException {
+ return getSource().verifyChunk(target);
+ }
+
+ protected VerifyChunk verifyAndApplyTo(List target) throws PatchFailedException {
+ final VerifyChunk verify = verifyChunkToFitTarget(target);
+ if (verify == VerifyChunk.OK) {
+ applyTo(target);
+ }
+ return verify;
+ }
+
+ protected abstract void applyTo(List target) throws PatchFailedException;
+
+ protected abstract void restore(List target);
+
+ /**
+ * Apply patch fuzzy.
+ *
+ * @param target the list this patch will be applied to
+ * @param fuzz the number of elements to ignore before/after the patched elements
+ * @param position the position this patch will be applied to. ignores {@code source.getPosition()}
+ * @see Description of Fuzzy Patch for more information.
+ */
+ @SuppressWarnings("RedundantThrows")
+ protected void applyFuzzyToAt(List target, int fuzz, int position) throws PatchFailedException {
+ throw new UnsupportedOperationException(this.getClass().getSimpleName() + " does not supports applying patch fuzzy");
+ }
+
+ /**
+ * Create a new delta of the actual instance with customized chunk data.
+ */
+ public abstract AbstractDelta withChunks(Chunk original, Chunk revised);
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.source, this.target, this.type);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final AbstractDelta> other = (AbstractDelta>) obj;
+ if (!Objects.equals(this.source, other.source)) {
+ return false;
+ }
+ if (!Objects.equals(this.target, other.target)) {
+ return false;
+ }
+ return this.type == other.type;
+ }
+}
diff --git a/src/com/github/difflib/patch/ChangeDelta.java b/src/com/github/difflib/patch/ChangeDelta.java
new file mode 100644
index 00000000..376fd625
--- /dev/null
+++ b/src/com/github/difflib/patch/ChangeDelta.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2009-2017 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.patch;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Describes the change-delta between original and revised texts.
+ *
+ * @author Dmitry Naumenko
+ * @param The type of the compared elements in the data 'lines'.
+ */
+public final class ChangeDelta extends AbstractDelta {
+
+ /**
+ * Creates a change delta with the two given chunks.
+ *
+ * @param source The source chunk. Must not be {@code null}.
+ * @param target The target chunk. Must not be {@code null}.
+ */
+ public ChangeDelta(Chunk source, Chunk target) {
+ super(DeltaType.CHANGE, source, target);
+ Objects.requireNonNull(source, "source must not be null");
+ Objects.requireNonNull(target, "target must not be null");
+ }
+
+ @Override
+ protected void applyTo(List target) throws PatchFailedException {
+ int position = getSource().getPosition();
+ int size = getSource().size();
+ for (int i = 0; i < size; i++) {
+ target.remove(position);
+ }
+ int i = 0;
+ for (T line : getTarget().getLines()) {
+ target.add(position + i, line);
+ i++;
+ }
+ }
+
+ @Override
+ protected void restore(List target) {
+ int position = getTarget().getPosition();
+ int size = getTarget().size();
+ for (int i = 0; i < size; i++) {
+ target.remove(position);
+ }
+ int i = 0;
+ for (T line : getSource().getLines()) {
+ target.add(position + i, line);
+ i++;
+ }
+ }
+
+ protected void applyFuzzyToAt(List target, int fuzz, int position) throws PatchFailedException {
+ int size = getSource().size();
+ for (int i = fuzz; i < size - fuzz; i++) {
+ target.remove(position + fuzz);
+ }
+
+ int i = fuzz;
+ for (T line : getTarget().getLines().subList(fuzz, getTarget().size() - fuzz)) {
+ target.add(position + i, line);
+ i++;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[ChangeDelta, position: " + getSource().getPosition() + ", lines: "
+ + getSource().getLines() + " to " + getTarget().getLines() + "]";
+ }
+
+ @Override
+ public AbstractDelta withChunks(Chunk original, Chunk revised) {
+ return new ChangeDelta(original, revised);
+ }
+}
diff --git a/src/com/github/difflib/patch/Chunk.java b/src/com/github/difflib/patch/Chunk.java
new file mode 100644
index 00000000..072198a6
--- /dev/null
+++ b/src/com/github/difflib/patch/Chunk.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2009-2017 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.patch;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Holds the information about the part of text involved in the diff process
+ *
+ *
+ * Text is represented as Object[] because the diff engine is
+ * capable of handling more than plain ascci. In fact, arrays or lists of any
+ * type that implements {@link Object#hashCode hashCode()} and
+ * {@link Object#equals equals()} correctly can be subject to
+ * differencing using this library.
+ *
+ *
+ * @author extends Serializable {
+
+ public void processConflict(VerifyChunk verifyChunk, AbstractDelta delta, List result) throws PatchFailedException;
+}
diff --git a/src/com/github/difflib/patch/DeleteDelta.java b/src/com/github/difflib/patch/DeleteDelta.java
new file mode 100644
index 00000000..890b8575
--- /dev/null
+++ b/src/com/github/difflib/patch/DeleteDelta.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009-2017 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.patch;
+
+import java.util.List;
+
+/**
+ * Describes the delete-delta between original and revised texts.
+ *
+ * @author Dmitry Naumenko
+ * @param The type of the compared elements in the 'lines'.
+ */
+public final class DeleteDelta extends AbstractDelta {
+
+ /**
+ * Creates a change delta with the two given chunks.
+ *
+ * @param original The original chunk. Must not be {@code null}.
+ * @param revised The original chunk. Must not be {@code null}.
+ */
+ public DeleteDelta(Chunk original, Chunk revised) {
+ super(DeltaType.DELETE, original, revised);
+ }
+
+ @Override
+ protected void applyTo(List target) throws PatchFailedException {
+ int position = getSource().getPosition();
+ int size = getSource().size();
+ for (int i = 0; i < size; i++) {
+ target.remove(position);
+ }
+ }
+
+ @Override
+ protected void restore(List target) {
+ int position = this.getTarget().getPosition();
+ List lines = this.getSource().getLines();
+ for (int i = 0; i < lines.size(); i++) {
+ target.add(position + i, lines.get(i));
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[DeleteDelta, position: " + getSource().getPosition() + ", lines: "
+ + getSource().getLines() + "]";
+ }
+
+ @Override
+ public AbstractDelta withChunks(Chunk original, Chunk revised) {
+ return new DeleteDelta(original, revised);
+ }
+}
diff --git a/src/com/github/difflib/patch/DeltaType.java b/src/com/github/difflib/patch/DeltaType.java
new file mode 100644
index 00000000..666e803a
--- /dev/null
+++ b/src/com/github/difflib/patch/DeltaType.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.patch;
+
+/**
+ * Specifies the type of the delta. There are three types of modifications from
+ * the original to get the revised text.
+ *
+ * CHANGE: a block of data of the original is replaced by another block of data.
+ * DELETE: a block of data of the original is removed
+ * INSERT: at a position of the original a block of data is inserted
+ *
+ * to be complete there is also
+ *
+ * EQUAL: a block of data of original and the revised text is equal
+ *
+ * which is no change at all.
+ *
+ */
+public enum DeltaType {
+ /**
+ * A change in the original.
+ */
+ CHANGE,
+ /**
+ * A delete from the original.
+ */
+ DELETE,
+ /**
+ * An insert into the original.
+ */
+ INSERT,
+ /**
+ * An do nothing.
+ */
+ EQUAL
+}
diff --git a/src/com/github/difflib/patch/DiffException.java b/src/com/github/difflib/patch/DiffException.java
new file mode 100644
index 00000000..da01d621
--- /dev/null
+++ b/src/com/github/difflib/patch/DiffException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009-2017 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.patch;
+
+/**
+ * Base class for all exceptions emanating from this package.
+ *
+ * @author Juanco Anez
+ */
+public class DiffException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public DiffException() {
+ }
+
+ public DiffException(String msg) {
+ super(msg);
+ }
+}
diff --git a/src/com/github/difflib/patch/EqualDelta.java b/src/com/github/difflib/patch/EqualDelta.java
new file mode 100644
index 00000000..17fdadc6
--- /dev/null
+++ b/src/com/github/difflib/patch/EqualDelta.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2020 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.patch;
+
+import java.util.List;
+
+/**
+ * This delta contains equal lines of data. Therefore nothing is to do in applyTo and restore.
+ * @author tobens
+ */
+public class EqualDelta extends AbstractDelta {
+
+ public EqualDelta(Chunk source, Chunk target) {
+ super(DeltaType.EQUAL, source, target);
+ }
+
+ @Override
+ protected void applyTo(List target) throws PatchFailedException {
+ }
+
+ @Override
+ protected void restore(List target) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void applyFuzzyToAt(List target, int fuzz, int delta) {
+ // equals so no operations
+ }
+
+ @Override
+ public String toString() {
+ return "[EqualDelta, position: " + getSource().getPosition() + ", lines: "
+ + getSource().getLines() + "]";
+ }
+
+ @Override
+ public AbstractDelta withChunks(Chunk original, Chunk revised) {
+ return new EqualDelta(original, revised);
+ }
+}
diff --git a/src/com/github/difflib/patch/InsertDelta.java b/src/com/github/difflib/patch/InsertDelta.java
new file mode 100644
index 00000000..6cff9103
--- /dev/null
+++ b/src/com/github/difflib/patch/InsertDelta.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009-2017 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.patch;
+
+import java.util.List;
+
+/**
+ * Describes the add-delta between original and revised texts.
+ *
+ * @author Dmitry Naumenko
+ * @param The type of the compared elements in the 'lines'.
+ */
+public final class InsertDelta extends AbstractDelta {
+
+ /**
+ * Creates an insert delta with the two given chunks.
+ *
+ * @param original The original chunk. Must not be {@code null}.
+ * @param revised The original chunk. Must not be {@code null}.
+ */
+ public InsertDelta(Chunk original, Chunk revised) {
+ super(DeltaType.INSERT, original, revised);
+ }
+
+ @Override
+ protected void applyTo(List target) throws PatchFailedException {
+ int position = this.getSource().getPosition();
+ List lines = this.getTarget().getLines();
+ for (int i = 0; i < lines.size(); i++) {
+ target.add(position + i, lines.get(i));
+ }
+ }
+
+ @Override
+ protected void restore(List target) {
+ int position = getTarget().getPosition();
+ int size = getTarget().size();
+ for (int i = 0; i < size; i++) {
+ target.remove(position);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[InsertDelta, position: " + getSource().getPosition()
+ + ", lines: " + getTarget().getLines() + "]";
+ }
+
+ @Override
+ public AbstractDelta withChunks(Chunk original, Chunk revised) {
+ return new InsertDelta(original, revised);
+ }
+}
diff --git a/src/com/github/difflib/patch/Patch.java b/src/com/github/difflib/patch/Patch.java
new file mode 100644
index 00000000..aaff7d94
--- /dev/null
+++ b/src/com/github/difflib/patch/Patch.java
@@ -0,0 +1,344 @@
+/*-
+ * #%L
+ * java-diff-utils
+ * %%
+ * Copyright (C) 2009 - 2017 java-diff-utils
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ * #L%
+ */
+package com.github.difflib.patch;
+
+import static java.util.Comparator.comparing;
+import com.github.difflib.algorithm.Change;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * Describes the patch holding all deltas between the original and revised
+ * texts.
+ *
+ * @author Dmitry Naumenko
+ * @param The type of the compared elements in the 'lines'.
+ */
+public final class Patch implements Serializable {
+
+ private final List> deltas;
+
+ public Patch() {
+ this(10);
+ }
+
+ public Patch(int estimatedPatchSize) {
+ deltas = new ArrayList<>(estimatedPatchSize);
+ }
+
+ /**
+ * Creates a new list, the patch is being applied to.
+ *
+ * @param target The list to apply the changes to.
+ * @return A new list containing the applied patch.
+ * @throws PatchFailedException if the patch cannot be applied
+ */
+ public List applyTo(List target) throws PatchFailedException {
+ List result = new ArrayList<>(target);
+ applyToExisting(result);
+ return result;
+ }
+
+ /**
+ * Applies the patch to the supplied list.
+ *
+ * @param target The list to apply the changes to. This list has to be modifiable,
+ * otherwise exceptions may be thrown, depending on the used type of list.
+ * @throws PatchFailedException if the patch cannot be applied
+ * @throws RuntimeException (or similar) if the list is not modifiable.
+ */
+ public void applyToExisting(List target) throws PatchFailedException {
+ ListIterator> it = getDeltas().listIterator(deltas.size());
+ while (it.hasPrevious()) {
+ AbstractDelta delta = it.previous();
+ VerifyChunk valid = delta.verifyAndApplyTo(target);
+ if (valid != VerifyChunk.OK) {
+ conflictOutput.processConflict(valid, delta, target);
+ }
+ }
+ }
+
+ private static class PatchApplyingContext {
+ public final List result;
+ public final int maxFuzz;
+
+ // the position last patch applied to.
+ public int lastPatchEnd = -1;
+
+ ///// passing values from find to apply
+ public int currentFuzz = 0;
+
+ public int defaultPosition;
+ public boolean beforeOutRange = false;
+ public boolean afterOutRange = false;
+
+ private PatchApplyingContext(List result, int maxFuzz) {
+ this.result = result;
+ this.maxFuzz = maxFuzz;
+ }
+ }
+
+ public List applyFuzzy(List target, int maxFuzz) throws PatchFailedException {
+ PatchApplyingContext ctx = new PatchApplyingContext<>(new ArrayList<>(target), maxFuzz);
+
+ // the difference between patch's position and actually applied position
+ int lastPatchDelta = 0;
+
+ for (AbstractDelta