proguard.util.ListParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of proguard-core Show documentation
Show all versions of proguard-core Show documentation
ProGuardCORE is a free library to read, analyze, modify, and write Java class files.
/*
* ProGuardCORE -- library to process Java bytecode.
*
* Copyright (c) 2002-2020 Guardsquare NV
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package proguard.util;
import java.util.List;
/**
* This {@link StringParser} can create {@link StringMatcher} instances for regular expressions.
* The regular expressions are either presented as a list, or they are
* interpreted as comma-separated lists, optionally prefixed with '!' negators.
* If an entry with a negator matches, a negative match is returned, without
* considering any subsequent entries in the list. The creation of {@link StringMatcher}
* instances for the entries is delegated to the given {@link StringParser}.
*
* For example,
* "*.xml,*.jpg" matches all strings with the given extensions;
* "!dummy" matches all strings except "dummy";
* "!dummy.xml,*.xml" matches all strings with .xml, except "dummy.xml";
* "special.xml,!*.xml" matches "special.xml" and all other non-.xml strings.
*
* @author Eric Lafortune
*/
public class ListParser implements StringParser
{
private final StringParser stringParser;
/**
* Creates a new ListParser that parses individual elements in the
* comma-separated list with the given StringParser.
*/
public ListParser(StringParser stringParser)
{
this.stringParser = stringParser;
}
// Implementations for StringParser.
public StringMatcher parse(String regularExpression)
{
// Split the regular expression to a list and parse it.
return parse(ListUtil.commaSeparatedList(regularExpression));
}
/**
* Creates a StringMatcher for the given regular expression, which can
* be a list of optionally negated simple entries.
*
* An empty list results in a StringMatcher that matches any string.
*/
public StringMatcher parse(List regularExpressions)
{
StringMatcher listMatcher = null;
// Loop over all simple regular expressions, backward, creating a
// linked list of matchers.
for (int index = regularExpressions.size()-1; index >= 0; )
{
String regularExpression = (String)regularExpressions.get(index);
boolean isNegated = isNegated(regularExpression);
// Group similar expressions (all negated or all not negated) in
// an array and an OrMatcher, to reduce the length of the linked
// list and the resulting recursion depth when using the matchers
// later on.
int lastNegatedIndex =
lastNegatedIndex(regularExpressions, index, isNegated);
StringMatcher[] stringMatchers =
parseEntries(regularExpressions, lastNegatedIndex, index);
StringMatcher stringMatcher =
new OrMatcher(stringMatchers);
// Account for the negator, if any.
if (isNegated)
{
stringMatcher = new NotMatcher(stringMatcher);
}
// Prepend the string matcher.
listMatcher =
listMatcher == null ? stringMatcher :
isNegated ? new AndMatcher(stringMatcher, listMatcher) :
new OrMatcher(stringMatcher, listMatcher);
index -= stringMatchers.length;
}
return listMatcher != null ? listMatcher : new ConstantMatcher(true);
}
// Small utility methods.
/**
* Returns the highest index that is negated or not, as specified.
*/
private int lastNegatedIndex(List regularExpressions,
int lastIndex,
boolean isNegated)
{
for (int index = lastIndex; index > 0; index--)
{
String regularExpression = (String)regularExpressions.get(index-1);
if (isNegated(regularExpression) != isNegated)
{
return index;
}
}
return 0;
}
/**
* Creates an array of StringMatcher instances for the specified simple
* regular expressions.
*/
private StringMatcher[] parseEntries(List regularExpressions,
int firstIndex,
int lastIndex)
{
StringMatcher[] stringMatchers =
new StringMatcher[lastIndex - firstIndex + 1];
for (int index = firstIndex; index <= lastIndex; index++)
{
String regularExpression = (String)regularExpressions.get(index);
stringMatchers[index - firstIndex] = parseEntry(regularExpression);
}
return stringMatchers;
}
/**
* Creates a StringMatcher for the given regular expression, stripping any
* negator.
*/
private StringMatcher parseEntry(String regularExpression)
{
// Strip the negator, if any.
if (isNegated(regularExpression))
{
regularExpression = regularExpression.substring(1);
}
return stringParser.parse(regularExpression);
}
/**
* Returns whether the given simple regular expression is negated.
*/
private boolean isNegated(String regularExpression)
{
return regularExpression.length() > 0 &&
regularExpression.charAt(0) == '!';
}
/**
* A main method for testing name matching.
*/
public static void main(String[] args)
{
try
{
System.out.println("Regular expression ["+args[0]+"]");
ListParser parser = new ListParser(new NameParser());
StringMatcher matcher = parser.parse(args[0]);
for (int index = 1; index < args.length; index++)
{
String string = args[index];
System.out.print("String ["+string+"]");
System.out.println(" -> match = "+matcher.matches(args[index]));
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy