mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 10:16:03 +02:00
Bug #121368: createReconciledPath() speed up.
Memory consumption is decreased seriously. From outside, method functionality is not affected. Tests behave in the same way before and after this change.
This commit is contained in:
parent
87084d47d1
commit
2e43c1a04b
1 changed files with 101 additions and 61 deletions
|
@ -12,7 +12,6 @@ package org.eclipse.cdt.internal.core.parser.scanner2;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.core.parser.CodeReader;
|
import org.eclipse.cdt.core.parser.CodeReader;
|
||||||
import org.eclipse.cdt.core.parser.ISourceElementRequestor;
|
import org.eclipse.cdt.core.parser.ISourceElementRequestor;
|
||||||
|
@ -23,76 +22,118 @@ import org.eclipse.cdt.core.parser.ISourceElementRequestor;
|
||||||
*/
|
*/
|
||||||
public class ScannerUtility {
|
public class ScannerUtility {
|
||||||
|
|
||||||
public static String reconcilePath(String originalPath ) {
|
static final char DOT = '.'; //$NON-NLS-1$
|
||||||
if( originalPath == null ) return null;
|
static final char SLASH = '/'; //$NON-NLS-1$
|
||||||
originalPath = removeQuotes( originalPath );
|
static final char BSLASH = '\\'; //$NON-NLS-1$
|
||||||
|
static final char QUOTE = '\"'; //$NON-NLS-1$
|
||||||
String [] segments = originalPath.split( "[/\\\\]" ); //$NON-NLS-1$
|
|
||||||
if( segments.length == 1 ) return originalPath;
|
|
||||||
Vector results = new Vector(segments.length);
|
|
||||||
for( int i = 0; i < segments.length; ++i )
|
|
||||||
{
|
|
||||||
String segment = segments[i];
|
|
||||||
if( segment.equals( ".") ) continue; //$NON-NLS-1$
|
|
||||||
if( segment.equals("..") ) //$NON-NLS-1$
|
|
||||||
{
|
|
||||||
if( results.size() > 0 )
|
|
||||||
results.removeElementAt( results.size() - 1 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
results.add( segment );
|
|
||||||
}
|
|
||||||
StringBuffer strbuff = new StringBuffer(128);
|
|
||||||
for( int i = 0; i < results.size(); ++i )
|
|
||||||
{
|
|
||||||
strbuff.append( (String)results.elementAt(i) );
|
|
||||||
if( i != results.size() - 1 )
|
|
||||||
strbuff.append( File.separatorChar );
|
|
||||||
}
|
|
||||||
return strbuff.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param originalPath
|
* This method is quick 1-pass path reconciler.
|
||||||
* @return
|
* Functions:
|
||||||
|
* - replace "/" or "\" by system's separator
|
||||||
|
* - replace multiple separators by single one
|
||||||
|
* - skip "/./"
|
||||||
|
* - skip quotes
|
||||||
|
* - process "/../" (skip previous directory level)
|
||||||
|
*
|
||||||
|
* @param originalPath - path to process
|
||||||
|
* @return - reconciled path
|
||||||
*/
|
*/
|
||||||
private static String removeQuotes(String originalPath) {
|
public static String reconcilePath(String originalPath ) {
|
||||||
String [] segments = originalPath.split( "\""); //$NON-NLS-1$
|
int len = originalPath.length();
|
||||||
if( segments.length == 1 ) return originalPath;
|
int len1 = len - 1; // to avoid multiple calculations
|
||||||
StringBuffer strbuff = new StringBuffer();
|
int j = 0; // index for output array
|
||||||
for( int i = 0; i < segments.length; ++ i )
|
boolean noSepBefore = true; // to avoid duplicate separators
|
||||||
if( segments[i] != null )
|
|
||||||
strbuff.append( segments[i]);
|
char[] ein = new char[len];
|
||||||
return strbuff.toString();
|
char[] aus = new char[len + 1];
|
||||||
|
|
||||||
|
originalPath.getChars(0, len, ein, 0);
|
||||||
|
for (int i=0; i<len; i++) {
|
||||||
|
char c = ein[i];
|
||||||
|
switch (c) {
|
||||||
|
case QUOTE: // quotes are removed
|
||||||
|
noSepBefore = true;
|
||||||
|
break;
|
||||||
|
case SLASH: // both separators are processed
|
||||||
|
case BSLASH: // in the same way
|
||||||
|
if (noSepBefore) {
|
||||||
|
noSepBefore = false;
|
||||||
|
aus[j++] = File.separatorChar;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DOT:
|
||||||
|
// no separator before, not a 1st string symbol.
|
||||||
|
if (noSepBefore && j>0)
|
||||||
|
aus[j++] = c;
|
||||||
|
else { // separator before "." !
|
||||||
|
if (i < len1) {
|
||||||
|
c = ein[i+1]; // check for next symbol
|
||||||
|
// check for "/./" case
|
||||||
|
if (c == SLASH || c == BSLASH) {
|
||||||
|
// write nothing to output
|
||||||
|
// skip the next symbol
|
||||||
|
i++;
|
||||||
|
noSepBefore = false;
|
||||||
|
}
|
||||||
|
// symbol other than "." - write it also
|
||||||
|
else if (c != DOT) {
|
||||||
|
i++;
|
||||||
|
noSepBefore = true;
|
||||||
|
aus[j++] = DOT;
|
||||||
|
aus[j++] = c;
|
||||||
|
}
|
||||||
|
// we found "/.." sequence. Look ahead.
|
||||||
|
else {
|
||||||
|
// we found "/../" (or "/.." is at the end of string)
|
||||||
|
// we should delete previous segment of output path
|
||||||
|
if (i == len1 || ein[i+2] == SLASH || ein[i+2] == BSLASH) {
|
||||||
|
i+=2;
|
||||||
|
noSepBefore = false;
|
||||||
|
if (j > 1) { // there is at least 1 segment before
|
||||||
|
int k = j - 2;
|
||||||
|
while ( k >= 0 ) {
|
||||||
|
if (aus[k] == File.separatorChar) break;
|
||||||
|
k--;
|
||||||
|
}
|
||||||
|
j = k + 1; // set index to previous segment or to 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Case "/..blabla" processed as usual
|
||||||
|
else {
|
||||||
|
i++;
|
||||||
|
noSepBefore = true;
|
||||||
|
aus[j++] = DOT;
|
||||||
|
aus[j++] = DOT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{} // do nothing when "." is last symbol
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
noSepBefore = true;
|
||||||
|
aus[j++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new String(aus, 0, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path - include path
|
||||||
|
* @param fileName - include file name
|
||||||
|
* @return - reconsiled path
|
||||||
|
*/
|
||||||
|
public static String createReconciledPath(String path, String fileName) {
|
||||||
|
boolean pathEmpty = (path == null || path.length() == 0);
|
||||||
|
return (pathEmpty ? fileName : reconcilePath(path + File.separatorChar + fileName));
|
||||||
|
}
|
||||||
|
|
||||||
public static CodeReader createReaderDuple( String path, ISourceElementRequestor requestor, Iterator workingCopies )
|
public static CodeReader createReaderDuple( String path, ISourceElementRequestor requestor, Iterator workingCopies )
|
||||||
{
|
{
|
||||||
return requestor.createReader( path, workingCopies );
|
return requestor.createReader( path, workingCopies );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param path
|
|
||||||
* @param fileName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String createReconciledPath(String path, String fileName) {
|
|
||||||
//TODO assert pathFile.isDirectory();
|
|
||||||
StringBuffer newPathBuffer = new StringBuffer();
|
|
||||||
if( ! path.equals( "" )) //$NON-NLS-1$
|
|
||||||
{
|
|
||||||
newPathBuffer.append( new File(path).getPath() );
|
|
||||||
|
|
||||||
if (fileName.length() > 0 && fileName.toCharArray()[0] != File.separatorChar)
|
|
||||||
newPathBuffer.append( File.separatorChar );
|
|
||||||
}
|
|
||||||
newPathBuffer.append( fileName );
|
|
||||||
//remove ".." and "." segments
|
|
||||||
return reconcilePath( newPathBuffer.toString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class InclusionDirective
|
public static class InclusionDirective
|
||||||
{
|
{
|
||||||
public InclusionDirective( String fileName, boolean useIncludePaths, int startOffset, int endOffset )
|
public InclusionDirective( String fileName, boolean useIncludePaths, int startOffset, int endOffset )
|
||||||
|
@ -133,5 +174,4 @@ public class ScannerUtility {
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue