in utils/common/src/main/java/org/apache/brooklyn/util/text/NaturalOrderComparator.java [128:222]
public int compareInternal(String a, String b) {
int ia = 0, ib = 0;
int nza = 0, nzb = 0;
char ca, cb;
int result;
while (true) {
// only count the number of zeroes leading the last number compared
nza = nzb = 0;
ca = charAt(a, ia); cb = charAt(b, ib);
// skip over leading spaces or zeros
while (Character.isSpaceChar(ca) || ca == '0') {
if (ca == '0') {
nza++;
} else {
// only count consecutive zeroes
nza = 0;
}
ca = charAt(a, ++ia);
}
while (Character.isSpaceChar(cb) || cb == '0') {
if (cb == '0') {
nzb++;
} else {
// only count consecutive zeroes
nzb = 0;
}
cb = charAt(b, ++ib);
}
// process run of digits
if (Character.isDigit(ca) && Character.isDigit(cb)) {
if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) {
return result;
}
// numeric portion is the same; previously we incremented and checked again
// which is inefficient (we keep checking remaining numbers here);
// also if we want to compare on 0's after comparing remainder of string
// we need to recurse here after skipping the digits we just checked above
do {
ia++; ib++;
boolean aDigitsDone = ia >= a.length() || !Character.isDigit(charAt(a, ia));
boolean bDigitsDone = ib >= b.length() || !Character.isDigit(charAt(b, ib));
if (aDigitsDone != bDigitsDone) {
// sanity check
throw new IllegalStateException("Digit sequence lengths should have matched, '"+a+"' v '"+b+"'");
}
if (aDigitsDone) break;
} while (true);
if (ia < a.length() || ib < b.length()) {
if (ia >= a.length()) return -1; // only b has more chars
if (ib >= b.length()) return 1; // only a has more chars
// both have remaining chars; neither is numeric due to compareRight; recurse into remaining
if ((result = compareInternal(a.substring(ia), b.substring(ib))) != 0) {
return result;
}
}
// numbers are equal value, remaining string compares identical;
// comes down to whether there are any leading zeroes here
return nzb-nza;
} else if ((Character.isDigit(ca) || nza>0) && (Character.isDigit(cb) || nzb>0)) {
// both sides are numbers, but at least one is a sequence of zeros
if (nza==0) {
// b=0, a>0
return 1;
}
if (nzb==0) {
// inverse
return -1;
}
// both sides were zero, continue to next check below
}
if (ca == 0 && cb == 0) {
// The strings compare the same. Perhaps the caller
// will want to call strcmp to break the tie.
return nza - nzb;
}
if (ca < cb) {
return -1;
} else if (ca > cb) {
return +1;
}
++ia; ++ib;
}
}