Skip to content

Commit e569b5c

Browse files
gnodetolamy
authored andcommitted
Speed optimization to avoid copying the string (through the StringBuilder) when not necessary (#23)
1 parent 1a2e3de commit e569b5c

File tree

1 file changed

+93
-85
lines changed

1 file changed

+93
-85
lines changed

src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java

+93-85
Original file line numberDiff line numberDiff line change
@@ -138,136 +138,144 @@ private String interpolate( String input, RecursionInterceptor recursionIntercep
138138
// return empty String to prevent NPE too
139139
return "";
140140
}
141-
StringBuilder result = new StringBuilder( input.length() * 2 );
142141

143142
int startIdx;
144143
int endIdx = -1;
145-
while ( ( startIdx = input.indexOf( startExpr, endIdx + 1 ) ) > -1 )
144+
if ( ( startIdx = input.indexOf( startExpr, endIdx + 1 ) ) > -1 )
146145
{
147-
result.append( input, endIdx + 1, startIdx );
148-
149-
endIdx = input.indexOf( endExpr, startIdx + 1 );
150-
if ( endIdx < 0 )
151-
{
152-
break;
153-
}
154-
155-
final String wholeExpr = input.substring( startIdx, endIdx + endExpr.length() );
156-
String realExpr = wholeExpr.substring( startExpr.length(), wholeExpr.length() - endExpr.length() );
157-
158-
if ( startIdx >= 0 && escapeString != null && escapeString.length() > 0 )
159-
{
160-
int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length();
161-
if ( startEscapeIdx >= 0 )
146+
StringBuilder result = new StringBuilder( input.length() * 2 );
147+
do
162148
{
163-
String escape = input.substring( startEscapeIdx, startIdx );
164-
if ( escapeString.equals( escape ) )
165-
{
166-
result.append( wholeExpr );
167-
result.replace( startEscapeIdx, startEscapeIdx + escapeString.length(), "" );
168-
continue;
169-
}
170-
}
171-
}
149+
result.append( input, endIdx + 1, startIdx );
172150

173-
boolean resolved = false;
174-
if ( !unresolvable.contains( wholeExpr ) )
175-
{
176-
if ( realExpr.startsWith( "." ) )
151+
endIdx = input.indexOf( endExpr, startIdx + 1 );
152+
if ( endIdx < 0 )
177153
{
178-
realExpr = realExpr.substring( 1 );
154+
break;
179155
}
180156

181-
if ( recursionInterceptor.hasRecursiveExpression( realExpr ) )
182-
{
183-
throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr );
184-
}
157+
final String wholeExpr = input.substring( startIdx, endIdx + endExpr.length() );
158+
String realExpr = wholeExpr.substring( startExpr.length(), wholeExpr.length() - endExpr.length() );
185159

186-
recursionInterceptor.expressionResolutionStarted( realExpr );
187-
try
160+
if ( startIdx >= 0 && escapeString != null && escapeString.length() > 0 )
188161
{
189-
Object value = existingAnswers.get( realExpr );
190-
Object bestAnswer = null;
191-
192-
for ( ValueSource valueSource : valueSources )
162+
int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length();
163+
if ( startEscapeIdx >= 0 )
193164
{
194-
if ( value != null )
165+
String escape = input.substring( startEscapeIdx, startIdx );
166+
if ( escapeString.equals( escape ) )
195167
{
196-
break;
168+
result.append(wholeExpr);
169+
result.replace(startEscapeIdx, startEscapeIdx + escapeString.length(), "");
170+
continue;
197171
}
198-
value = valueSource.getValue( realExpr );
172+
}
173+
}
199174

200-
if ( value != null && value.toString().contains( wholeExpr ) )
201-
{
202-
bestAnswer = value;
203-
value = null;
204-
}
175+
boolean resolved = false;
176+
if ( !unresolvable.contains( wholeExpr ) )
177+
{
178+
if ( realExpr.startsWith( "." ) )
179+
{
180+
realExpr = realExpr.substring(1);
205181
}
206182

207-
// this is the simplest recursion check to catch exact recursion
208-
// (non synonym), and avoid the extra effort of more string
209-
// searching.
210-
if ( value == null && bestAnswer != null )
183+
if ( recursionInterceptor.hasRecursiveExpression( realExpr ) )
211184
{
212185
throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr );
213186
}
214187

215-
if ( value != null )
188+
recursionInterceptor.expressionResolutionStarted( realExpr );
189+
try
216190
{
217-
value = interpolate( String.valueOf( value ), recursionInterceptor, unresolvable );
191+
Object value = existingAnswers.get( realExpr );
192+
Object bestAnswer = null;
193+
194+
for ( ValueSource valueSource : valueSources )
195+
{
196+
if ( value != null )
197+
{
198+
break;
199+
}
200+
value = valueSource.getValue( realExpr );
201+
202+
if ( value != null && value.toString().contains( wholeExpr ) )
203+
{
204+
bestAnswer = value;
205+
value = null;
206+
}
207+
}
218208

219-
if ( postProcessors != null && !postProcessors.isEmpty() )
209+
// this is the simplest recursion check to catch exact recursion
210+
// (non synonym), and avoid the extra effort of more string
211+
// searching.
212+
if ( value == null && bestAnswer != null )
220213
{
221-
for ( InterpolationPostProcessor postProcessor : postProcessors )
214+
throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr );
215+
}
216+
217+
if ( value != null )
218+
{
219+
value = interpolate( String.valueOf(value), recursionInterceptor, unresolvable );
220+
221+
if ( postProcessors != null && !postProcessors.isEmpty() )
222222
{
223-
Object newVal = postProcessor.execute( realExpr, value );
224-
if ( newVal != null )
223+
for ( InterpolationPostProcessor postProcessor : postProcessors )
225224
{
226-
value = newVal;
227-
break;
225+
Object newVal = postProcessor.execute( realExpr, value );
226+
if ( newVal != null )
227+
{
228+
value = newVal;
229+
break;
230+
}
228231
}
229232
}
230-
}
231233

232-
// could use:
233-
// result = matcher.replaceFirst( stringValue );
234-
// but this could result in multiple lookups of stringValue, and replaceAll is not correct
235-
// behaviour
236-
result.append( String.valueOf( value ) );
237-
resolved = true;
234+
// could use:
235+
// result = matcher.replaceFirst( stringValue );
236+
// but this could result in multiple lookups of stringValue, and replaceAll is not correct
237+
// behaviour
238+
result.append( String.valueOf( value ) );
239+
resolved = true;
240+
}
241+
else
242+
{
243+
unresolvable.add( wholeExpr );
244+
}
238245
}
239-
else
246+
finally
240247
{
241-
unresolvable.add( wholeExpr );
248+
recursionInterceptor.expressionResolutionFinished( realExpr );
242249
}
243250
}
244-
finally
251+
252+
if (!resolved)
245253
{
246-
recursionInterceptor.expressionResolutionFinished( realExpr );
254+
result.append( wholeExpr );
255+
}
256+
257+
if ( endIdx > -1 )
258+
{
259+
endIdx += endExpr.length() - 1;
247260
}
248261
}
262+
while ( ( startIdx = input.indexOf( startExpr, endIdx + 1 ) ) > -1);
249263

250-
if ( !resolved )
264+
if ( endIdx == -1 && startIdx > -1 )
251265
{
252-
result.append( wholeExpr );
266+
result.append( input, startIdx, input.length());
253267
}
254-
255-
if ( endIdx > -1 )
268+
else if ( endIdx < input.length() )
256269
{
257-
endIdx += endExpr.length() - 1;
270+
result.append( input, endIdx + 1, input.length() );
258271
}
259-
}
260272

261-
if ( endIdx == -1 && startIdx > -1 )
262-
{
263-
result.append( input, startIdx, input.length());
273+
return result.toString();
264274
}
265-
else if ( endIdx < input.length() )
275+
else
266276
{
267-
result.append( input, endIdx + 1, input.length() );
277+
return input;
268278
}
269-
270-
return result.toString();
271279
}
272280

273281
/**

0 commit comments

Comments
 (0)