StringUtils:

- use new StringUtils.split(..., boolean trim, boolean excludeEmpty) where possible
- added substringTrimmed() and isTrimmedEmpty() to avoid temporary string  allocation
This commit is contained in:
Karl Tauber
2021-09-30 01:14:45 +02:00
parent 2d232124dd
commit d93dde0a03
4 changed files with 113 additions and 42 deletions

View File

@@ -392,7 +392,7 @@ class UIDefaultsLoader
// Syntax: lazy(uiKey)
if( value.startsWith( "lazy(" ) && value.endsWith( ")" ) ) {
resultValueType[0] = ValueType.LAZY;
String uiKey = value.substring( 5, value.length() - 1 ).trim();
String uiKey = StringUtils.substringTrimmed( value, 5, value.length() - 1 );
return (LazyValue) t -> {
return lazyUIManagerGet( uiKey );
};
@@ -514,7 +514,7 @@ class UIDefaultsLoader
private static Object parseBorder( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
if( value.indexOf( ',' ) >= 0 ) {
// top,left,bottom,right[,lineColor[,lineThickness]]
List<String> parts = split( value, ',' );
List<String> parts = StringUtils.split( value, ',', true, false );
Insets insets = parseInsets( value );
ColorUIResource lineColor = (parts.size() >= 5)
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver, true )
@@ -571,7 +571,7 @@ class UIDefaultsLoader
}
private static Insets parseInsets( String value ) {
List<String> numbers = split( value, ',' );
List<String> numbers = StringUtils.split( value, ',', true, false );
try {
return new InsetsUIResource(
Integer.parseInt( numbers.get( 0 ) ),
@@ -584,7 +584,7 @@ class UIDefaultsLoader
}
private static Dimension parseDimension( String value ) {
List<String> numbers = split( value, ',' );
List<String> numbers = StringUtils.split( value, ',', true, false );
try {
return new DimensionUIResource(
Integer.parseInt( numbers.get( 0 ) ),
@@ -672,7 +672,7 @@ class UIDefaultsLoader
return null;
}
String function = value.substring( 0, paramsStart ).trim();
String function = StringUtils.substringTrimmed( value, 0, paramsStart );
List<String> params = splitFunctionParams( value.substring( paramsStart + 1, value.length() - 1 ), ',' );
if( params.isEmpty() )
throwMissingParametersException( value );
@@ -1075,7 +1075,7 @@ class UIDefaultsLoader
}
private static Object parseGrayFilter( String value ) {
List<String> numbers = split( value, ',' );
List<String> numbers = StringUtils.split( value, ',', true, false );
try {
int brightness = Integer.parseInt( numbers.get( 0 ) );
int contrast = Integer.parseInt( numbers.get( 1 ) );
@@ -1089,20 +1089,6 @@ class UIDefaultsLoader
}
}
/**
* Split string and trim parts.
*/
private static List<String> split( String str, char delim ) {
List<String> result = StringUtils.split( str, delim );
// trim strings
int size = result.size();
for( int i = 0; i < size; i++ )
result.set( i, result.get( i ).trim() );
return result;
}
/**
* Splits function parameters and allows using functions as parameters.
* In other words: Delimiters surrounded by '(' and ')' are ignored.
@@ -1119,11 +1105,11 @@ class UIDefaultsLoader
else if( ch == ')' )
nestLevel--;
else if( nestLevel == 0 && ch == delim ) {
strs.add( str.substring( start, i ).trim() );
strs.add( StringUtils.substringTrimmed( str, start, i ) );
start = i + 1;
}
}
strs.add( str.substring( start ).trim() );
strs.add( StringUtils.substringTrimmed( str, start ) );
return strs;
}

View File

@@ -252,7 +252,7 @@ public class FlatStylingSupport
if( style instanceof String ) {
// handle style in CSS syntax
String str = (String) style;
if( str.trim().isEmpty() )
if( StringUtils.isTrimmedEmpty( str ) )
return null;
return applyStyle( parse( str ), applyProperty );
@@ -307,26 +307,21 @@ public class FlatStylingSupport
public static Map<String, Object> parse( String style )
throws IllegalArgumentException
{
if( style == null || style.trim().isEmpty() )
if( style == null || StringUtils.isTrimmedEmpty( style ) )
return null;
Map<String, Object> map = null;
// split style into parts and process them
for( String part : StringUtils.split( style, ';' ) ) {
// ignore empty parts
part = part.trim();
if( part.isEmpty() )
continue;
for( String part : StringUtils.split( style, ';', true, true ) ) {
// find separator colon
int sepIndex = part.indexOf( ':' );
if( sepIndex < 0 )
throw new IllegalArgumentException( "missing colon in '" + part + "'" );
// split into key and value
String key = part.substring( 0, sepIndex ).trim();
String value = part.substring( sepIndex + 1 ).trim();
String key = StringUtils.substringTrimmed( part, 0, sepIndex );
String value = StringUtils.substringTrimmed( part, sepIndex + 1 );
if( key.isEmpty() )
throw new IllegalArgumentException( "missing key in '" + part + "'" );
if( value.isEmpty() )

View File

@@ -79,18 +79,66 @@ public class StringUtils
return strs;
}
private static void add( List<String> strs, String str, int begin, int end, boolean trim, boolean excludeEmpty ) {
private static void add( List<String> strs, String str, int beginIndex, int endIndex,
boolean trim, boolean excludeEmpty )
{
if( trim ) {
// skip leading whitespace
while( begin < end && str.charAt( begin ) <= ' ' )
begin++;
// skip trailing whitespace
while( begin < end && str.charAt( end - 1 ) <= ' ' )
end--;
beginIndex = trimBegin( str, beginIndex, endIndex );
endIndex = trimEnd( str, beginIndex, endIndex );
}
if( !excludeEmpty || end > begin )
strs.add( str.substring( begin, end ) );
if( !excludeEmpty || endIndex > beginIndex )
strs.add( str.substring( beginIndex, endIndex ) );
}
/**
* This is equal to {@code str.substring( beginIndex, endIndex ).trim()},
* but avoids temporary untrimmed substring allocation.
* If the trimmed string is empty, a shared empty string is returned.
*
* @since 2
*/
public static String substringTrimmed( String str, int beginIndex ) {
return substringTrimmed( str, beginIndex, str.length() );
}
/**
* This is equal to {@code str.substring( beginIndex ).trim()},
* but avoids temporary untrimmed substring allocation.
* If the trimmed string is empty, a shared empty string is returned.
*
* @since 2
*/
public static String substringTrimmed( String str, int beginIndex, int endIndex ) {
beginIndex = trimBegin( str, beginIndex, endIndex );
endIndex = trimEnd( str, beginIndex, endIndex );
return (endIndex > beginIndex) ? str.substring( beginIndex, endIndex ) : "";
}
/**
* This is equal to {@code str.trim().isEmpty()},
* but avoids temporary trimmed substring allocation.
*
* @since 2
*/
public static boolean isTrimmedEmpty( String str ) {
int length = str.length();
int beginIndex = trimBegin( str, 0, length );
int endIndex = trimEnd( str, beginIndex, length );
return beginIndex >= endIndex;
}
private static int trimBegin( String str, int beginIndex, int endIndex ) {
// skip leading whitespace
while( beginIndex < endIndex && str.charAt( beginIndex ) <= ' ' )
beginIndex++;
return beginIndex;
}
private static int trimEnd( String str, int beginIndex, int endIndex ) {
// skip trailing whitespace
while( beginIndex < endIndex && str.charAt( endIndex - 1 ) <= ' ' )
endIndex--;
return endIndex;
}
}

View File

@@ -195,4 +195,46 @@ public class TestStringUtils
Arrays.asList( "a", "b", "c" ),
StringUtils.split( "a\n\n\nb\n\nc", '\n', true, true ) );
}
@Test
void substringTrimmed() {
testSubstringTrimmed( "", 0 );
testSubstringTrimmed( "a", 0 );
testSubstringTrimmed( "a", 1 );
testSubstringTrimmed( "a ", 0 );
testSubstringTrimmed( " a", 0 );
testSubstringTrimmed( " a ", 0 );
testSubstringTrimmed( " a ", 1 );
testSubstringTrimmed( " a ", 0, 3 );
testSubstringTrimmed( " a ", 1, 4 );
}
private void testSubstringTrimmed( String str, int beginIndex ) {
assertEquals(
str.substring( beginIndex ).trim(),
StringUtils.substringTrimmed( str, beginIndex ) );
}
private void testSubstringTrimmed( String str, int beginIndex, int endIndex ) {
assertEquals(
str.substring( beginIndex, endIndex ).trim(),
StringUtils.substringTrimmed( str, beginIndex, endIndex ) );
}
@Test
void trimmedEmpty() {
testTrimmedEmpty( "" );
testTrimmedEmpty( "a" );
testTrimmedEmpty( " a " );
testTrimmedEmpty( " " );
testTrimmedEmpty( " " );
}
private void testTrimmedEmpty( String str ) {
assertEquals( str.trim().isEmpty(), StringUtils.isTrimmedEmpty( str ) );
}
}