mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-09 17:25:38 +02:00
refactor
This commit is contained in:
parent
69b06bd290
commit
1bf2a95bf6
5 changed files with 467 additions and 502 deletions
|
@ -1,3 +1,13 @@
|
|||
2004-03-26 David Inglis
|
||||
|
||||
Refactor to move exclusion matching methods out into public class.
|
||||
|
||||
* model/org/eclipse/cdt/core/model/CoreModelUtil.java
|
||||
* model/org/eclipse/cdt/internal/core/model/CProject.java
|
||||
* model/org/eclipse/cdt/internal/core/model/SourceRoot.java
|
||||
* model/org/eclipse/cdt/internal/core/model/Util.java
|
||||
|
||||
|
||||
2004-03-25 David Inglis
|
||||
|
||||
Added util class for core model
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.eclipse.cdt.core.model;
|
||||
|
||||
import org.eclipse.cdt.internal.core.CharOperation;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
|
||||
public class CoreModelUtil {
|
||||
|
@ -9,7 +9,7 @@ public class CoreModelUtil {
|
|||
char[] path = resourcePath.toString().toCharArray();
|
||||
for (int i = 0, length = exclusionPatterns.length; i < length; i++) {
|
||||
char[] pattern = exclusionPatterns[i].toString().toCharArray();
|
||||
if (CharOperation.pathMatch(pattern, path, true, '/')) {
|
||||
if (pathMatch(pattern, path, true, '/')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -17,19 +17,465 @@ public class CoreModelUtil {
|
|||
}
|
||||
|
||||
/*
|
||||
* Returns whether the given resource path matches one of the exclusion
|
||||
* patterns.
|
||||
* Returns whether the given resource path matches one of the exclusion patterns.
|
||||
*
|
||||
* @see IPathEntry#getExclusionPatterns
|
||||
* @see IClasspathEntry#getExclusionPatterns
|
||||
*/
|
||||
public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
|
||||
if (exclusionPatterns == null)
|
||||
return false;
|
||||
char[] path = resourcePath.toString().toCharArray();
|
||||
for (int i = 0, length = exclusionPatterns.length; i < length; i++)
|
||||
if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
|
||||
if (pathMatch(exclusionPatterns[i], path, true, '/'))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the given resource matches one of the exclusion patterns.
|
||||
*
|
||||
* @see IClasspathEntry#getExclusionPatterns
|
||||
*/
|
||||
public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
|
||||
IPath path = resource.getFullPath();
|
||||
// ensure that folders are only excluded if all of their children are
|
||||
// excluded
|
||||
if (resource.getType() == IResource.FOLDER)
|
||||
path = path.append("*"); //$NON-NLS-1$
|
||||
return isExcluded(path, exclusionPatterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching accepts wild-cards '*' and
|
||||
* '?'.
|
||||
*
|
||||
* When not case sensitive, the pattern is assumed to already be lowercased, the name will be lowercased character per character
|
||||
* as comparing. If name is null, the answer is false. If pattern is null, the answer is true if name is not null. <br>
|
||||
* <br>
|
||||
* For example:
|
||||
* <ol>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* pattern = { '?', 'b', '*' }
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* isCaseSensitive = true
|
||||
* result => true
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* pattern = { '?', 'b', '?' }
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* isCaseSensitive = true
|
||||
* result => false
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* pattern = { 'b', '*' }
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* isCaseSensitive = true
|
||||
* result => false
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @param pattern
|
||||
* the given pattern
|
||||
* @param name
|
||||
* the given name
|
||||
* @param isCaseSensitive
|
||||
* flag to know whether or not the matching should be case sensitive
|
||||
* @return true if the pattern matches the given name, false otherwise
|
||||
*/
|
||||
public static final boolean match(char[] pattern, char[] name, boolean isCaseSensitive) {
|
||||
if (name == null)
|
||||
return false; // null name cannot match
|
||||
if (pattern == null)
|
||||
return true; // null pattern is equivalent to '*'
|
||||
return match(pattern, 0, pattern.length, name, 0, name.length, isCaseSensitive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers true if the a sub-pattern matches the subpart of the given name, false otherwise. char[] pattern matching, accepting
|
||||
* wild-cards '*' and '?'. Can match only subset of name/pattern. end positions are non-inclusive. The subpattern is defined by
|
||||
* the patternStart and pattternEnd positions. When not case sensitive, the pattern is assumed to already be lowercased, the
|
||||
* name will be lowercased character per character as comparing. <br>
|
||||
* <br>
|
||||
* For example:
|
||||
* <ol>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* pattern = { '?', 'b', '*' }
|
||||
* patternStart = 1
|
||||
* patternEnd = 3
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* nameStart = 1
|
||||
* nameEnd = 4
|
||||
* isCaseSensitive = true
|
||||
* result => true
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* pattern = { '?', 'b', '*' }
|
||||
* patternStart = 1
|
||||
* patternEnd = 2
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* nameStart = 1
|
||||
* nameEnd = 2
|
||||
* isCaseSensitive = true
|
||||
* result => false
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @param pattern
|
||||
* the given pattern
|
||||
* @param patternStart
|
||||
* the given pattern start
|
||||
* @param patternEnd
|
||||
* the given pattern end
|
||||
* @param name
|
||||
* the given name
|
||||
* @param nameStart
|
||||
* the given name start
|
||||
* @param nameEnd
|
||||
* the given name end
|
||||
* @param isCaseSensitive
|
||||
* flag to know if the matching should be case sensitive
|
||||
* @return true if the a sub-pattern matches the subpart of the given name, false otherwise
|
||||
*/
|
||||
public static final boolean match(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd,
|
||||
boolean isCaseSensitive) {
|
||||
if (name == null)
|
||||
return false; // null name cannot match
|
||||
if (pattern == null)
|
||||
return true; // null pattern is equivalent to '*'
|
||||
int iPattern = patternStart;
|
||||
int iName = nameStart;
|
||||
if (patternEnd < 0)
|
||||
patternEnd = pattern.length;
|
||||
if (nameEnd < 0)
|
||||
nameEnd = name.length;
|
||||
/* check first segment */
|
||||
char patternChar = 0;
|
||||
while ((iPattern < patternEnd) && (patternChar = pattern[iPattern]) != '*') {
|
||||
if (iName == nameEnd)
|
||||
return false;
|
||||
if (patternChar != (isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName])) && patternChar != '?') {
|
||||
return false;
|
||||
}
|
||||
iName++;
|
||||
iPattern++;
|
||||
}
|
||||
/* check sequence of star+segment */
|
||||
int segmentStart;
|
||||
if (patternChar == '*') {
|
||||
segmentStart = ++iPattern; // skip star
|
||||
} else {
|
||||
segmentStart = 0; // force iName check
|
||||
}
|
||||
int prefixStart = iName;
|
||||
checkSegment : while (iName < nameEnd) {
|
||||
if (iPattern == patternEnd) {
|
||||
iPattern = segmentStart; // mismatch - restart current segment
|
||||
iName = ++prefixStart;
|
||||
continue checkSegment;
|
||||
}
|
||||
/* segment is ending */
|
||||
if ((patternChar = pattern[iPattern]) == '*') {
|
||||
segmentStart = ++iPattern; // skip start
|
||||
if (segmentStart == patternEnd) {
|
||||
return true;
|
||||
}
|
||||
prefixStart = iName;
|
||||
continue checkSegment;
|
||||
}
|
||||
/* check current name character */
|
||||
if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName])) != patternChar && patternChar != '?') {
|
||||
iPattern = segmentStart; // mismatch - restart current segment
|
||||
iName = ++prefixStart;
|
||||
continue checkSegment;
|
||||
}
|
||||
iName++;
|
||||
iPattern++;
|
||||
}
|
||||
return (segmentStart == patternEnd) || (iName == nameEnd && iPattern == patternEnd)
|
||||
|| (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
|
||||
*
|
||||
* Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks conventions, also see
|
||||
* "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes"). Path pattern matching is enhancing regular pattern
|
||||
* matching in supporting extra rule where '**' represent any folder combination. Special rule: - foo\ is equivalent to foo\**
|
||||
* When not case sensitive, the pattern is assumed to already be lowercased, the name will be lowercased character per character
|
||||
* as comparing.
|
||||
*
|
||||
* @param pattern
|
||||
* the given pattern
|
||||
* @param filepath
|
||||
* the given path
|
||||
* @param isCaseSensitive
|
||||
* to find out whether or not the matching should be case sensitive
|
||||
* @param pathSeparator
|
||||
* the given path separator
|
||||
* @return true if the pattern matches the filepath using the pathSepatator, false otherwise
|
||||
*/
|
||||
public static final boolean pathMatch(char[] pattern, char[] filepath, boolean isCaseSensitive, char pathSeparator) {
|
||||
if (filepath == null)
|
||||
return false; // null name cannot match
|
||||
if (pattern == null)
|
||||
return true; // null pattern is equivalent to '*'
|
||||
// offsets inside pattern
|
||||
int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
|
||||
int pLength = pattern.length;
|
||||
int pSegmentEnd = indexOf(pathSeparator, pattern, pSegmentStart + 1);
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
// special case: pattern foo\ is equivalent to foo\**
|
||||
boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
|
||||
// offsets inside filepath
|
||||
int fSegmentStart, fLength = filepath.length;
|
||||
if (filepath[0] != pathSeparator) {
|
||||
fSegmentStart = 0;
|
||||
} else {
|
||||
fSegmentStart = 1;
|
||||
}
|
||||
if (fSegmentStart != pSegmentStart) {
|
||||
return false; // both must start with a separator or none.
|
||||
}
|
||||
int fSegmentEnd = indexOf(pathSeparator, filepath, fSegmentStart + 1);
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
// first segments
|
||||
while (pSegmentStart < pLength
|
||||
&& !(pSegmentEnd == pLength && freeTrailingDoubleStar || (pSegmentEnd == pSegmentStart + 2
|
||||
&& pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*'))) {
|
||||
if (fSegmentStart >= fLength)
|
||||
return false;
|
||||
if (!match(pattern, pSegmentStart, pSegmentEnd, filepath, fSegmentStart, fSegmentEnd, isCaseSensitive)) {
|
||||
return false;
|
||||
}
|
||||
// jump to next segment
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
fSegmentEnd = indexOf(pathSeparator, filepath, fSegmentStart = fSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
}
|
||||
/* check sequence of doubleStar+segment */
|
||||
int pSegmentRestart;
|
||||
if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
|
||||
|| (pSegmentEnd == pSegmentStart + 2 && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')) {
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
pSegmentRestart = pSegmentStart;
|
||||
} else {
|
||||
if (pSegmentStart >= pLength)
|
||||
return fSegmentStart >= fLength; // true if filepath is done
|
||||
// too.
|
||||
pSegmentRestart = 0; // force fSegmentStart check
|
||||
}
|
||||
int fSegmentRestart = fSegmentStart;
|
||||
checkSegment : while (fSegmentStart < fLength) {
|
||||
if (pSegmentStart >= pLength) {
|
||||
if (freeTrailingDoubleStar)
|
||||
return true;
|
||||
// mismatch - restart current path segment
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
fSegmentRestart = indexOf(pathSeparator, filepath, fSegmentRestart + 1);
|
||||
// skip separator
|
||||
if (fSegmentRestart < 0) {
|
||||
fSegmentRestart = fLength;
|
||||
} else {
|
||||
fSegmentRestart++;
|
||||
}
|
||||
fSegmentEnd = indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
continue checkSegment;
|
||||
}
|
||||
/* path segment is ending */
|
||||
if (pSegmentEnd == pSegmentStart + 2 && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*') {
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
pSegmentRestart = pSegmentStart;
|
||||
fSegmentRestart = fSegmentStart;
|
||||
if (pSegmentStart >= pLength)
|
||||
return true;
|
||||
continue checkSegment;
|
||||
}
|
||||
/* chech current path segment */
|
||||
if (!match(pattern, pSegmentStart, pSegmentEnd, filepath, fSegmentStart, fSegmentEnd, isCaseSensitive)) {
|
||||
// mismatch - restart current path segment
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
fSegmentRestart = indexOf(pathSeparator, filepath, fSegmentRestart + 1);
|
||||
// skip separator
|
||||
if (fSegmentRestart < 0) {
|
||||
fSegmentRestart = fLength;
|
||||
} else {
|
||||
fSegmentRestart++;
|
||||
}
|
||||
fSegmentEnd = indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
continue checkSegment;
|
||||
}
|
||||
// jump to next segment
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
fSegmentEnd = indexOf(pathSeparator, filepath, fSegmentStart = fSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
}
|
||||
return (pSegmentRestart >= pSegmentEnd) || (fSegmentStart >= fLength && pSegmentStart >= pLength)
|
||||
|| (pSegmentStart == pLength - 2 && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')
|
||||
|| (pSegmentStart == pLength && freeTrailingDoubleStar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers the first index in the array for which the corresponding character is equal to toBeFound. Answers -1 if no occurrence
|
||||
* of this character is found. <br>
|
||||
* <br>
|
||||
* For example:
|
||||
* <ol>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* toBeFound = 'c'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* result => 2
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* toBeFound = 'e'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* result => -1
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @param toBeFound
|
||||
* the character to search
|
||||
* @param array
|
||||
* the array to be searched
|
||||
* @return the first index in the array for which the corresponding character is equal to toBeFound, -1 otherwise
|
||||
* @throws NullPointerException
|
||||
* if array is null
|
||||
*/
|
||||
public static final int indexOf(char toBeFound, char[] array) {
|
||||
for (int i = 0; i < array.length; i++)
|
||||
if (toBeFound == array[i])
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers the first index in the array for which the corresponding character is equal to toBeFound starting the search at index
|
||||
* start. Answers -1 if no occurrence of this character is found. <br>
|
||||
* <br>
|
||||
* For example:
|
||||
* <ol>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* toBeFound = 'c'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* start = 2
|
||||
* result => 2
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* toBeFound = 'c'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* start = 3
|
||||
* result => -1
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* toBeFound = 'e'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* start = 1
|
||||
* result => -1
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @param toBeFound
|
||||
* the character to search
|
||||
* @param array
|
||||
* the array to be searched
|
||||
* @param start
|
||||
* the starting index
|
||||
* @return the first index in the array for which the corresponding character is equal to toBeFound, -1 otherwise
|
||||
* @throws NullPointerException
|
||||
* if array is null
|
||||
* @throws ArrayIndexOutOfBoundsException
|
||||
* if start is lower than 0
|
||||
*/
|
||||
public static final int indexOf(char toBeFound, char[] array, int start) {
|
||||
for (int i = start; i < array.length; i++)
|
||||
if (toBeFound == array[i])
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@ import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
|
|||
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.model.CoreModelUtil;
|
||||
import org.eclipse.cdt.core.model.IArchiveContainer;
|
||||
import org.eclipse.cdt.core.model.IBinaryContainer;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
|
@ -462,7 +463,7 @@ public class CProject extends Openable implements ICProject {
|
|||
}
|
||||
|
||||
private boolean isOnOutputEntry(IOutputEntry entry, IPath path) {
|
||||
if (entry.getPath().isPrefixOf(path) && !Util.isExcluded(path, entry.fullExclusionPatternChars())) {
|
||||
if (entry.getPath().isPrefixOf(path) && !CoreModelUtil.isExcluded(path, entry.fullExclusionPatternChars())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.model;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.CoreModelUtil;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ISourceEntry;
|
||||
|
@ -118,7 +119,7 @@ public class SourceRoot extends CContainer implements ISourceRoot {
|
|||
|
||||
private boolean isOnSourceEntry(IPath path) {
|
||||
if (sourceEntry.getPath().isPrefixOf(path)
|
||||
&& !Util.isExcluded(path, sourceEntry.fullExclusionPatternChars())) {
|
||||
&& !CoreModelUtil.isExcluded(path, sourceEntry.fullExclusionPatternChars())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -9,15 +9,14 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.ICLogConstants;
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.ICModelStatusConstants;
|
||||
import org.eclipse.cdt.internal.core.model.IDebugLogConstants.DebugLogConstant;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
|
@ -286,496 +285,4 @@ public class Util implements ICLogConstants {
|
|||
}
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the given resource path matches one of the exclusion
|
||||
* patterns.
|
||||
*
|
||||
* @see IClasspathEntry#getExclusionPatterns
|
||||
*/
|
||||
public final static boolean isExcluded(IPath resourcePath,
|
||||
char[][] exclusionPatterns) {
|
||||
if (exclusionPatterns == null)
|
||||
return false;
|
||||
char[] path = resourcePath.toString().toCharArray();
|
||||
for (int i = 0, length = exclusionPatterns.length; i < length; i++)
|
||||
if (pathMatch(exclusionPatterns[i], path, true, '/'))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the given resource matches one of the exclusion
|
||||
* patterns.
|
||||
*
|
||||
* @see IClasspathEntry#getExclusionPatterns
|
||||
*/
|
||||
public final static boolean isExcluded(IResource resource,
|
||||
char[][] exclusionPatterns) {
|
||||
IPath path = resource.getFullPath();
|
||||
// ensure that folders are only excluded if all of their children are
|
||||
// excluded
|
||||
if (resource.getType() == IResource.FOLDER)
|
||||
path = path.append("*"); //$NON-NLS-1$
|
||||
return isExcluded(path, exclusionPatterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers true if the pattern matches the given name, false otherwise.
|
||||
* This char[] pattern matching accepts wild-cards '*' and '?'.
|
||||
*
|
||||
* When not case sensitive, the pattern is assumed to already be
|
||||
* lowercased, the name will be lowercased character per character as
|
||||
* comparing. If name is null, the answer is false. If pattern is null, the
|
||||
* answer is true if name is not null. <br>
|
||||
* <br>
|
||||
* For example:
|
||||
* <ol>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* pattern = { '?', 'b', '*' }
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* isCaseSensitive = true
|
||||
* result => true
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* pattern = { '?', 'b', '?' }
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* isCaseSensitive = true
|
||||
* result => false
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* pattern = { 'b', '*' }
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* isCaseSensitive = true
|
||||
* result => false
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @param pattern
|
||||
* the given pattern
|
||||
* @param name
|
||||
* the given name
|
||||
* @param isCaseSensitive
|
||||
* flag to know whether or not the matching should be case
|
||||
* sensitive
|
||||
* @return true if the pattern matches the given name, false otherwise
|
||||
*/
|
||||
public static final boolean match(char[] pattern, char[] name,
|
||||
boolean isCaseSensitive) {
|
||||
if (name == null)
|
||||
return false; // null name cannot match
|
||||
if (pattern == null)
|
||||
return true; // null pattern is equivalent to '*'
|
||||
return match(pattern, 0, pattern.length, name, 0, name.length,
|
||||
isCaseSensitive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers true if the a sub-pattern matches the subpart of the given name,
|
||||
* false otherwise. char[] pattern matching, accepting wild-cards '*' and
|
||||
* '?'. Can match only subset of name/pattern. end positions are
|
||||
* non-inclusive. The subpattern is defined by the patternStart and
|
||||
* pattternEnd positions. When not case sensitive, the pattern is assumed
|
||||
* to already be lowercased, the name will be lowercased character per
|
||||
* character as comparing. <br>
|
||||
* <br>
|
||||
* For example:
|
||||
* <ol>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* pattern = { '?', 'b', '*' }
|
||||
* patternStart = 1
|
||||
* patternEnd = 3
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* nameStart = 1
|
||||
* nameEnd = 4
|
||||
* isCaseSensitive = true
|
||||
* result => true
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* pattern = { '?', 'b', '*' }
|
||||
* patternStart = 1
|
||||
* patternEnd = 2
|
||||
* name = { 'a', 'b', 'c' , 'd' }
|
||||
* nameStart = 1
|
||||
* nameEnd = 2
|
||||
* isCaseSensitive = true
|
||||
* result => false
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @param pattern
|
||||
* the given pattern
|
||||
* @param patternStart
|
||||
* the given pattern start
|
||||
* @param patternEnd
|
||||
* the given pattern end
|
||||
* @param name
|
||||
* the given name
|
||||
* @param nameStart
|
||||
* the given name start
|
||||
* @param nameEnd
|
||||
* the given name end
|
||||
* @param isCaseSensitive
|
||||
* flag to know if the matching should be case sensitive
|
||||
* @return true if the a sub-pattern matches the subpart of the given name,
|
||||
* false otherwise
|
||||
*/
|
||||
public static final boolean match(char[] pattern, int patternStart,
|
||||
int patternEnd, char[] name, int nameStart, int nameEnd,
|
||||
boolean isCaseSensitive) {
|
||||
if (name == null)
|
||||
return false; // null name cannot match
|
||||
if (pattern == null)
|
||||
return true; // null pattern is equivalent to '*'
|
||||
int iPattern = patternStart;
|
||||
int iName = nameStart;
|
||||
if (patternEnd < 0)
|
||||
patternEnd = pattern.length;
|
||||
if (nameEnd < 0)
|
||||
nameEnd = name.length;
|
||||
/* check first segment */
|
||||
char patternChar = 0;
|
||||
while ((iPattern < patternEnd)
|
||||
&& (patternChar = pattern[iPattern]) != '*') {
|
||||
if (iName == nameEnd)
|
||||
return false;
|
||||
if (patternChar != (isCaseSensitive ? name[iName] : Character
|
||||
.toLowerCase(name[iName]))
|
||||
&& patternChar != '?') {
|
||||
return false;
|
||||
}
|
||||
iName++;
|
||||
iPattern++;
|
||||
}
|
||||
/* check sequence of star+segment */
|
||||
int segmentStart;
|
||||
if (patternChar == '*') {
|
||||
segmentStart = ++iPattern; // skip star
|
||||
} else {
|
||||
segmentStart = 0; // force iName check
|
||||
}
|
||||
int prefixStart = iName;
|
||||
checkSegment : while (iName < nameEnd) {
|
||||
if (iPattern == patternEnd) {
|
||||
iPattern = segmentStart; // mismatch - restart current segment
|
||||
iName = ++prefixStart;
|
||||
continue checkSegment;
|
||||
}
|
||||
/* segment is ending */
|
||||
if ((patternChar = pattern[iPattern]) == '*') {
|
||||
segmentStart = ++iPattern; // skip start
|
||||
if (segmentStart == patternEnd) {
|
||||
return true;
|
||||
}
|
||||
prefixStart = iName;
|
||||
continue checkSegment;
|
||||
}
|
||||
/* check current name character */
|
||||
if ((isCaseSensitive ? name[iName] : Character
|
||||
.toLowerCase(name[iName])) != patternChar
|
||||
&& patternChar != '?') {
|
||||
iPattern = segmentStart; // mismatch - restart current segment
|
||||
iName = ++prefixStart;
|
||||
continue checkSegment;
|
||||
}
|
||||
iName++;
|
||||
iPattern++;
|
||||
}
|
||||
return (segmentStart == patternEnd)
|
||||
|| (iName == nameEnd && iPattern == patternEnd)
|
||||
|| (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers true if the pattern matches the filepath using the
|
||||
* pathSepatator, false otherwise.
|
||||
*
|
||||
* Path char[] pattern matching, accepting wild-cards '**', '*' and '?'
|
||||
* (using Ant directory tasks conventions, also see
|
||||
* "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
|
||||
* Path pattern matching is enhancing regular pattern matching in
|
||||
* supporting extra rule where '**' represent any folder combination.
|
||||
* Special rule: - foo\ is equivalent to foo\** When not case sensitive,
|
||||
* the pattern is assumed to already be lowercased, the name will be
|
||||
* lowercased character per character as comparing.
|
||||
*
|
||||
* @param pattern
|
||||
* the given pattern
|
||||
* @param filepath
|
||||
* the given path
|
||||
* @param isCaseSensitive
|
||||
* to find out whether or not the matching should be case
|
||||
* sensitive
|
||||
* @param pathSeparator
|
||||
* the given path separator
|
||||
* @return true if the pattern matches the filepath using the
|
||||
* pathSepatator, false otherwise
|
||||
*/
|
||||
public static final boolean pathMatch(char[] pattern, char[] filepath,
|
||||
boolean isCaseSensitive, char pathSeparator) {
|
||||
if (filepath == null)
|
||||
return false; // null name cannot match
|
||||
if (pattern == null)
|
||||
return true; // null pattern is equivalent to '*'
|
||||
// offsets inside pattern
|
||||
int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
|
||||
int pLength = pattern.length;
|
||||
int pSegmentEnd = indexOf(pathSeparator, pattern, pSegmentStart + 1);
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
// special case: pattern foo\ is equivalent to foo\**
|
||||
boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
|
||||
// offsets inside filepath
|
||||
int fSegmentStart, fLength = filepath.length;
|
||||
if (filepath[0] != pathSeparator) {
|
||||
fSegmentStart = 0;
|
||||
} else {
|
||||
fSegmentStart = 1;
|
||||
}
|
||||
if (fSegmentStart != pSegmentStart) {
|
||||
return false; // both must start with a separator or none.
|
||||
}
|
||||
int fSegmentEnd = indexOf(pathSeparator, filepath, fSegmentStart + 1);
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
// first segments
|
||||
while (pSegmentStart < pLength
|
||||
&& !(pSegmentEnd == pLength && freeTrailingDoubleStar || (pSegmentEnd == pSegmentStart + 2
|
||||
&& pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*'))) {
|
||||
if (fSegmentStart >= fLength)
|
||||
return false;
|
||||
if (!match(pattern, pSegmentStart, pSegmentEnd, filepath,
|
||||
fSegmentStart, fSegmentEnd, isCaseSensitive)) {
|
||||
return false;
|
||||
}
|
||||
// jump to next segment
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern,
|
||||
pSegmentStart = pSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
fSegmentEnd = indexOf(pathSeparator, filepath,
|
||||
fSegmentStart = fSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
}
|
||||
/* check sequence of doubleStar+segment */
|
||||
int pSegmentRestart;
|
||||
if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
|
||||
|| (pSegmentEnd == pSegmentStart + 2
|
||||
&& pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')) {
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern,
|
||||
pSegmentStart = pSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
pSegmentRestart = pSegmentStart;
|
||||
} else {
|
||||
if (pSegmentStart >= pLength)
|
||||
return fSegmentStart >= fLength; // true if filepath is done
|
||||
// too.
|
||||
pSegmentRestart = 0; // force fSegmentStart check
|
||||
}
|
||||
int fSegmentRestart = fSegmentStart;
|
||||
checkSegment : while (fSegmentStart < fLength) {
|
||||
if (pSegmentStart >= pLength) {
|
||||
if (freeTrailingDoubleStar)
|
||||
return true;
|
||||
// mismatch - restart current path segment
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern,
|
||||
pSegmentStart = pSegmentRestart);
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
fSegmentRestart = indexOf(pathSeparator, filepath,
|
||||
fSegmentRestart + 1);
|
||||
// skip separator
|
||||
if (fSegmentRestart < 0) {
|
||||
fSegmentRestart = fLength;
|
||||
} else {
|
||||
fSegmentRestart++;
|
||||
}
|
||||
fSegmentEnd = indexOf(pathSeparator, filepath,
|
||||
fSegmentStart = fSegmentRestart);
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
continue checkSegment;
|
||||
}
|
||||
/* path segment is ending */
|
||||
if (pSegmentEnd == pSegmentStart + 2
|
||||
&& pattern[pSegmentStart] == '*'
|
||||
&& pattern[pSegmentStart + 1] == '*') {
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern,
|
||||
pSegmentStart = pSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
pSegmentRestart = pSegmentStart;
|
||||
fSegmentRestart = fSegmentStart;
|
||||
if (pSegmentStart >= pLength)
|
||||
return true;
|
||||
continue checkSegment;
|
||||
}
|
||||
/* chech current path segment */
|
||||
if (!match(pattern, pSegmentStart, pSegmentEnd, filepath,
|
||||
fSegmentStart, fSegmentEnd, isCaseSensitive)) {
|
||||
// mismatch - restart current path segment
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern,
|
||||
pSegmentStart = pSegmentRestart);
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
fSegmentRestart = indexOf(pathSeparator, filepath,
|
||||
fSegmentRestart + 1);
|
||||
// skip separator
|
||||
if (fSegmentRestart < 0) {
|
||||
fSegmentRestart = fLength;
|
||||
} else {
|
||||
fSegmentRestart++;
|
||||
}
|
||||
fSegmentEnd = indexOf(pathSeparator, filepath,
|
||||
fSegmentStart = fSegmentRestart);
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
continue checkSegment;
|
||||
}
|
||||
// jump to next segment
|
||||
pSegmentEnd = indexOf(pathSeparator, pattern,
|
||||
pSegmentStart = pSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (pSegmentEnd < 0)
|
||||
pSegmentEnd = pLength;
|
||||
fSegmentEnd = indexOf(pathSeparator, filepath,
|
||||
fSegmentStart = fSegmentEnd + 1);
|
||||
// skip separator
|
||||
if (fSegmentEnd < 0)
|
||||
fSegmentEnd = fLength;
|
||||
}
|
||||
return (pSegmentRestart >= pSegmentEnd)
|
||||
|| (fSegmentStart >= fLength && pSegmentStart >= pLength)
|
||||
|| (pSegmentStart == pLength - 2
|
||||
&& pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')
|
||||
|| (pSegmentStart == pLength && freeTrailingDoubleStar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers the first index in the array for which the corresponding
|
||||
* character is equal to toBeFound. Answers -1 if no occurrence of this
|
||||
* character is found. <br>
|
||||
* <br>
|
||||
* For example:
|
||||
* <ol>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* toBeFound = 'c'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* result => 2
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* toBeFound = 'e'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* result => -1
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @param toBeFound
|
||||
* the character to search
|
||||
* @param array
|
||||
* the array to be searched
|
||||
* @return the first index in the array for which the corresponding
|
||||
* character is equal to toBeFound, -1 otherwise
|
||||
* @throws NullPointerException
|
||||
* if array is null
|
||||
*/
|
||||
public static final int indexOf(char toBeFound, char[] array) {
|
||||
for (int i = 0; i < array.length; i++)
|
||||
if (toBeFound == array[i])
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers the first index in the array for which the corresponding
|
||||
* character is equal to toBeFound starting the search at index start.
|
||||
* Answers -1 if no occurrence of this character is found. <br>
|
||||
* <br>
|
||||
* For example:
|
||||
* <ol>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* toBeFound = 'c'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* start = 2
|
||||
* result => 2
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* toBeFound = 'c'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* start = 3
|
||||
* result => -1
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>
|
||||
*
|
||||
* <pre>
|
||||
* toBeFound = 'e'
|
||||
* array = { ' a', 'b', 'c', 'd' }
|
||||
* start = 1
|
||||
* result => -1
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @param toBeFound
|
||||
* the character to search
|
||||
* @param array
|
||||
* the array to be searched
|
||||
* @param start
|
||||
* the starting index
|
||||
* @return the first index in the array for which the corresponding
|
||||
* character is equal to toBeFound, -1 otherwise
|
||||
* @throws NullPointerException
|
||||
* if array is null
|
||||
* @throws ArrayIndexOutOfBoundsException
|
||||
* if start is lower than 0
|
||||
*/
|
||||
public static final int indexOf(char toBeFound, char[] array, int start) {
|
||||
for (int i = start; i < array.length; i++)
|
||||
if (toBeFound == array[i])
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue