/* * SubstringDiff.java * * Copyright (C) 2009-12 by RStudio, Inc. * * Unless you have received this program directly from RStudio pursuant * to the terms of a commercial license agreement with RStudio, then * this program is licensed to you under the terms of version 3 of the * GNU Affero General Public License. This program is distributed WITHOUT * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. * */ package org.rstudio.core.client.patch; public class SubstringDiff { public SubstringDiff(String origVal, String newVal) { // Figure out how many characters at the beginning of the two strings // are identical. int headLimit = Math.min(origVal.length(), newVal.length()); int head; for (head = 0; head < headLimit && origVal.charAt(head) == newVal.charAt(head); head++) {} // Figure out how many characters at the end of the two strings are // identical, but don't go past the range we established in the above // step (i.e., anything already in the head can't be part of the tail). int tailDelta = newVal.length() - origVal.length(); int tailLimit = Math.max(head, head - tailDelta); int tail; for (tail = origVal.length(); tail > tailLimit && origVal.charAt(tail-1) == newVal.charAt(tail+tailDelta-1); tail--) {} // Now we have a chunk of newVal that is unique (it may simply be "") // and offset_/length_ show what region within oldDoc it replaces. replacement_ = newVal.substring(head, tail + tailDelta); offset_ = head; length_ = tail - head; } public String getReplacement() { return replacement_; } public int getOffset() { return offset_; } public int getLength() { return length_; } public String patch(String original) { if (isEmpty()) return original; return original.substring(0, offset_) + replacement_ + original.substring(offset_ + length_); } /** * @return True iff there was no difference between the strings. */ public boolean isEmpty() { return length_ == 0 && replacement_.length() == 0; } private final int offset_; private final int length_; private final String replacement_; /* public static void test() { test("", "", 0, 0, ""); test("a", "a", 1, 0, ""); test("ab", "ab", 2, 0, ""); test("ab", "a", 1, 1, ""); test("abc", "ac", 1, 1, ""); test("abc", "adc", 1, 1, "d"); test("abc", "bc", 0, 1, ""); test("bc", "abc", 0, 0, "a"); test("a\nb\nc", "a\nc", 2, 2, ""); } static void test(String old, String neu, int offset, int len, String repl) { SubstringDiff diff = new SubstringDiff(old, neu); assert diff.getOffset() == offset && diff.getLength() == len && diff.getReplacement().equals(repl) : "\"" + old + "\" - \"" + neu + "\" => " + "\"" + diff.getReplacement() + "\" [" + diff.getOffset() + ", " + diff.getLength() + "]"; assert diff.patch(old).equals(neu); } */ }