record (int offset, int oldLength, int newLength) { public Fragment { if (offset < 0) throw new IllegalArgumentException("Negative offset"); if (oldLength < 0) throw new IllegalArgumentException("Negative oldLength"); if (newLength < 0) throw new IllegalArgumentException("Negative newLength"); } public @NotNull Fragment shift(int diff) { return diff == 0 ? this : new Fragment(offset + diff, oldLength, newLength); } public boolean intersects(@NotNull Fragment other) { return Math.max(offset, other.offset) <= Math.min(offset + newLength, other.offset + other.oldLength); } private int adjustForward(int pos) { if (pos <= offset) return pos; if (pos <= offset + oldLength) return offset; return pos - oldLength + newLength; } private int adjustForwardLeanRight(int pos) { if (pos < offset) return pos; if (pos <= offset + oldLength) return offset + newLength; return pos - oldLength + newLength; } private int adjustBackward(int pos) { if (pos <= offset) return pos; if (pos <= offset + newLength) return offset; return pos - newLength + oldLength; } public @NotNull Fragment mergeWithNext(@NotNull Fragment next) { int newStartOffset = Math.min(offset, next.offset); int newOrigEndOffset = Math.max(offset + oldLength, adjustBackward(next.offset + next.oldLength)); int newUpdatedEndOffset = Math.max(next.adjustForward(offset + newLength), next.offset + next.newLength); return new Fragment(newStartOffset, newOrigEndOffset - newStartOffset, newUpdatedEndOffset - newStartOffset); } }