2 *******************************************************************************
3 * Copyright (C) 1996-2009, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
8 package com.ibm.icu.impl;
10 /** VERY Basic Diff program. Compares two sequences of objects fed into it, and
11 * lets you know where they are different.
16 final public class Differ<T> {
17 // public static final String copyright =
18 // "Copyright (C) 2010, International Business Machines Corporation and others. All Rights Reserved.";
21 * @param stackSize The size of the largest difference you expect.
22 * @param matchCount The number of items that have to be the same to count as a match
24 @SuppressWarnings("unchecked")
25 public Differ(int stackSize, int matchCount) {
26 this.STACKSIZE = stackSize;
27 this.EQUALSIZE = matchCount;
28 a = (T[]) new Object[stackSize+matchCount];
29 b = (T[]) new Object[stackSize+matchCount];
32 public void add (T aStr, T bStr) {
37 public void addA (T aStr) {
42 public void addB (T bStr) {
47 public int getALine(int offset) {
48 return aLine + maxSame + offset;
51 public T getA(int offset) {
52 if (offset < 0) return last;
53 if (offset > aTop-maxSame) return next;
57 public int getACount() {
61 public int getBCount() {
65 public int getBLine(int offset) {
66 return bLine + maxSame + offset;
69 public T getB(int offset) {
70 if (offset < 0) return last;
71 if (offset > bTop-maxSame) return next;
75 public void checkMatch(boolean finalPass) {
76 // find the initial strings that are the same
78 if (max > bCount) max = bCount;
80 for (i = 0; i < max; ++i) {
81 if (!a[i].equals(b[i])) break;
83 // at this point, all items up to i are equal
85 aTop = bTop = maxSame;
86 if (maxSame > 0) last = a[maxSame-1];
96 if (aCount - maxSame < EQUALSIZE || bCount - maxSame < EQUALSIZE) return;
98 // now see if the last few a's occur anywhere in the b's, or vice versa
99 int match = find (a, aCount-EQUALSIZE, aCount, b, maxSame, bCount);
101 aTop = aCount-EQUALSIZE;
106 match = find (b, bCount-EQUALSIZE, bCount, a, maxSame, aCount);
108 bTop = bCount-EQUALSIZE;
113 if (aCount >= STACKSIZE || bCount >= STACKSIZE) {
114 // flush some of them
115 aCount = (aCount + maxSame) / 2;
116 bCount = (bCount + maxSame) / 2;
121 /** Convenient utility
122 * finds a segment of the first array in the second array.
123 * @return -1 if not found, otherwise start position in b
126 public int find (T[] aArr, int aStart, int aEnd, T[] bArr, int bStart, int bEnd) {
127 int len = aEnd - aStart;
128 int bEndMinus = bEnd - len;
130 for (int i = bStart; i <= bEndMinus; ++i) {
131 for (int j = 0; j < len; ++j) {
132 if (!bArr[i + j].equals(aArr[aStart + j])) continue tryA;
134 return i; // we have a match!
139 // ====================== PRIVATES ======================
141 private void flush() {
143 int newCount = aCount-aTop;
144 System.arraycopy(a, aTop, a, 0, newCount);
151 int newCount = bCount-bTop;
152 System.arraycopy(b, bTop, b, 0, newCount);
159 private int STACKSIZE;
160 private int EQUALSIZE;
164 private T last = null;
165 private T next = null;
166 private int aCount = 0;
167 private int bCount = 0;
168 private int aLine = 1;
169 private int bLine = 1;
170 private int maxSame = 0, aTop = 0, bTop = 0;