1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/textandlocutils/sortutil/src/SortUtilJapan.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,280 @@
1.4 +/*
1.5 +* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +
1.23 +
1.24 +
1.25 +
1.26 +// INCLUDE FILES
1.27 +#include "SortUtilJapan.h"
1.28 +#include "SortUtilImpl.h"
1.29 +#include "SortUtilImplExport.h"
1.30 +#include <jplangutil.h>
1.31 +
1.32 +// Unnamed namespace for local definitions
1.33 +namespace
1.34 + {
1.35 +
1.36 + /**
1.37 + * Character classes for Japanese sorting, in sorting order.
1.38 + */
1.39 + enum TJapaneseCharClass
1.40 + {
1.41 + ECharClassKana,
1.42 + ECharClassLatin,
1.43 + ECharClassDigit,
1.44 + ECharClassKanji,
1.45 + ECharClassSpecial
1.46 + };
1.47 +
1.48 + /**
1.49 + * Returns the Japanese character class of aChar.
1.50 + */
1.51 + TJapaneseCharClass CharClass(TUint aChar)
1.52 + {
1.53 + const TChar ch(aChar);
1.54 + // Special characters
1.55 + if (ch.IsSpace() || ch.IsPunctuation() || ch.IsControl()
1.56 + || aChar >= 0xF0000 && aChar <= 0xFFFD)
1.57 + {
1.58 + return ECharClassSpecial;
1.59 + }
1.60 + // Digit
1.61 + else if (aChar >= '0' && aChar <= '9' ||
1.62 + aChar >= 0xFF10 && aChar <= 0xFF19)
1.63 + {
1.64 + return ECharClassDigit;
1.65 + }
1.66 + // Latin
1.67 + else if (aChar >= 'A' && aChar <= 'Z' ||
1.68 + aChar >= 'a' && aChar <= 'z' ||
1.69 + aChar >= 0x00C0 && aChar <= 0x1EF3 && aChar != 0x00D7 && aChar != 0x00F7 ||
1.70 + aChar >= 0xFF21 && aChar <= 0xFF3A ||
1.71 + aChar >= 0xFF41 && aChar <= 0xFF5A)
1.72 + {
1.73 + return ECharClassLatin;
1.74 + }
1.75 + // Kana
1.76 + else if (JPLangUtil::IsKatakana(static_cast<TText>(aChar)) ||
1.77 + JPLangUtil::IsHiragana(static_cast<TText>(aChar)))
1.78 + {
1.79 + return ECharClassKana;
1.80 + }
1.81 + // Kanji
1.82 + else if (JPLangUtil::IsKanji(static_cast<TText>(aChar)))
1.83 + {
1.84 + return ECharClassKanji;
1.85 + }
1.86 + // All other charcters are "special"
1.87 + else
1.88 + {
1.89 + return ECharClassSpecial;
1.90 + }
1.91 + }
1.92 +
1.93 + /**
1.94 + * Compares two characters with Japanese comparison rules.
1.95 + */
1.96 + TInt JapaneseCompareC(TUint aLhs, TUint aRhs)
1.97 + {
1.98 + // First compare character classes
1.99 + const TInt lhsCls = CharClass(aLhs);
1.100 + const TInt rhsCls = CharClass(aRhs);
1.101 + return lhsCls - rhsCls;
1.102 + }
1.103 +
1.104 + /**
1.105 + * Compares two strings with Japanese comparison rules.
1.106 + */
1.107 + TInt JapaneseCompareS(const TDesC& aLhs, const TDesC& aRhs)
1.108 + {
1.109 + TInt result = 0;
1.110 +
1.111 + const TInt minLen = Min(aLhs.Length(), aRhs.Length());
1.112 + TInt i;
1.113 + TInt prevCompPos(0);
1.114 + for (i = 0; i < minLen && result == 0; ++i)
1.115 + {
1.116 + result = JapaneseCompareC(aLhs[i], aRhs[i]);
1.117 + if (result == 0)
1.118 + {
1.119 + TInt orgClass = CharClass(aLhs[i]);
1.120 + TPtrC lPart;
1.121 + TPtrC rPart;
1.122 + if (orgClass == ECharClassKana)
1.123 + {
1.124 + int j = i;
1.125 + for (; j < aLhs.Length(); ++j)
1.126 + {
1.127 + if (orgClass != CharClass(aLhs[j]))
1.128 + {
1.129 + break;
1.130 + }
1.131 + }
1.132 + lPart.Set(aLhs.Mid(prevCompPos, j - prevCompPos));
1.133 + for (j = i; j < aRhs.Length(); ++j)
1.134 + {
1.135 + if (orgClass != CharClass(aRhs[j]))
1.136 + {
1.137 + break;
1.138 + }
1.139 + }
1.140 + rPart.Set(aRhs.Mid(prevCompPos, j - prevCompPos));
1.141 + result = lPart.CompareC(rPart);
1.142 + if (result != 0)
1.143 + {
1.144 + const TInt minKanaLen = Min(lPart.Length(), rPart.Length());
1.145 + TPtrC lKanaPart(lPart.Left(minKanaLen));
1.146 + TPtrC rKanaPart(rPart.Left(minKanaLen));
1.147 + TInt resultKana = lKanaPart.MatchC(rKanaPart);
1.148 + if (resultKana == 0)
1.149 + {
1.150 + TInt maxKanaLen = i+minKanaLen;
1.151 + if (i+minKanaLen+1 >= minLen)
1.152 + {
1.153 + if (maxKanaLen < aLhs.Length()
1.154 + || maxKanaLen < aRhs.Length())
1.155 + {
1.156 + result = 0;
1.157 + i += (minKanaLen-1);
1.158 + }
1.159 + else
1.160 + {
1.161 + result = lKanaPart.CompareC(rKanaPart);;
1.162 + }
1.163 + }
1.164 + else
1.165 + {
1.166 + result = 0;
1.167 + i += (minKanaLen-1);
1.168 + }
1.169 + }
1.170 + }
1.171 +
1.172 + }
1.173 + else
1.174 + {
1.175 + lPart.Set(aLhs.Mid(i, 1));
1.176 + rPart.Set(aRhs.Mid(i, 1));
1.177 + result = lPart.CompareC(rPart);
1.178 + }
1.179 + }
1.180 + else
1.181 + {
1.182 + prevCompPos = i;
1.183 + }
1.184 + }
1.185 + if (result == 0)
1.186 + {
1.187 + if (i < aLhs.Length())
1.188 + {
1.189 + // aLhs is longer than aRhs
1.190 + result += User::Collate(aLhs[i]);
1.191 + }
1.192 + if (i < aRhs.Length())
1.193 + {
1.194 + // aRhs is longer that aLhs
1.195 + result -= User::Collate(aRhs[i]);
1.196 + }
1.197 + }
1.198 + return result;
1.199 + }
1.200 + } // namespace
1.201 +
1.202 +// Only export in DLL
1.203 +EXPORT_C MSortUtil* SortUtilFactoryFunctionL()
1.204 + {
1.205 + MSortUtil* util = new (ELeave) TSortUtilJapan;
1.206 + return util;
1.207 + }
1.208 +
1.209 +inline TSortUtilJapan::TSortUtilJapan()
1.210 + {
1.211 + }
1.212 +
1.213 +TSortUtilJapan::~TSortUtilJapan()
1.214 + {
1.215 + }
1.216 +
1.217 +TInt TSortUtilJapan::CompareItems
1.218 + (const MSortKeyArray& aLhs,
1.219 + const MSortKeyArray& aRhs) const
1.220 + {
1.221 + TInt result(0);
1.222 + TInt lhsIndex(0);
1.223 + TInt rhsIndex(0);
1.224 +
1.225 + // Compare only pronounciation keys in the first pass
1.226 + do
1.227 + {
1.228 + const TDesC& lhsText =
1.229 + SortUtilImpl::FindNextNonEmptyKey(aLhs, ESortKeyPronounciation, lhsIndex);
1.230 + const TDesC& rhsText =
1.231 + SortUtilImpl::FindNextNonEmptyKey(aRhs, ESortKeyPronounciation, rhsIndex);
1.232 + if (lhsText.Length() > 0)
1.233 + {
1.234 + // lhs has pronounciation key
1.235 + if (rhsText.Length() > 0)
1.236 + {
1.237 + // Both lhs and rhs have pronounciation key: compare the key texts
1.238 + result = JapaneseCompareS(lhsText, rhsText);
1.239 + }
1.240 + else
1.241 + {
1.242 + // Only lhs has pronounciation key
1.243 + result = -1;
1.244 + }
1.245 + }
1.246 + else
1.247 + {
1.248 + // lhs does not have pronounciation key
1.249 + if (rhsText.Length() > 0)
1.250 + {
1.251 + // Only rhs has pronounciation key
1.252 + result = 1;
1.253 + }
1.254 + }
1.255 +
1.256 + if (result != 0)
1.257 + {
1.258 + return result;
1.259 + }
1.260 + }
1.261 + while (lhsIndex <= aLhs.SortKeyCount() && rhsIndex < aRhs.SortKeyCount());
1.262 +
1.263 + // No difference found with pronounciation keys: compare basic keys
1.264 + lhsIndex = 0;
1.265 + rhsIndex = 0;
1.266 + do
1.267 + {
1.268 + const TDesC& lhsText =
1.269 + SortUtilImpl::FindNextNonEmptyKey(aLhs, ESortKeyBasic, lhsIndex);
1.270 + const TDesC& rhsText =
1.271 + SortUtilImpl::FindNextNonEmptyKey(aRhs, ESortKeyBasic, rhsIndex);
1.272 + result = JapaneseCompareS(lhsText, rhsText);
1.273 + if (result != 0)
1.274 + {
1.275 + return result;
1.276 + }
1.277 + }
1.278 + while (lhsIndex <= aLhs.SortKeyCount() && rhsIndex < aRhs.SortKeyCount());
1.279 +
1.280 + return result;
1.281 + }
1.282 +
1.283 +// End of file