Has anybody implemented a natural order sort function for juce strings? I’ve thought about just using StrCmpLogicalW(), but I would like something that is portable.
Also, it would be nice if StringArray had a sort function that you could pass an ElementComparator into.
I recently ran into the case where for a set of strings, I knew that sorting by doing the comparison from right to left would be more efficient 90% of the time, and it would have been useful if a custom sort comparator could be set.
Obviously it’s easy enough to create an owned array of string, but string array is more descriptive.
// FOR THE STRING CLASS
/* This converts a char pointer to an int like stroul ... but only in
base 10 (boring!) Assumes that we already have a digit. */
unsigned long charPtrToIntInternal(CharPointerType & s) const {
unsigned int digit; // careful. must be unsigned so negs roll around.
long int result(0);
while (s.isDigit()) {
digit = (*s) - '0';
result *= 10;
result += digit;
++s;
}
return result;
}
/* This is a stripped back version of DOJ's code. Adjusted to be a bit more
JUCE friendly. */
int compareWithYogicKarma(const String & other) const noexcept
{
enum Mode {
mString,
mNumber
} mode;
CharPointerType s1 (text);
CharPointerType s2 (other.text);
while (*s1 && *s2) {
if (mode == mString) {
// mString. Flips into number mode if it
// spots a digit at the same point in both
// strings.
char s1c, s2c;
while ((s1c = *s1) && (s2c = *s2)) {
const bool s1dig = s1.isDigit();
const bool s2dig = s2.isDigit();
if (s1dig && s2dig) {
mode = mNumber;
break;
}
if (s1dig) return -1;
if (s2dig) return 1;
const int diff = *s1 - *s2;
if (diff != 0) return diff;
s1++;
s2++;
}
} else {
// mNumber.
// Note that charPtrToIntInternal advances s1 or s2 past the number!
unsigned long s1int = charPtrToIntInternal(s1);
unsigned long s2int = charPtrToIntInternal(s2);
const long int diff = s1int - s2int;
if (diff != 0)
return diff;
mode = mString;
}
}
if (*s1) return -1;
if (*s2) return 1;
return 0;
}
The sort code is based on http://www.davekoelle.com/files/alphanum.hpp and probably warrants the inclusion of the copyright message from there. Though I've had to modify a few bits to make it more JUCE friendly.
The following test passes. It doesn't crash, but doesn't properly sort, if numbers in the string are bigger than a long int can hold.