in vault-diff/src/main/java/org/apache/jackrabbit/vault/util/diff/DocumentDiff3.java [137:267]
private void initHunks() {
MyChange[] changes = {
wrap(leftChanges),
wrap(rightChanges)
};
int basePos = 0;
Hunk3 hunk = hunks; // the last hunk
while (changes[0] != null || changes[1] != null) {
MyChange[] using = {null, null};
MyChange[] lastUsing = {null, null};
int baseIdx;
if (changes[0] == null) {
baseIdx = 1;
} else if (changes[1] == null) {
baseIdx = 0;
} else {
// use the change that is smaller
baseIdx = changes[0].low0 < changes[1].low0 ? 0 : 1;
}
int highIdx = baseIdx;
int highMark = changes[highIdx].high0;
// add the change to the using set and unchain it
using[highIdx] = lastUsing[highIdx] = changes[highIdx];
changes[highIdx] = changes[highIdx].next;
lastUsing[highIdx].next = null;
int otherIdx = highIdx^1;
MyChange other = changes[otherIdx];
// search for region that ends in a 'void' of changes
// i.e. when the end of the 'other' is greater than the high mark.
//
// a a a
// a a b a b
// b b a
// b
while (other != null && other.low0 <= highMark) {
// add this change to the using set
if (using[otherIdx] == null) {
using[otherIdx] = other;
} else {
using[otherIdx].next = other;
}
lastUsing[otherIdx] = other;
// advance other and unchain it
changes[otherIdx] = changes[otherIdx].next;
other.next = null;
// if the high mark is beyond the end of the other diff
// we're finished
if (other.high0 > highMark) {
// switch roles
highIdx ^= 1;
highMark = other.high0;
}
otherIdx = highIdx^1;
other = changes[otherIdx];
}
// now build the hunks from the set of changes in 'using'
// first deal with the stuff that was common before the first change
int lowMark = using[baseIdx].low0;
if (basePos < lowMark) {
hunk = new Hunk3(
new Range(base, basePos, lowMark),
null,
null,
hunk);
basePos = lowMark;
//System.out.println(hunks.getLast().toString());
}
// get the ranges for the changsets
int[] deltaLow = {0,0};
if (using[baseIdx^1] != null) {
deltaLow[baseIdx^1] = using[baseIdx^1].low0 - using[baseIdx].low0;
}
int[] deltaHigh = {0,0};
if (using[highIdx^1] != null) {
deltaHigh[highIdx^1] = using[highIdx].high0 - using[highIdx^1].high0;
}
Range leftRange = null;
Range rightRange = null;
if (using[0] != null) {
leftRange = new Range(left, using[0].low1 - deltaLow[0], lastUsing[0].high1 + deltaHigh[0]);
}
if (using[1] != null) {
rightRange = new Range(right, using[1].low1 - deltaLow[1], lastUsing[1].high1 + deltaHigh[1]);
}
// check if the conflict is really one
boolean conflict = false;
if (leftRange != null && rightRange != null) {
if (leftRange.len() == rightRange.len()) {
for (int i=0; i< leftRange.len(); i++) {
if (!left.getElements()[leftRange.low + i].equals(right.getElements()[rightRange.low + i])) {
// yes, it is
conflict = true;
break;
}
}
// if all lines match, we can discard one of the ranges
if (!conflict) {
rightRange = null;
}
} else {
conflict = true;
}
}
// get the range for the base
int baseHigh = using[highIdx].high0;
Range baseRange = new Range(base, basePos, baseHigh);
basePos = baseHigh;
// and create new hunk
hunk = new Hunk3(baseRange, leftRange, rightRange, hunk);
hasConflicts |= conflict;
//System.out.println(hunks.getLast().toString());
} /* while */
// deal with last hunk
if (basePos < base.getElements().length) {
new Hunk3(
new Range(base, basePos, base.getElements().length),
null,
null,
hunk);
//System.out.println(hunks.getLast().toString());
}
}