Skip to content

Commit

Permalink
Speed optimization to avoid copying the string (through the StringBui…
Browse files Browse the repository at this point in the history
…lder) when not necessary (#23)
  • Loading branch information
gnodet authored and olamy committed Jun 25, 2019
1 parent 1a2e3de commit e569b5c
Showing 1 changed file with 93 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,136 +138,144 @@ private String interpolate( String input, RecursionInterceptor recursionIntercep
// return empty String to prevent NPE too
return "";
}
StringBuilder result = new StringBuilder( input.length() * 2 );

int startIdx;
int endIdx = -1;
while ( ( startIdx = input.indexOf( startExpr, endIdx + 1 ) ) > -1 )
if ( ( startIdx = input.indexOf( startExpr, endIdx + 1 ) ) > -1 )
{
result.append( input, endIdx + 1, startIdx );

endIdx = input.indexOf( endExpr, startIdx + 1 );
if ( endIdx < 0 )
{
break;
}

final String wholeExpr = input.substring( startIdx, endIdx + endExpr.length() );
String realExpr = wholeExpr.substring( startExpr.length(), wholeExpr.length() - endExpr.length() );

if ( startIdx >= 0 && escapeString != null && escapeString.length() > 0 )
{
int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length();
if ( startEscapeIdx >= 0 )
StringBuilder result = new StringBuilder( input.length() * 2 );
do
{
String escape = input.substring( startEscapeIdx, startIdx );
if ( escapeString.equals( escape ) )
{
result.append( wholeExpr );
result.replace( startEscapeIdx, startEscapeIdx + escapeString.length(), "" );
continue;
}
}
}
result.append( input, endIdx + 1, startIdx );

boolean resolved = false;
if ( !unresolvable.contains( wholeExpr ) )
{
if ( realExpr.startsWith( "." ) )
endIdx = input.indexOf( endExpr, startIdx + 1 );
if ( endIdx < 0 )
{
realExpr = realExpr.substring( 1 );
break;
}

if ( recursionInterceptor.hasRecursiveExpression( realExpr ) )
{
throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr );
}
final String wholeExpr = input.substring( startIdx, endIdx + endExpr.length() );
String realExpr = wholeExpr.substring( startExpr.length(), wholeExpr.length() - endExpr.length() );

recursionInterceptor.expressionResolutionStarted( realExpr );
try
if ( startIdx >= 0 && escapeString != null && escapeString.length() > 0 )
{
Object value = existingAnswers.get( realExpr );
Object bestAnswer = null;

for ( ValueSource valueSource : valueSources )
int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length();
if ( startEscapeIdx >= 0 )
{
if ( value != null )
String escape = input.substring( startEscapeIdx, startIdx );
if ( escapeString.equals( escape ) )
{
break;
result.append(wholeExpr);
result.replace(startEscapeIdx, startEscapeIdx + escapeString.length(), "");
continue;
}
value = valueSource.getValue( realExpr );
}
}

if ( value != null && value.toString().contains( wholeExpr ) )
{
bestAnswer = value;
value = null;
}
boolean resolved = false;
if ( !unresolvable.contains( wholeExpr ) )
{
if ( realExpr.startsWith( "." ) )
{
realExpr = realExpr.substring(1);
}

// this is the simplest recursion check to catch exact recursion
// (non synonym), and avoid the extra effort of more string
// searching.
if ( value == null && bestAnswer != null )
if ( recursionInterceptor.hasRecursiveExpression( realExpr ) )
{
throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr );
}

if ( value != null )
recursionInterceptor.expressionResolutionStarted( realExpr );
try
{
value = interpolate( String.valueOf( value ), recursionInterceptor, unresolvable );
Object value = existingAnswers.get( realExpr );
Object bestAnswer = null;

for ( ValueSource valueSource : valueSources )
{
if ( value != null )
{
break;
}
value = valueSource.getValue( realExpr );

if ( value != null && value.toString().contains( wholeExpr ) )
{
bestAnswer = value;
value = null;
}
}

if ( postProcessors != null && !postProcessors.isEmpty() )
// this is the simplest recursion check to catch exact recursion
// (non synonym), and avoid the extra effort of more string
// searching.
if ( value == null && bestAnswer != null )
{
for ( InterpolationPostProcessor postProcessor : postProcessors )
throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr );
}

if ( value != null )
{
value = interpolate( String.valueOf(value), recursionInterceptor, unresolvable );

if ( postProcessors != null && !postProcessors.isEmpty() )
{
Object newVal = postProcessor.execute( realExpr, value );
if ( newVal != null )
for ( InterpolationPostProcessor postProcessor : postProcessors )
{
value = newVal;
break;
Object newVal = postProcessor.execute( realExpr, value );
if ( newVal != null )
{
value = newVal;
break;
}
}
}
}

// could use:
// result = matcher.replaceFirst( stringValue );
// but this could result in multiple lookups of stringValue, and replaceAll is not correct
// behaviour
result.append( String.valueOf( value ) );
resolved = true;
// could use:
// result = matcher.replaceFirst( stringValue );
// but this could result in multiple lookups of stringValue, and replaceAll is not correct
// behaviour
result.append( String.valueOf( value ) );
resolved = true;
}
else
{
unresolvable.add( wholeExpr );
}
}
else
finally
{
unresolvable.add( wholeExpr );
recursionInterceptor.expressionResolutionFinished( realExpr );
}
}
finally

if (!resolved)
{
recursionInterceptor.expressionResolutionFinished( realExpr );
result.append( wholeExpr );
}

if ( endIdx > -1 )
{
endIdx += endExpr.length() - 1;
}
}
while ( ( startIdx = input.indexOf( startExpr, endIdx + 1 ) ) > -1);

if ( !resolved )
if ( endIdx == -1 && startIdx > -1 )
{
result.append( wholeExpr );
result.append( input, startIdx, input.length());
}

if ( endIdx > -1 )
else if ( endIdx < input.length() )
{
endIdx += endExpr.length() - 1;
result.append( input, endIdx + 1, input.length() );
}
}

if ( endIdx == -1 && startIdx > -1 )
{
result.append( input, startIdx, input.length());
return result.toString();
}
else if ( endIdx < input.length() )
else
{
result.append( input, endIdx + 1, input.length() );
return input;
}

return result.toString();
}

/**
Expand Down

0 comments on commit e569b5c

Please sign in to comment.