blob: a8e930719d95862d78c61a261bf63fb3ece640b5 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2007, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.r.core;
import java.util.Comparator;
import java.util.Locale;
import com.ibm.icu.text.Collator;
import com.ibm.icu.text.RuleBasedCollator;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
/**
*
*/
@NonNullByDefault
public class RSymbolComparator implements Comparator<String> {
public static final class PrefixPattern {
private final char[] prefix;
public PrefixPattern(final String namePrefix) {
this.prefix= namePrefix.toLowerCase().toCharArray();
}
/**
* Tolerant string comparison
*
* @param candidate string to test against prefix
* @param prefix char array of lowercase prefix
* @return if candidate starts with prefix
*/
public boolean matches(final @Nullable String candidate) {
if (candidate == null || candidate.isEmpty()) {
return false;
}
if (this.prefix.length == 0) {
return (candidate.charAt(0) != '.');
}
int pC= this.prefix[0];
int cC= Character.toLowerCase(candidate.charAt(0));
if (cC != pC) {
return false;
}
int pIdx= 0;
int cIdx= 0;
while (true) {
if (pC == cC) {
if (++pIdx >= this.prefix.length) {
return true;
}
if (++cIdx >= candidate.length()) {
return false;
}
pC= this.prefix[pIdx];
cC= Character.toLowerCase(candidate.charAt(cIdx));
continue;
}
if (pC == '.' || pC == '_') {
if (++pIdx >= this.prefix.length) {
return true;
}
pC= this.prefix[pIdx];
continue;
}
if (cC == '.' || cC == '_') {
if (++cIdx >= candidate.length()) {
return false;
}
cC= Character.toLowerCase(candidate.charAt(cIdx));
continue;
}
return false;
}
}
}
public static final Collator R_NAMES_COLLATOR= Collator.getInstance(Locale.ENGLISH);
static {
((RuleBasedCollator) R_NAMES_COLLATOR).setUpperCaseFirst(true);
}
@Override
public int compare(final String name1, final String name2) {
return R_NAMES_COLLATOR.compare(check(name1), check(name2));
}
private String check(final String name) {
if (name.length() > 0 && name.charAt(0) == '`') {
return name.substring(1);
}
return name;
}
}