Optimize misc::naturalSort()

Previous implementation used QRegExp to find a first digit. That is
utterly ineffective.

When torrent list is sorted by name (a column that uses the naturalSort() for
comparison), naturalSort could take 18.6% of the time of the UI thread. Optimize it
so now it takes 1% of the time of the UI thread.
This commit is contained in:
Ivan Sorokin 2014-10-18 01:29:23 +04:00
parent f9dc945730
commit a278261806

View file

@ -541,15 +541,29 @@ QString misc::toQString(time_t t)
bool misc::naturalSort(QString left, QString right, bool &result) { // uses lessThan comparison bool misc::naturalSort(QString left, QString right, bool &result) { // uses lessThan comparison
// Return value indicates if functions was successful // Return value indicates if functions was successful
// result argument will contain actual comparison result if function was successful // result argument will contain actual comparison result if function was successful
int posL = 0;
int posR = 0;
do { do {
int posL = left.indexOf(QRegExp("[0-9]")); for (;;) {
int posR = right.indexOf(QRegExp("[0-9]")); if (posL == left.size() || posR == right.size())
if (posL == -1 || posR == -1) return false; // No data
break; // No data
else if (posL != posR) QChar leftChar = left.at(posL);
break; // Digit positions mismatch QChar rightChar = right.at(posR);
else if (left.left(posL) != right.left(posR)) bool leftCharIsDigit = leftChar.isDigit();
break; // Strings' subsets before digit do not match bool rightCharIsDigit = rightChar.isDigit();
if (leftCharIsDigit != rightCharIsDigit)
return false; // Digit positions mismatch
if (leftCharIsDigit)
break; // Both are digit, break this loop and compare numbers
if (leftChar != rightChar)
return false; // Strings' subsets before digit do not match
++posL;
++posR;
}
QString temp; QString temp;
while (posL < left.size()) { while (posL < left.size()) {
@ -578,8 +592,6 @@ bool misc::naturalSort(QString left, QString right, bool &result) { // uses less
// Strings + digits do match and we haven't hit string end // Strings + digits do match and we haven't hit string end
// Do another round // Do another round
left.remove(0, posL);
right.remove(0, posR);
} while (true); } while (true);