1
0
mirror of https://github.com/mitb-archive/filebot synced 2024-08-13 17:03:45 -04:00
filebot/source/net/filebot/util/AlphanumComparator.java

105 lines
2.6 KiB
Java

package net.filebot.util;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
public class AlphanumComparator implements Comparator<String> {
protected Collator collator;
public AlphanumComparator(Collator collator) {
this.collator = collator;
}
public AlphanumComparator(Locale locale) {
this.collator = Collator.getInstance(locale);
this.collator.setDecomposition(Collator.FULL_DECOMPOSITION);
this.collator.setStrength(Collator.PRIMARY);
}
protected boolean isDigit(String s, int i) {
return Character.isDigit(s.charAt(i));
}
protected int getNumericValue(String s, int i) {
return Character.getNumericValue(s.charAt(i));
}
protected String getChunk(String s, int start) {
int index = start;
int length = s.length();
boolean mode = isDigit(s, index++);
while (index < length) {
if (mode != isDigit(s, index)) {
break;
}
++index;
}
return s.substring(start, index);
}
public int compare(String s1, String s2) {
int length1 = s1.length();
int length2 = s2.length();
int index1 = 0;
int index2 = 0;
int result = 0;
while (result == 0 && index1 < length1 && index2 < length2) {
String chunk1 = getChunk(s1, index1);
index1 += chunk1.length();
String chunk2 = getChunk(s2, index2);
index2 += chunk2.length();
if (isDigit(chunk1, 0) && isDigit(chunk2, 0)) {
int chunkLength1 = chunk1.length();
int chunkLength2 = chunk2.length();
// count and skip leading zeros
int zeroIndex1 = 0;
while (zeroIndex1 < chunkLength1 && getNumericValue(chunk1, zeroIndex1) == 0) {
++zeroIndex1;
}
// count and skip leading zeros
int zeroIndex2 = 0;
while (zeroIndex2 < chunkLength2 && getNumericValue(chunk2, zeroIndex2) == 0) {
++zeroIndex2;
}
// the longer run of non-zero digits is greater
result = (chunkLength1 - zeroIndex1) - (chunkLength2 - zeroIndex2);
// if the length is the same, the first differing digit decides
// which one is deemed greater.
int numberIndex1 = zeroIndex1;
int numberIndex2 = zeroIndex2;
while (result == 0 && numberIndex1 < chunkLength1 && numberIndex2 < chunkLength2) {
result = getNumericValue(chunk1, numberIndex1++) - getNumericValue(chunk2, numberIndex2++);
}
// if still no difference, the longer zeros-prefix is greater
if (result == 0) {
result = numberIndex1 - numberIndex2;
}
} else {
result = collator.compare(chunk1, chunk2);
}
}
// if there was no difference at all, let the longer one be the greater one
if (result == 0) {
result = length1 - length2;
}
// limit result to (-1, 0, or 1)
return Integer.signum(result);
}
}