charconvfw/SortUtil/src/SortUtilJapan.cpp
changeset 0 1fb32624e06b
child 12 5390220f13c1
child 16 56cd22a7a1cb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/charconvfw/SortUtil/src/SortUtilJapan.cpp	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,280 @@
+/*
+* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:     
+*
+*/
+
+
+
+
+
+
+// INCLUDE FILES
+#include "SortUtilJapan.h"
+#include "SortUtilImpl.h"
+#include "SortUtilImplExport.h"
+#include <JpLangUtil.h>
+
+// Unnamed namespace for local definitions
+namespace
+    {
+
+    /**
+     * Character classes for Japanese sorting, in sorting order.
+     */
+    enum TJapaneseCharClass
+        {
+        ECharClassKana,
+        ECharClassLatin,
+        ECharClassDigit,
+        ECharClassKanji,
+        ECharClassSpecial
+        };
+
+    /**
+     * Returns the Japanese character class of aChar.
+     */
+    TJapaneseCharClass CharClass(TUint aChar)
+        {
+        const TChar ch(aChar);
+        // Special characters
+        if (ch.IsSpace() || ch.IsPunctuation() || ch.IsControl()
+            || aChar >= 0xF0000 && aChar <= 0xFFFD)
+            {
+            return ECharClassSpecial;
+            }
+        // Digit
+        else if (aChar >= '0' && aChar <= '9' ||
+            aChar >= 0xFF10 && aChar <= 0xFF19)
+            {
+            return ECharClassDigit;
+            }
+        // Latin
+        else if (aChar >= 'A' && aChar <= 'Z' ||
+            aChar >= 'a' && aChar <= 'z' ||
+            aChar >= 0x00C0 && aChar <= 0x1EF3 && aChar != 0x00D7 && aChar != 0x00F7 ||
+            aChar >= 0xFF21 && aChar <= 0xFF3A ||
+            aChar >= 0xFF41 && aChar <= 0xFF5A)
+            {
+            return ECharClassLatin;
+            }
+        // Kana
+        else if (JPLangUtil::IsKatakana(static_cast<TText>(aChar)) ||
+            JPLangUtil::IsHiragana(static_cast<TText>(aChar)))
+            {
+            return ECharClassKana;
+            }
+        // Kanji
+        else if (JPLangUtil::IsKanji(static_cast<TText>(aChar)))
+            {
+            return ECharClassKanji;
+            }
+        // All other charcters are "special"
+        else
+            {
+            return ECharClassSpecial;
+            }
+        }
+
+    /**
+     * Compares two characters with Japanese comparison rules.
+     */
+    TInt JapaneseCompareC(TUint aLhs, TUint aRhs)
+        {
+        // First compare character classes
+        const TInt lhsCls = CharClass(aLhs);
+        const TInt rhsCls = CharClass(aRhs);
+        return lhsCls - rhsCls;
+        }
+
+    /**
+     * Compares two strings with Japanese comparison rules.
+     */
+    TInt JapaneseCompareS(const TDesC& aLhs, const TDesC& aRhs)
+        {
+        TInt result = 0;
+
+        const TInt minLen = Min(aLhs.Length(), aRhs.Length());
+        TInt i;
+        TInt prevCompPos(0);
+        for (i = 0; i < minLen && result == 0; ++i)
+            {
+            result = JapaneseCompareC(aLhs[i], aRhs[i]);
+            if (result == 0)
+                {
+                TInt orgClass = CharClass(aLhs[i]);
+                TPtrC lPart;
+                TPtrC rPart;
+                if (orgClass == ECharClassKana)
+                    {
+                    int j = i;
+                    for (; j < aLhs.Length(); ++j)
+                        {
+                        if (orgClass != CharClass(aLhs[j]))
+                            {
+                            break;
+                            }
+                        }
+                    lPart.Set(aLhs.Mid(prevCompPos, j - prevCompPos));
+                    for (j = i; j < aRhs.Length(); ++j)
+                        {
+                        if (orgClass != CharClass(aRhs[j]))
+                            {
+                            break;
+                            }
+                        }
+                    rPart.Set(aRhs.Mid(prevCompPos, j - prevCompPos));
+                    result = lPart.CompareC(rPart);
+                    if (result != 0)
+                        {
+                        const TInt minKanaLen = Min(lPart.Length(), rPart.Length());
+                        TPtrC lKanaPart(lPart.Left(minKanaLen));
+                        TPtrC rKanaPart(rPart.Left(minKanaLen));
+                        TInt resultKana = lKanaPart.MatchC(rKanaPart);
+                        if (resultKana == 0)
+                            {
+                            TInt maxKanaLen = i+minKanaLen;
+                            if (i+minKanaLen+1 >= minLen)
+                                {
+                                if (maxKanaLen < aLhs.Length()
+                                 || maxKanaLen < aRhs.Length())
+                                    {
+                                    result = 0;
+                                    i += (minKanaLen-1);
+                                    }
+                                else
+                                    {
+                                    result = lKanaPart.CompareC(rKanaPart);;
+                                    }
+                                }
+                            else
+                                {
+                                result = 0;
+                                i += (minKanaLen-1);
+                                }
+                            }
+                        }
+
+                    }
+                else
+                    {
+                    lPart.Set(aLhs.Mid(i, 1));
+                    rPart.Set(aRhs.Mid(i, 1));
+                    result = lPart.CompareC(rPart);
+                    }
+                }
+            else
+                {
+                prevCompPos = i;
+                }
+            }
+        if (result == 0)
+            {
+            if (i < aLhs.Length())
+                {
+                // aLhs is longer than aRhs
+                result += User::Collate(aLhs[i]);
+                }
+            if (i < aRhs.Length())
+                {
+                // aRhs is longer that aLhs
+                result -= User::Collate(aRhs[i]);
+                }
+            }
+        return result;
+        }
+    }  // namespace
+
+// Only export in DLL
+EXPORT_C MSortUtil* SortUtilFactoryFunctionL()
+    {
+    MSortUtil* util = new (ELeave) TSortUtilJapan;
+    return util;
+    }
+
+inline TSortUtilJapan::TSortUtilJapan()
+    {
+    }
+
+TSortUtilJapan::~TSortUtilJapan()
+    {
+    }
+
+TInt TSortUtilJapan::CompareItems
+        (const MSortKeyArray& aLhs,
+        const MSortKeyArray& aRhs) const
+    {
+    TInt result(0);
+    TInt lhsIndex(0);
+    TInt rhsIndex(0);
+
+    // Compare only pronounciation keys in the first pass
+    do
+        {
+        const TDesC& lhsText =
+            SortUtilImpl::FindNextNonEmptyKey(aLhs, ESortKeyPronounciation, lhsIndex);
+        const TDesC& rhsText =
+            SortUtilImpl::FindNextNonEmptyKey(aRhs, ESortKeyPronounciation, rhsIndex);
+        if (lhsText.Length() > 0)
+            {
+            // lhs has pronounciation key
+            if (rhsText.Length() > 0)
+                {
+                // Both lhs and rhs have pronounciation key: compare the key texts
+                result = JapaneseCompareS(lhsText, rhsText);
+                }
+            else
+                {
+                // Only lhs has pronounciation key
+                result = -1;
+                }
+            }
+        else
+            {
+            // lhs does not have pronounciation key
+            if (rhsText.Length() > 0)
+                {
+                // Only rhs has pronounciation key
+                result = 1;
+                }
+            }
+
+        if (result != 0)
+            {
+            return result;
+            }
+        }
+    while (lhsIndex <= aLhs.SortKeyCount() && rhsIndex < aRhs.SortKeyCount());
+
+    // No difference found with pronounciation keys: compare basic keys
+    lhsIndex = 0;
+    rhsIndex = 0;
+    do
+        {
+        const TDesC& lhsText =
+            SortUtilImpl::FindNextNonEmptyKey(aLhs, ESortKeyBasic, lhsIndex);
+        const TDesC& rhsText =
+            SortUtilImpl::FindNextNonEmptyKey(aRhs, ESortKeyBasic, rhsIndex);
+        result = JapaneseCompareS(lhsText, rhsText);
+        if (result != 0)
+            {
+            return result;
+            }
+        }
+    while (lhsIndex <= aLhs.SortKeyCount() && rhsIndex < aRhs.SortKeyCount());
+
+    return result;
+    }
+
+// End of file