001: /*
002:
003: Derby - Class org.apache.derbyTesting.functionTests.harness.SimpleDiff
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: //SimpleDiff.java
023: package org.apache.derbyTesting.functionTests.harness;
024:
025: import java.io.IOException;
026: import java.io.BufferedInputStream;
027: import java.util.Vector;
028: import java.io.File;
029: import java.io.PrintWriter;
030: import java.io.BufferedReader;
031: import java.io.FileReader;
032:
033: public class SimpleDiff {
034:
035: PrintWriter pw;
036:
037: boolean debugOn = Boolean.getBoolean("simplediff.debug");
038: int debugLevel = 1;
039:
040: boolean diffsFound = true;
041:
042: int lookAhead = 20;
043:
044: public void debug(int level, String msg) {
045: if (debugLevel >= level) {
046: debug(msg);
047: }
048: }
049:
050: public void debug(String msg) {
051: if (debugOn) {
052: System.out.println("DEBUG: " + msg);
053: }
054: }
055:
056: int lineCount(String file) throws IOException {
057: BufferedReader input = new BufferedReader(new FileReader(file));
058: int count = 0;
059: String aLine = input.readLine();
060: while (aLine != null) {
061: count++;
062: aLine = input.readLine();
063: }
064: input.close();
065: return count;
066: }
067:
068: public String[] readFile(BufferedReader input) throws IOException {
069:
070: Vector vec = new Vector();
071:
072: String aLine = "";
073: //int count = 0;
074: aLine = input.readLine();
075: while (aLine != null) {
076: vec.addElement(aLine);
077: //count++;
078: aLine = input.readLine();
079: }
080: input.close();
081:
082: String rV[] = new String[vec.size()];
083: //debug(2, ""+count + " lines in " + filename);
084: debug(2, "" + vec.size() + " lines in input");
085: vec.copyInto(rV);
086:
087: return rV;
088: }
089:
090: public void printFile(String file[]) {
091: for (int i = 0; i < file.length; i++) {
092: pw.println(i + ": " + file[i]);
093: System.out.println(i + ": " + file[i]);
094: }
095: }
096:
097: public static String usage = "java SimpleDiff <file1> <file2>";
098:
099: /**
100: @param filename Name of file to be read
101: @return String array of file contents
102: @exception IOException thrown by underlying calls
103: to the file system
104: */
105:
106: public String[] diffFiles(DiffBuffer file1, DiffBuffer file2)
107: throws IOException {
108:
109: int currentLine1 = 0;
110: int currentLine2 = 0;
111: Vector returnVec = new Vector();
112:
113: while (file1.isValidOffset(currentLine1)
114: && file2.isValidOffset(currentLine2)) {
115: String f1 = file1.lineAt(currentLine1);
116: String f2 = file2.lineAt(currentLine2);
117:
118: if (f1.equals(f2)) {
119: debug(1, currentLine1 + ": match");
120: currentLine1++;
121: currentLine2++;
122: file1.setLowWater(currentLine1);
123: file2.setLowWater(currentLine2);
124: } else {
125: boolean foundMatch = false;
126: int checkLine2 = currentLine2;
127: int checkCount = 1;
128: // while ( (currentLine2 + checkCount) < (file2Length - 1) &&
129: while (file2.isValidOffset(currentLine2 + checkCount)
130: && checkCount < lookAhead) {
131: debug(1, "currentLine1 " + currentLine1
132: + " currentLine2 "
133: + (currentLine2 + checkCount));
134: debug(1, "about to reference file2["
135: + (currentLine2 + checkCount) + "]");
136: f2 = file2.lineAt(currentLine2 + checkCount);
137: debug(2, "did");
138: if (f1.equals(f2)) {
139: foundMatch = true;
140: if (checkCount > 1) {
141: returnVec.addElement(currentLine1 + "a"
142: + (currentLine2 + 1) + ","
143: + (currentLine2 + checkCount));
144: } else {
145: returnVec.addElement(currentLine1 + "a"
146: + (currentLine2 + 1));
147: }
148:
149: for (int j = 0; j < checkCount; j++) {
150: returnVec.addElement("> "
151: + file2.lineAt(currentLine2 + j));
152: }
153: currentLine2 = currentLine2 + checkCount;
154: checkCount = 0;
155:
156: // This break statement was commented out, which
157: // caused problems in the diff output. I don't
158: // know why it was commented out, and uncommenting
159: // it fixed the problem.
160: //
161: // - Jeff Lichtman
162: // March 24, 1999
163: break;
164: }
165: checkCount++;
166: }
167: if (!foundMatch && file2.isValidOffset(currentLine2)) {
168: int checkLine1 = currentLine1;
169: checkCount = 1;
170: f2 = file2.lineAt(currentLine2);
171: while (file1.isValidOffset(currentLine1
172: + checkCount)
173: && checkCount < lookAhead) {
174: debug(1, "currentLine2 " + currentLine2
175: + " currentLine1 "
176: + (currentLine1 + checkCount));
177: f1 = file1.lineAt(currentLine1 + checkCount);
178: if (f2.equals(f1)) {
179: foundMatch = true;
180: if (checkCount > 1) {
181: returnVec.addElement((currentLine1 + 1)
182: + ","
183: + (currentLine1 + checkCount)
184: + "d" + currentLine2);
185: } else {
186: returnVec.addElement((currentLine1 + 1)
187: + "d" + currentLine2);
188: }
189:
190: for (int j = 0; j < checkCount; j++) {
191: returnVec.addElement("< "
192: + file1
193: .lineAt(currentLine1
194: + j));
195:
196: }
197: currentLine1 = currentLine1 + checkCount;
198: checkCount = 0;
199: debug(1, "continuing");
200: break;
201: }
202: checkCount++;
203: }
204:
205: }
206: if (!foundMatch) {
207: debug(1, currentLine1 + ": NOMATCH");
208: returnVec.addElement((currentLine1 + 1) + " del");// + (currentLine2 + 1));
209: returnVec.addElement("< "
210: + file1.lineAt(currentLine1));
211: currentLine1++;
212: } else {
213: currentLine1++;
214: currentLine2++;
215: file1.setLowWater(currentLine1);
216: file2.setLowWater(currentLine2);
217: }
218: }
219: }
220:
221: if (file1.isValidOffset(currentLine1)) {
222: returnVec.addElement((currentLine2) + " del");
223: for (int i = currentLine1; file1.isValidOffset(i); i++) {
224: returnVec.addElement("< " + file1.lineAt(i));
225: }
226: }
227: if (file2.isValidOffset(currentLine2)) {
228: returnVec.addElement((currentLine1) + " add");
229: for (int i = currentLine2; file2.isValidOffset(i); i++) {
230: returnVec.addElement("> " + file2.lineAt(i));
231: }
232: }
233:
234: file1.close();
235: file2.close();
236:
237: if (returnVec.size() == 0) {
238: return null;
239: }
240:
241: String[] returnArray = new String[returnVec.size()];
242: returnVec.copyInto(returnArray);
243: return returnArray;
244:
245: }
246:
247: private void reportMemory() {
248: reportMemory(null);
249: }
250:
251: private void reportMemory(String header) {
252: if (header != null) {
253: System.out.println(header);
254: }
255: long free = Runtime.getRuntime().freeMemory();
256: long total = Runtime.getRuntime().totalMemory();
257:
258: System.out.println("total: " + total);
259: System.out.println("free: " + free);
260: System.out.println("used: " + (total - free));
261: System.gc();
262: System.out.println("used: <postgc> "
263: + (Runtime.getRuntime().totalMemory() - Runtime
264: .getRuntime().freeMemory()));
265: System.out.println(" ");
266: }
267:
268: public boolean doWork(BufferedReader in1, BufferedReader in2,
269: PrintWriter localPW) throws IOException {
270: this .pw = (localPW == null ? new PrintWriter(System.out)
271: : localPW);
272: try {
273: DiffBuffer db1 = new DiffBuffer(in1, "1");
274: DiffBuffer db2 = new DiffBuffer(in2, "2");
275:
276: String diffs[] = diffFiles(db1, db2);
277:
278: if (diffs == null) {
279: debug(1, "no diff");
280: return false;
281: } else {
282: for (int i = 0; i < diffs.length; i++) {
283: this .pw.println(diffs[i]);
284: System.out.println(diffs[i]);
285: }
286: }
287:
288: } catch (IOException ioe) {
289: System.err.println("IOException comparing <" + in1
290: + "> and <" + in2 + ">");
291: System.err.println(ioe);
292:
293: this .pw.println("IOException comparing <" + in1 + "> and <"
294: + in2 + ">");
295: this .pw.println(ioe);
296: }
297: return true;
298: }
299:
300: public static void main(String args[]) throws IOException {
301:
302: if (args.length < 2) {
303: System.err.println("Invalid number of arguments");
304: System.err.println("Usage: " + usage);
305: System.exit(1);
306: }
307:
308: SimpleDiff me = new SimpleDiff();
309:
310: try {
311: BufferedReader br1 = new BufferedReader(new FileReader(
312: args[0]));
313: BufferedReader br2 = new BufferedReader(new FileReader(
314: args[1]));
315: me.doWork(br1, br2, null);
316: } catch (IOException ioe) {
317: System.out.println("IOExeption: " + ioe);
318: }
319: }
320:
321: public void pause() {
322: BufferedInputStream bis = new BufferedInputStream(System.in);
323: try {
324: bis.read();
325: } catch (IOException ioe) {
326: pw.println("Error trying to pause...");
327: System.out.println("Error trying to pause...");
328: }
329: }
330:
331: class DiffBuffer extends Vector {
332:
333: public boolean atEOF() {
334: return atEnd;
335: }
336:
337: public DiffBuffer(BufferedReader rb) {
338: this (rb, "");
339: }
340:
341: public DiffBuffer(BufferedReader rb, String name) {
342: this (rb, name, 1024);
343: }
344:
345: public DiffBuffer(BufferedReader rb, String name, int size) {
346: super (size);
347: readBuffer = rb;
348: currentLowWater = 0;
349: currentHighWater = -1;
350: oldLow = 0;
351: myName = name;
352: atEnd = false;
353: }
354:
355: public boolean isValidOffset(int lineNumber) throws IOException {
356: if (atEnd) {
357: return lineNumber <= actualEndOfFile;
358: }
359:
360: if (lineAt(lineNumber) == null) {
361: return false;
362: }
363: return true;
364: }
365:
366: public String lineAt(int offset) throws IOException {
367: /*
368: System.out.println("offset: " + offset);
369: System.out.println("currentHighWater: " + currentHighWater);
370: System.out.println("");
371: */
372: if (offset > currentHighWater) {
373: for (int i = 0; i < offset - currentHighWater; i++) {
374: String aLine = readBuffer.readLine();
375: addElement(aLine);
376: /*
377: System.out.println("aLine: " + aLine);
378: */
379: if (aLine == null) {
380: if (!atEnd) {
381: //first time we've tried to read past the EOF
382: actualEndOfFile = currentHighWater + i;
383: //System.out.println(myName + ": length " + actualEndOfFile);
384: atEnd = true;
385: }
386: }
387: }
388: currentHighWater = offset;
389: }
390: return (String) elementAt(offset);
391: }
392:
393: public final String EMPTY = null;
394: protected BufferedReader readBuffer;
395: protected int currentLowWater;
396: protected int currentHighWater;
397: private int oldLow;
398: protected String myName;
399: protected boolean atEnd;
400: protected int actualEndOfFile;
401:
402: /**
403: Useful to keep memory requirements low
404: */
405: public void setLowWater(int newLow) {
406:
407: for (int i = oldLow; i < newLow; i++) {
408: setElementAt(EMPTY, i);
409: }
410: currentLowWater = newLow;
411: oldLow = newLow - 1;
412: }
413:
414: public void iterate(boolean verbose) {
415: int nulls = 0;
416: int nonnulls = 0;
417:
418: for (int i = 0; i < this .size(); i++) {
419: if (elementAt(i) == null) {
420: if (verbose) {
421: System.out.print("[" + i + "] ");
422: System.out.println("null");
423: }
424: nulls++;
425:
426: } else {
427: if (verbose) {
428: System.out.print("[" + i + "] ");
429: System.out.println("NotNULL");
430: }
431: nonnulls++;
432: }
433: }
434: System.out.println("nulls: " + nulls + " nonNull: "
435: + nonnulls);
436: }
437:
438: public void close() throws IOException {
439: // System.out.println("Closing BufferedReader");
440: readBuffer.close();
441: readBuffer = null;
442: }
443: }
444:
445: }
|