Kaydet (Commit) 2d62a101 authored tarafından Eike Rathke's avatar Eike Rathke

Resolves: tdf#95192 correctly split non-numeral/numeral parts for natural sort

XCharacterClassification::parsePredefinedToken() with
KParseType::IDENTNAME and KParseTokens::ANY_LETTER does exactly
that, it parses one identifier name consisting of Unicode letters
and stops at the first non-letter character (additionally '-'
hyphen-minus was allowed as character).

Instead, scan for the first (any Unicode) digit and split there.

Also, copying the whole string to the prefix string if no split
happens was unnecessary, the caller does not use the prefix if no
number was found. Nail this as post condition.

Change-Id: I941f9739b39c36c83b63145e3b762ec558738c1c
üst f737c938
...@@ -87,13 +87,16 @@ using namespace ::com::sun::star::i18n; ...@@ -87,13 +87,16 @@ using namespace ::com::sun::star::i18n;
Original string to be split into pieces Original string to be split into pieces
@param sPrefix @param sPrefix
Prefix string that consists of the part before the first number token Prefix string that consists of the part before the first number token.
If no number was found, sPrefix is unchanged.
@param sSuffix @param sSuffix
String after the last number token. This may still contain number strings. String after the last number token. This may still contain number strings.
If no number was found, sSuffix is unchanged.
@param fNum @param fNum
Number converted from the middle number string Number converted from the middle number string
If no number was found, fNum is unchanged.
@return Returns TRUE if a numeral element is found in a given string, or @return Returns TRUE if a numeral element is found in a given string, or
FALSE if no numeral element is found. FALSE if no numeral element is found.
...@@ -101,28 +104,34 @@ using namespace ::com::sun::star::i18n; ...@@ -101,28 +104,34 @@ using namespace ::com::sun::star::i18n;
bool SplitString( const OUString &sWhole, bool SplitString( const OUString &sWhole,
OUString &sPrefix, OUString &sSuffix, double &fNum ) OUString &sPrefix, OUString &sSuffix, double &fNum )
{ {
i18n::LocaleDataItem2 aLocaleItem = ScGlobal::pLocaleData->getLocaleItem(); // Get prefix element, search for any digit and stop.
sal_Int32 nPos = 0;
// Get prefix element while (nPos < sWhole.getLength())
OUString sUser = "-"; {
ParseResult aPRPre = ScGlobal::pCharClass->parsePredefinedToken( const sal_uInt16 nType = ScGlobal::pCharClass->getCharacterType( sWhole, nPos);
KParseType::IDENTNAME, sWhole, 0, if (nType & KCharacterType::DIGIT)
KParseTokens::ANY_LETTER, sUser, KParseTokens::ANY_LETTER, sUser ); break;
sPrefix = sWhole.copy( 0, aPRPre.EndPos ); sWhole.iterateCodePoints( &nPos );
}
// Return FALSE if no numeral element is found // Return FALSE if no numeral element is found
if ( aPRPre.EndPos == sWhole.getLength() ) if ( nPos == sWhole.getLength() )
return false; return false;
// Get numeral element // Get numeral element
sUser = aLocaleItem.decimalSeparator; OUString sUser = ScGlobal::pLocaleData->getNumDecimalSep();
ParseResult aPRNum = ScGlobal::pCharClass->parsePredefinedToken( ParseResult aPRNum = ScGlobal::pCharClass->parsePredefinedToken(
KParseType::ANY_NUMBER, sWhole, aPRPre.EndPos, KParseType::ANY_NUMBER, sWhole, nPos,
KParseTokens::ANY_NUMBER, "", KParseTokens::ANY_NUMBER, sUser ); KParseTokens::ANY_NUMBER, "", KParseTokens::ANY_NUMBER, sUser );
if ( aPRNum.EndPos == aPRPre.EndPos ) if ( aPRNum.EndPos == nPos )
{
SAL_WARN("sc.core","naturalsort::SplitString - digit found but no number parsed, pos " <<
nPos << " : " << sWhole);
return false; return false;
}
sPrefix = sWhole.copy( 0, nPos );
fNum = aPRNum.Value; fNum = aPRNum.Value;
sSuffix = sWhole.copy( aPRNum.EndPos ); sSuffix = sWhole.copy( aPRNum.EndPos );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment