okular/generators/comicbook/qnatsort.cpp
Tom Albers 2bfe44c45c RELICENSE: relicense to GPL2/3. All contributors agreed to the relicense. Received separate mail from Martin Pool:
--------------------------------------------
 > You are listed as copyright holder for the files 
 > in kdegraphics/okular/generators/comicbook/qnatsort.cpp. 
 > Please let me know if you approve of such a relicense.
 >
 > I hope you approce.
 
 I'm willing to relicence to GPL2/3.  I'm reluctant to sign a blank
 cheque by agreeing to all future versions of the licence.
 
 -- 
 Martin
--------------------------------------------
CCMAIL: mbp@sourcefrog.net

svn path=/trunk/KDE/kdegraphics/okular/; revision=749279
2007-12-16 23:34:09 +00:00

139 lines
3.8 KiB
C++

/**
Natural order sorting of strings which contains numbers.
Copyright 2007 Tobias Koenig <tokoe@kde.org>
based on the natural order code by Martin Pool <mbp sourcefrog net>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License version 2 or at your option version 3 as published by
the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "qnatsort.h"
static int compare_right( const QString &leftStr, int left, const QString &rightStr, int right )
{
int bias = 0;
/**
* The longest run of digits wins. That aside, the greatest
* value wins, but we can't know that it will until we've scanned
* both numbers to know that they have the same magnitude, so we
* remember it in BIAS.
*/
for ( ;; left++, right++ ) {
if ( !leftStr[ left ].isDigit() && !rightStr[ right ].isDigit() )
return bias;
else if ( !leftStr[ left ].isDigit() )
return -1;
else if ( !rightStr[ right ].isDigit() )
return +1;
else if ( leftStr[ left ] < rightStr[ right ] ) {
if ( !bias )
bias = -1;
} else if ( leftStr[ left ] > rightStr[ right ] ) {
if ( !bias )
bias = +1;
} else if ( leftStr[ left ].isNull() && rightStr[ right ].isNull() )
return bias;
}
return 0;
}
static int compare_left( const QString &leftStr, int left, const QString &rightStr, int right )
{
/**
* Compare two left-aligned numbers: the first to have a
* different value wins.
*/
for ( ;; left++, right++ ) {
if ( !leftStr[ left ].isDigit() && !rightStr[ right ].isDigit() )
return 0;
else if ( !leftStr[ left ].isDigit() )
return -1;
else if ( !rightStr[ right ].isDigit() )
return +1;
else if ( leftStr[ left ] < rightStr[ right ] )
return -1;
else if ( leftStr[ left ] > rightStr[ right ] )
return +1;
}
return 0;
}
static int natural_order_compare( const QString &leftStr, const QString &rightStr, bool fold_case )
{
if ( leftStr.isEmpty() && rightStr.isEmpty() )
return 0;
int ai, bi;
QChar ca, cb;
int fractional, result;
ai = bi = 0;
while ( true ) {
ca = leftStr[ ai ]; cb = rightStr[ bi ];
/* skip over leading spaces or zeros */
while ( ca.isSpace() )
ca = leftStr[ ++ai ];
while ( cb.isSpace() )
cb = rightStr[ ++bi ];
/* process run of digits */
if ( ca.isDigit() && cb.isDigit() ) {
fractional = (ca == '0' || cb == '0');
if ( fractional ) {
if ( (result = compare_left( leftStr, ai, rightStr, bi )) != 0 )
return result;
} else {
if ( (result = compare_right( leftStr, ai, rightStr, bi )) != 0 )
return result;
}
}
if ( ca.isNull() && cb.isNull() ) {
/* The strings compare the same. Perhaps the caller
will want to call strcmp to break the tie. */
return 0;
}
if ( fold_case ) {
ca = ca.toUpper();
cb = cb.toUpper();
}
if ( ca < cb )
return -1;
else if ( ca > cb )
return +1;
++ai; ++bi;
}
}
bool caseSensitiveNaturalOrderLessThen( const QString &left, const QString &right )
{
return (natural_order_compare( left, right, false ) < 0);
}
bool caseInsensitiveNaturalOrderLessThen( const QString &left, const QString &right )
{
return (natural_order_compare( left, right, true ) < 0);
}