Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package de.schildbach.pte.util;
/*
* Copyright (C) 1997 Roger Whitney
*
* This file is part of the San Diego State University Java Library.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
import java.io.BufferedReader;
import java.io.FilterReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
/**
* Given a string pattern, a string replacementPattern and an input stream, this class will
* replace all occurrences of pattern with replacementPattern in the inputstream. You can give
* multiple pattern-replacementPattern pairs. Multiple pairs are done in order they are given. If first pair
* is "cat"-"dog" and second pair is "dog"-"house", then the result will be all occurrences of "cat" or "dog"
* will be replaced with "house".
*
* @version 0.6 21 August 1997
* @since version 0.5, Fixed error that occurred when input was shorter than the pattern
* @author Roger Whitney ([email protected])
*/
public class StringReplaceReader extends FilterReader implements Cloneable {
protected CharQueue outputBuffer; // holds filtered data
protected char[] inputBuffer;
protected int[] shiftTable; // quick search shift table
protected int inputBufferCharCount; // number of chars in inputBuffer
protected char[] patternToFind = null;
protected char[] replacementPattern = null;
protected boolean reachedEOF = false;
protected static int EOFIndicator = -1;
protected static int DEFAULT_BUFFER_SIZE = 1024;
/**
* Create an StringReplaceReader object that will replace all occurrences of pattern with
* replacementPattern in the Reader in.
*/
public StringReplaceReader(Reader in, String pattern, String replacementPattern) {
super(in);
patternToFind = pattern.toCharArray();
this.replacementPattern = replacementPattern.toCharArray();
allocateBuffers();
}
/**
* Create an StringReplaceReader object that will replace all occurrences of pattern with
* replacementPattern in the inputstream in.
*/
public StringReplaceReader(InputStream in, String pattern, String replacementPattern) {
this(new BufferedReader(new InputStreamReader(in)), pattern, replacementPattern);
}
/**
* Create an StringReplaceReader object that will replace all occurrences of pattern with
* replacementPattern in the string input.
*/
public StringReplaceReader(String input, String pattern, String replacementPattern) {
this(new StringReader(input), pattern, replacementPattern);
}
/**
* Returns the entire contents of the input stream.
*/
public String contents() throws IOException {
StringBuffer contents = new StringBuffer(1024);
int readSize = 512;
char[] filteredChars = new char[readSize];
int charsRead = read(filteredChars, 0, readSize);
while (charsRead != EOFIndicator) {
contents.append(filteredChars, 0, charsRead);
charsRead = read(filteredChars, 0, readSize);
}
return contents.toString();
}
/**
* Adds another pattern-replacementPattern pair. All occurrences of pattern will be replaced with
* replacementPattern.
*
* @exception OutOfMemoryError
* if there is not enough memory to add new pattern-replacementPattern pair
*/
public void replace(String pattern, String replacementPattern) throws OutOfMemoryError {
// Chain StringReplaceReader objects. Clone current object
// add clone to input stream to insure it filters before this
// object, which gets the new pattern-replacement pair
if (patternToFind != null) {
// Replace this with clone
try {
StringReplaceReader currentReplace = (StringReplaceReader) this.clone();
in = currentReplace;
} catch (CloneNotSupportedException x) {
}
}
patternToFind = pattern.toCharArray();
this.replacementPattern = replacementPattern.toCharArray();
allocateBuffers();
reachedEOF = false;
}
/**
* Read characters into a portion of an array. This method will block until some input is available, an
* I/O error occurs, or the end of the stream is reached.
*
* @parm buffer Destination buffer
* @parm offset location in buffer to start storing characters
* @parm charsToRead maximum characters to read
* @return number of characters actually read, -1 if reach EOF on reading first character
* @exception IOException
* if an I/O error occurs
*/
@Override
public int read(char[] buffer, int offset, int charsToRead) throws IOException {
int charsRead = 0;
while ((charsRead < charsToRead) && (!eof())) {
if (outputBuffer.isEmpty()) {
fillInputWindow();
filterInput();
}
charsRead += outputBuffer.dequeue(buffer, offset + charsRead, charsToRead - charsRead);
}
if (charsRead > 0)
return charsRead;
else if (outputBuffer.size() > 0) {
charsRead = outputBuffer.dequeue(buffer, offset, charsToRead);
return charsRead;
} else if ((eof()) && (inputBufferCharCount > 0) && (inputBufferCharCount < patternToFind.length)) {
// remaining input is less than length of pattern
transferRemainingInputToOutputBuffer();
charsRead = outputBuffer.dequeue(buffer, offset, charsToRead);
return charsRead;
} else if (eof())
return EOFIndicator;
else
// this should never happen
throw new IOException("Read attempted. Did not reach EOF and " + " no chars were read");
}
/**
* Call when remaining input is less than the pattern size, so pattern can not exist in remaining input.
* Just shift all input to output. Assumes that have reached EOF and inputBufferCharCount <
* patternToFind.length
*/
private void transferRemainingInputToOutputBuffer() {
outputBuffer.enqueue(inputBuffer, 0, inputBufferCharCount);
inputBufferCharCount = 0;
}
/**
* Returns the next character in the inputstream with string replacement done.
*
* @exception IOException
* if error occurs reading io stream
*/
@Override
public int read() throws IOException {
char[] output = new char[1];
int charsRead = read(output, 0, 1);
if (charsRead == EOFIndicator)
return EOFIndicator;
else if (charsRead == 1)
return output[0];
else
throw new IOException("Single Read attempted. Did not reach EOF and " + " no chars were read");
}
/**
* Determines if a previous ASCII I/O operation caught End Of File.
*
* @return true if end of file was reached.
*/
public boolean eof() {
return reachedEOF;
}
/**
* Read input to see if we have found the pattern. Requires: When this is called we have already
* have read first character in pattern.
* Side Effects: After attempt to find pattern, output buffer contains either the replacement
* pattern or all characters we know are not part of pattern.
*/
protected void filterInput() throws IOException {
// Use quick-search to find pattern. Fill inputBuffer with text.
// Process all text in inputBuffer. Place processed text in
// outputBuffer.
int searchStart = 0;
int windowStart = 0;
int patternLength = patternToFind.length;
// Search until pattern extends past end of inputBuffer
while (searchStart < inputBufferCharCount - patternLength + 1) {
boolean foundPattern = true;
// The search
for (int index = 0; index < patternLength; index++)
if (patternToFind[index] != inputBuffer[index + searchStart]) {
foundPattern = false;
break; // for loop
}
if (foundPattern) {
// move text before pattern
outputBuffer.enqueue(inputBuffer, windowStart, searchStart - windowStart);
replacementPatternToBuffer();
windowStart = searchStart + patternLength;
searchStart = windowStart;
} else {
// look farther along in inputBuffer
int charLocationAfterPattern = searchStart + patternLength;
if (charLocationAfterPattern >= inputBufferCharCount)
searchStart += 1;
else
searchStart += getShift(inputBuffer[charLocationAfterPattern]);
}
}
if (searchStart > inputBufferCharCount)
searchStart = inputBufferCharCount;
// move chars already searched
if (reachedEOF) {
outputBuffer.enqueue(inputBuffer, windowStart, inputBufferCharCount - windowStart);
inputBufferCharCount = 0;
} else {
outputBuffer.enqueue(inputBuffer, windowStart, searchStart - windowStart);
System.arraycopy(inputBuffer, searchStart, inputBuffer, 0, inputBufferCharCount - searchStart);
inputBufferCharCount = inputBufferCharCount - searchStart;
}
}
/**
* Fill sliding input window with chars from input Read until window is full or reach EOF
*/
final protected void fillInputWindow() throws IOException {
int charsToRead = inputBuffer.length - inputBufferCharCount;
int firstEmptySlotInWindow = inputBufferCharCount;
int charsRead = in.read(inputBuffer, firstEmptySlotInWindow, charsToRead);
if (charsRead == charsToRead) // full read
{
inputBufferCharCount = inputBufferCharCount + charsRead;
charsToRead = 0;
} else if (charsRead > 0) // parial read
{
inputBufferCharCount = inputBufferCharCount + charsRead;
charsToRead = charsToRead - charsRead;
} else if (charsRead == EOFIndicator) {
reachedEOF = true;
} else
throw new IOException("Read attempted. Did not reach EOF and " + " no chars were read");
}
/**
* Return the number of positions we can shift pattern when findMyShift is character in inputBuffer after
* the pattern
*/
protected int getShift(char findMyShift) {
if (findMyShift >= shiftTable.length)
return 1;
else
return shiftTable[findMyShift];
}
/**
* Put replacement pattern in output buffer. Subclass overrides for more complex replacement
*/
protected void replacementPatternToBuffer() {
outputBuffer.enqueue(replacementPattern);
}
private void allocateBuffers() {
outputBuffer = new CharQueue(DEFAULT_BUFFER_SIZE);
inputBuffer = new char[Math.max(patternToFind.length + 1, DEFAULT_BUFFER_SIZE)];
inputBufferCharCount = 0;
// allocate for most ascii characters
shiftTable = new int[126];
// build shiftTable for quick search
// Entry for character X contains how far to shift
// pattern when pattern does not match text and
// character X is the character in text after end of
// pattern
// Default for characters not in pattern
for (int k = 0; k < shiftTable.length; k++)
shiftTable[k] = patternToFind.length + 1;
for (int k = 0; k < patternToFind.length; k++)
if (patternToFind[k] < shiftTable.length)
shiftTable[patternToFind[k]] = patternToFind.length - k;
}
}