blob: 52381601ddd603cbe6dd80e1c0860eeffcbac478 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.search.internal.core.text;
import java.io.IOException;
import java.io.Reader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.search.internal.ui.SearchMessages;
/**
* A class finding matches withing a file.
* @since 3.0
*/
public class MatchLocator {
protected static final int fgLF= '\n';
protected static final int fgCR= '\r';
private Matcher fMatcher;
protected int fPushbackChar;
protected boolean fPushback;
private String fPattern;
private boolean fIsRegEx;
public MatchLocator(String pattern, String options) {
fPattern= pattern;
Pattern regExPattern;
fIsRegEx= options.indexOf('r') != -1;
if (!isRegExSearch())
pattern= asRegEx(pattern);
if (options.indexOf('i') != -1)
regExPattern= Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
else
regExPattern= Pattern.compile(pattern);
fMatcher= regExPattern.matcher(""); //$NON-NLS-1$
}
public boolean isEmtpy() {
return getPattern().length() == 0;
}
public String getPattern() {
return fPattern;
}
public void locateMatches(IProgressMonitor monitor, IResourceProxy proxy, Reader reader, ITextSearchResultCollector collector) throws CoreException, IOException {
int lineCounter= 1;
int charCounter=0;
boolean eof= false;
try {
while (!eof) {
StringBuffer sb= new StringBuffer(200);
int eolStrLength= readLine(reader, sb);
int lineLength= sb.length();
int start= 0;
eof= eolStrLength == -1;
String line= sb.toString();
while (start < lineLength) {
fMatcher.reset(line);
if (fMatcher.find(start)) {
start= charCounter + fMatcher.start();
int length= fMatcher.end() - fMatcher.start();
collector.accept(proxy, line.trim(), start, length, lineCounter);
start= fMatcher.end();
}
else // no match in this line
start= lineLength;
}
charCounter+= lineLength + eolStrLength;
lineCounter++;
if (monitor.isCanceled())
throw new OperationCanceledException(SearchMessages.getString("TextSearchVisitor.canceled")); //$NON-NLS-1$
}
} finally {
if (reader != null)
reader.close();
}
}
/*
* Converts '*' and '?' to regEx variables.
*/
private String asRegEx(String pattern) {
StringBuffer out= new StringBuffer(pattern.length());
boolean escaped= false;
boolean quoting= false;
int i= 0;
while (i < pattern.length()) {
char ch= pattern.charAt(i++);
if (ch == '*' && !escaped) {
if (quoting) {
out.append("\\E"); //$NON-NLS-1$
quoting= false;
}
out.append(".*"); //$NON-NLS-1$
escaped= false;
continue;
} else if (ch == '?' && !escaped) {
if (quoting) {
out.append("\\E"); //$NON-NLS-1$
quoting= false;
}
out.append("."); //$NON-NLS-1$
escaped= false;
continue;
} else if (ch == '\\' && !escaped) {
escaped= true;
continue;
} else if (ch == '\\' && escaped) {
escaped= false;
if (quoting) {
out.append("\\E"); //$NON-NLS-1$
quoting= false;
}
out.append("\\\\"); //$NON-NLS-1$
continue;
}
if (!quoting) {
out.append("\\Q"); //$NON-NLS-1$
quoting= true;
}
if (escaped && ch != '*' && ch != '?' && ch != '\\')
out.append('\\');
out.append(ch);
escaped= ch == '\\';
}
if (quoting)
out.append("\\E"); //$NON-NLS-1$
return out.toString();
}
protected int readLine(Reader reader, StringBuffer sb) throws IOException {
int ch= -1;
if (fPushback) {
ch= fPushbackChar;
fPushback= false;
}
else
ch= reader.read();
while (ch >= 0) {
if (ch == fgLF)
return 1;
if (ch == fgCR) {
ch= reader.read();
if (ch == fgLF)
return 2;
else {
fPushbackChar= ch;
fPushback= true;
return 1;
}
}
sb.append((char)ch);
ch= reader.read();
}
return -1;
}
public boolean isRegExSearch() {
return fIsRegEx;
}
}