phonebookui/Phonebook/Engine/src/PbkEngUtils.cpp
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook/Engine/src/PbkEngUtils.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,584 @@
+/*
+* Copyright (c) 2002 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: 
+*		Namespace structure for Phonebook engine helper functions
+*
+*/
+
+
+// INCLUDE FILES
+#include <PbkEngUtils.h>
+#include <f32file.h>
+#include <barsc.h>
+#include <bautils.h>
+#include <featmgr.h>
+#include "PbkDataCaging.hrh"
+
+/// Unnamed namespace for local definitions
+namespace __RVCT_UNS_PbkEngUtils {
+
+// LOCAL CONSTANTS
+enum TPanicCode
+    {
+    EPanicPreCond_CopyAndReplaceChars = 1,
+    EPanicPostCond_TrimAllLength,
+    EPanicPostCond_TrimRightLength,
+    EPanicPreCond_TrimAllAppend,
+    EPanicPostCond_TrimAllAppend,
+    EPanicPreCond_TrimRightAppend,
+    EPanicPostCond_TrimRightAppend
+
+    };
+
+_LIT(KEngDefResFileName, "PbkEng.rsc");  // default resource file name
+_LIT(KEngChineseResFileName, "PbkEngChinese.rsc");   // Chinese resource
+_LIT(KEngJapaneseResFileName, "PbkEngJapanese.rsc"); // Japanese resource
+
+// ================= LOCAL FUNCTIONS =======================
+#ifdef _DEBUG
+void Panic(TPanicCode aReason)
+    {
+    _LIT(KPanicText, "PbkEngUtils");
+    User::Panic(KPanicText, aReason);
+    }
+#endif
+
+const TUint KPbkZWSCharacter = 0x200B;
+const TUint KPbkZWNJCharacter = 0x200C;
+
+// Check if the given char is a Zero Width Space or Non-Joiner character
+inline TBool ZWSCharacter( const TChar aChar )
+    {
+    const TChar zwsChar( KPbkZWSCharacter );
+    const TChar zwnjChar( KPbkZWNJCharacter );
+    return (aChar == zwsChar) || (aChar == zwnjChar);
+    }
+
+/**
+ * Implementation class for PbkEngUtils::BreakInWordsLC.
+ */
+NONSHARABLE_CLASS(CWords) : 
+        public CBase, 
+        public MDesCArray
+    {
+    public:  // Constructors and destructor
+        /**
+         * Creates a new instance of this class.
+		 * @param aText the text to separate
+		 * @param aWordSeparatorFunc function for detecting
+		 *        word separator characters
+         */
+        static CWords* NewLC
+            (const TDesC& aText, 
+            PbkEngUtils::TIsWordSeparator aWordSeparatorFunc);
+        /**
+         * Destructor.
+		 */
+        ~CWords();
+        
+    public:  // from MDesCArray
+        TInt MdcaCount() const;
+        TPtrC16 MdcaPoint(TInt aIndex) const;
+
+    private:  // Implementation
+        CWords(PbkEngUtils::TIsWordSeparator aWordSeparatorFunc);
+        void ConstructL
+            (const TDesC& aText);
+        static TBool DefaultIsWordSeparator(TChar aChar);
+
+    private:
+		/// Own: function for detecting word separator characters
+        PbkEngUtils::TIsWordSeparator iWordSeparatorFunc;
+		/// Own: array of words
+        RArray<TPtrC> iWords;
+    };
+    
+/**
+ * Solves correct language specific engine resource filename. 
+ *
+ * @return A reference to resource file
+ */
+inline const TDesC& EngResFileName()
+    {
+    if (FeatureManager::FeatureSupported(KFeatureIdChinese))
+        {
+        return KEngChineseResFileName;
+        }
+    else if (FeatureManager::FeatureSupported(KFeatureIdJapanese))
+        {
+        return KEngJapaneseResFileName;
+        }
+    return KEngDefResFileName;
+    }
+    
+    
+}
+using namespace __RVCT_UNS_PbkEngUtils;
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+EXPORT_C void PbkEngUtils::FindAndOpenResourceFileLC
+        (RFs& aFs, 
+        const TDesC& aResFileName, 
+        const TDesC& aResFilePath, 
+        const TDesC& aResFileDrive,
+        RResourceFile& aResFile)
+    {
+    _LIT(KSeparator, "\\");
+    TFileName fileName;
+    fileName.Copy(aResFileDrive);
+    fileName.Append(aResFilePath);
+    fileName.Append(KSeparator);
+    fileName.Append(aResFileName);
+
+	BaflUtils::NearestLanguageFile(aFs, fileName);
+    aResFile.OpenL(aFs, fileName);
+    CleanupClosePushL(aResFile);
+    }
+
+EXPORT_C void PbkEngUtils::FindAndOpenDefaultResourceFileLC
+        (RFs& aFs, 
+        RResourceFile& aResFile)
+    {
+    FindAndOpenResourceFileLC(aFs, EngResFileName(), KDC_RESOURCE_FILES_DIR, 
+            KPbkRomFileDrive, aResFile);
+    aResFile.ConfirmSignatureL();
+    }
+
+EXPORT_C TInt PbkEngUtils::CopyDigitsFromEnd(
+        const TDesC& aNumText, 
+        TInt aNumberOfDigits,
+        TDes& aDigitsText)
+    {
+    aDigitsText.Zero();
+    // Scan aNumText from the end
+    TInt pos = aNumText.Length();
+
+    // Loop for number of digits to extract
+    TInt digit = 0;
+    for (; digit < aNumberOfDigits; ++digit)
+        {
+        // Scan aNumText backwars for the next number
+        while (--pos >= 0 && !TChar(aNumText[pos]).IsDigit()) { }
+        if (pos < 0)
+            break;
+        // Number found, append it to result string
+        aDigitsText.Append(aNumText[pos]);
+        }
+
+    // Reverse result string to correct order
+    TInt end = aDigitsText.Length();
+    for (pos = 0; pos < --end ; ++pos)
+        {
+        const TText tmp = aDigitsText[pos];
+        aDigitsText[pos] = aDigitsText[end];
+        aDigitsText[end] = tmp;
+        }
+
+    // Return number of digits extracted
+    return digit;
+    }
+
+EXPORT_C TBool PbkEngUtils::ContainSameDigits
+        (const TDesC& aNumText1, 
+        const TDesC& aNumText2, 
+        TInt aNumberOfDigits/*=0*/)
+    {
+    TInt pos1 = aNumText1.Length();
+    TInt pos2 = aNumText2.Length();
+    FOREVER
+        {
+        // Scan for the next digit in both strings
+        while (--pos1 >= 0 && !TChar(aNumText1[pos1]).IsDigit()) { }
+        while (--pos2 >= 0 && !TChar(aNumText2[pos2]).IsDigit()) { }
+
+        if (pos1 < 0 && pos2 < 0)
+            {
+            // Run to the end of both strings
+            break;
+            }
+
+        if ((pos1 < 0 && pos2 >= 0) || (pos1 >= 0 && pos2 < 0))
+            {
+            // Run out of the other string while the other still
+            // contains digits to compare
+            return EFalse;
+            }
+
+        if (pos1 >= 0 && pos2 >= 0 && aNumText1[pos1] != aNumText2[pos2])
+            {
+            // Different digits found
+            return EFalse;
+            }
+
+        if (--aNumberOfDigits == 0)
+            {
+            // All requested digits compared ok
+            break;
+            }
+        }
+
+    // Didn't find nonmatching digits
+    return ETrue;
+    }
+
+EXPORT_C TInt PbkEngUtils::AppendAndReplaceChars
+        (TDes& aDest, const TDesC& aSrc, 
+        const TDesC& aCharsToReplace, const TDesC& aReplaceChars)
+    {
+    // Check that aDest has enough capacity
+    __ASSERT_DEBUG((aDest.MaxLength()-aDest.Length()) >= aSrc.Length(),
+        Panic(EPanicPreCond_CopyAndReplaceChars));
+    // Check that a replacament is provided for all characters
+    __ASSERT_DEBUG(aCharsToReplace.Length() == aReplaceChars.Length(),
+        Panic(EPanicPreCond_CopyAndReplaceChars));
+
+    TInt count, i;
+    const TInt sourceLenght = aSrc.Length();
+    for (count=0, i=0; i < sourceLenght; ++i)
+        {
+        TText ch = aSrc[i];
+        const TInt replacePos = aCharsToReplace.Locate(aSrc[i]);
+        if (replacePos != KErrNotFound)
+            {
+            ++count;
+            ch = aReplaceChars[replacePos];
+            }
+        aDest.Append(ch);
+        }
+
+    return count;
+    }
+
+EXPORT_C TInt PbkEngUtils::CountSpaces(const TDesC& aText)
+    {
+    TInt result = 0;
+    const TInt length = aText.Length();
+    for (TInt i=0; i<length; ++i)
+        {
+        if (TChar(aText[i]).IsSpace())
+            {
+            ++result;
+            }
+        }
+    return result;
+    }
+
+EXPORT_C void PbkEngUtils::ReplaceNonGraphicCharacters
+        (TDes& aText, TText aChar)
+    {
+    const TInt len = aText.Length();
+    for (TInt i=0; i < len; ++i)
+        {
+        if (!TChar(aText[i]).IsGraph() &&
+            !ZWSCharacter( aText[i] ) )
+            {
+            // replace non-graphic character with aChar
+            aText[i] = aChar;
+            }
+        }
+    }
+
+EXPORT_C void PbkEngUtils::AppendGraphicCharacters
+        (TDes& aDest, const TDesC& aSrc, TText aChar)
+    {
+    const TInt len = aSrc.Length();
+    for (TInt i=0; i < len; ++i)
+        {
+        TText ch(aSrc[i]);
+        if (TChar(ch).IsGraph() || 
+            ZWSCharacter(ch))
+            {
+            aDest.Append(ch);
+            }
+        else
+            {
+            aDest.Append(aChar);
+            }
+        }
+    }
+
+EXPORT_C MDesCArray* PbkEngUtils::BreakInWordsLC
+        (const TDesC& aText, 
+        TIsWordSeparator aWordSeparatorFunc/*=NULL*/)
+    {
+    return CWords::NewLC(aText,aWordSeparatorFunc);
+    }
+
+EXPORT_C HBufC* PbkEngUtils::AllocL(HBufC* aBuffer, TInt aMaxLength)
+    {
+    if (aBuffer)
+        {
+        TPtr bufPtr(aBuffer->Des());
+        if (bufPtr.MaxLength() < aMaxLength)
+            {
+            aBuffer = aBuffer->ReAllocL(aMaxLength);
+            }
+        }
+    else
+        {
+        aBuffer = HBufC::NewL(aMaxLength);
+        }
+    return aBuffer;
+    }
+
+EXPORT_C HBufC* PbkEngUtils::CopyL
+        (HBufC* aBuffer, const TDesC& aText, TInt aMinBufLength/*=0*/)
+    {
+    aBuffer = AllocL(aBuffer,Max(aText.Length(),aMinBufLength));
+    *aBuffer = aText;
+    return aBuffer;
+    }
+
+EXPORT_C TInt PbkEngUtils::TrimAllLength(const TDesC& aText)
+    {
+    const TInt textLength=aText.Length();
+    TInt result=0;
+    TBool uncommittedSpace=EFalse;
+    for (TInt i=0; i < textLength; ++i)
+        {
+        if (TChar(aText[i]).IsSpace())
+            {
+            if (result > 0)
+                {
+                // Not a leading space, set uncommitted space flag
+                uncommittedSpace = ETrue;
+                }
+            }
+        else
+            {
+            if (uncommittedSpace)
+                {
+                // Add previously encountered space(s)
+                ++result;
+                uncommittedSpace = EFalse;
+                }
+            // Add the character
+            ++result;
+            }
+        }
+
+    __ASSERT_DEBUG(result <= aText.Length(), 
+        Panic(EPanicPostCond_TrimAllLength));
+    return result;
+    }
+
+EXPORT_C TInt PbkEngUtils::TrimAllAppend(const TDesC& aText, TDes& aDest)
+    {
+#ifdef _DEBUG
+    const TInt oldDestLength = aDest.Length();
+    __ASSERT_DEBUG(aDest.MaxLength()-oldDestLength >= TrimAllLength(aText), 
+        Panic(EPanicPreCond_TrimAllAppend));
+#endif
+
+    const TInt textLength=aText.Length();
+    TInt result=0;
+    TBool uncommittedSpace=EFalse;
+    for (TInt i=0; i < textLength; ++i)
+        {
+        const TChar ch(aText[i]);
+        if (ch.IsSpace() &&
+            !ZWSCharacter( ch ) )
+            {
+            if (result > 0)
+                {
+                // Not a leading space, set uncommitted space flag
+                uncommittedSpace = ETrue;
+                }
+            }
+        else
+            {
+            if (uncommittedSpace)
+                {
+                // Add previously encountered space(s)
+                ++result;
+                aDest.Append(' ');
+                uncommittedSpace = EFalse;
+                }
+            // Add the character
+            ++result;
+            aDest.Append(ch);
+            }
+        }
+
+    __ASSERT_DEBUG(aDest.Length()-oldDestLength == TrimAllLength(aText), 
+        Panic(EPanicPostCond_TrimAllAppend));
+    return result;
+    }
+
+EXPORT_C TInt PbkEngUtils::TrimRightLength(const TDesC& aText)
+    {
+    const TInt textLength=aText.Length();
+    TInt result=0;
+    TBool uncommittedSpace=EFalse;
+    TBool leadingSpace=ETrue;
+    for (TInt i=0; i < textLength; ++i)
+        {
+        if (TChar(aText[i]).IsSpace() &&
+            !ZWSCharacter( aText[i] ) )
+            {
+            if (leadingSpace)
+                {
+                // Add all leading spaces
+                ++result;
+                }
+            else
+                {
+                // Not a leading space, set uncommitted space flag
+                uncommittedSpace = ETrue;
+                }
+            }
+        else
+            {
+            // First non-space character found, adjust leading space flag
+            leadingSpace = EFalse;
+            if (uncommittedSpace)
+                {
+                // Add previously encountered space(s)
+                ++result;
+                uncommittedSpace = EFalse;
+                }
+            // Add the character
+            ++result;
+            }
+        }
+
+    __ASSERT_DEBUG(result <= aText.Length(), 
+        Panic(EPanicPostCond_TrimRightLength));
+    return result;
+    }
+
+EXPORT_C TInt PbkEngUtils::TrimRightAppend(const TDesC& aText, TDes& aDest)
+    {
+#ifdef _DEBUG
+    const TInt oldDestLength = aDest.Length();
+    __ASSERT_DEBUG(aDest.MaxLength()-oldDestLength >= TrimRightLength(aText), 
+        Panic(EPanicPreCond_TrimRightAppend));
+#endif
+
+    const TInt textLength=aText.Length();
+    TInt result=0;
+    TBool uncommittedSpace=EFalse;
+    TBool leadingSpace=ETrue;
+    for (TInt i=0; i < textLength; ++i)
+        {
+        const TChar ch(aText[i]);
+        if (ch.IsSpace() &&
+            !ZWSCharacter( ch ) )
+            {
+            if (leadingSpace)
+                {
+                // Add all leading spaces
+                ++result;
+                aDest.Append(' ');
+                }
+            else
+                {
+                // Not a leading space, set uncommitted space flag
+                uncommittedSpace = ETrue;
+                }
+            }
+        else
+            {
+            // First non-space character found, adjust leading space flag
+            leadingSpace = EFalse;
+            if (uncommittedSpace)
+                {
+                // Add previously encountered space(s)
+                ++result;
+                aDest.Append(' ');
+                uncommittedSpace = EFalse;
+                }
+            // Add the character
+            ++result;
+            aDest.Append(ch);
+            }
+        }
+
+    __ASSERT_DEBUG(aDest.Length()-oldDestLength == TrimRightLength(aText), 
+        Panic(EPanicPostCond_TrimRightAppend));
+    return result;
+    }
+
+
+
+// CWords
+inline CWords::CWords(PbkEngUtils::TIsWordSeparator aWordSeparatorFunc)
+    : iWordSeparatorFunc
+        (aWordSeparatorFunc ? 
+        aWordSeparatorFunc : CWords::DefaultIsWordSeparator)
+    {
+    }
+
+CWords* CWords::NewLC
+        (const TDesC& aText, 
+        PbkEngUtils::TIsWordSeparator aWordSeparatorFunc)
+    {
+    CWords* self = new(ELeave) CWords(aWordSeparatorFunc);
+    CleanupStack::PushL(self);
+    self->ConstructL(aText);
+    return self;
+    }
+
+CWords::~CWords()
+    {
+    iWords.Close();
+    }
+
+TInt CWords::MdcaCount() const
+    {
+    return iWords.Count();
+    }
+
+TPtrC16 CWords::MdcaPoint(TInt aIndex) const
+    {
+    return iWords[aIndex];
+    }
+
+void CWords::ConstructL(const TDesC& aText)
+    {
+    const TInt textLength = aText.Length();
+    for (TInt beg=0; beg < textLength; ++beg)
+        {
+        // Skip separators before next word
+        if (!iWordSeparatorFunc(aText[beg]))
+            {
+            // Scan the end of the word
+            TInt end = beg;
+            for (; end < textLength && !iWordSeparatorFunc(aText[end]); ++end)
+                {
+                }
+            const TInt len = end-beg;
+            // Append found word to the array
+            User::LeaveIfError(iWords.Append(aText.Mid(beg,len)));
+            // Scan for next word
+            beg = end;
+            }
+        }
+
+    if (iWords.Count()==0 && textLength > 0)
+        {
+        // aText is all word separator characters -> make a "word" out of those
+        User::LeaveIfError(iWords.Append(aText));
+        }
+    }
+
+TBool CWords::DefaultIsWordSeparator(TChar aChar)
+    {
+    return (aChar.IsSpace());
+    }
+
+
+// End of File