symport/e32/euser/unicode/collate.cpp
changeset 1 0a7b44b10206
child 2 806186ab5e14
equal deleted inserted replaced
0:c55016431358 1:0a7b44b10206
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // The Unicode collation system.
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "collateimp.h"
       
    19 #include "foldtable.inl"
       
    20 
       
    21 #include <collate.h>
       
    22 #include <unicode.h>
       
    23 #include "u32std.h"
       
    24 
       
    25 // maximum size of string which has its own sort key
       
    26 static const TInt KKeyedStringBufferSize = 8;
       
    27 
       
    28 // Creates a one or two collation keys sequence corresponding to the input character.
       
    29 // Returns the number of keys output.
       
    30 static TInt CreateDefaultCollationKeySequence(TInt aChar, TCollationKey* aBuffer)
       
    31 	{
       
    32 	if (aChar >= 0x3400 && aChar <= 0x9FFF)	// CJK
       
    33 		{
       
    34 		aBuffer[0].iLow = (TUint32)aChar << 16 | 0x0105;
       
    35 		aBuffer[0].iHigh = aChar;
       
    36 		return 1;//Collation key sequence consists of 1 key
       
    37 		}
       
    38 	aBuffer[0].iLow = 0xFF800000 | ((aChar << 1) & 0x3F0000) | 0x0104;	// no stop bit
       
    39 	aBuffer[0].iHigh = 1;
       
    40 	aBuffer[1].iLow = (aChar << 16) | 0x80000105;		// stop bit
       
    41 	aBuffer[1].iHigh = 0;
       
    42 	return 2;//Collation key sequence consists of 2 keys
       
    43 	}
       
    44 
       
    45 // Finds a character's key in the main index, or returns -1 if it is not there
       
    46 static TInt FindCollationKeyIndex(TInt aChar, const TCollationKeyTable& aTable)
       
    47 	{
       
    48 	TInt n = aTable.iIndices;
       
    49 	const TUint32 *base = aTable.iIndex;
       
    50 	const TUint32 *p = base;
       
    51 
       
    52 	while (n > 0)
       
    53 		{
       
    54 		TInt pivot = n / 2;
       
    55 		p += pivot;
       
    56 		TInt c = *p >> 16;
       
    57 		if (aChar == c)		// found it
       
    58 			return *p & 0xFFFF;
       
    59 		if (aChar < c)		// it's before
       
    60 			n = pivot;
       
    61 		else					// it's after
       
    62 			{
       
    63 			base = p + 1;
       
    64 			n -= pivot + 1;
       
    65 			}
       
    66 		p = base;
       
    67 		}
       
    68 	return -1;
       
    69 	}
       
    70 
       
    71 static void ProcessKeys(TUint32& aKey1, TUint32& aKey2, TUint aFlags)
       
    72 	{
       
    73 	if (aFlags & TCollationMethod::EFoldCase)
       
    74 		{
       
    75 		static const TUint case_fold_table[21] =
       
    76 			{ 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x6,
       
    77 			  0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14 };
       
    78 		aKey1 = case_fold_table[aKey1];
       
    79 		aKey2 = case_fold_table[aKey2];
       
    80 		}					
       
    81 	if (aFlags & TCollationMethod::ESwapCase)
       
    82 		{
       
    83 		static const TUint case_swap_table[21] =
       
    84 			{ 0, 0x1, 0x8, 0x9, 0xA, 0xB, 0xC, 0x7, 0x2, 0x3, 0x4, 0x5, 0x6,
       
    85 			  0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14 };
       
    86 		aKey1 = case_swap_table[aKey1];
       
    87 		aKey2 = case_swap_table[aKey2];
       
    88 		}
       
    89 	if (aFlags & TCollationMethod::ESwapKana)
       
    90 		{
       
    91 		static const TUint kana_swap_table[21] =
       
    92 			{ 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC,
       
    93 			  0x13, 0x14, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12 };
       
    94 		aKey1 = kana_swap_table[aKey1];
       
    95 		aKey2 = kana_swap_table[aKey2];
       
    96 		}
       
    97 	}
       
    98 
       
    99 // Returns the position of the character in the string, or aLength if it is not present.
       
   100 // If aChar is found but it is preceded by aEscapeChar (aEscapeChar != 0), then the search continues.
       
   101 static TInt FindCharacter(TInt aChar, TInt aEscapeChar, const TUint16* aString, TInt aLength)
       
   102 	{
       
   103 	TBool isEscaped = EFalse;
       
   104 	for(TInt pos=0;pos!=aLength;++pos,++aString)
       
   105 		{
       
   106 		if(isEscaped) 
       
   107 			{ 
       
   108 			isEscaped = EFalse; 
       
   109 			} 
       
   110 		else if(*aString == aEscapeChar) 
       
   111 			{ 
       
   112 			isEscaped = ETrue; 
       
   113 			} 
       
   114 		else if(*aString == aChar) 
       
   115 			{ 
       
   116 			if(!isEscaped)
       
   117 				{
       
   118 				return pos; 
       
   119 				}
       
   120 			}		
       
   121 		}
       
   122 	return aLength;
       
   123 	}
       
   124 
       
   125 /*
       
   126 The standard collation data, containing keys for all the WGL4 characters, plus
       
   127 commonly-used control characters and spaces. Generated by COLTAB.
       
   128 */
       
   129 static const TUint32 TheKey[] = 
       
   130 	{
       
   131 	0x21e0112,0x21e0113,0x2260112,0x2260112,0x2260113,0x2740112,0x2740113,0x6c60178,
       
   132 	0x266017a,0x6c70179,0x6c60178,0x266017a,0x6c90179,0x6c60178,0x266017a,0x6cd0179,
       
   133 	0x6c80178,0x266017a,0x6c90179,0x6c80178,0x266017a,0x6cd0179,0x6ca0178,0x266017a,
       
   134 	0x6cd0179,0x6cc0178,0x266017a,0x6cd0179,0x6f70110,0x2650112,0x8050111,0x74b0110,
       
   135 	0x78d0111,0x74b0110,0x7bd0111,0x78d0110,0x7a10111,0x78d0128,0x7a10129,0x7bd0110,
       
   136 	0x2290113,0x7bd0128,0x2290113,0x7ed0128,0x8050111,0x805dd10,0x71f0111,0x805dd28,
       
   137 	0x71f0129,0x85ddd10,0x85d0111,0x8750150,0x7e50151,0x9060110,0x7ed0111,0x3,
       
   138 	0x201010b,0x202010b,0x203010b,0x204010b,0x205010b,0x206010b,0x207010b,0x208010b,
       
   139 	0x209010b,0x2090113,0x209016f,0x209020b,0x209130b,0x209160b,0x209180b,0x2091d0b,
       
   140 	0x209240b,0x209280b,0x2092a0b,0x2092f0b,0x209330b,0x209360b,0x209390b,0x2093b0b,
       
   141 	0x2093f0b,0x2096b0b,0x20b010b,0x20c010b,0x20d010b,0x20d016f,0x20e010b,0x20f010b,
       
   142 	0x210010b,0x211010b,0x214010b,0x21a010b,0x21c010b,0x21e010b,0x21f010b,0x221010b,
       
   143 	0x222010b,0x226010b,0x229010b,0x22d010b,0x22e010b,0x22f010b,0x230010b,0x231010b,
       
   144 	0x232010b,0x233010b,0x234010b,0x235010b,0x236010b,0x237010b,0x23c010b,0x23d010b,
       
   145 	0x23e010b,0x23f010b,0x240010b,0x241010b,0x242010b,0x243010b,0x25e010b,0x25f010b,
       
   146 	0x260010b,0x261010b,0x262010b,0x263010b,0x265010b,0x266010b,0x267010b,0x268010b,
       
   147 	0x269010b,0x26a010b,0x26c010b,0x26e010b,0x26f010b,0x270010b,0x274010b,0x2ac010b,
       
   148 	0x2ad010b,0x2af010b,0x2d6010b,0x2ff010b,0x300010b,0x301010b,0x302010b,0x303010b,
       
   149 	0x304010b,0x317010b,0x35c010b,0x35f010b,0x366010b,0x368010b,0x369010b,0x36a010b,
       
   150 	0x36b010b,0x36c010b,0x36d010b,0x36e010b,0x36f010b,0x370010b,0x371010b,0x372010b,
       
   151 	0x374010b,0x375010b,0x378010b,0x37c010b,0x37d010b,0x381010b,0x382010b,0x38a010b,
       
   152 	0x38c010b,0x3a2010b,0x3b9010b,0x3bb010b,0x3bc010b,0x42f010b,0x43d010b,0x44d010b,
       
   153 	0x44e010b,0x4d6010b,0x4d8010b,0x4e2010b,0x4e6010b,0x4ea010b,0x4ee010b,0x4f2010b,
       
   154 	0x4fa010b,0x502010b,0x50a010b,0x512010b,0x526010b,0x527010b,0x528010b,0x529010b,
       
   155 	0x52a010b,0x52b010b,0x52c010b,0x52d010b,0x52e010b,0x52f010b,0x530010b,0x531010b,
       
   156 	0x532010b,0x533010b,0x534010b,0x535010b,0x536010b,0x537010b,0x538010b,0x539010b,
       
   157 	0x53a010b,0x53b010b,0x53c010b,0x53d010b,0x53e010b,0x53f010b,0x540010b,0x541010b,
       
   158 	0x542010b,0x556010b,0x55a010b,0x55e010b,0x562010b,0x566010b,0x567010b,0x568010b,
       
   159 	0x569010b,0x56c010b,0x56d010b,0x576010b,0x577010b,0x578010b,0x57e010b,0x586010b,
       
   160 	0x588010b,0x590010b,0x596010b,0x597010b,0x59b010b,0x5a4010b,0x5a5010b,0x5b2010b,
       
   161 	0x5f0010b,0x5f1010b,0x5f2010b,0x5f6010b,0x5f8010b,0x616010b,0x619010b,0x61b010b,
       
   162 	0x61c010b,0x620010b,0x621010b,0x6b4010b,0x6b5010b,0x1309,0x1609,0x1809,
       
   163 	0x1d09,0x2209,0x2409,0x2809,0x2f09,0x3009,0x3309,0x3609,
       
   164 	0x3909,0x3b09,0x4109,0x2c20109,0x2c30109,0x2c40109,0x2c50109,0x2c60109,
       
   165 	0x2cd0109,0x2ce0109,0x2d10109,0x2d50109,0x2fa0109,0x6c50109,0x6c60109,0x6c60151,
       
   166 	0x6c70109,0x6c70151,0x6c80109,0x6c80151,0x6c90109,0x6ca0109,0x6cb0109,0x6cc0109,
       
   167 	0x6cd0109,0x6ce0109,0x6cf0109,0x6cf0121,0x6cf0151,0x6d30109,0x6d30121,0x6e30109,
       
   168 	0x6e30121,0x6f70109,0x6f70121,0x7030109,0x7030121,0x7070109,0x7070121,0x7170109,
       
   169 	0x7170121,0x71f0109,0x71f0121,0x74b0109,0x74b0121,0x74f0109,0x7530109,0x7530121,
       
   170 	0x7730109,0x7730121,0x77f0109,0x77f0121,0x78d0109,0x78d0121,0x7910109,0x7a10109,
       
   171 	0x7a10121,0x7b10109,0x7b10121,0x7bd0109,0x7bd0115,0x7bd0121,0x7c50109,0x7c50121,
       
   172 	0x7e50109,0x7e50121,0x7ed0109,0x7ed0121,0x7ed0151,0x8010109,0x8010121,0x8050109,
       
   173 	0x8050121,0x8050151,0x80d0109,0x80d0121,0x81d0109,0x81d0121,0x8290109,0x8290121,
       
   174 	0x8310109,0x8350109,0x8350121,0x85d0109,0x85d0121,0x85dde11,0x8750109,0x8750121,
       
   175 	0x8790109,0x8790121,0x88d0109,0x88d0121,0x8a50109,0x8a50121,0x8b10109,0x8b10121,
       
   176 	0x8b90109,0x8b90121,0x8bd0109,0x8bd0121,0x8c90109,0x8c90121,0x8e90109,0x8e90121,
       
   177 	0x9360109,0x9360121,0x9370109,0x9370121,0x9380109,0x9380121,0x9390109,0x9390121,
       
   178 	0x93a0109,0x93a0121,0x93d0109,0x93d0121,0x93e0109,0x93e0121,0x93f0109,0x93f0121,
       
   179 	0x9400109,0x9400121,0x9420109,0x9420121,0x9430109,0x9430121,0x9440109,0x9440111,
       
   180 	0x9440121,0x9450109,0x9450121,0x9460109,0x9460121,0x9470109,0x9470121,0x9480109,
       
   181 	0x9480121,0x94a0109,0x94a0121,0x94b0109,0x94b0121,0x94c0109,0x94c0121,0x94d0109,
       
   182 	0x94d0121,0x94e0109,0x94e0121,0x94f0109,0x94f0121,0x9500109,0x9500121,0x9510109,
       
   183 	0x9510121,0x95a0109,0x95a0121,0x9660109,0x9660121,0x96a0109,0x96a0121,0x96e0109,
       
   184 	0x96e0121,0x9720109,0x9720121,0x97e0109,0x97e0121,0x9820109,0x9820121,0x98a0109,
       
   185 	0x98a0121,0x98e0109,0x98e0121,0x9920109,0x9920121,0x99a0109,0x99a0121,0x99e0109,
       
   186 	0x99e0121,0x9a60109,0x9a60121,0x9aa0109,0x9aa0121,0x9ae0109,0x9ae0121,0x9b20109,
       
   187 	0x9b20121,0x9ca0109,0x9ca0121,0x9ce0109,0x9ce0121,0x9d20109,0x9d20121,0x9d60109,
       
   188 	0x9d60121,0x9e60109,0x9e60121,0x9ea0109,0x9ea0121,0x9f20109,0x9f20121,0x9fe0109,
       
   189 	0x9fe0121,0xa020109,0xa020121,0xa0a0109,0xa0a0121,0xa120109,0xa120121,0xa160109,
       
   190 	0xa160121,0xa260109,0xa260121,0xa2a0109,0xa2a0121,0xa460109,0xa460121,0xa4e0109,
       
   191 	0xa4e0121,0xa660109,0xa660121,0xa6a0109,0xa6a0121,0xa6e0109,0xa6e0121,0xa720109,
       
   192 	0xa720121,0xa760109,0xa760121,0xa7a0109,0xa7a0121,0xa820109,0xa820121,0xa860109,
       
   193 	0xa860121,0xa8a0109,0xa8a0121,
       
   194 	};
       
   195 
       
   196 static const TUint32 TheIndex[] = 
       
   197 	{
       
   198 	0x37,0x10037,0x20037,0x30037,0x40037,0x50037,0x60037,0x70037,
       
   199 	0x80037,0x90038,0xa0039,0xb003a,0xc003b,0xd003c,0xe0037,0xf0037,
       
   200 	0x100037,0x110037,0x120037,0x130037,0x140037,0x150037,0x160037,0x170037,
       
   201 	0x180037,0x190037,0x1a0037,0x1b0037,0x1c0037,0x1d0037,0x1e0037,0x1f0037,
       
   202 	0x200040,0x21005d,0x22006a,0x230080,0x24010d,0x250081,0x26007f,0x270063,
       
   203 	0x280070,0x290071,0x2a007b,0x2b0096,0x2c005a,0x2d0053,0x2e0061,0x2f007c,
       
   204 	0x300115,0x310116,0x320118,0x33011a,0x34011c,0x35011d,0x36011e,0x37011f,
       
   205 	0x380120,0x390121,0x3a005c,0x3b005b,0x3c009a,0x3d009b,0x3e009c,0x3f005f,
       
   206 	0x40007a,0x410123,0x420128,0x43012a,0x44012c,0x450132,0x460134,0x470137,
       
   207 	0x480139,0x49013d,0x4a0140,0x4b0142,0x4c0145,0x4d0149,0x4e014b,0x4f0150,
       
   208 	0x500155,0x510157,0x52015a,0x53015c,0x54015f,0x550163,0x560165,0x570167,
       
   209 	0x580169,0x59016b,0x5a016d,0x5b0072,0x5c007e,0x5d0073,0x5e0047,0x5f0043,
       
   210 	0x600045,0x610122,0x620127,0x630129,0x64012b,0x650131,0x660133,0x670136,
       
   211 	0x680138,0x69013c,0x6a013f,0x6b0141,0x6c0143,0x6d0148,0x6e014a,0x6f014f,
       
   212 	0x700154,0x710156,0x720159,0x73015b,0x74015e,0x750162,0x760164,0x770166,
       
   213 	0x780168,0x79016a,0x7a016c,0x7b0074,0x7c009e,0x7d0075,0x7e00a0,0xa00042,
       
   214 	0xa1005e,0xa2010c,0xa3010e,0xa4010b,0xa5010f,0xa6009f,0xa70076,0xa80049,
       
   215 	0xa90078,0xaa0124,0xab006e,0xac009d,0xad0052,0xae0079,0xaf004f,0xb0008a,
       
   216 	0xb10097,0xb20119,0xb3011b,0xb40044,0xb50187,0xb60077,0xb70062,0xb8004d,
       
   217 	0xb90117,0xba0151,0xbb006f,0xbc000a,0xbd0007,0xbe0010,0xbf0060,0xc60126,
       
   218 	0xd00130,0xd70099,0xd80153,0xde016f,0xdf0031,0xe60125,0xf0012f,0xf70098,
       
   219 	0xf80152,0xfe016e,0x110012e,0x111012d,0x126013b,0x127013a,0x131013e,0x1320025,
       
   220 	0x1330023,0x1380158,0x13f0029,0x1400027,0x1410147,0x1420146,0x1490035,0x14a014e,
       
   221 	0x14b014d,0x152002f,0x153002d,0x1660161,0x1670160,0x17f015d,0x1920135,0x2c60087,
       
   222 	0x2c70088,0x2c90089,0x2d80046,0x2d9004c,0x2da0048,0x2db004e,0x2dd004b,0x30000fe,
       
   223 	0x30100fd,0x3020100,0x3030105,0x3040109,0x30600ff,0x3070106,0x3080103,0x30a0102,
       
   224 	0x30b0104,0x30c0101,0x30d010a,0x3270107,0x3280108,0x3840044,0x385004a,0x3870062,
       
   225 	0x3910171,0x3920173,0x3930175,0x3940177,0x3950179,0x396017b,0x397017d,0x398017f,
       
   226 	0x3990181,0x39a0183,0x39b0185,0x39c0188,0x39d018a,0x39e018c,0x39f018e,0x3a00190,
       
   227 	0x3a10192,0x3a30194,0x3a40196,0x3a50198,0x3a6019a,0x3a7019c,0x3a8019e,0x3a901a0,
       
   228 	0x3b10170,0x3b20172,0x3b30174,0x3b40176,0x3b50178,0x3b6017a,0x3b7017c,0x3b8017e,
       
   229 	0x3b90180,0x3ba0182,0x3bb0184,0x3bc0186,0x3bd0189,0x3be018b,0x3bf018d,0x3c0018f,
       
   230 	0x3c10191,0x3c20193,0x3c30193,0x3c40195,0x3c50197,0x3c60199,0x3c7019b,0x3c8019d,
       
   231 	0x3c9019f,0x40201ae,0x40401b2,0x40501b8,0x40601bc,0x40801be,0x40901c4,0x40a01ca,
       
   232 	0x40b01d6,0x40f01e2,0x41001a2,0x41101a4,0x41201a6,0x41301a8,0x41401ac,0x41501b0,
       
   233 	0x41601b4,0x41701b6,0x41801ba,0x41a01c0,0x41b01c2,0x41c01c6,0x41d01c8,0x41e01cc,
       
   234 	0x41f01ce,0x42001d0,0x42101d2,0x42201d4,0x42301d8,0x42401da,0x42501dc,0x42601de,
       
   235 	0x42701e0,0x42801e4,0x42901e6,0x42a01e8,0x42b01ea,0x42c01ec,0x42d01ee,0x42e01f0,
       
   236 	0x42f01f2,0x43001a1,0x43101a3,0x43201a5,0x43301a7,0x43401ab,0x43501af,0x43601b3,
       
   237 	0x43701b5,0x43801b9,0x43a01bf,0x43b01c1,0x43c01c5,0x43d01c7,0x43e01cb,0x43f01cd,
       
   238 	0x44001cf,0x44101d1,0x44201d3,0x44301d7,0x44401d9,0x44501db,0x44601dd,0x44701df,
       
   239 	0x44801e3,0x44901e5,0x44a01e7,0x44b01e9,0x44c01eb,0x44d01ed,0x44e01ef,0x44f01f1,
       
   240 	0x45201ad,0x45401b1,0x45501b7,0x45601bb,0x45801bd,0x45901c3,0x45a01c9,0x45b01d5,
       
   241 	0x45f01e1,0x49001aa,0x49101a9,0x20000041,0x20010041,0x20020041,0x20030041,0x20040041,
       
   242 	0x20050041,0x20060041,0x20070042,0x20080041,0x20090041,0x200a0041,0x200b003f,0x200c0037,
       
   243 	0x200d0037,0x200e0037,0x200f0037,0x20100054,0x20110055,0x20120056,0x20130057,0x20140058,
       
   244 	0x20150059,0x20170051,0x20180064,0x20190065,0x201a0066,0x201b0067,0x201c006b,0x201d006c,
       
   245 	0x201e006d,0x20200083,0x20210084,0x20220085,0x20260002,0x2028003d,0x2029003e,0x202a0037,
       
   246 	0x202b0037,0x202c0037,0x202d0037,0x202e0037,0x20300082,0x20320086,0x20330005,0x20390068,
       
   247 	0x203a0069,0x203c0000,0x203e0050,0x2044007d,0x207f014c,0x20a30110,0x20a40111,0x20a70112,
       
   248 	0x20ac0113,0x2105001c,0x21130144,0x2116002b,0x21220033,0x212601a0,0x212e0114,0x215b000d,
       
   249 	0x215c0013,0x215d0016,0x215e0019,0x2190008b,0x2191008d,0x2192008c,0x2193008e,0x2194008f,
       
   250 	0x21950090,0x21a80091,0x22020092,0x22060093,0x220f0094,0x22110095,0x221200a1,0x221500a2,
       
   251 	0x221900a3,0x221a00a4,0x221e00a5,0x221f00a6,0x222900a7,0x222b00a8,0x224800a9,0x226100aa,
       
   252 	0x226400ab,0x226500ac,0x230200ad,0x231000ae,0x232000af,0x232100b0,0x250000b1,0x250200b2,
       
   253 	0x250c00b3,0x251000b4,0x251400b5,0x251800b6,0x251c00b7,0x252400b8,0x252c00b9,0x253400ba,
       
   254 	0x253c00bb,0x255000bc,0x255100bd,0x255200be,0x255300bf,0x255400c0,0x255500c1,0x255600c2,
       
   255 	0x255700c3,0x255800c4,0x255900c5,0x255a00c6,0x255b00c7,0x255c00c8,0x255d00c9,0x255e00ca,
       
   256 	0x255f00cb,0x256000cc,0x256100cd,0x256200ce,0x256300cf,0x256400d0,0x256500d1,0x256600d2,
       
   257 	0x256700d3,0x256800d4,0x256900d5,0x256a00d6,0x256b00d7,0x256c00d8,0x258000d9,0x258400da,
       
   258 	0x258800db,0x258c00dc,0x259000dd,0x259100de,0x259200df,0x259300e0,0x25a000e1,0x25a100e2,
       
   259 	0x25aa00e3,0x25ab00e4,0x25ac00e5,0x25b200e6,0x25ba00e7,0x25bc00e8,0x25c400e9,0x25ca00ea,
       
   260 	0x25cb00eb,0x25cf00ec,0x25d800ed,0x25d900ee,0x25e600ef,0x263a00f0,0x263b00f1,0x263c00f2,
       
   261 	0x264000f3,0x264200f4,0x266000f5,0x266300f6,0x266500f7,0x266600f8,0x266a00f9,0x266b00fa,
       
   262 	0xfb01001f,0xfb020021,0xfeff0037,0xfffc00fb,0xfffd00fc,
       
   263 	};
       
   264 
       
   265 static const TCollationKeyTable TheStandardTable = 
       
   266 	{ TheKey, TheIndex, 517, NULL, NULL, 0 };
       
   267 
       
   268 const TCollationKeyTable* StandardCollationMethod()
       
   269 	{
       
   270 	return &TheStandardTable;
       
   271 	};
       
   272 
       
   273 inline void Increment(TUint16 const *& aPointer,TBool aNarrow)
       
   274 	{
       
   275 	aPointer =  aNarrow ? (const TUint16*)(((const TUint8*)aPointer) + 1) : aPointer + 1;
       
   276 	}
       
   277 
       
   278 /////////////////////////////////////////////////////////////////////////////////////////////////
       
   279 // TCollationValueIterator
       
   280 /////////////////////////////////////////////////////////////////////////////////////////////////
       
   281 
       
   282 /**
       
   283 Initializes TCollationValueIterator object with a new character sequence.
       
   284 @param aSourceIt An iterator used to access the input character (non-normalized or 
       
   285                  normalized) sequence.
       
   286 @internalComponent
       
   287 */
       
   288 void TCollationValueIterator::SetSourceIt(TUTF32Iterator& aSourceIt)
       
   289 	{
       
   290     iCurrentKeyPos = 0;
       
   291 	iKey.iKeys = 0;
       
   292     iDecompStrIt.Set(aSourceIt);
       
   293 	}
       
   294 
       
   295 /**
       
   296 Gets current raw key.
       
   297 Note: the method may move the iterator one or more positions forward if there are no produced
       
   298       collation keys.
       
   299 @param aKey A reference to a TCollationKey object, initialized with the
       
   300             current collation key after the call, if there is available key.
       
   301 @return ETrue Successfull call, aKey initialized with the current collation key,
       
   302         EFalse - the iteration has come to the end.
       
   303 @internalComponent
       
   304 */
       
   305 TBool TCollationValueIterator::GetCurrentKey(TCollationKey& aKey)
       
   306 	{
       
   307     ASSERT(iCurrentKeyPos <= iKey.iKeys);
       
   308 	if(!ProduceCollationKeys())
       
   309         {
       
   310         return EFalse;
       
   311         }
       
   312 	aKey = iKey.iKey[iCurrentKeyPos];
       
   313 	return ETrue;
       
   314 	}
       
   315 
       
   316 /**
       
   317 Gets current key at the specified level.
       
   318 Note: the method may move the iterator one or more positions forward if there are no produced
       
   319       collation keys.
       
   320 @param aLevel Desired level of the collation key: 0..3
       
   321 @param aKey A reference to TUint32 where the retrieved key will be stored.
       
   322 @return ETrue Success, EFalse - end of the iteration.
       
   323 @internalComponent
       
   324 */
       
   325 TBool TCollationValueIterator::GetCurrentKey(TInt aLevel, TUint32& aKey)
       
   326 	{
       
   327 	TCollationKey rawKey;
       
   328 	if(GetCurrentKey(rawKey))
       
   329         {
       
   330 	    //Key values are ignored if their ignore bit is set and the level is less than 3: in other words, the
       
   331 	    //actual Unicode value is never ignored. This does NOT conform to the system of alternate weightings
       
   332 	    //described in Unicode Technical Report 10, and will probably have to be changed.
       
   333         aKey = (aLevel < 3 && (rawKey.iLow & TCollationKeyTable::EIgnoreFlag) && !IgnoringNone()) ? 0 : rawKey.Level(aLevel);
       
   334         return ETrue;
       
   335         }
       
   336     return EFalse;
       
   337 	}
       
   338 
       
   339 /**
       
   340 The method iterates through the controlled character sequence and tries to find first non-zero
       
   341 corresponding collation key at the specified level.
       
   342 @param aLevel Desired level of the collation key: 0..3
       
   343 @return Non-zero collation key value or 0 if the iteration has come to the end.
       
   344 @internalComponent
       
   345 */
       
   346 TUint32 TCollationValueIterator::GetNextNonZeroKey(TInt aLevel)
       
   347 	{
       
   348     TUint32 key = 0;
       
   349 	while(GetCurrentKey(aLevel, key) && key == 0)
       
   350 		{
       
   351 		Increment();
       
   352 		}
       
   353 	return key;
       
   354 	}
       
   355 
       
   356 /**
       
   357 The method determines wheter the specified as a parameter character matches current iterator's
       
   358 character.
       
   359 If there is a match, the iterator will be moved one position forward.
       
   360 Note: the method may move the iterator one or more positions forward if there are no produced
       
   361       collation keys.
       
   362 @param aMatch The character to compare with the current iterator's character.
       
   363 @return ETrue The characters match, EFalse otherwise (or the iteration has come to the end).
       
   364 @internalComponent
       
   365 */
       
   366 TBool TCollationValueIterator::MatchChar(TChar aMatch)
       
   367 	{
       
   368     TUint32 key;
       
   369     if(GetCurrentKey(3, key))
       
   370         {
       
   371 	    // Find a match for the quaternary key.. will probably be the unicode value
       
   372 	    // This is a bit poor.
       
   373 	    if(aMatch == key)
       
   374 		    {
       
   375 		    Increment();
       
   376 		    return ETrue;
       
   377 		    }
       
   378         }
       
   379 	return EFalse;
       
   380 	}
       
   381 
       
   382 /**
       
   383 Note: the method may move the iterator one or more positions forward if there are no produced
       
   384       collation keys.
       
   385 @return The method returns ETrue if the iterator is at a combining character, EFalse otherwise
       
   386         (or the iterator has come to the end)
       
   387 @internalComponent
       
   388 */
       
   389 TBool TCollationValueIterator::AtCombiningCharacter()
       
   390 	{
       
   391 	TCollationKey rawKey;
       
   392 	if(!GetCurrentKey(rawKey))
       
   393         {
       
   394 		return EFalse;		// iteration ended
       
   395         }
       
   396 	return rawKey.IsStarter() ? (TBool)EFalse : (TBool)ETrue;
       
   397 	}
       
   398 
       
   399 /**
       
   400 Skips the following combining characters if they are.
       
   401 Note: the method may move the iterator one or more positions forward.
       
   402 @return The number of skipped combining characters.
       
   403 @internalComponent
       
   404 */
       
   405 TInt TCollationValueIterator::SkipCombiningCharacters()
       
   406 	{
       
   407 	TInt count;
       
   408 	for(count=0;AtCombiningCharacter();++count)
       
   409         {
       
   410 		Increment();
       
   411         }
       
   412 	return count;
       
   413 	}
       
   414 
       
   415 /**
       
   416 Moves the iterator one step forward making the next collation key available for getting
       
   417 using GetCurrentKey().
       
   418 @return ETrue Successfull call, there is a collation key available.
       
   419         EFalse - the iteration has come to the end.
       
   420 @internalComponent
       
   421 @see TCollationValueIterator::GetCurrentKey()
       
   422 */
       
   423 TBool TCollationValueIterator::Increment()
       
   424 	{
       
   425 	ASSERT(iCurrentKeyPos <= iKey.iKeys);
       
   426 	if(!ProduceCollationKeys())
       
   427         {
       
   428         return EFalse;
       
   429         }
       
   430 	++iCurrentKeyPos;
       
   431 	return ETrue;
       
   432 	}
       
   433 
       
   434 /**
       
   435 Returns the position in the underlying string of the iteration,
       
   436 if this is well defined. It is not well defined if either we are
       
   437 half way through keys defined as a string in the collation table
       
   438 or if we are half way through a canonically reordered sequence.
       
   439 @return The position in the underlying string if this is well
       
   440 	defined, or 0 if it is not.
       
   441 */
       
   442 const TText16* TCollationValueIterator::CurrentPositionIfAtCharacter()
       
   443 	{
       
   444 	if (!ProduceCollationKeys())
       
   445 		return iCurrentPosition;
       
   446 	return iCurrentKeyPos == 0? iCurrentPosition : 0;
       
   447 	}
       
   448 
       
   449 /**
       
   450 Produces the longest possible collation keys sequence using the decomposed character sequence,
       
   451 pointed by iDecompStrIt iterator. But this will happen only if all keys from iKey array are 
       
   452 consumed.
       
   453 @return ETrue Successfull call, iKey initialized with the produced collation keys sequence,
       
   454         EFalse - the iteration has come to the end.
       
   455 @internalComponent
       
   456 */
       
   457 TBool TCollationValueIterator::ProduceCollationKeys()
       
   458 	{
       
   459     //iKey.iKeys represents the keys count in iKey array, so load more keys, only if all 
       
   460     //collation keys are already consumed.
       
   461     if(iCurrentKeyPos == iKey.iKeys)
       
   462         {
       
   463 		iCurrentPosition = iDecompStrIt.CurrentPositionIfAtCharacter();
       
   464 		if(iDecompStrIt.AtEnd())
       
   465             {//No more characters in the input decomposed canonical string
       
   466 			return EFalse;
       
   467             }
       
   468         //Try to get the next collation key sequence. There should be at least one key.
       
   469 		GetNextRawKeySequence();
       
   470 	    ASSERT(iKey.iKeys > 0);
       
   471         iCurrentKeyPos = 0;
       
   472         }
       
   473 	return ETrue;
       
   474 	}
       
   475 
       
   476 /**
       
   477 Consume zero or more characters from the input and convert them into zero or more collation keys.
       
   478 @internalComponent
       
   479 */
       
   480 void TCollationValueIterator::GetNextRawKeySequence()
       
   481 	{
       
   482     //Store the first character combining class type for later use.
       
   483     TChar firstChar = iDecompStrIt.Get(0);
       
   484     TBool combining = !::IsBaseCharacter(firstChar);
       
   485 	// Initialise.
       
   486 	iKey.iCharactersConsumed = 0;
       
   487 	iKey.iKeys = 0;
       
   488 	// See if the override table has a key for the current collation unit.
       
   489 	if(iMethod.iOverrideTable)
       
   490         {
       
   491 		GetKeyFromTable(iMethod.iOverrideTable);
       
   492         }
       
   493 	// If not, try the main table.
       
   494 	if(iKey.iCharactersConsumed == 0)
       
   495         {
       
   496 		GetKeyFromTable(iMethod.iMainTable);
       
   497         }
       
   498 	//If no key was found use a default value depending on the current character.
       
   499 	//For CJK characters:
       
   500 	//the Unicode value itself as the primary key and 1 as the secondary and tertiary keys;
       
   501 	//the lower 16 bits end up as 0x0105 because the bottom two bits are used for the ignorable bit,
       
   502 	//which is clear, and the stop bit, which is set.
       
   503 	//For other characters:
       
   504 	//Return two keys containing the 21 bits of the character code (anything from 0 to 0x10FFFF), as
       
   505 	//explained in Unicode Technical Report 10.
       
   506 	if(iKey.iCharactersConsumed == 0)
       
   507 		{
       
   508 		iKey.iCharactersConsumed = 1;
       
   509 		iDecompStrIt.Next(1);
       
   510         iKey.iKeys = ::CreateDefaultCollationKeySequence(firstChar, iKey.iKey);
       
   511 		}
       
   512 	if(!combining)
       
   513         {
       
   514 		iKey.iKey[0].iHigh |= (TUint32)TCollationKey::KFlagIsStarter;
       
   515         }
       
   516 	}
       
   517 
       
   518 /**
       
   519 Search for the string aText.
       
   520 Put the key index in aIndex if found, otherwise set aIndex to -1.
       
   521 If the sought string might be a prefix to a key in the table set aPossiblePrefix to TRUE.
       
   522 @internalComponent
       
   523 */
       
   524 static void GetStringKey(const TCollationKeyTable* aTable,const TText* aText,TInt aLength,
       
   525 						 TInt& aIndex,TBool& aPossiblePrefix)
       
   526 	{
       
   527 	aIndex = -1;
       
   528 	aPossiblePrefix = EFalse;
       
   529 	TInt n =	aTable->iStringIndices;
       
   530 	const TUint32* base = aTable->iStringIndex;
       
   531 	const TUint32* p = base;
       
   532 	TInt pivot;
       
   533 	while (n > 0)
       
   534 		{
       
   535 		pivot = n / 2;
       
   536 		p += pivot;
       
   537 		TUint16 string_index = (TUint16)(*p >> 16);
       
   538 		const TText* cur_text = aTable->iString + string_index + 1;
       
   539 		TInt cur_length = aTable->iString[string_index];
       
   540 		TInt order = TUnicode::Compare(aText,aLength,cur_text,cur_length);
       
   541 		if (order == 0) // found it
       
   542 			{
       
   543 			aIndex = *p & 0xFFFF;
       
   544 			aPossiblePrefix = ETrue;
       
   545 			break;
       
   546 			}
       
   547 		if (order < 1 && !aPossiblePrefix)
       
   548 			{
       
   549 			if (aLength < cur_length && TUnicode::Compare(aText,aLength,cur_text,aLength) == 0)
       
   550 				aPossiblePrefix = ETrue;
       
   551 			n = pivot;
       
   552 			}
       
   553 		else
       
   554 			{
       
   555 			base = p + 1;
       
   556 			n -= pivot + 1;
       
   557 			}
       
   558 		p = base;
       
   559 		}
       
   560 	}
       
   561 
       
   562 /**
       
   563 Consumes output from iDecompStrIt, produces list of keys in iKey.
       
   564 @param aTable A const pointer to the collation key table used by the method.
       
   565 @internalComponent
       
   566 */
       
   567 void TCollationValueIterator::GetKeyFromTable(const TCollationKeyTable* aTable)
       
   568 	{
       
   569     ASSERT(aTable != NULL);
       
   570 	iKey.iCharactersConsumed = 0;
       
   571 	iKey.iKeys = 0;
       
   572 
       
   573 	TInt cur_char = iDecompStrIt.Get(0);
       
   574     if (0xFFFF < cur_char)
       
   575         // Supplementary character: we can't handle these yet.
       
   576         return;
       
   577 
       
   578 	// Find the longest matching string.
       
   579 	TInt index = -1;
       
   580 	if(aTable->iStringIndices > 0)
       
   581 		{
       
   582 		TInt moved = 0;
       
   583 		TText text[KKeyedStringBufferSize];
       
   584 		text[0] = static_cast <TText> (cur_char);
       
   585 		TBool possible_prefix = ETrue;
       
   586 		for(TInt i = 1; (i < KKeyedStringBufferSize) && possible_prefix; i++)
       
   587 			{
       
   588 			++moved;
       
   589 			TInt c = iDecompStrIt.Get(i);//get the next character
       
   590 			if(c == -1)
       
   591                 {
       
   592 				break;
       
   593                 }
       
   594 			text[i] = static_cast <TText> (c);
       
   595 			TInt cur_index = -1;
       
   596             ::GetStringKey(aTable, text, i + 1, cur_index, possible_prefix);
       
   597 			if(cur_index != -1)
       
   598 				{
       
   599 				index = cur_index;
       
   600 				iKey.iCharactersConsumed = i + 1;
       
   601 				}
       
   602 			}
       
   603 		if (iKey.iCharactersConsumed < moved)
       
   604 			{
       
   605 			moved = 0;
       
   606 			}
       
   607 		while (moved != iKey.iCharactersConsumed)
       
   608 			{
       
   609 			++moved;
       
   610 			}
       
   611         if(moved > 0)
       
   612             {
       
   613 		    iDecompStrIt.Next(moved);//adjust the iterator start position
       
   614             }
       
   615 		}
       
   616 
       
   617 	// Now search the main index.
       
   618 	if(index == -1)
       
   619 		{
       
   620         index = ::FindCollationKeyIndex(cur_char, *aTable);
       
   621 		if(0 <= index)
       
   622 			{
       
   623 			iKey.iCharactersConsumed = 1;
       
   624 		    iDecompStrIt.Next(1);//adjust the iterator start position
       
   625 			}
       
   626 		}
       
   627 
       
   628 	// Fill in the key or keys.
       
   629 	if(index != -1)
       
   630 		{
       
   631 		const TUint32* p = &aTable->iKey[index];
       
   632 		TCollationKey* q = iKey.iKey;
       
   633 		iKey.iKeys = 0;
       
   634 		while(iKey.iKeys < TKeyInfo::EMaxKeys)
       
   635 			{
       
   636 			q->iLow = *p;
       
   637 			q->iHigh = cur_char;
       
   638 			iKey.iKeys++;
       
   639 			if(*p & 1)
       
   640                 {
       
   641 				break;
       
   642                 }
       
   643 			q++;
       
   644 			p++;
       
   645 			}
       
   646 		}
       
   647 	}
       
   648 
       
   649 /////////////////////////////////////////////////////////////////////////////////////////////////
       
   650 // TCollate
       
   651 /////////////////////////////////////////////////////////////////////////////////////////////////
       
   652 
       
   653 /**
       
   654 Construct a TCollate object based on the collation method specified
       
   655 within aCharSet, if any. If there is none, or aCharSet is null, the
       
   656 standard collation method will be used. 
       
   657 aMask and aFlags provide a method for overriding the flags in the collation method: 
       
   658 Each flag set to 1 in aMask is a flag that will be overridden and set to the
       
   659 corresponding flag value in aFlags.
       
   660 Ownership of aCharSet is not passed.
       
   661 @param aCharSet Locale-specific character attribute and collation data
       
   662 @param aMask Provides a method for overriding the flags in the collation method
       
   663 @param aFlags Provides a method for overriding the flags in the collation method
       
   664 @internalComponent
       
   665 */
       
   666 TCollate::TCollate(const LCharSet* aCharSet, TUint aMask, TUint aFlags)
       
   667 	{
       
   668 	iMethod.iMainTable = NULL;
       
   669 	iMethod.iOverrideTable = NULL;
       
   670 	iMethod.iFlags = 0;
       
   671 	if (aCharSet && aCharSet->iCollationDataSet && aCharSet->iCollationDataSet->iMethod)
       
   672         {
       
   673 		iMethod = aCharSet->iCollationDataSet->iMethod[0];
       
   674         }
       
   675 	if (iMethod.iMainTable == NULL)
       
   676         {
       
   677 		iMethod.iMainTable = &TheStandardTable;
       
   678         }
       
   679 	if (aMask)
       
   680 		{
       
   681 		iMethod.iFlags &= ~aMask;
       
   682 		iMethod.iFlags |= (aMask & aFlags);
       
   683 		}
       
   684 	}
       
   685 
       
   686 /**
       
   687 Construct a TCollate object based on an already constructed
       
   688 TCollationMethod specified in aMethod. 
       
   689 Ownership is not passed.
       
   690 @param aMethod Collation keys table
       
   691 @internalComponent
       
   692 */
       
   693 TCollate::TCollate(const TCollationMethod& aMethod) :
       
   694 	iMethod(aMethod)
       
   695 	{
       
   696 	if(!iMethod.iMainTable)
       
   697         {
       
   698 		iMethod.iMainTable = &TheStandardTable;
       
   699         }
       
   700 	}
       
   701 
       
   702 /**
       
   703 Compare the string beginning at aString1 of length aLength1 against the
       
   704 string beginning at aString2 of length aLength2. 
       
   705 
       
   706 @param aString1 First string to compare
       
   707 @param aLength1 Length of aString1
       
   708 @param aString2 Second string to compare
       
   709 @param aLength2 Length of aString2
       
   710 @param aMaxLevel Determines the tightness of the collation. At level 0, only
       
   711                  character identities are distinguished. At level 1 accents are
       
   712                  distinguished as well. At level 2 case is distinguished as well. At
       
   713                  level 3 all non canonically equivalent Unicode characters are considered 
       
   714                  different. By default aMaxLevel is 3.
       
   715 @return EStringsIdentical The strings are identical.
       
   716         ELeftComparesLessAndIsNotPrefix For example: aString1 = "aaa", aString2 = "zzzz".
       
   717         ELeftIsPrefixOfRight For example: aString1 = "abc", aString2 = "abcd".
       
   718         ERightIsPrefixOfLeft For example: aString1 = "abcd", aString2 = "abc".
       
   719         ERightComparesLessAndIsNotPrefix For example: aString1 = "zzzz", aString2 = "aaa".
       
   720 @internalComponent
       
   721 */
       
   722 TCollate::TComparisonResult TCollate::Compare(const TUint16 *aString1, TInt aLength1,
       
   723                                               const TUint16 *aString2, TInt aLength2,
       
   724                                               TInt aMaxLevel) const
       
   725 	{
       
   726     TUTF32Iterator itL(aString1, aString1 + aLength1);
       
   727     TUTF32Iterator itR(aString2, aString2 + aLength2);
       
   728 	return CompareKeySequences(itL, itR, aMaxLevel, 0, 0);
       
   729 	}
       
   730 
       
   731 /**
       
   732 Find the string beginning at aString2 of length aLength2 in the string
       
   733 beginning at aString1 of length aLength1.
       
   734 
       
   735 @param aString1 String to search
       
   736 @param aLength1 Length of aString1
       
   737 @param aString2 String to search for
       
   738 @param aLength2 Length of aString2
       
   739 @param aMaxLevel Determines the tightness of the collation. At level 0, only
       
   740                  character identities are distinguished. At level 1 accents are
       
   741                  distinguished as well. At level 2 case is distinguishes as well. At
       
   742                  level 3 all valid different Unicode characters are considered different.
       
   743 @param aString2WildChar Wild card character which may be specified for aString2. By default
       
   744                  wild card character is not specified and not used.
       
   745 @return KErrNotFound aString2 not found in aString1. 
       
   746         Non-negative value telling the position in aString1 where the first occurrence of 
       
   747         aString2 was found.
       
   748 @internalComponent
       
   749 */
       
   750 TInt TCollate::Find(const TUint16 *aString1, TInt aLength1,
       
   751                     const TUint16 *aString2, TInt aLength2,
       
   752                     TInt aMaxLevel, TUint aString2WildChar) const
       
   753 	{
       
   754 	TInt dummy(0);
       
   755 	return Find(aString1, aLength1, aString2,aLength2, dummy, aMaxLevel,aString2WildChar );
       
   756 	}
       
   757 
       
   758 /**
       
   759 Find the string beginning at aString2 of length aLength2 in the string
       
   760 beginning at aString1 of length aLength1.
       
   761 
       
   762 @param aString1 String to search
       
   763 @param aLength1 Length of aString1
       
   764 @param aString2 String to search for
       
   765 @param aLength2 Length of aString2
       
   766 @param aLengthFound A refernce to the length of the match found in the candidate string
       
   767 @param aMaxLevel Determines the tightness of the collation. At level 0, only
       
   768                  character identities are distinguished. At level 1 accents are
       
   769                  distinguished as well. At level 2 case is distinguishes as well. At
       
   770                  level 3 all valid different Unicode characters are considered different.
       
   771 @param aString2WildChar Wild card character which may be specified for aString2. By default
       
   772                  wild card character is not specified and not used.
       
   773 @return KErrNotFound aString2 not found in aString1. 
       
   774         Non-negative value telling the position in aString1 where the first occurrence of 
       
   775         aString2 was found.
       
   776 @internalComponent
       
   777 */
       
   778 TInt TCollate::Find(const TUint16 *aString1, TInt aLength1,
       
   779                     const TUint16 *aString2, TInt aLength2,
       
   780                     TInt &aLengthFound, TInt aMaxLevel, TUint aString2WildChar) const
       
   781 	{
       
   782     TUTF32Iterator itL(aString1, aString1 + aLength1);
       
   783     TUTF32Iterator itR(aString2, aString2 + aLength2);
       
   784 	return FindKeySequence(itL, itR, aMaxLevel, aString2WildChar, 0, aLengthFound);
       
   785 	}
       
   786 	
       
   787 /**
       
   788 Match the pattern defined by aSearchTerm with aCandidate. 
       
   789 Return the index in aCandidate of the start of the first pattern matched - 
       
   790 that is, the first character in aSearchTerm after all wild-sequence characters
       
   791 have been matched. Return KErrNotFound if there is no match.
       
   792 
       
   793 For example, if aCandidate is "abcdefghijkl", the following values of aSearchTerm yield the 
       
   794 following results:
       
   795 "abc*" gives 0
       
   796 "abc" gives KErrNotFound
       
   797 "xyz" gives KErrNotFound
       
   798 "*def" gives KErrNotFound
       
   799 "*def*" gives 3
       
   800 "*d?f*" gives 3
       
   801 "a*kl" gives 0
       
   802 "*d*kl" gives 4
       
   803 
       
   804 To match a pattern anywhere in aCandidate, aSearchTerm must both start and end 
       
   805 with aString2WildSequenceChar
       
   806 
       
   807 @param aCandidate String to search
       
   808 @param aCandidateLength Length of aCandidate
       
   809 @param aSearchTerm String to search for
       
   810 @param aSearchTermLength Length of aSearchTerm
       
   811 @param aMaxLevel Determines the tightness of the collation. At level 0, only
       
   812                  character identities are distinguished. At level 1 accents are
       
   813                  distinguished as well. At level 2 case is distinguishes as well. At
       
   814                  level 3 all valid different Unicode characters are considered different.
       
   815 @param aWildChar Wild card character which may be specified for aSearchTerm. By default
       
   816                  the wild card character used is '?'.
       
   817 @param aWildSequenceChar Wild card sequence character which may be specified for aSearchTerm.
       
   818                  Its default value is '*'.
       
   819 @param aEscapeChar Escape character. If it is non-zero and precdes aWildChar and aWildSequenceChar characters in
       
   820                  aCandidate string, then these characters should be treated as normal characters.
       
   821 @return The index in aCandidate of the start of the first pattern matched.
       
   822 
       
   823 @internalComponent.
       
   824 */
       
   825 TInt TCollate::Match(const TUint16 *aCandidate, TInt aCandidateLength,
       
   826                      const TUint16 *aSearchTerm,TInt aSearchTermLength, 
       
   827                      TInt aMaxLevel, TUint aWildChar, TUint aWildSequenceChar,
       
   828                      TUint aEscapeChar) const
       
   829 	{
       
   830 	ASSERT(0 <= aSearchTermLength);
       
   831 	ASSERT(0 <= aCandidateLength);
       
   832 
       
   833 	if(aMaxLevel == 3 && (iMethod.iFlags & TCollationMethod::EFoldCase))
       
   834         {
       
   835 		aMaxLevel = 2;
       
   836         }
       
   837 
       
   838     TUTF32Iterator candidate(aCandidate, aCandidate + aCandidateLength);
       
   839     TUTF32Iterator searchTerm(aSearchTerm, aSearchTerm + aSearchTermLength);
       
   840 
       
   841 	TInt firstMatch = KErrNotFound;
       
   842     TInt segEnd = ::FindCharacter(aWildSequenceChar, aEscapeChar, aSearchTerm, aSearchTermLength);
       
   843 
       
   844 	// Is there any prefix that the candidate string must have?
       
   845     // aSearchTerm looks like "abc*...". Then segEnd will be 3 (the position of '*').
       
   846     // Check that aCandidate begins with "abc" too.
       
   847 	if(segEnd != 0 || aSearchTermLength == 0)
       
   848 		{
       
   849 		searchTerm = TUTF32Iterator(aSearchTerm, aSearchTerm + segEnd);
       
   850 		TComparisonResult order = CompareKeySequences(candidate, searchTerm, aMaxLevel, aWildChar, aEscapeChar);
       
   851 		if(order != ERightIsPrefixOfLeft && order != EStringsIdentical)
       
   852             {
       
   853 			return KErrNotFound;
       
   854             }
       
   855 		if(aSearchTermLength == segEnd)
       
   856             {
       
   857 			return order == EStringsIdentical ? 0 : KErrNotFound;
       
   858             }
       
   859 		firstMatch = 0;
       
   860 		}
       
   861 
       
   862 	// search for all remaining segments
       
   863     // For example: aSearchTerm = "abc*def*ghi", aCandidate = "abc...".
       
   864     // aCandidate was already searched for "abc" and segEnd = 3. 
       
   865     // Search aCandidate for the remaining segments: "def" and "ghi".
       
   866 	while(aSearchTermLength != (segEnd + 1))
       
   867 		{
       
   868 		++segEnd;
       
   869 		aSearchTermLength -= segEnd;
       
   870 		aSearchTerm += segEnd;
       
   871         segEnd = ::FindCharacter(aWildSequenceChar, aEscapeChar, aSearchTerm, aSearchTermLength);
       
   872 		searchTerm = TUTF32Iterator(aSearchTerm, aSearchTerm + segEnd);//searchTerm holds the next aSearchTerm segment
       
   873         //We will store here the current position of candidate string.
       
   874         const TUint16* candidateCurrentPos = candidate.CurrentPosition();		
       
   875         TInt dummy(0);
       
   876         TInt match = FindKeySequence(candidate, searchTerm, aMaxLevel, aWildChar, aEscapeChar, dummy);	
       
   877 		if (match < 0)
       
   878             {
       
   879 			return KErrNotFound;
       
   880             }
       
   881 		if (aSearchTermLength == segEnd)
       
   882 			{
       
   883 			candidate.SetStart(candidateCurrentPos + match);
       
   884    			TComparisonResult order = CompareKeySequences(candidate, searchTerm, aMaxLevel, aWildChar, aEscapeChar);
       
   885 			if (order == EStringsIdentical)
       
   886 				return firstMatch < 0 ? (match + candidateCurrentPos - aCandidate): firstMatch;
       
   887 			while (match >= 0)
       
   888 				{
       
   889 				// We are at the very end of the search term, so this segment must
       
   890 				// match the end of the candidate string.
       
   891 				candidate.SetStart(candidateCurrentPos + match + 1);
       
   892 	            candidateCurrentPos = candidate.CurrentPosition();
       
   893 				match = FindKeySequence(candidate, searchTerm, aMaxLevel, aWildChar, aEscapeChar, dummy);
       
   894 				candidate.SetStart(candidateCurrentPos + match);
       
   895 				order = CompareKeySequences(candidate, searchTerm, aMaxLevel, aWildChar, aEscapeChar);
       
   896 				if (order == EStringsIdentical)
       
   897 					return firstMatch < 0 ? (match + candidateCurrentPos - aCandidate): firstMatch;
       
   898 				}
       
   899 			return KErrNotFound;
       
   900 			}
       
   901         //Initialize the first match position, if not initialized yet
       
   902 		if (firstMatch < 0 && segEnd != 0)
       
   903             {
       
   904 			firstMatch = match;
       
   905             }
       
   906 		}
       
   907 	return firstMatch < 0 ? aCandidateLength : firstMatch;
       
   908 	}
       
   909 
       
   910 /**
       
   911 Compare values output from the iterators. After the comparison, if
       
   912 ERightIsPrefixOfLeft or EStringsIdentical is returned, then aLeft
       
   913 will be pointing at the next character (at MaxLevel) after the match.
       
   914 If right is shown to be a prefix of left, this means that it has been
       
   915 checked at all requested levels. If it is reported that the right is a
       
   916 prefix of the left, then this will mean also that there are no unmatched
       
   917 combining characters on the left.
       
   918 
       
   919 @internalComponent
       
   920 */
       
   921 TCollate::TComparisonResult TCollate::CompareKeySequences(TUTF32Iterator& aLeft, TUTF32Iterator& aRight,
       
   922                                                           TInt aMaxLevel, TInt aRightStringWildChar, TInt aEscapeChar) const
       
   923 	{
       
   924 	// Clamp the maximum level of the comparison.
       
   925 	if(aMaxLevel < 0)
       
   926         {
       
   927 		aMaxLevel = 0;
       
   928         }
       
   929 	if(aMaxLevel > 3)
       
   930         {
       
   931 		aMaxLevel = 3;
       
   932         }
       
   933 	//Case folding forces the maximum level to 2. Case folding could only be done at level 3, which
       
   934 	//makes use of the actual Unicode values, if we had access to a case conversion table appropriate for
       
   935 	//the collation method.
       
   936 	if(aMaxLevel == 3 && (iMethod.iFlags & TCollationMethod::EFoldCase))
       
   937         {
       
   938 		aMaxLevel = 2;
       
   939         }
       
   940     TCollationValueIterator itL(iMethod);
       
   941     TCollationValueIterator itR(iMethod);
       
   942 	// Perform the comparison.
       
   943 	TComparisonResult order = EStringsIdentical;
       
   944 	TComparisonResult accumulatedOrder = EStringsIdentical;
       
   945 	const TText16* endOfLeft = 0;
       
   946 	for (int cur_level = 0; cur_level <= aMaxLevel; cur_level++)
       
   947 		{
       
   948 	    itL.SetSourceIt(aLeft);
       
   949 	    itR.SetSourceIt(aRight);
       
   950 
       
   951 		for (;;)
       
   952 			{
       
   953 			TUint32 c2 = itR.GetNextNonZeroKey(cur_level);
       
   954 			if (c2 == 0)
       
   955 				{
       
   956 				TUint32 more = itL.GetNextNonZeroKey(cur_level);
       
   957 				if (cur_level == 0)
       
   958 					endOfLeft = itL.CurrentPositionIfAtCharacter();
       
   959    				if (more == 0)
       
   960                    {//No non-zero keys at all
       
   961 					order = EStringsIdentical;
       
   962 					}
       
   963 				else if (!(TCollationMethod::EIgnoreCombining & iMethod.iFlags)
       
   964 					&& itL.AtCombiningCharacter())
       
   965 					{
       
   966 					order = ERightComparesLessAndIsNotPrefix;
       
   967 					}
       
   968 				else
       
   969 					{
       
   970 					order = ERightIsPrefixOfLeft;
       
   971 					}
       
   972 				break;
       
   973 				}
       
   974 			TUint32 c1 = itL.GetNextNonZeroKey(cur_level);
       
   975 			if (c1 == 0)
       
   976 				{
       
   977 				order = ELeftIsPrefixOfRight;
       
   978 				break;
       
   979 				}
       
   980 				
       
   981 			itL.Increment();
       
   982 			if(cur_level == 0 && aEscapeChar != 0 && itR.MatchChar(aEscapeChar)) 
       
   983 				{//Escape character found. Get the next key.
       
   984 				c2 = itR.GetNextNonZeroKey(cur_level);
       
   985 				itR.Increment();
       
   986 				}
       
   987 			else
       
   988 				{
       
   989 				if(aRightStringWildChar && itR.MatchChar(aRightStringWildChar))
       
   990 					{
       
   991 					itL.SkipCombiningCharacters();
       
   992 					itR.SkipCombiningCharacters();
       
   993 					c1 = c2;
       
   994 					}
       
   995 				else
       
   996 	                {
       
   997 					itR.Increment();
       
   998 	                }
       
   999 				}
       
  1000 
       
  1001 			// Has an order been determined by key difference?
       
  1002 			if (c1 != c2)
       
  1003 				{
       
  1004 				// Fold to lower case, or switch ordering for case or kana syllabary if necessary.
       
  1005 				if (cur_level == 2 && (c1 <= (0x14 * 4) && c2 <= (0x14 * 4)))
       
  1006 					{
       
  1007 					// Divide keys by 4 to get them back into the range 0..63
       
  1008 					// because keys returned by GetKey are masked but not shifted.
       
  1009 					c1 /= 4;
       
  1010 					c2 /= 4;
       
  1011 					ProcessKeys(c1, c2, iMethod.iFlags);
       
  1012 					}
       
  1013 				if (c1 != c2) // test equality again because case folding might have made them equal
       
  1014 					{
       
  1015 					order = c1 > c2 ? ERightComparesLessAndIsNotPrefix : ELeftComparesLessAndIsNotPrefix;
       
  1016 					TBool backwards = cur_level == 1 && (iMethod.iFlags & TCollationMethod::EAccentsBackwards);
       
  1017 					if (order && !backwards)
       
  1018                         {
       
  1019 						break;
       
  1020                         }
       
  1021 					}
       
  1022 				}
       
  1023 			}
       
  1024 		if (accumulatedOrder != order && order != EStringsIdentical)
       
  1025 			{
       
  1026 			if (accumulatedOrder == ERightIsPrefixOfLeft)
       
  1027 				{
       
  1028 				return ERightComparesLessAndIsNotPrefix;
       
  1029 				}
       
  1030 			else if (accumulatedOrder == ELeftIsPrefixOfRight)
       
  1031 				{
       
  1032 				return ELeftComparesLessAndIsNotPrefix;
       
  1033 				}
       
  1034 			else
       
  1035 				{
       
  1036 				// accumulatedOrder == EStringsIdentical
       
  1037 				if (order == ELeftComparesLessAndIsNotPrefix || order == ERightComparesLessAndIsNotPrefix)
       
  1038 					{
       
  1039 					return order;
       
  1040 					}
       
  1041 				}
       
  1042 			accumulatedOrder = order;
       
  1043 			}
       
  1044 		}
       
  1045 
       
  1046 	if (accumulatedOrder == EStringsIdentical || accumulatedOrder == ERightIsPrefixOfLeft)
       
  1047 		{
       
  1048 		if (endOfLeft)
       
  1049 			{
       
  1050 			aLeft.SetStart(endOfLeft);
       
  1051 			}
       
  1052 		else if (accumulatedOrder == ERightIsPrefixOfLeft)
       
  1053 			{
       
  1054 			accumulatedOrder = ERightComparesLessAndIsNotPrefix;
       
  1055 			}
       
  1056 		}
       
  1057 	return accumulatedOrder;
       
  1058 	}
       
  1059 
       
  1060 /**
       
  1061 Finds search term inside candidate string. Returns KErrNotFound if there
       
  1062 is no match, returns the offset into the candidate string at which the
       
  1063 search term was found. If a string was found, the search term iterator is left
       
  1064 pointing at the end of the search term, and the candidate iterator is
       
  1065 left pointing just after the matched keys. aMatchPos returns where in
       
  1066 the candidate string the match was found.
       
  1067 
       
  1068 @internalComponent
       
  1069 */
       
  1070 TInt TCollate::FindKeySequence(TUTF32Iterator& aCandidate, TUTF32Iterator& aSearchTerm, 
       
  1071                                TInt aMaxLevel, TInt aWildChar, TInt aEscapeChar, TInt& aLengthFound) const
       
  1072 	{
       
  1073     TInt matchOffset = 0;
       
  1074     //Save the start of the candidate string
       
  1075     const TText* candidateStart = aCandidate.CurrentPosition();
       
  1076     //Create copies of aCandidate and aSearchTerm
       
  1077     TUTF32Iterator candidateCopy(aCandidate);
       
  1078     TUTF32Iterator searchTermCopy(aSearchTerm);
       
  1079     aLengthFound = KErrNotFound;
       
  1080     //Do the search
       
  1081 	for(;;)
       
  1082 		{
       
  1083 		TComparisonResult order = CompareKeySequences(aCandidate, aSearchTerm, aMaxLevel, aWildChar, aEscapeChar);
       
  1084 		if(order == ELeftIsPrefixOfRight)
       
  1085             {
       
  1086 			return KErrNotFound;
       
  1087             }
       
  1088 		if(order == ERightIsPrefixOfLeft || order == EStringsIdentical)
       
  1089 			{
       
  1090 			aLengthFound = (aCandidate.CurrentPosition() - candidateStart) - matchOffset;
       
  1091 			return matchOffset;
       
  1092 			}
       
  1093 
       
  1094         aCandidate = candidateCopy;
       
  1095 		aCandidate.Next();
       
  1096         ::SkipCombiningCharacters(aCandidate);
       
  1097         candidateCopy = aCandidate;
       
  1098 
       
  1099 		matchOffset = aCandidate.CurrentPosition() - candidateStart;
       
  1100 
       
  1101 		aSearchTerm = searchTermCopy;
       
  1102 		}
       
  1103 	}