diff -r c55016431358 -r 0a7b44b10206 symport/e32test/buffer/t_match.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symport/e32test/buffer/t_match.cpp Thu Jun 25 15:59:54 2009 +0100 @@ -0,0 +1,2274 @@ +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\buffer\t_match.cpp +// Overview: +// Test the match methods of TPtrC8 and TPtrC16 objects and the +// TCharIterator TCombiningCharIterator, TCollationValueIterator +// and TCollationRawValueIterator classes. +// API Information: +// TPtrC8, TPtrC16, TCharIterator, TCombiningCharIterator, +// TCollationValueIterator, TCollationRawValueIterator +// Details: +// - Test and verify the results of TPtrC8 Match and MatchF methods +// on a variety of constant strings. Verify both match and mismatch +// conditions. +// - Test and verify the results of TPtrC16 Match and MatchF methods +// on a variety of constant strings. Verify both match and mismatch +// conditions. +// - For a TCharIterator object, test and verify: +// - basic character handling +// - ability to reset the iterator correctly +// - combining characters works as expected +// - ability to jump into the middle of combined characters +// - full-width variants are not modified +// - narrow strings work as expected +// - surrogate pairs work as expected +// - Using a TCombiningCharIterator object with a variety of character +// strings as input, verify that the output is as expected. +// - Using TCollationValueIterator and TCollationRawValueIterator objects: +// - test the raw iterator +// - test starting at different points in the iteration and verify capitals +// are ignored at level 0 +// - verify capitals are ignored at level 1 +// - verify capitals do not match at level 2 +// - check the TCollationValueIterator Restart method +// - test collation keys, when they success and when they fail halfway +// - exhaust the internal cache, verify object still works +// - test different decompositions at level 3 +// - verify results are as expected +// - Test and verify the results of the TUnicodeFold::FindWildcardMatchFolded() +// method on a variety of constant strings: find a string within another +// string, verify the offset into the candidate string if it is present, or +// KErrNotFound if it is not. +// - Test and verify the results of the TUnicodeFold::FindFolded() method on +// a variety of constant strings: compare two strings, verify return value. +// - Test and verify results of UnicodeFoldCase() on a variety of characters. +// - Test and verify results of MatchLeadingWildcards() on a variety of strings. +// - Test and verify results of MatchesHereFoldedWithPrefixTest() on a variety +// of strings. +// - Test and verify results of LocateFolded() on a variety of strings. +// - Test and verify results of FindFoldedWithWildcard() and FindMatchFolded() +// on a variety of strings. +// - Test and verify results of TDesc.CompareF() on a variety of strings. +// Platforms/Drives/Compatibility: +// All +// Assumptions/Requirement/Pre-requisites: +// Failures and causes: +// Base Port information: +// +// + +#include +#include +#include +#include "collateimp.h" +#include "compareimp.h" +#include "u32std.h" + +#ifndef __TOOLS2__ +///***************** copied from locale euser source code *********************** +static const TCollationMethod TheCollationMethod[] = + { + { + KUidBasicCollationMethod, // this is the standard unlocalised method + NULL, // null means use the standard table + NULL, // there's no override table + 0 // the flags are standard + } + }; +static const TCollationDataSet TheCollationDataSet = + { + TheCollationMethod, + 1 + }; +const LCharSet TheCharSet = + { + NULL, + &TheCollationDataSet + }; +const LCharSet* GetLocaleCharSet() + { + return &TheCharSet; + } +#endif +///******************************************************************************* + + +#ifdef __VC32__ + // Solve compilation problem caused by non-English locale + #pragma setlocale("english") +#endif + +#define ARRAY_SIZE(ar) (sizeof(ar) / (sizeof(ar[0]))) + +LOCAL_D RTest test(_L("T_MATCH")); + +#ifndef __TOOLS2__ +_LIT(KUnicodeTestDataFile, "z:\\Test\\UnicodeData.txt"); +#else +_LIT(KUnicodeTestDataFile, "UnicodeData.txt"); +#endif + +static const TUint32 TheDevanagariKey[] = + { + 0x22a010b,0x22b010b,0x285010b,0xb109,0xb209,0xb309,0xb409,0xb509, + 0x6c5e609,0x6c6e609,0x6c7e609,0x6c8e609,0x6c9e609,0x6cae609,0x6cbe609,0x6cce609, + 0x6cde609,0x6cee609,0xba40109,0xba50109,0xba60109,0xba70109,0xba80109,0xba90109, + 0xbaa0109,0xbab0109,0xbac0109,0xbad0109,0xbae0109,0xbaf0109,0xbb00109,0xbb10109, + 0xbb20109,0xbb30109,0xbb40109,0xbb50109,0xbb60109,0xbb70109,0xbb80109,0xbb90109, + 0xbb9b109,0xbba0109,0xbbab109,0xbbb0109,0xbbbb109,0xbbc0109,0xbbd0109,0xbbe0109, + 0xbbf0109,0xbc00109,0xbc0b109,0xbc10109,0xbc20109,0xbc30109,0xbc40109,0xbc50109, + 0xbc5b109,0xbc60109,0xbc6b109,0xbc70109,0xbc80109,0xbc90109,0xbca0109,0xbcb0109, + 0xbcc0109,0xbccb109,0xbcd0109,0xbce0109,0xbceb109,0xbcf0109,0xbd00109,0xbd10109, + 0xbd20109,0xbd2b109,0xbd30109,0xbd3b109,0xbd40109,0xbd50109,0xbd5b109,0xbd60109, + 0xbd70109,0xbd80109,0xbd90109,0xbda0109,0xbdb0109,0xbdc0109,0xbdd0109,0xbde0109, + 0xbdf0109,0xbe00109,0xbe10109,0xbe20109,0xbe30109,0xbe40109,0xbe50109,0xbe60109, + 0xbe70109,0xbe80109,0xbe90109,0xbea0109,0xbeb0109,0xbec0109,0xbed0109, + }; + +static const TUint32 TheDevanagariIndex[] = + { + 0x9010012,0x9020013,0x9030014,0x9050015,0x9060016,0x9070017,0x9080018,0x9090019, + 0x90a001a,0x90b001b,0x90c001d,0x90d001f,0x90e0020,0x90f0021,0x9100022,0x9110023, + 0x9120024,0x9130025,0x9140026,0x9150027,0x9160029,0x917002b,0x918002d,0x919002e, + 0x91a002f,0x91b0030,0x91c0031,0x91d0033,0x91e0034,0x91f0035,0x9200036,0x9210037, + 0x9220039,0x923003b,0x924003c,0x925003d,0x926003e,0x927003f,0x9280040,0x9290041, + 0x92a0042,0x92b0043,0x92c0045,0x92d0046,0x92e0047,0x92f0048,0x930004a,0x931004b, + 0x932004c,0x933004d,0x934004e,0x935004f,0x9360050,0x9370051,0x9380052,0x9390053, + 0x93c0003,0x93d0054,0x93e0055,0x93f0056,0x9400057,0x9410058,0x9420059,0x943005a, + 0x944005b,0x945005e,0x946005f,0x9470060,0x9480061,0x9490062,0x94a0063,0x94b0064, + 0x94c0065,0x94d0066,0x9510004,0x9520005,0x9530006,0x9540007,0x9580028,0x959002a, + 0x95a002c,0x95b0032,0x95c0038,0x95d003a,0x95e0044,0x95f0049,0x960001c,0x961001e, + 0x962005c,0x963005d,0x9640000,0x9650001,0x9660008,0x9670009,0x968000a,0x969000b, + 0x96a000c,0x96b000d,0x96c000e,0x96d000f,0x96e0010,0x96f0011,0x9700002, + }; + +static const TCollationKeyTable TheDevanagariTable = + { TheDevanagariKey, TheDevanagariIndex, 103, 0, 0, 0 }; + +static const TCollationMethod TheDevanagariMethod = + { 0, 0, &TheDevanagariTable, 0 }; + +static const TCollationMethod TheDevanagariIgnoreCombiningMethod = + { 0, 0, &TheDevanagariTable, TCollationMethod::EIgnoreCombining }; + +static const TUint32 TheSwedishKey[] = + { + 0x8f60109,0x8f70109,0x8f80109,0x8f60121,0x8f70121,0x8f80121,0x8dd0109,0x8dd0121, + 0x8c50121,0x8c50109, + }; + +static const TUint32 TheSwedishIndex[] = + { + 0x570008,0x770009, + }; + +static const TUint16 TheSwedishStringElement[] = + { + 0x2,0x61,0x30a,0x2,0x61,0x308,0x2,0x6f, + 0x308,0x2,0x41,0x30a,0x2,0x41,0x308,0x2, + 0x4f,0x308,0x2,0x75,0x308,0x2,0x55,0x308, + }; + +static const TUint32 TheSwedishStringIndex[] = + { + 0xc0004,0x90003,0xf0005,0x150007,0x30001,0x0,0x60002,0x120006, + }; + +static const TCollationKeyTable TheSwedishTable = + { TheSwedishKey, TheSwedishIndex, 2, TheSwedishStringElement, TheSwedishStringIndex, 8 }; + +static const TCollationMethod TheSwedishMethod = + { 0, 0, &TheSwedishTable, TCollationMethod::EIgnoreNone }; + +static const TCollationMethod TheIgnoreNoneMethod = + { 0, 0, 0, TCollationMethod::EIgnoreNone }; + +void TestPrintCaption(const TDesC& aTestName, const TText16 aStr[], TInt aLen) + { + test.Next(aTestName); + RDebug::Print(_L("Char seq: ")); + for(TInt i=0;i search, target; + //All Devanagari dependant vowels are in the following range + for(TInt dependantVowel=0x93e; dependantVowel<=0x94c; dependantVowel++) + { + //Most of the Devanagari consonants are in the following range + for(TInt consonant=0x915; consonant<=0x939; consonant++) + { + target.Format(_L("%c%c"),consonant,dependantVowel); + search.Format(_L("%c*"),consonant); + TestDisableCombiningCharacterCheckFlag(target, search); + } + } + //Test same situation but where consonants decompose to consonant + dependant vowel + TestDisableCombiningCharacterCheckFlag(_L("\x929"), _L("\x928*")); + TestDisableCombiningCharacterCheckFlag(_L("\x931"), _L("\x930*")); + TestDisableCombiningCharacterCheckFlag(_L("\x934"), _L("\x933*")); + TestDisableCombiningCharacterCheckFlag(_L("\x958"), _L("\x915*")); + TestDisableCombiningCharacterCheckFlag(_L("\x959"), _L("\x916*")); + TestDisableCombiningCharacterCheckFlag(_L("\x95a"), _L("\x917*")); + TestDisableCombiningCharacterCheckFlag(_L("\x95b"), _L("\x91c*")); + TestDisableCombiningCharacterCheckFlag(_L("\x95c"), _L("\x921*")); + TestDisableCombiningCharacterCheckFlag(_L("\x95d"), _L("\x922*")); + TestDisableCombiningCharacterCheckFlag(_L("\x95e"), _L("\x92b*")); + TestDisableCombiningCharacterCheckFlag(_L("\x95f"), _L("\x92f*")); + } + +_LIT(KHelloT, "Hello"); +_LIT(KLatin1AccentsC, "\xE0\xD2p\xE2\xEB\xED\xF1\xC7"); +_LIT(KLatin1AccentsD, "a\x300O\x300pa\x302\x65\x308i\x301n\x303\x43\x327"); +// four alpha + psili + varia + ypogegrameni +_LIT(KGreekAccentsC, "\x1f82\x1f82\x1f82\x1f82"); +// decomposed in four different ways +_LIT(KGreekAccentsS, "\x1f82\x1f02\x345\x1f00\x300\x345\x3b1\x313\x300\x345"); +// completely decomposed +_LIT(KGreekAccentsD, "\x3b1\x313\x300\x345\x3b1\x313\x300\x345\x3b1\x313\x300\x345\x3b1\x313\x300\x345"); +// full-width variants +_LIT(KFullWidth, "\xFF21\xFF42\xFF43"); +// surrogate pair, unpaired low surrogate, unpaired high surrogate, unpaired +// high surrogate at end of string +_LIT(KSurrogates, "\xD965\xDEF0\xDF12\xDB10\xDA4E"); +_LIT(KSurrogatesTest, "\xD965\xDEF0"); + +void TestIteratorOutput(TDecompositionIterator& aIt, const TDesC& aCheck) + { + TBool unpairedHighSurrogate = EFalse; + for(TInt i = 0; i != aCheck.Length(); aIt.Next()) + { + if (aIt.AtEnd()) + { + test(0); + return; + } + TInt c = aIt.Current(); + // test that we are not looking at an unpaired low surrogate that + // follows an unpaired high surrogate: this is not possible. + test((c & 0xFC00) != 0xDC00 || !unpairedHighSurrogate); + unpairedHighSurrogate = (c & 0xFC00) == 0xD800? (TBool)ETrue : (TBool)EFalse; + if (c < 0x10000) + { + test(c == aCheck[i]); + ++i; + } + else + { + TInt sp = ((aCheck[i] - 0xD7F7) << 10) + aCheck[i + 1]; + test(c == sp); + i += 2; + } + } + test(aIt.AtEnd()); + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0097 +@SYMTestCaseDesc TUTF32Iterator functionality tested on 2 character sequences: + (1) single character + (2) surrogate pair +@SYMTestPriority High +@SYMTestActions TUTF32Iterator test. +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void TestUTF32Iterator() + { + //Single character + const TText16 KStr[] = {0x01D5}; + ::TestPrintCaption(_L("TUTF32Iterator"), KStr, ARRAY_SIZE(KStr)); + TUTF32Iterator it(KStr, KStr + ARRAY_SIZE(KStr)); + TInt itCount = 0; + for(;!it.AtEnd();++itCount, it.Next()) + { + TChar ch = it.Current(); + test(ch == static_cast (KStr[0])); + RDebug::Print(_L("%04X "), (TUint)ch); + } + test(itCount == 1); + RDebug::Print(_L("\n")); + //Surrogate pair + ::TestPrintCaption(_L("TUTF32Iterator-surrogates"), KSurrogatesTest().Ptr(), KSurrogatesTest().Length()); + it = TUTF32Iterator(KSurrogatesTest().Ptr(), KSurrogatesTest().Ptr() + KSurrogatesTest().Length()); + for(itCount=0;!it.AtEnd();++itCount, it.Next()) + { + TChar ch = it.Current(); + test(ch == 0x696F0); + RDebug::Print(_L("%06X "), (TUint)ch); + } + test(itCount == 1); + RDebug::Print(_L("\n")); + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0098 +@SYMTestCaseDesc TFoldedDecompIterator functionality tested on 2 character sequences. +@SYMTestPriority High +@SYMTestActions TFoldedDecompIterator test. +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void TestFoldedDecompIterator() + { + //Character sequence 1: + //(1) DEVANAGARI LETTER FA - 0x095E, (2) LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON - 0x01D5 + //Decompositions: + //(1) 0x095E decomposed to: 0x092B 0x093C + //(2) 0x01D5 decomposed to: 0x00DC 0x0304 + // 0x00DC decomposed to: 0x0055 0x0308 + // 0x0055 decomposed to: 0x0075 + const TText16 KStr[] = {0x095E, 0x01D5}; + const TText16 KStrOut[] = {0x092B, 0x093C, 0x0075, 0x0308, 0x0304}; + ::TestPrintCaption(_L("TFoldedDecompIterator-1"), KStr, ARRAY_SIZE(KStr)); + TUTF32Iterator itSrc(KStr, KStr + ARRAY_SIZE(KStr)); + TFoldedDecompIterator it(itSrc); + TInt itCount = 0; + for(;!it.AtEnd();++itCount, it.Next()) + { + if(!it.IsInFoldedSequence()) + { + it.EnterFoldedSequence(); + } + TChar ch = it.Current(); + test(ch == static_cast (KStrOut[itCount])); + RDebug::Print(_L("%04X "), (TUint)ch); + } + test(itCount == ARRAY_SIZE(KStrOut)); + RDebug::Print(_L("\n")); + //Character sequence 2: + //(1) GREEK CAPITAL LETTER BETA - 0x0392 + //(2) COMBINING GRAVE ACCENT - 0x0300 + //(3) COMBINING GRAVE ACCENT BELOW - 0x0316 + //(4) GREEK CAPITAL LETTER GAMMA - 0x0393 + //(5) HEBREW POINT TSERE - 0x05B5 + //(6) TIBETAN MARK HALANTA - 0x0F84 + //Decompositions: + //(1) 0x0392 decomposed to: 0x03B2 + //(2) 0x0300 decomposed to: 0x0300 + //(3) 0x0316 decomposed to: 0x0316 + //(4) 0x0393 decomposed to: 0x03B3 + //(5) 0x05B5 decomposed to: 0x05B5 + //(6) 0x0F84 decomposed to: 0x0F84 + const TText16 KStr2[] = {0x0392, 0x0300, 0x0316, 0x0393, 0x05B5, 0x0F84}; + const TText16 KStrOut2[] = {0x03B2, 0x0300, 0x0316, 0x03B3, 0x05B5, 0x0F84}; + ::TestPrintCaption(_L("TFoldedDecompIterator-2"), KStr2, ARRAY_SIZE(KStr2)); + itSrc = TUTF32Iterator(KStr2, KStr2 + ARRAY_SIZE(KStr2)); + it = TFoldedDecompIterator(itSrc); + for(itCount=0;!it.AtEnd();++itCount, it.Next()) + { + if(!it.IsInFoldedSequence()) + { + it.EnterFoldedSequence(); + } + TChar ch = it.Current(); + test(ch == static_cast (KStrOut2[itCount])); + RDebug::Print(_L("%04X "), (TUint)ch); + } + test(itCount == ARRAY_SIZE(KStrOut2)); + RDebug::Print(_L("\n")); + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0099 +@SYMTestCaseDesc TFoldedSortedDecompIterator functionality tested on 1 character sequence. +@SYMTestPriority High +@SYMTestActions TFoldedSortedDecompIterator test. +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void TestFoldedSortedDecompIterator() + { + //Character sequence 1: + //(1) GREEK CAPITAL LETTER BETA - 0x0392 + //(2) COMBINING GRAVE ACCENT - 0x0300 + //(3) COMBINING GRAVE ACCENT BELOW - 0x0316 + //(4) GREEK CAPITAL LETTER GAMMA - 0x0393 + //(5) HEBREW POINT TSERE - 0x05B5 + //(6) TIBETAN MARK HALANTA - 0x0F84 + //Decompositions: + //0x03B2 Class 0 + //0x0316 Class 220 + //0x0300 Class 230 + //0x03B3 Class 0 + //0x0F84 Class 9 + //0x05B5 Class 15 + const TText16 KStr[] = {0x0392, 0x0300, 0x0316, 0x0393, 0x05B5, 0x0F84}; + const TText16 KStrOut[] = {0x03B2, 0x0316, 0x0300, 0x03B3, 0x0F84, 0x05B5}; + const TInt KClass[] = {0, 220, 230, 0, 9, 15}; + ::TestPrintCaption(_L("TFoldedSortedDecompIterator"), KStr, ARRAY_SIZE(KStr)); + RDebug::Print(_L("\n")); + TUTF32Iterator itSrc(KStr, KStr + ARRAY_SIZE(KStr)); + TFoldedDecompIterator itDecomp(itSrc); + TInt itCount = 0; + while(!itDecomp.AtEnd()) + { + if(!itDecomp.IsInFoldedSequence()) + { + itDecomp.EnterFoldedSequence(); + } + if(itDecomp.Current().GetCombiningClass() == 0) + { + TChar ch = itDecomp.Current(); + TInt clss = itDecomp.Current().GetCombiningClass(); + test(ch == static_cast (KStrOut[itCount])); + test(clss == KClass[itCount]); + RDebug::Print(_L("BaseCh %04X Class %d\n"), (TUint)ch, clss); + itDecomp.Next(); + ++itCount; + } + else + { + TFoldedSortedDecompIterator it; + it.Set(itDecomp); + while(!it.AtEnd()) + { + TChar ch = it.Current(); + TInt clss = it.Current().GetCombiningClass(); + test(ch == static_cast (KStrOut[itCount])); + test(clss == KClass[itCount]); + RDebug::Print(_L("CombCh %04X Class %d\n"), (TUint)ch, clss); + it.Next(); + ++itCount; + } + } + } + test(itCount == ARRAY_SIZE(KStrOut)); + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0100 +@SYMTestCaseDesc TFoldedCanonicalIterator functionality tested on 1 character sequence. +@SYMTestPriority High +@SYMTestActions TFoldedCanonicalIterator test. +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void TestFoldedCanonicalIterator() + { + //Character sequence 1: + //(1) GREEK CAPITAL LETTER BETA - 0x0392 + //(2) COMBINING GRAVE ACCENT - 0x0300 + //(3) COMBINING GRAVE ACCENT BELOW - 0x0316 + //(4) GREEK CAPITAL LETTER GAMMA - 0x0393 + //(5) HEBREW POINT TSERE - 0x05B5 + //(6) TIBETAN MARK HALANTA - 0x0F84 + //(7) LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON - 0x01D5 + //Decompositions: + //0x0392 to 0x03B2 + //0x0316 to 0x0316 + //0x0300 to 0x0300 + //0x0393 to 0x03B3 + //0x0F84 to 0x0F84 + //0x05B5 to 0x05B5 + //0x01D5 to 0x0075 0x0308 0x0304 + const TText16 KStr[] = {0x0392, 0x0300, 0x0316, 0x0393, 0x05B5, 0x0F84, 0x01D5}; + const TText16 KStrOut[] = {0x03B2, 0x0316, 0x0300, 0x03B3, 0x0F84, 0x05B5, 0x0075, 0x0308, 0x0304}; + TestPrintCaption(_L("TFoldedCanonicalIterator"), KStr, ARRAY_SIZE(KStr)); + TUTF32Iterator itSrc(KStr, KStr + ARRAY_SIZE(KStr)); + TFoldedCanonicalIterator it(itSrc); + TInt itCount = 0; + + const TUnicodeDataSet* charDataSet = GetLocaleCharSet()->iCharDataSet; + + for(;!it.AtEnd();++itCount, it.Next(charDataSet)) + { + TChar ch = it.Current(); + test(ch == static_cast (KStrOut[itCount])); + RDebug::Print(_L("%04X "), (TUint)ch); + } + test(itCount == ARRAY_SIZE(KStrOut)); + RDebug::Print(_L("\n")); + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0101 +@SYMTestCaseDesc TDecompositionIterator functionality tested on 1 character sequence +@SYMTestPriority High +@SYMTestActions TDecompositionIterator test. +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void TestDecompositionIterator2() + { + //Character sequence 1 + //LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON - 0x01D5 + //Decomposition: + //0x01D5 to: 0x0055 0x0308 0x0304 + const TText16 KStr[] = {0x01D5}; + const TText16 KStrOut[] = {0x0055, 0x0308, 0x0304}; + TestPrintCaption(_L("TDecompositionIterator"), KStr, ARRAY_SIZE(KStr)); + TUTF32Iterator itSrc(KStr, KStr + ARRAY_SIZE(KStr)); + TDecompositionIterator it; + it.Set(itSrc); + TInt itCount = 0; + for(;!it.AtEnd(); ++itCount, it.Next()) + { + TChar ch = it.Current(); + test(ch == static_cast (KStrOut[itCount])); + RDebug::Print(_L("%04X "), (TUint)ch); + } + test(itCount == ARRAY_SIZE(KStrOut)); + RDebug::Print(_L("\n")); + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0102 +@SYMTestCaseDesc TCanonicalDecompositionIterator functionality tested on 1 character sequence +@SYMTestPriority High +@SYMTestActions TCanonicalDecompositionIterator test. +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void TestCanonicalDecompositionIterator2() + { + //Character sequence 1 + //LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON - 0x01D5 + //Decomposition: + //0x01D5 to: 0x0055 0x0308 0x0304 + const TText16 KStr[] = {0x01D5}; + const TText16 KStrOut[] = {0x0055, 0x0308, 0x0304}; + TestPrintCaption(_L("TCanonicalDecompositionIterator"), KStr, ARRAY_SIZE(KStr)); + TUTF32Iterator itSrc(KStr, KStr + ARRAY_SIZE(KStr)); + TCanonicalDecompositionIterator it; + it.Set(itSrc); + TInt itCount = 0; + for(;!it.AtEnd();++itCount, it.Next()) + { + TChar ch = it.Current(); + test(ch == static_cast (KStrOut[itCount])); + RDebug::Print(_L("%04X "), (TUint)ch); + } + test(itCount == ARRAY_SIZE(KStrOut)); + RDebug::Print(_L("\n")); + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0103 +@SYMTestCaseDesc TCanonicalDecompositionIteratorCached functionality tested on 1 character sequence +@SYMTestPriority High +@SYMTestActions TCanonicalDecompositionIteratorCached test. +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void TestCanonicalDecompositionIteratorCached() + { + //Character sequence 1 + //LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON - 0x01D5 + //Decomposition: + //0x01D5 to: 0x0055 0x0308 0x0304 + const TText16 KStr[] = {0x01D5}; + const TText16 KStrOut[] = {0x0055, 0x0308, 0x0304}; + TestPrintCaption(_L("TCanonicalDecompositionIteratorCached"), KStr, ARRAY_SIZE(KStr)); + TUTF32Iterator itSrc(KStr, KStr + ARRAY_SIZE(KStr)); + TCanonicalDecompositionIteratorCached it; + it.Set(itSrc); + TInt itCount = 0; + for(;!it.AtEnd();++itCount, it.Next(1)) + { + TChar ch = it.Get(0); + test(ch == static_cast (KStrOut[itCount])); + RDebug::Print(_L("%04X "), (TUint)ch); + } + test(itCount == ARRAY_SIZE(KStrOut)); + RDebug::Print(_L("\n")); + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0104 +@SYMTestCaseDesc TDecompositionIterator test +@SYMTestPriority High +@SYMTestActions TDecompositionIterator test. +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void TestDecompositionIterator() + { + TDecompositionIterator i; + + // test basic character handling + TUTF32Iterator i1(KHelloT().Ptr(), KHelloT().Ptr() + KHelloT().Length()); + i.Set(i1); + TestIteratorOutput(i, KHelloT); + + TUTF32Iterator i2(KHelloT().Ptr() + 3, KHelloT().Ptr() + KHelloT().Length()); + i.Set(i2); + TestIteratorOutput(i, KHelloT().Mid(3)); + + // test combining characters + TUTF32Iterator i3(KLatin1AccentsC().Ptr(), KLatin1AccentsC().Ptr() + KLatin1AccentsC().Length()); + i.Set(i3); + TestIteratorOutput(i, KLatin1AccentsD); + + TUTF32Iterator i4(KGreekAccentsC().Ptr(), KGreekAccentsC().Ptr() + KGreekAccentsC().Length()); + i.Set(i4); + TestIteratorOutput(i, KGreekAccentsD); + + TUTF32Iterator i5(KGreekAccentsS().Ptr(), KGreekAccentsS().Ptr() + KGreekAccentsS().Length()); + i.Set(i5); + TestIteratorOutput(i, KGreekAccentsD); + + // test that full-width variants are not fiddled with + TUTF32Iterator i6(KFullWidth().Ptr(), KFullWidth().Ptr() + KFullWidth().Length()); + i.Set(i6); + TestIteratorOutput(i, KFullWidth); + + TUTF32Iterator i7(KSurrogates().Ptr(), KSurrogates().Ptr() + KSurrogates().Length()); + i.Set(i7); + TestIteratorOutput(i, KSurrogatesTest); + } + +//The function collects collation keys at the specified level aLevel from aIt iterator +//and stores them in aBuf output parameter. +//aExpectedNumKeys value specifies the count of expected collation keys. +void GetKeys(TCollationValueIterator& aIt, TUint32* aBuf, TInt aLevel, TInt aExpectedNumKeys) + { + //Zero the output parameter + Mem::FillZ(aBuf, sizeof(TUint32) * aExpectedNumKeys); + //Get the keys + TInt i = 0; + for(;i!=aExpectedNumKeys;++i) + { + for (;;) + { + (void)aIt.GetCurrentKey(aLevel, aBuf[i]); + test(aIt.Increment()); + if(aBuf[i] != 0) + { + break; + } + } + } + //The rest of the keys at that level should have 0 value. + for(;aIt.Increment();) + { + TUint32 key = 0; + (void)aIt.GetCurrentKey(aLevel, key); + test(key == 0); + } + } + +//The function collects the raw keys from aIt iterator and stores them in aBuf output parameter. +//aExpectedNumKeys value specifies the count of expected raw collation keys. +void GetRawKeys(TCollationValueIterator& aIt, TCollationKey* aBuf, TInt aExpectedNumKeys) + { + //Zero the output parameter + Mem::FillZ(aBuf, sizeof(TCollationKey) * aExpectedNumKeys); + //Get the keys + for(TInt i=0;i!=aExpectedNumKeys;++i) + { + test(aIt.GetCurrentKey(aBuf[i])); + aIt.Increment(); + } + //One additional GetCurrentKey() call. Because there shouldn't be more raw keys than + //aExpectedNumKeys, the call should fail returning EFalse. + TCollationKey dummy; + test(!aIt.GetCurrentKey(dummy)); + } + +//The function gets a sequence of raw collation keys in aBuf parameter and a character number +//aCharNo in the original string. +//It returns the position in aBuf where raw collation key sequence for aCharNo starts. +TInt CharNo2CollKeyPos(const TCollationKey* aBuf, TInt aBufLen, TInt aCharNo) + { + TInt starterCnt = 0; + TInt pos = 0; + do + { + if(aBuf[pos].IsStarter()) + { + ++starterCnt; + } + } while(starterCnt!=(aCharNo+1) && ++pos!=aBufLen); + test(pos != aBufLen); + return pos; + } + +//The function compares aBuf1 and aBuf2 and returns how many elements in aBuf1 differ +//from the elements in aBuf2 at the same position. +TInt CountDiscrepancies(TUint32* aBuf1, TUint32* aBuf2, TInt aCount) + { + TInt discrepancies = 0; + for (; aCount; --aCount) + { + if (*aBuf1++ != *aBuf2++) + ++discrepancies; + } + return discrepancies; + } + +TInt CountDiscrepancies(TCollationKey* aBuf1, TCollationKey* aBuf2, TInt aCount) + { + TInt discrepancies = 0; + for (; aCount; --aCount) + { + if (aBuf1->iHigh != aBuf2->iHigh || aBuf1->iLow != aBuf2->iLow) + ++discrepancies; + ++aBuf1; + ++aBuf2; + } + return discrepancies; + } + +_LIT(KAYZAccentsAbove, "\xE0\x301y\x302z\x303\x304"); +_LIT(KCapitalAYZAccentsAbove, "A\x300\x301Y\x302Z\x303\x304"); +_LIT(KCapitalYAYZAccentsAbove, "a\x300\x301Y\x302z\x303\x304"); +_LIT(KABCRuleTest, "abcwabkakb"); +_LIT(KABCRuleExpected, "eeabkakb"); +//_LIT(KExhaustCaches, "0123456789ABCDEFexhausted"); +_LIT(KGreekOPVY1, "\x1f82"); +_LIT(KGreekOPVY2, "\x1f02\x345"); +_LIT(KGreekOPVY3, "\x1f00\x300\x345"); +_LIT(KGreekOPVY4, "\x3b1\x313\x300\x345"); +_LIT(KGreekOPVY5, "\x3b1\x313\x345\x300"); +_LIT(KGreekOPVY6, "\x3b1\x345\x313\x300"); + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0105 +@SYMTestCaseDesc TCollationValueIterator test +@SYMTestPriority High +@SYMTestActions TCollationValueIterator tests +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void TestCollationValueIterator() + { + // a funny pair of extra collation rules: w and abc both collate as e. + TUint32 abcWTLKey[] = {0/* key for 'e' will go here */, + 0x8ff00101, 0x8ff10101, 0x8ff20101, 0x8ff30101, + 0x8ff40101, 0x8ff50101, 0x8ff60101}; + const TUint32 overrideIndex[] = {0x00770000, 0x0E010001, 0x0E400002, 0x0E440003, + 0x0E810004, 0x0EC10005, 0x0EC20006, 0xEC30007}; + const TUint16 abcString[4] = {0x0003, 0x0061, 0x0062, 0x0063}; + const TUint32 abcStringIndex = 0; + TCollationMethod method; + method.iId = 0; + method.iMainTable = StandardCollationMethod(); + method.iFlags = TCollationMethod::EIgnoreNone; + TInt charindex; + for (charindex = 0; method.iMainTable->iIndex[charindex] >> 16 != 'e'; ++charindex) + { + } + abcWTLKey[0] = method.iMainTable->iKey[method.iMainTable->iIndex[charindex] & 0xFFFF]; + TCollationKeyTable overrideTable = {abcWTLKey, overrideIndex, sizeof(abcWTLKey)/4, abcString, &abcStringIndex, 1}; + method.iOverrideTable = &overrideTable; + + TCollationValueIterator v(method); + TCollationValueIterator rv(method); + + TUint32 buf1[32]; + TUint32 buf2[32]; + + TCollationKey raw1[32]; + TCollationKey raw2[32]; + const TInt KRawKeyCnt = 8;//Raw collation key count produced from KAYZAccentsAbove string. + + //Get the raw key sequence for the whole KAYZAccentsAbove string. + TUTF32Iterator it(KAYZAccentsAbove().Ptr(), KAYZAccentsAbove().Ptr() + KAYZAccentsAbove().Length()); + rv.SetSourceIt(it); + ::GetRawKeys(rv, raw1, KRawKeyCnt); + + //KAYZAccentsAbove related constants + const TInt KBaseCharCnt = 3;//The number of base characters (A, y, z) in KAYZAccentsAbove string. + const TInt KOrgPosA = 0;//A position in KAYZAccentsAbove + const TInt KOrgPosY = 2;//y position in KAYZAccentsAbove + const TInt KOrgPosZ = 4;//z position in KAYZAccentsAbove + //Find where the collation key sequences start for A, y, z characters in KAYZAccentsAbove string. + const TInt KCollKeyPosA = ::CharNo2CollKeyPos(raw1, KRawKeyCnt, 0); + const TInt KCollKeyPosY = ::CharNo2CollKeyPos(raw1, KRawKeyCnt, 1); + const TInt KCollKeyPosZ = ::CharNo2CollKeyPos(raw1, KRawKeyCnt, 2); + + //Get the raw key sequence for character A in KAYZAccentsAbove string. + it = TUTF32Iterator(KAYZAccentsAbove().Ptr() + KOrgPosA, KAYZAccentsAbove().Ptr() + KAYZAccentsAbove().Length()); + rv.SetSourceIt(it); + ::GetRawKeys(rv, raw2 + KCollKeyPosA, KRawKeyCnt - KCollKeyPosA); + // + test(0 == ::CountDiscrepancies(raw1, raw2, KRawKeyCnt)); + + //Get the raw key sequence for character Y in KAYZAccentsAbove string. + it = TUTF32Iterator(KAYZAccentsAbove().Ptr() + KOrgPosY, KAYZAccentsAbove().Ptr() + KAYZAccentsAbove().Length()); + rv.SetSourceIt(it); + ::GetRawKeys(rv, raw2 + KCollKeyPosY, KRawKeyCnt - KCollKeyPosY); + // + test(0 == ::CountDiscrepancies(raw1, raw2, KRawKeyCnt)); + + //Get the raw key sequence for character Z in KAYZAccentsAbove string. + it = TUTF32Iterator(KAYZAccentsAbove().Ptr() + KOrgPosZ, KAYZAccentsAbove().Ptr() + KAYZAccentsAbove().Length()); + rv.SetSourceIt(it); + ::GetRawKeys(rv, raw2 + KCollKeyPosZ, KRawKeyCnt - KCollKeyPosZ); + // + test(0 == ::CountDiscrepancies(raw1, raw2, KRawKeyCnt)); + + //Test starting at different points in the iteration + + //Level 0 + //The whole string + it = TUTF32Iterator(KAYZAccentsAbove().Ptr(), KAYZAccentsAbove().Ptr() + KAYZAccentsAbove().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf1, 0, KBaseCharCnt); + //String from Y pos. + it = TUTF32Iterator(KAYZAccentsAbove().Ptr() + KOrgPosY, KAYZAccentsAbove().Ptr() + KAYZAccentsAbove().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 0, KBaseCharCnt - 1); + // + test(0 == ::CountDiscrepancies(buf1 + 1, buf2, KBaseCharCnt - 1)); + //String from Z pos. + it = TUTF32Iterator(KAYZAccentsAbove().Ptr() + KOrgPosZ, KAYZAccentsAbove().Ptr() + KAYZAccentsAbove().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 0, KBaseCharCnt - 2); + // + test(0 == ::CountDiscrepancies(buf1 + 2, buf2, KBaseCharCnt - 2)); + + //Level 1 + //KCapitalAYZAccentsAbove is used in this test. + it = TUTF32Iterator(KCapitalAYZAccentsAbove().Ptr(), KCapitalAYZAccentsAbove().Ptr() + KCapitalAYZAccentsAbove().Length()); + v.SetSourceIt(it); + ::GetRawKeys(v, raw1, 8); + const TInt KOrgPosY2 = 3;//Y position in KCapitalAYZAccentsAbove + const TInt KCollKeyPosY2 = ::CharNo2CollKeyPos(raw1, KRawKeyCnt, 1); + //The whole string + it = TUTF32Iterator(KCapitalAYZAccentsAbove().Ptr(), KCapitalAYZAccentsAbove().Ptr() + KCapitalAYZAccentsAbove().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf1, 1, 8); + //String from Y pos. + it = TUTF32Iterator(KCapitalAYZAccentsAbove().Ptr() + KOrgPosY2, KCapitalAYZAccentsAbove().Ptr() + KCapitalAYZAccentsAbove().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 1, 8 - KCollKeyPosY2); + // + test(0 == ::CountDiscrepancies(buf1 + KCollKeyPosY2, buf2, 8 - KCollKeyPosY2)); + + //Level 2 + //Capitals do not match at level 2 + it = TUTF32Iterator(KAYZAccentsAbove().Ptr(), KAYZAccentsAbove().Ptr() + KAYZAccentsAbove().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf1, 2, 8); + it = TUTF32Iterator(KCapitalYAYZAccentsAbove().Ptr(), KCapitalYAYZAccentsAbove().Ptr() + KCapitalYAYZAccentsAbove().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 2, 8); + // + test(1 == CountDiscrepancies(buf1, buf2, 8)); + test(buf1[3] != buf2[3]); + + //Test funny collation keys, when they succeed and when they fail half way. + it = TUTF32Iterator(KABCRuleTest().Ptr(), KABCRuleTest().Ptr() + KABCRuleTest().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf1, 0, 8); + it = TUTF32Iterator(KABCRuleExpected().Ptr(), KABCRuleExpected().Ptr() + KABCRuleExpected().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 0, 8); + // + test(0 == ::CountDiscrepancies(buf1, buf2, 8)); + + //Test different decompositions at level 3 + it = TUTF32Iterator(KGreekOPVY1().Ptr(), KGreekOPVY1().Ptr() + KGreekOPVY1().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf1, 3, 4); + // + it = TUTF32Iterator(KGreekOPVY2().Ptr(), KGreekOPVY2().Ptr() + KGreekOPVY2().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 3, 4); + // + test(0 == ::CountDiscrepancies(buf1, buf2, 4)); + // + it = TUTF32Iterator(KGreekOPVY3().Ptr(), KGreekOPVY3().Ptr() + KGreekOPVY3().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 3, 4); + // + test(0 == ::CountDiscrepancies(buf1, buf2, 4)); + // + it = TUTF32Iterator(KGreekOPVY4().Ptr(), KGreekOPVY4().Ptr() + KGreekOPVY4().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 3, 4); + // + test(0 == ::CountDiscrepancies(buf1, buf2, 4)); + // + it = TUTF32Iterator(KGreekOPVY5().Ptr(), KGreekOPVY5().Ptr() + KGreekOPVY5().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 3, 4); + // + test(0 == ::CountDiscrepancies(buf1, buf2, 4)); + // + it = TUTF32Iterator(KGreekOPVY6().Ptr(), KGreekOPVY6().Ptr() + KGreekOPVY6().Length()); + v.SetSourceIt(it); + ::GetKeys(v, buf2, 3, 4); + // + test(0 == ::CountDiscrepancies(buf1, buf2, 4)); + } + +// folding tests + +// equivalence classes: all codes that fold to the same letter (which must be present +// in the list). The lists are separated by -1. The end is marked with two -1s. +// Each list must be in increasing order. +TInt FoldingEquivalenceClasses[] = + { + 'A', 'a', -1, 'Z', 'z', -1, '@', -1, '[', -1, '{', -1, 127, -1, 'I', 'i', 0x131, -1, 0, -1, + ' ', 0xA0, -1, + 0x300, -1, 0x301, -1, + 0x141, 0x142, -1, + 0x1c4, 0x1c5, 0x1c6, -1, 0x1c7, 0x1c8, 0x1c9, -1, 0x1ca, 0x1cb, 0x1cc, -1, + 0x1f1, 0x1f2, 0x1f3, -1, 0x3a3, 0x3c2, 0x3c3, 0x3f2, -1, + 0x402, 0x452, -1, 0x40F, 0x45F, -1, 0x460, 0x461, -1, 0x480, 0x481, -1, 0x482, -1, + 0x410, 0x430, -1, 0x42F, 0x44f, -1, 0x48C, 0x48D, -1, 0x4e8, 0x4e9, -1, + 0x531, 0x561, -1, 0x556, 0x586, -1, 0x559, -1, 0x55f, -1, -1 + }; + +//_LIT(KMatchLeadingCandidate1, "\xE1\x65\x300\x301\x302\x303pqa\x301"); +//_LIT(KNoQMs, "a???"); +//_LIT(KOneQM, "?a"); +//_LIT(KTwoQMs, "??"); +//_LIT(KThreeQMs, "???*?"); + +//Constructs TUTF32Iterator iterator from aStr +TUTF32Iterator UTF32It(const TDesC16& aStr) + { + return TUTF32Iterator(aStr.Ptr(), aStr.Ptr() + aStr.Length()); + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-0107 +@SYMTestCaseDesc MatchSectionFolded test +@SYMTestPriority High +@SYMTestActions MatchSectionFolded test +@SYMTestExpectedResults The test must not fail. +@SYMPREQ814 Optimise folded string comparisons. +*/ +void MatchSectionFoldedTest() + { + TUTF32Iterator candidateIt, searchTermIt; + + candidateIt = UTF32It(_L16("\xE1")); + searchTermIt = UTF32It(_L16("a")); + test(!MatchSectionFolded(candidateIt, searchTermIt)); + + candidateIt = UTF32It(_L16("a")); + searchTermIt = UTF32It(_L16("\xE1")); + test(!MatchSectionFolded(candidateIt, searchTermIt)); + + candidateIt = UTF32It(_L16("abca\xE1\x62\x62\x61\x61\x61\x62\x63\x62\x61")); + searchTermIt = UTF32It(_L16("aBc")); + test(MatchSectionFolded(candidateIt, searchTermIt)); + test(searchTermIt.AtEnd()); + TPtrC16 p1(_L16("a\xE1\x62\x62\x61\x61\x61\x62\x63\x62\x61")); + TPtrC16 p2(candidateIt.CurrentPosition(), 11); + test(p1 == p2); + + candidateIt = UTF32It(_L16("aaaacdeiooo")); + searchTermIt = UTF32It(_L16("acde")); + test(!MatchSectionFolded(candidateIt, searchTermIt)); + } + +//FindMatchSectionFolded test +void DoFindMatchSectionFoldedTest(const TDesC16& aCandidate, const TDesC16& aSearchTerm, TInt aPos) + { + TUTF32Iterator candidateIt, searchTermIt; + candidateIt = UTF32It(aCandidate); + searchTermIt = UTF32It(aSearchTerm); + if(aPos >= 0) + { + test(FindMatchSectionFolded(candidateIt, searchTermIt)); + test(searchTermIt.AtEnd()); + } + else + { + test(!FindMatchSectionFolded(candidateIt, searchTermIt)); + } + } + +//This class is used for reading lines from the unicode data file. +class RUnicodeTestDataFile + { +public: + RUnicodeTestDataFile(); + void OpenLC(); + void Close(); + TBool NextStmt(TPtrC8& aStmt); +private: + HBufC8* iFileData; + TInt iStartPos; + }; + +RUnicodeTestDataFile::RUnicodeTestDataFile() : + iFileData(NULL), + iStartPos(0) + { + } + +void RUnicodeTestDataFile::OpenLC() + { + __ASSERT_ALWAYS(!iFileData && !iStartPos, User::Invariant()); + iFileData = NULL; + iStartPos = 0; + CleanupClosePushL(*this); + + RFs fileSess; + CleanupClosePushL(fileSess); + User::LeaveIfError(fileSess.Connect()); + + RFile file; + CleanupClosePushL(file); + User::LeaveIfError(file.Open(fileSess, KUnicodeTestDataFile, EFileRead)); + + TInt fileSize; + User::LeaveIfError(file.Size(fileSize)); + __ASSERT_ALWAYS(fileSize > 0, User::Invariant()); + + iFileData = HBufC8::NewL(fileSize + 1); + + TPtr8 p = iFileData->Des(); + User::LeaveIfError(file.Read(p)); + + CleanupStack::PopAndDestroy(2, &fileSess); + } + +void RUnicodeTestDataFile::Close() + { + delete iFileData; + iFileData = NULL; + iStartPos = 0; + } + +TBool RUnicodeTestDataFile::NextStmt(TPtrC8& aStmt) + { + aStmt.Set(NULL, 0); + if(iStartPos < iFileData->Length()) + { + const TUint8* pStart = iFileData->Des().Ptr() + iStartPos; + const TUint8* pEnd = pStart; + while(*pEnd++ != 0x0A) + { + } + iStartPos += pEnd - pStart; + aStmt.Set(pStart, pEnd - pStart - 1); + return ETrue; + } + return EFalse; + } + +//Get a field "aFieldNo" from "aStr" statement containing encoded unicode character data +TPtrC8 GetUnicodeDataField(const TPtrC8& aStr, TInt aFieldNo) + { + const TUint8* pStart = aStr.Ptr(); + //Find the beginning of the field + TInt count = 0; + while(count < aFieldNo) + { + if(*pStart++ == ';') + { + ++count; + } + } + //Find the end of the field + const TUint8* pEnd = pStart; + while(*pEnd++ != ';') + { + } + //Construct a string from the field data + TPtrC8 ptr(pStart, pEnd - pStart - 1); + return ptr; + } + +//Construct a string "aStr" with the extracted hex codes from "aUnicodeData" +//The extracted unicodes are placed not from position 0, because some of +//the decomposable unicode characters are combining characters. If "aStr" is a search +//string, then the searching algorithm will not work. +void FillStringL(TDes16& aStr, const TDesC8& aUnicodeData) + { + aStr.SetLength(aStr.MaxLength()); + TLex8 lex(aUnicodeData); + TInt len = 0; + for(len=0;!lex.Eos();++len) + { + TUint32 code; + User::LeaveIfError(lex.Val(code, EHex)); + lex.Assign(lex.NextToken()); + aStr[1+len] = (TUint16)code; + } + __ASSERT_ALWAYS(len > 0, User::Invariant()); + aStr.SetLength(1 + len); + } + +//Get the character unicode, which is at position 0 +TUint32 GetChCodeL(const TDesC8& aStr) + { + TLex8 lex(aStr); + TUint32 chCode; + User::LeaveIfError(lex.Val(chCode, EHex)); + return chCode; + } + +//Simple unicode folding tests +void FindMatchSectionFoldedTestSimple() + { + _LIT16(KCandidate, "abca\xE1\x62\x62\x61\x61\x61\x62\x63\x62\x61"); + DoFindMatchSectionFoldedTest(KCandidate, _L("abc"), 0); + DoFindMatchSectionFoldedTest(KCandidate, _L("abb"), -1); + DoFindMatchSectionFoldedTest(KCandidate, _L("caa"), -1); + DoFindMatchSectionFoldedTest(KCandidate, _L("abcb"), 9); + DoFindMatchSectionFoldedTest(KCandidate, _L("\xE1"), 4); + DoFindMatchSectionFoldedTest(KCandidate, _L("a\x301"), 4); + DoFindMatchSectionFoldedTest(KCandidate, _L("A\xC1\x42\x42"), 3); + DoFindMatchSectionFoldedTest(KCandidate, _L("a\x301\x42\x42"), 4); + DoFindMatchSectionFoldedTest(KCandidate, _L("a?BB"), 3); + DoFindMatchSectionFoldedTest(KCandidate, _L(""), 0); + DoFindMatchSectionFoldedTest(KCandidate, _L("?"), 0); + DoFindMatchSectionFoldedTest(KCandidate, _L("??????????????"), 0); + DoFindMatchSectionFoldedTest(KCandidate, _L("???????????????"), -1); + DoFindMatchSectionFoldedTest(KCandidate, _L("????a?????????"), -1); + DoFindMatchSectionFoldedTest(KCandidate, _L("???a??????????"), 0); + DoFindMatchSectionFoldedTest(KCandidate, _L("caa?"), -1); + DoFindMatchSectionFoldedTest(KCandidate, _L("abcb?"), 9); + DoFindMatchSectionFoldedTest(KCandidate, _L("abcb??"), -1); + DoFindMatchSectionFoldedTest(KCandidate, _L("b?aa"), 5); + } + +//Extended tests - all characters, having non-zero "character decomposition mapping" field +//or non-zero "upper case mapping" field +void FindMatchSectionFoldedTestComplexL() + { + TBuf16<10> candidate; + candidate.Copy(_L16("abcdefghij")); + TBuf16<10> searchTerm; + searchTerm.Copy(_L16("eeeeefghij")); + const TInt KChPos = 5; + //Read and parse each line from the unicode data file. + RUnicodeTestDataFile unicodeTestDataFile; + unicodeTestDataFile.OpenLC(); + TPtrC8 stmt; + while(unicodeTestDataFile.NextStmt(stmt) && stmt.Length() > 0) + { + //Get the character code + TUint32 chCode = GetChCodeL(stmt); + //Do not test characters, which code is > 0xFFFF + if(chCode > (TUint32)0xFFFF) + { + continue; + } + //"LATIN CAPITAL LETTER I WITH DOT ABOVE" - the searching algorithm does not work with it. + if(chCode == (TUint32)0x0130) + { + continue; + } + candidate[KChPos] = (TUint16)chCode; + //"Character decomposition mapping" is the 5th field, starting from 0. + TPtrC8 decomp(GetUnicodeDataField(stmt, 5)); + if(decomp.Length() > 1 && decomp[0] != '<') + { + //This character has valid decomposition mapping - test it. + //Construct the search string + FillStringL(searchTerm, decomp); + //Test + DoFindMatchSectionFoldedTest(candidate, searchTerm, KChPos); + } + //"Uppercase mapping" is the 12th field, starting from 0. + TPtrC8 upperc(GetUnicodeDataField(stmt, 12)); + if(upperc.Length() > 1) + { + //This character has valid uppercase mapping - test it. + //Construct the search string + FillStringL(searchTerm, upperc); + //Test + DoFindMatchSectionFoldedTest(candidate, searchTerm, KChPos); + } + }//end of "while" - for each file statement + CleanupStack::PopAndDestroy(&unicodeTestDataFile); + } + +//MatchStringFolded test +void MatchStringFoldedTestL() + { + TBuf16<2> candidate; + candidate.Copy(_L16("aa")); + TBuf16<10> searchTerm; + searchTerm.Copy(_L16("aaaaaaaaaa")); + const TInt KChPos = 1; + //Read and parse each line from the unicode data file. + RUnicodeTestDataFile unicodeTestDataFile; + unicodeTestDataFile.OpenLC(); + TPtrC8 stmt; + while(unicodeTestDataFile.NextStmt(stmt) && stmt.Length() > 0) + { + //Get the character code + TUint32 chCode = GetChCodeL(stmt); + //Do not test characters, which code is > 0xFFFF + if(chCode > (TUint32)0xFFFF) + { + continue; + } + //"LATIN CAPITAL LETTER I WITH DOT ABOVE" - the searching algorithm does not work with it. + if(chCode == (TUint32)0x0130) + { + continue; + } + candidate[KChPos] = (TUint16)chCode; + //"Character decomposition mapping" is the 5th field, starting from 0. + TPtrC8 decomp(GetUnicodeDataField(stmt, 5)); + if(decomp.Length() > 1 && decomp[0] != '<') + { + //This character has valid decomposition mapping - test it. + //Construct the search string + FillStringL(searchTerm, decomp); + //Test + test(MatchStringFolded(candidate.Ptr(), candidate.Ptr() + candidate.Length(), + searchTerm.Ptr(), searchTerm.Ptr() + searchTerm.Length())); + } + //"Uppercase mapping" is the 12th field, starting from 0. + TPtrC8 upperc(GetUnicodeDataField(stmt, 12)); + if(upperc.Length() > 1) + { + //This character has valid uppercase mapping - test it. + //Construct the search string + FillStringL(searchTerm, upperc); + //Test + test(MatchStringFolded(candidate.Ptr(), candidate.Ptr() + candidate.Length(), + searchTerm.Ptr(), searchTerm.Ptr() + searchTerm.Length())); + } + }//end of "while" - for each file statement + CleanupStack::PopAndDestroy(&unicodeTestDataFile); + } + +void FindMatchSectionFoldedTestL() + { + FindMatchSectionFoldedTestSimple(); + FindMatchSectionFoldedTestComplexL(); + } + +void TestFindMatchFoldedL() + { + MatchSectionFoldedTest(); + FindMatchSectionFoldedTestL(); + MatchStringFoldedTestL(); + } + +void TestCompareFoldedEqual(const TDesC& a, const TDesC& b) + { + test(a.CompareF(b) == 0); + test(b.CompareF(a) == 0); + } + +void TestCompareFolded() + { + // Latin Extended A + TestCompareFoldedEqual(_L("\x100"), _L("\x101")); + TestCompareFoldedEqual(_L("\x100"), _L("A\x304")); + TestCompareFoldedEqual(_L("\x100"), _L("a\x304")); + TestCompareFoldedEqual(_L("\x104"), _L("\x105")); + TestCompareFoldedEqual(_L("\x104"), _L("a\x328")); + TestCompareFoldedEqual(_L("\x107"), _L("C\x301")); + TestCompareFoldedEqual(_L("\x10F"), _L("\x10E")); + TestCompareFoldedEqual(_L("\x10F"), _L("D\x30C")); + TestCompareFoldedEqual(_L("\x110"), _L("\x111")); + TestCompareFoldedEqual(_L("\x123"), _L("G\x327")); + TestCompareFoldedEqual(_L("\x132"), _L("\x133")); + TestCompareFoldedEqual(_L("\x131"), _L("i")); + TestCompareFoldedEqual(_L("\x131"), _L("I")); + TestCompareFoldedEqual(_L("i"), _L("I")); + TestCompareFoldedEqual(_L("\x13F"), _L("\x140")); + TestCompareFoldedEqual(_L("\x141"), _L("\x142")); + TestCompareFoldedEqual(_L("\x14A"), _L("\x14B")); + TestCompareFoldedEqual(_L("\x150"), _L("\x151")); + TestCompareFoldedEqual(_L("\x150"), _L("o\x30B")); + TestCompareFoldedEqual(_L("\x152"), _L("\x153")); + TestCompareFoldedEqual(_L("\x17D"), _L("\x17E")); + TestCompareFoldedEqual(_L("\x17D"), _L("z\x30C")); + // Latin Extended B + TestCompareFoldedEqual(_L("\x182"), _L("\x183")); + TestCompareFoldedEqual(_L("\x184"), _L("\x185")); + TestCompareFoldedEqual(_L("\x187"), _L("\x188")); + TestCompareFoldedEqual(_L("\x18A"), _L("\x257")); + TestCompareFoldedEqual(_L("\x194"), _L("\x263")); + TestCompareFoldedEqual(_L("\x195"), _L("\x1F6")); + TestCompareFoldedEqual(_L("\x196"), _L("\x269")); + TestCompareFoldedEqual(_L("\x1A2"), _L("\x1A3")); + TestCompareFoldedEqual(_L("\x1A6"), _L("\x280")); + TestCompareFoldedEqual(_L("\x1BF"), _L("\x1F7")); + TestCompareFoldedEqual(_L("\x1DC"), _L("\x1DB")); + TestCompareFoldedEqual(_L("\x1DC"), _L("u\x308\x300")); + TestCompareFoldedEqual(_L("\x1DD"), _L("\x18E")); + TestCompareFoldedEqual(_L("\x1EC"), _L("\x1ED")); + TestCompareFoldedEqual(_L("\x1FC"), _L("\x1FD")); + TestCompareFoldedEqual(_L("\x200"), _L("\x201")); + TestCompareFoldedEqual(_L("\x216"), _L("u\x311")); + TestCompareFoldedEqual(_L("\x21B"), _L("T\x326")); + TestCompareFoldedEqual(_L("\x21C"), _L("\x21D")); + TestCompareFoldedEqual(_L("\x229"), _L("E\x327")); + TestCompareFoldedEqual(_L("\x22A"), _L("\x22B")); + TestCompareFoldedEqual(_L("\x22A"), _L("O\x308\x304")); + TestCompareFoldedEqual(_L("\x22A"), _L("\xF6\x304")); + TestCompareFoldedEqual(_L("\x233"), _L("y\x304")); + TestCompareFoldedEqual(_L("\x233"), _L("\x232")); + } + +void TestCompareFoldedNotEqual(TDesC& a, TDesC& b, TInt aValue) + { + test(a.CompareF(b) == aValue); + } + +static void TestCompareFoldedAdditional() + { + const TText16 UnicodeTextOne16[] = {'a', 0}; + const TText16 ErrUnicodeTextOne16[] = {'[', 0}; + + const TText16 UnicodeTextTwo16[] = {0x00EA, 0x0323, 0}; + const TText16 ErrUnicodeTextTwo16[] = {0x00EA, 't', 0}; + + const TText16 UnicodeTextThree16[] = {0x00EA, 0x03B1, 0}; + const TText16 ErrUnicodeTextThree16[] = {0x00EA, 0x0323, 0}; + + TBufC16 oriUnicodeSmallTextOne(UnicodeTextOne16); + TBufC16 nonMatchUnicodeSmallTextOne(ErrUnicodeTextOne16); + + TBufC16 oriUnicodeSmallTextTwo(UnicodeTextTwo16); + TBufC16 nonMatchUnicodeSmallTextTwo(ErrUnicodeTextTwo16); + + TBufC16 oriUnicodeSmallTextThree(UnicodeTextThree16); + TBufC16 nonMatchUnicodeSmallTextThree(ErrUnicodeTextThree16); + + const TText16 AsciiText16[] = {'A', 'B', 'C', 'D', 'E', 0}; + + TBufC16<5> oriAsciiSmallText(_L("ABCDE")); + + // Check that characters are non matching with return value as stated + + TestCompareFoldedNotEqual(oriUnicodeSmallTextOne, nonMatchUnicodeSmallTextOne, 6); + TestCompareFoldedNotEqual(oriUnicodeSmallTextTwo, nonMatchUnicodeSmallTextTwo, 33); + TestCompareFoldedNotEqual(oriUnicodeSmallTextThree, nonMatchUnicodeSmallTextThree, -33); + + // Try other way around... + + TestCompareFoldedNotEqual(nonMatchUnicodeSmallTextOne, oriUnicodeSmallTextOne, -6); + TestCompareFoldedNotEqual(nonMatchUnicodeSmallTextTwo, oriUnicodeSmallTextTwo, -33); + TestCompareFoldedNotEqual(nonMatchUnicodeSmallTextThree, oriUnicodeSmallTextThree, 33); + + // Declare a TPtrC16 which is base from AsciiText16... + + TPtrC16 AsciiSmallText; + + AsciiSmallText.Set(AsciiText16, 4); + + // Check the boundary case + + TestCompareFoldedNotEqual(oriAsciiSmallText, AsciiSmallText, 1); + + // Try other way around... + + TestCompareFoldedNotEqual(AsciiSmallText, oriAsciiSmallText, -1); + + } + +void TestFoldingL() + { + TestFindMatchFoldedL(); + TestCompareFolded(); + TestCompareFoldedAdditional(); + } + +// collation tests +_LIT(KCandidateString1, "abcdefg"); +_LIT(KCandidateString2, "\x1f82\x1f02\x345\x1f00\x300\x345\x3b1\x313\x300\x345"); +_LIT(KCandidateString3, "abcabcdababc"); +_LIT(KCandidateString4, "xyzxyxyzxyxyyxyzxyy"); + +_LIT(KMatch1, "abc"); +_LIT(KMatch2, "abc*"); +_LIT(KMatch3, "*abc*"); +_LIT(KMatch4, "abc*def"); +_LIT(KMatch5, "abc*def*g*"); +_LIT(KMatch6, "*def"); +_LIT(KMatch7, "**d?f?"); +_LIT(KMatch8, "*d?f??"); +_LIT(KMatch9, "***d?f??*"); +_LIT(KMatch10, "a*c*g"); +_LIT(KMatch11, "*c*g"); + +_LIT(KMatch12, "*\x1f82"); +_LIT(KMatch13, "*\x1f82*"); +//_LIT(KMatch14, "*\x3b1*"); +_LIT(KMatch15, "*\x313*"); +_LIT(KMatch16, "*\x300*"); +//_LIT(KMatch17, "*\x345*"); +//_LIT(KMatch18, "*\x3b1\x313*"); +//_LIT(KMatch19, "*\x3b1\x313\x300*"); +_LIT(KMatch20, "*\x1f82*\x1f82*\x1f82\x1f82"); +_LIT(KMatch21, "*\x1f82*\x1f82*\x1f82\x1f82*\x1f82*"); + +_LIT(KMatch22, "*aba*"); +_LIT(KMatch23, "*abc"); +_LIT(KMatch24, "a*abc"); +_LIT(KMatch25, "a*ab"); +_LIT(KMatch26, "*ca*abc"); +_LIT(KMatch27, "*ca*??c"); +_LIT(KMatch28, "*??c"); +_LIT(KMatch29, "a*babc"); +_LIT(KMatch30, "*xyy"); + +_LIT(KFoo1, "foo"); +_LIT(KPeach, "pe\x302\x63he"); +_LIT(KFooMatch1, "fo*"); +_LIT(KFooMatch2, "*Fo*"); +_LIT(KFooMatch3, "*f*O*o"); +_LIT(KFooMatch4, "*f*o*o*"); +_LIT(KFooMatch5, "*o"); +_LIT(KFooMatch6, "???"); +_LIT(KFooMatch7, "*?o?*"); +_LIT(KFooMatch8, "*?"); +_LIT(KFooNonMatch1, "oo*"); +_LIT(KFooNonMatch2, "??"); +_LIT(KFooNonMatch3, "????"); +_LIT(KFooNonMatch4, "*?f*"); +_LIT(KFooNonMatch5, "*f*f*"); +_LIT(KFooNonMatch6, "*?*f*"); +_LIT(KPeachMatch1, "p?che"); +_LIT(KPeachNonMatch1, "peche"); +_LIT(KPeachNonMatch2, "pe?che"); +_LIT(KPeachNonMatch3, "pe?he"); +_LIT(KPeachNonMatch4, "pe*"); + +void TestMatchIdentifiersTDesC(const TDesC& aCandidate, const TDesC& aSearchTerm, TInt aExpectedResult) + { + const TText16* candidateStart = aCandidate.Ptr(); + const TText16* candidateEnd = candidateStart + aCandidate.Length(); + const TText16* searchTermStart = aSearchTerm.Ptr(); + const TText16* searchTermEnd = searchTermStart + aSearchTerm.Length(); + TInt pos = ::LocateMatchStringFolded(candidateStart, candidateEnd, searchTermStart, searchTermEnd); + test(aExpectedResult == pos); + } + +void TestMatchIdentifiers() + { + TestMatchIdentifiersTDesC(KCandidateString1, KMatch1, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch2, 0); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch3, 0); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch4, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch5, 0); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch6, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch7, 3); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch8, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch9, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch10, 0); + TestMatchIdentifiersTDesC(KCandidateString1, KMatch11, 2); + TestMatchIdentifiersTDesC(KCandidateString2, KMatch12, 6); + TestMatchIdentifiersTDesC(KCandidateString2, KMatch13, 0); + //The next test does not pass with the new optimised methods + //TestMatchIdentifiersTDesC(KCandidateString2, KMatch14, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString2, KMatch15, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString2, KMatch16, KErrNotFound); + // I have taken this test out: it tests that combining ypogegrammeni is not + // found on its own: but with case folding it can become a non-combining + // character (iota), so this test is not relevant. + // TestMatchIdentifiersTDesC(KCandidateString2, KMatch17, KErrNotFound); + //The next tests do not pass with the new optimised methods + //TestMatchIdentifiersTDesC(KCandidateString2, KMatch18, KErrNotFound); + //TestMatchIdentifiersTDesC(KCandidateString2, KMatch19, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString2, KMatch20, 0); + TestMatchIdentifiersTDesC(KCandidateString2, KMatch21, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString3, KMatch22, 7); + TestMatchIdentifiersTDesC(KCandidateString3, KMatch23, 9); + TestMatchIdentifiersTDesC(KCandidateString3, KMatch24, 0); + TestMatchIdentifiersTDesC(KCandidateString3, KMatch25, KErrNotFound); + TestMatchIdentifiersTDesC(KCandidateString3, KMatch26, 2); + TestMatchIdentifiersTDesC(KCandidateString3, KMatch27, 2); + TestMatchIdentifiersTDesC(KCandidateString3, KMatch28, 9); + TestMatchIdentifiersTDesC(KCandidateString3, KMatch29, 0); + TestMatchIdentifiersTDesC(KCandidateString4, KMatch30, 16); + + TestMatchIdentifiersTDesC(KFoo1, KFoo1, 0); + TestMatchIdentifiersTDesC(KFoo1, KFooMatch1, 0); + TestMatchIdentifiersTDesC(KFoo1, KFooMatch2, 0); + TestMatchIdentifiersTDesC(KFoo1, KFooMatch3, 0); + TestMatchIdentifiersTDesC(KFoo1, KFooMatch4, 0); + TestMatchIdentifiersTDesC(KFoo1, KFooMatch5, 2); + TestMatchIdentifiersTDesC(KFoo1, KFooMatch6, 0); + TestMatchIdentifiersTDesC(KFoo1, KFooMatch7, 0); + TestMatchIdentifiersTDesC(KFoo1, KFooMatch8, 2); + TestMatchIdentifiersTDesC(KFoo1, KFooNonMatch1, KErrNotFound); + TestMatchIdentifiersTDesC(KFoo1, KFooNonMatch2, KErrNotFound); + TestMatchIdentifiersTDesC(KFoo1, KFooNonMatch3, KErrNotFound); + TestMatchIdentifiersTDesC(KFoo1, KFooNonMatch4, KErrNotFound); + TestMatchIdentifiersTDesC(KFoo1, KFooNonMatch5, KErrNotFound); + TestMatchIdentifiersTDesC(KFoo1, KFooNonMatch6, KErrNotFound); + TestMatchIdentifiersTDesC(KPeach, KPeachMatch1, 0); + TestMatchIdentifiersTDesC(KPeach, KPeachNonMatch1, KErrNotFound); + TestMatchIdentifiersTDesC(KPeach, KPeachNonMatch2, KErrNotFound); + TestMatchIdentifiersTDesC(KPeach, KPeachNonMatch3, KErrNotFound); + TestMatchIdentifiersTDesC(KPeach, KPeachNonMatch4, KErrNotFound); + + TestMatchIdentifiersTDesC(_L(""), _L(""), 0); + TestMatchIdentifiersTDesC(_L("a"), _L(""), KErrNotFound); + TestMatchIdentifiersTDesC(_L(""), _L("*"), 0); + } + +void TestFindIdentifierTDesC(const TDesC& aCandidateString, const TDesC& aSearchTerm, TInt /*aExpectedResult*/) + { + TUTF32Iterator candidateIt(aCandidateString.Ptr(), aCandidateString.Ptr() + aCandidateString.Length()); + TUTF32Iterator searchIt(aSearchTerm.Ptr(), aSearchTerm.Ptr() + aSearchTerm.Length()); + /*aExpectedResult = */::FindFolded(candidateIt, searchIt); + } + +//INC057641 - NTT Functional BC break in 8.1a: string comparison changed +static void INC057641L() + { + _LIT16(KEmptyText, ""); + HBufC16* str = HBufC16::NewLC(4); + str->Des().Copy(_L("****")); + TInt res = str->CompareC(KEmptyText); + CleanupStack::PopAndDestroy(str); + test(res == 1); + } + +_LIT(KFind1, "abc"); +_LIT(KFind2, "def"); +_LIT(KFind3, "efg"); +_LIT(KFind4, "fga"); +_LIT(KFind5, "acd"); +_LIT(KFind6, "\x1f82"); +_LIT(KFind7, "\x3b1\x313\x300\x345"); +_LIT(KFind8, "\x3b1"); +_LIT(KFind9, "aba"); +_LIT(KFind10, "abc"); + +void TestFindIdentifier() + { + TestFindIdentifierTDesC(KCandidateString1, TPtrC(), 0); + TestFindIdentifierTDesC(KCandidateString1, KFind1, 0); + TestFindIdentifierTDesC(KCandidateString1, KFind2, 3); + TestFindIdentifierTDesC(KCandidateString1, KFind3, 4); + TestFindIdentifierTDesC(KCandidateString1, KFind4, KErrNotFound); + TestFindIdentifierTDesC(KCandidateString1, KFind5, KErrNotFound); + TestFindIdentifierTDesC(KCandidateString2, KFind6, 0); + TestFindIdentifierTDesC(KCandidateString2, KFind7, 0); + TestFindIdentifierTDesC(KCandidateString2, KFind8, KErrNotFound); + TestFindIdentifierTDesC(KCandidateString3, KFind9, 7); + TestFindIdentifierTDesC(KCandidateString3, KFind10, 0); + } + +struct TestMatch8 + { + TText8 const* iLeft; + TText8 const* iRight; + TInt iResult; + }; + +TestMatch8 const Tests8[]= + { + {_S8(""),_S8(""),0}, + {_S8(""),_S8("?"),KErrNotFound}, + {_S8(""),_S8("*"),0}, + {_S8(""),_S8("**"),0}, + {_S8(""),_S8("*x*"),KErrNotFound}, + {_S8("x"),_S8(""),KErrNotFound}, + {_S8("x"),_S8("?"),0}, + {_S8("x"),_S8("*"),0}, + {_S8("x"),_S8("**"),0}, + {_S8("x"),_S8("**?"),0}, + {_S8("x"),_S8("?**"),0}, + {_S8("x"),_S8("**?*"),0}, + {_S8("x"),_S8("x"),0}, + {_S8("x"),_S8("a"),KErrNotFound}, + {_S8("x"),_S8("xx"),KErrNotFound}, + {_S8("x"),_S8("?x"),KErrNotFound}, + {_S8("x"),_S8("x*"),0}, + {_S8("x"),_S8("*x"),0}, + {_S8("x"),_S8("*x*"),0}, + {_S8("x"),_S8("**x*"),0}, + {_S8("abc"),_S8(""),KErrNotFound}, + {_S8("abc"),_S8("?*"),0}, + {_S8("abc"),_S8("*?"),2}, + {_S8("abc"),_S8("*?*?"),0}, + {_S8("abc"),_S8("*a*"),0}, + {_S8("abc"),_S8("*b*"),1}, + {_S8("abc"),_S8("*c*"),2}, + {_S8("abc"),_S8("*a"),KErrNotFound}, + {_S8("abc"),_S8("*c"),2}, + {_S8("abc"),_S8("*?c"),1}, + {_S8("abc"),_S8("??c"),0}, + {_S8("abc"),_S8("*b?"),1}, + }; + +struct TestMatch16 + { + TText16 const* iLeft; + TText16 const* iRight; + TInt iResult; + }; + +TestMatch16 const Tests16[]= + { + {_S16(""),_S16(""),0}, + {_S16(""),_S16("?"),KErrNotFound}, + {_S16(""),_S16("*"),0}, + {_S16(""),_S16("**"),0}, + {_S16(""),_S16("*x*"),KErrNotFound}, + {_S16("x"),_S16(""),KErrNotFound}, + {_S16("x"),_S16("?"),0}, + {_S16("x"),_S16("*"),0}, + {_S16("x"),_S16("**"),0}, + {_S16("x"),_S16("**?"),0}, + {_S16("x"),_S16("?**"),0}, + {_S16("x"),_S16("**?*"),0}, + {_S16("x"),_S16("x"),0}, + {_S16("x"),_S16("a"),KErrNotFound}, + {_S16("x"),_S16("xx"),KErrNotFound}, + {_S16("x"),_S16("?x"),KErrNotFound}, + {_S16("x"),_S16("x*"),0}, + {_S16("x"),_S16("*x"),0}, + {_S16("x"),_S16("*x*"),0}, + {_S16("x"),_S16("**x*"),0}, + {_S16("abc"),_S16(""),KErrNotFound}, + {_S16("abc"),_S16("?*"),0}, + {_S16("abc"),_S16("*?"),2}, + {_S16("abc"),_S16("*?*?"),0}, + {_S16("abc"),_S16("*a*"),0}, + {_S16("abc"),_S16("*b*"),1}, + {_S16("abc"),_S16("*c*"),2}, + {_S16("abc"),_S16("*a"),KErrNotFound}, + {_S16("abc"),_S16("*c"),2}, + {_S16("abc"),_S16("*?c"),1}, + {_S16("abc"),_S16("??c"),0}, + {_S16("abc"),_S16("*b?"),1}, + }; + +TInt KTests=sizeof(Tests8)/sizeof(Tests8[0]); + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-1770 +@SYMTestCaseDesc TDes16 Collation conversion function test +@SYMTestPriority High +@SYMTestActions Testing the three collation conversion function + in TDesC16::GetNormalizedDecomposedFormL, + TDesC16::GetFoldedDecomposedFormL, + TDesC16::GetCollationKeysL +@SYMTestExpectedResults The test must not fail. +@SYMREQ 6178 Add several new Unicode utility functions +*/ +static void TestDes16CollationFunctionL() + { + /**----------------Test TDesC16::GetNormalizedDecomposedFormL------------------*/ + + HBufC16* outputBuffer=NULL; + _LIT16(KTestString1,"abc") ; + //LATIN CAPITAL LETTER W WITH DIAERESIS(\x0057\x0308) + //LATIN SMALL LETTER A(\x0061) + //LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE(\x006F\x0302\x0303) + //GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI(\x03B1\x0313\x0342\x0345) + _LIT16(KTestString2,"\x1E84\x0061\x1ED7\x1F86"); + _LIT16(KTestStringNDF2,"\x0057\x0308\x0061\x006F\x0302\x0303\x03B1\x0313\x0342\x0345"); + + outputBuffer=KTestString1().GetNormalizedDecomposedFormL(); + test(outputBuffer->Compare(KTestString1())==0); + delete outputBuffer; + + outputBuffer=KTestString2().GetNormalizedDecomposedFormL(); + test(outputBuffer->Compare(KTestStringNDF2())==0); + delete outputBuffer; + + /**----------------Test TDesC16::GetFoldedDecomposedFormL------------------*/ + _LIT16(KTestString6,"AbC"); + _LIT16(KTestStringFolded6,"abc"); + //GREEK CAPITAL LETTER OMICRON WITH PSILI =>\x03BF\x0313 + //LATIN SMALL LETTER M WITH ACUTE =>\x006D\x0301 + //LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE => \x006F\x0302\x0309 + _LIT16(KTestString7,"\x1F48\x1E3F\x1ED4"); + _LIT16(KTestStringFolded7,"\x03BF\x0313\x006D\x0301\x006F\x0302\x0309"); + + outputBuffer=KTestString6().GetFoldedDecomposedFormL(); + test(outputBuffer->Compare(KTestStringFolded6())==0); + delete outputBuffer; + + outputBuffer=KTestString7().GetFoldedDecomposedFormL(); + test(outputBuffer->Compare(KTestStringFolded7())==0); + delete outputBuffer; + + /**----------------Test TDesC16::GetCollationKeysL------------------*/ + TCollationMethod method; + method.iId = 0; + //purposely set the maintable to NULL, this will result in the DefaultTable being used + method.iMainTable = 0; + method.iOverrideTable = 0; + method.iFlags = TCollationMethod::EIgnoreNone; + + //---------------Test key generation functionality---------------- + /** + Collation keys for + x=08b90108-00000078 + y=08bd0108-00000079 + z=08c90108-0000007a + */ + _LIT(KInputString1,"xyz"); + HBufC8* outbuf=NULL; + //Max Level 0 keys + _LIT8(KMaxLevel0Key,"\x08\xb9\x08\xbd\x08\xc9"); + outbuf=KInputString1().GetCollationKeysL(0,&method); + test(outbuf->Compare(KMaxLevel0Key())==0); + delete outbuf; + //Max Level 1 keys + _LIT8(KMaxLevel1Key,"\x08\xb9\x08\xbd\x08\xc9\x00\x00\x01\x01\x01"); + outbuf=KInputString1().GetCollationKeysL(1,&method); + test(outbuf->Compare(KMaxLevel1Key())==0); + delete outbuf; + //Max Level 2 keys + _LIT8(KMaxLevel2Key,"\x08\xb9\x08\xbd\x08\xc9\x00\x00\x01\x01\x01\x00\x08\x08\x08"); + outbuf=KInputString1().GetCollationKeysL(2,&method); + test(outbuf->Compare(KMaxLevel2Key())==0); + delete outbuf; + //Max Level 3 keys + _LIT8(KMaxLevel3Key,"\x08\xb9\x08\xbd\x08\xc9\x00\x00\x01\x01\x01\x00\x08\x08\x08\x00\x00\x00\x78\x00\x00\x79\x00\x00\x7A"); + outbuf=KInputString1().GetCollationKeysL(3,&method); + test(outbuf->Compare(KMaxLevel3Key())==0); + delete outbuf; + + /** + Decomposition for 1F70 + 1F70=03B1 0300 + Collation keys for + \x03B1 =09360108-000003B1 + \x0300 =00001609-00000300 + y =08bd0108-00000079 + */ + _LIT(KInputString2,"\x1F70y"); + //Max Level 2 keys + _LIT8(KCollationString22,"\x09\x36\x08\xBD\x00\x00\x01\x16\x01\x00\x08\x08\x08"); + outbuf=KInputString2().GetCollationKeysL(2,&method); + test(outbuf->Compare(KCollationString22())==0); + delete outbuf; + + //Max Level 3 keys + _LIT8(KCollationString23,"\x09\x36\x08\xBD\x00\x00\x01\x16\x01\x00\x08\x08\x08\x00\x00\x03\xB1\x00\x03\x00\x00\x00\x79"); + outbuf=KInputString2().GetCollationKeysL(3,&method); + test(outbuf->Compare(KCollationString23())==0); + delete outbuf; + + /** + Decomposition for 1EAC + 1EAC= 1EA0 0302 = 0041 0323 0302 + Collation keys for + \x0041 =06CF0121-00000041 + \x0323 =FF800104-00000001,83230105-00000000(2 keys for one character) + \x0302 =00001D09-00000302 + */ + _LIT(KInputString3,"\x1EAC"); + //Max Level 0 keys + _LIT8(KCollationString30,"\x06\xCF\xFF\x80\x83\x23"); + //Max Level 1 keys + _LIT8(KCollationString31,"\x06\xCF\xFF\x80\x83\x23\x00\x00\x01\x01\x01\x1d"); + outbuf=KInputString3().GetCollationKeysL(1,&method); + test(outbuf->Compare(KCollationString31())==0); + delete outbuf; + + //Max Level 3 keys + _LIT8(KCollationString33,"\x06\xCF\xFF\x80\x83\x23\x00\x00\x01\x01\x01\x1d\x00\x20\x04\x04\x08\x00\x00\x00\x41\x00\x00\x01\x00\x03\x02"); + outbuf=KInputString3().GetCollationKeysL(3,&method); + test(outbuf->Compare(KCollationString33())==0); + delete outbuf; + + //--------------Test using NULL collationMethod----------------------- + outbuf=KInputString3().GetCollationKeysL(3,NULL); + test(outbuf->Compare(KCollationString33())==0); + delete outbuf; + + //--------------Test using out of limit level------------------------- + outbuf=KInputString3().GetCollationKeysL(6,NULL); + test(outbuf->Compare(KCollationString33())==0); + delete outbuf; + + outbuf=KInputString3().GetCollationKeysL(-1,NULL); + test(outbuf->Compare(KCollationString30())==0); + delete outbuf; + + } + +/** +@SYMTestCaseID SYSLIB-UNICODE-CT-1771 +@SYMTestCaseDesc TDes16 Collation conversion function OOM test +@SYMTestPriority High +@SYMTestActions OOM Testing the three collation conversion function + in TDesC16::GetNormalizedDecomposedFormL, + TDesC16::GetFoldedDecomposedFormL, + TDesC16::GetCollationKeysL +@SYMTestExpectedResults The test must not fail. +@SYMREQ 6178 Add several new Unicode utility functions +*/ +static void TestDes16CollationFunctionOOM() + { + test.Next(_L("TestDes16CollationFunctionOOM")); + + TInt err, tryCount = 0; + do + { + __UHEAP_MARK; + // find out the number of open handles + TInt startProcessHandleCount; + TInt startThreadHandleCount; + RThread().HandleCount(startProcessHandleCount, startThreadHandleCount); + + // Setting Heap failure for OOM test + __UHEAP_SETFAIL(RHeap::EDeterministic, ++tryCount); + TRAP(err,TestDes16CollationFunctionL() ); + __UHEAP_SETFAIL(RHeap::ENone, 0); + + // check that no handles have leaked + TInt endProcessHandleCount; + TInt endThreadHandleCount; + RThread().HandleCount(endProcessHandleCount, endThreadHandleCount); + + test(startProcessHandleCount == endProcessHandleCount); + test(startThreadHandleCount == endThreadHandleCount); + + __UHEAP_MARKEND; + } while(err == KErrNoMemory); + + test(err == KErrNone); + test.Printf(_L("- TestDes16CollationFunctionOOM succeeded at heap failure rate of %i\n"), tryCount); + } + +GLDEF_C TInt E32Main() +// +// entry point +// + { + CTrapCleanup* trapCleanup = CTrapCleanup::New(); + test(trapCleanup != NULL); + + test.Title(); +// + + test.Start(_L("Match8")); + TInt ii; + for (ii=0;ii