|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (developer.feedback@nokia.com) |
|
6 ** |
|
7 ** This file is part of the HbCore module of the UI Extensions for Mobile. |
|
8 ** |
|
9 ** GNU Lesser General Public License Usage |
|
10 ** This file may be used under the terms of the GNU Lesser General Public |
|
11 ** License version 2.1 as published by the Free Software Foundation and |
|
12 ** appearing in the file LICENSE.LGPL included in the packaging of this file. |
|
13 ** Please review the following information to ensure the GNU Lesser General |
|
14 ** Public License version 2.1 requirements will be met: |
|
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
16 ** |
|
17 ** In addition, as a special exception, Nokia gives you certain additional |
|
18 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
20 ** |
|
21 ** If you have questions regarding the use of this file, please contact |
|
22 ** Nokia at developer.feedback@nokia.com. |
|
23 ** |
|
24 ****************************************************************************/ |
|
25 |
|
26 #include <hbextendedlocale.h> |
|
27 #include <QtAlgorithms> |
|
28 |
|
29 #include "hbstringutil_p.h" |
|
30 #include "hbstringutil.h" |
|
31 |
|
32 #if defined(__SYMBIAN32__) |
|
33 #include <e32std.h> |
|
34 #include <e32def.h> |
|
35 #include <e32des16.h> |
|
36 #include <collate.h> |
|
37 #define Q_OS_SYMBIAN |
|
38 #endif |
|
39 |
|
40 #ifndef QT_NO_REGEXP |
|
41 #include <QRegExp> |
|
42 #endif |
|
43 |
|
44 /*! |
|
45 @beta |
|
46 @hbcore |
|
47 \class HbStringUtil |
|
48 \brief The HbStringUtil class can be used to execute operations on strings, |
|
49 such as comparisons and finding data sequences. |
|
50 |
|
51 \ingroup i18n |
|
52 |
|
53 \warning This class is only useful in Symbian platforms since it uses Symbian |
|
54 methods in order to implement different functionalities. |
|
55 |
|
56 \sa HbStringUtil |
|
57 */ |
|
58 |
|
59 /*! |
|
60 \enum HbStringUtil::Option |
|
61 |
|
62 This enum describes the way collation is done for matchC, compareC |
|
63 Pass one of these values to setReadChannel() to set the |
|
64 current read channel of QProcess. |
|
65 |
|
66 \value Default Use the default System flags. |
|
67 |
|
68 \value IgnoreNone Don't ignore anything. |
|
69 |
|
70 \value SwapCase Reverse case ordering. |
|
71 |
|
72 \value AccentsBackwards Compare secondary keys which represent accents in reverse order. |
|
73 |
|
74 \value SwapKana Reverse order for katakana/hiragana. |
|
75 |
|
76 \value FoldCase Fold to lower case, file comparisons. |
|
77 |
|
78 \value MatchingTable Table used for matching. |
|
79 |
|
80 \value IgnoreCombining Ignore check for adjacent combining characters. |
|
81 |
|
82 \sa compareC, matchC |
|
83 */ |
|
84 |
|
85 /*! |
|
86 \deprecated HbStringUtil::collationMethods() |
|
87 is deprecated. |
|
88 |
|
89 Returns the number of collation methods supported. |
|
90 On Symbian platform uses Mem::CollationMethods, |
|
91 elsewhere return 0. |
|
92 |
|
93 \return The number of collation methods available. |
|
94 */ |
|
95 int HbStringUtil::collationMethods() |
|
96 { |
|
97 qWarning("HbStringUtil::collationMethods is DEPRECATED. Do not use this function."); |
|
98 #if defined( Q_OS_SYMBIAN ) |
|
99 return Mem::CollationMethods(); |
|
100 #else |
|
101 return 0; |
|
102 #endif |
|
103 } |
|
104 |
|
105 /*! |
|
106 Searches source string's collated data for a |
|
107 match with collated data supplied in pattern string |
|
108 |
|
109 \param strFrom Source string. |
|
110 \param strToMatch Pattern string. |
|
111 \param maxLevel Determines the tightness of the collation. |
|
112 Level 0 - Character identity; |
|
113 Level 1 - Character identity and accents; |
|
114 Level 2 - Character identity, accents and case; |
|
115 Level 3 - Character identity, accents, case and Unicode value; |
|
116 \param flags The flags that will be used. Default value is Default. |
|
117 \param wildChar Wild card character. |
|
118 \param wildSequenceChar Wild card sequence character. |
|
119 \param escapeChar The escape character, for example, '?', '*'. |
|
120 \return If a match is found the offset within source string's |
|
121 data where the match first occurs. -1 if match is not found. |
|
122 |
|
123 Example |
|
124 \snippet{unittest_hbstringutil/unittest_hbstringutil.cpp,3} |
|
125 */ |
|
126 int HbStringUtil::matchC( const QString &strFrom, const QString &strToMatch, |
|
127 int maxLevel, Options flags, |
|
128 int wildChar, int wildSequenceChar, int escapeChar ) |
|
129 { |
|
130 #if defined( Q_OS_SYMBIAN ) |
|
131 TPtrC s1Ptr( strFrom.utf16() ); |
|
132 TPtrC s2Ptr( strToMatch.utf16() ); |
|
133 |
|
134 if ( (maxLevel < 0) || (maxLevel > 3) ) { |
|
135 maxLevel = 0; |
|
136 } |
|
137 if ( (flags < 0) || (flags > 127) ) { |
|
138 flags = Default; |
|
139 } |
|
140 |
|
141 TCollationMethod m = *Mem::GetDefaultMatchingTable(); |
|
142 m.iFlags |= flags; |
|
143 |
|
144 return s1Ptr.MatchC(s2Ptr, wildChar, wildSequenceChar, escapeChar, maxLevel, &m); |
|
145 #else |
|
146 Q_UNUSED(maxLevel); |
|
147 Q_UNUSED(flags); |
|
148 Q_UNUSED(wildChar); |
|
149 Q_UNUSED(wildSequenceChar); |
|
150 Q_UNUSED(escapeChar); |
|
151 #ifdef QT_NO_REGEXP |
|
152 // if no regular expressions defined do standard MatchF |
|
153 return strFrom.indexOf( strToMatch, 0, Qt::CaseSensitive ); |
|
154 #else |
|
155 // works with standard wildcards is not correct |
|
156 QRegExp locStrToMatch( strToMatch, Qt::CaseSensitive, QRegExp::Wildcard ); |
|
157 return strFrom.indexOf( locStrToMatch, 0 ); |
|
158 #endif |
|
159 |
|
160 #endif |
|
161 } |
|
162 |
|
163 /*! |
|
164 Compares source string's data with the other string's |
|
165 data using the specified collation method. |
|
166 |
|
167 \param string1 Source string. |
|
168 \param string2 String whose data is to be compared with the source string. |
|
169 \param maxLevel Maximum level to use for comparing. |
|
170 Level 0 - Character identity; |
|
171 Level 1 - Character identity and accents; |
|
172 Level 2 - Character identity, accents and case; |
|
173 Level 3 - Character identity, accents, case and Unicode value; |
|
174 \param flags The flags that will be used. Default value is Default. |
|
175 \return Positive if source string is greater, negative if it is less and |
|
176 zero if the content of both strings match. |
|
177 |
|
178 Example |
|
179 \snippet{unittest_hbstringutil/unittest_hbstringutil.cpp,1} |
|
180 */ |
|
181 int HbStringUtil::compareC( const QString &string1, const QString &string2, |
|
182 int maxLevel, Options flags ) |
|
183 { |
|
184 #if defined( Q_OS_SYMBIAN ) |
|
185 TPtrC s1Ptr(string1.utf16()); |
|
186 TPtrC s2Ptr(string2.utf16()); |
|
187 |
|
188 if ( (maxLevel < 0) || (maxLevel > 3) ) { |
|
189 maxLevel = 3; |
|
190 } |
|
191 if ( (flags < 0) || (flags > 127) ) { |
|
192 flags = Default; |
|
193 } |
|
194 |
|
195 TCollationMethod m = *Mem::CollationMethodByIndex( 0 ); |
|
196 m.iFlags |= flags; |
|
197 |
|
198 return s1Ptr.CompareC( s2Ptr, maxLevel, &m); |
|
199 #else |
|
200 Q_UNUSED(maxLevel); |
|
201 Q_UNUSED(flags); |
|
202 return string1.localeAwareCompare( string2 ); |
|
203 #endif |
|
204 } |
|
205 |
|
206 /*! |
|
207 Searches for the first occurence of the specified collated |
|
208 data sequence in the aStrFrom to the specified maximum |
|
209 collation level. |
|
210 |
|
211 \param strFrom Source string. |
|
212 \param strToFind String whose data is to be compared with the source string. |
|
213 \param maxLevel The maximum collation level. |
|
214 Level 0 - Character identity; |
|
215 Level 1 - Character identity and accents; |
|
216 Level 2 - Character identity, accents and case; |
|
217 Level 3 - Character identity, accents, case and Unicode value; |
|
218 \return Offset of the data sequence from the beginning of the |
|
219 aStrFrom. -1 if the data sequence cannot be found. |
|
220 |
|
221 Example |
|
222 \snippet{unittest_hbstringutil/unittest_hbstringutil.cpp,5} |
|
223 */ |
|
224 int HbStringUtil::findC( const QString &strFrom, |
|
225 const QString &strToFind, |
|
226 int maxLevel ) |
|
227 { |
|
228 #if defined( Q_OS_SYMBIAN ) |
|
229 TPtrC s1Ptr( strFrom.utf16() ); |
|
230 TPtrC s2Ptr( strToFind.utf16() ); |
|
231 |
|
232 if ( (maxLevel < 0) || (maxLevel > 3) ) { |
|
233 maxLevel = 0; |
|
234 } |
|
235 return s1Ptr.FindC( s2Ptr.Ptr(), |
|
236 s2Ptr.Length(), |
|
237 maxLevel ); |
|
238 #else |
|
239 Q_UNUSED(maxLevel); |
|
240 return strFrom.indexOf( strToFind, 0, Qt::CaseSensitive ); |
|
241 #endif |
|
242 } |
|
243 |
|
244 /*! |
|
245 Searches source string's folded data for a |
|
246 match with folded data supplied in pattern string |
|
247 |
|
248 \param strFrom Source string. |
|
249 \param strToMatch Pattern string. |
|
250 \return If a match is found the offset within source string's |
|
251 data where the match first occurs. -1 if match is not found. |
|
252 |
|
253 Example |
|
254 \snippet{unittest_hbstringutil/unittest_hbstringutil.cpp,4} |
|
255 */ |
|
256 int HbStringUtil::matchF( const QString &strFrom, |
|
257 const QString &strToMatch ) |
|
258 { |
|
259 #if defined( Q_OS_SYMBIAN ) |
|
260 TPtrC s1Ptr( strFrom.utf16() ); |
|
261 TPtrC s2Ptr( strToMatch.utf16() ); |
|
262 return s1Ptr.MatchF( s2Ptr ); |
|
263 #else |
|
264 // folding is just case insensitive |
|
265 #ifdef QT_NO_REGEXP |
|
266 // if no regular expressions defined do standard FindF |
|
267 return strFrom.indexOf( strToMatch, 0, Qt::CaseInsensitive ); |
|
268 #else |
|
269 QRegExp locStrToMatch( strToMatch, Qt::CaseInsensitive, QRegExp::Wildcard ); |
|
270 return strFrom.indexOf( locStrToMatch, 0 ); |
|
271 #endif |
|
272 |
|
273 #endif |
|
274 } |
|
275 |
|
276 /*! |
|
277 Searches for the first occurence of the specified folded |
|
278 data sequence in the strFrom. |
|
279 |
|
280 \param strFrom Source string. |
|
281 \param strToFind String whose data is to be compared with the source string. |
|
282 \return Offset of the data sequence from the beginning of the |
|
283 strFrom. -1 if the data sequence cannot be found. Zero, |
|
284 if the length of search data sequence is zero. |
|
285 |
|
286 Example |
|
287 \snippet{unittest_hbstringutil/unittest_hbstringutil.cpp,6} |
|
288 */ |
|
289 int HbStringUtil::findF( const QString &strFrom, |
|
290 const QString &strToFind ) |
|
291 { |
|
292 #if defined( Q_OS_SYMBIAN ) |
|
293 TPtrC s1Ptr( strFrom.utf16() ); |
|
294 TPtrC s2Ptr( strToFind.utf16() ); |
|
295 return s1Ptr.FindF( s2Ptr ); |
|
296 #else |
|
297 // folding is just case insensitive |
|
298 return strFrom.indexOf( strToFind, 0, Qt::CaseInsensitive ); |
|
299 #endif |
|
300 } |
|
301 |
|
302 /*! |
|
303 Compares source string's folded data with the other string's |
|
304 folded data. |
|
305 |
|
306 \param string1 Source string. |
|
307 \param string2 String whose data is to be compared with the source string. |
|
308 \return Positive if source string is greater, negative if it is less and |
|
309 zero if the content of both strings match. |
|
310 |
|
311 Example |
|
312 \snippet{unittest_hbstringutil/unittest_hbstringutil.cpp,2} |
|
313 */ |
|
314 int HbStringUtil::compareF( const QString &string1, |
|
315 const QString &string2 ) |
|
316 { |
|
317 #if defined( Q_OS_SYMBIAN ) |
|
318 TPtrC s1Ptr( string1.utf16() ); |
|
319 TPtrC s2Ptr( string2.utf16() ); |
|
320 return s1Ptr.CompareF( s2Ptr ); |
|
321 #else |
|
322 // folding is just case insensitive |
|
323 return string1.compare( string2, Qt::CaseInsensitive ); |
|
324 #endif |
|
325 } |
|
326 |
|
327 /*! |
|
328 \deprecated HbStringUtil::collate( const uint chr ) |
|
329 is deprecated. |
|
330 |
|
331 Converts the character to its collated form. |
|
332 Collating is the process of removing differences between characters |
|
333 that are considered unimportant for the purposes of ordering characters. |
|
334 The result of the conversion depends on the locale |
|
335 |
|
336 \param chr The charcter to be collated. |
|
337 \return The converted character. |
|
338 */ |
|
339 uint HbStringUtil::collate( const uint chr ) |
|
340 { |
|
341 qWarning("HbStringUtil::collate is DEPRECATED. Do not use this function."); |
|
342 #if defined( Q_OS_SYMBIAN ) |
|
343 return User::Collate( chr ); |
|
344 #else |
|
345 return chr; |
|
346 #endif |
|
347 } |
|
348 |
|
349 /*! |
|
350 Returns the starting digit range of the native digit |
|
351 \param ch native digit |
|
352 \return starting digit range |
|
353 */ |
|
354 static QChar nativeDigitBase(QChar ch) |
|
355 { |
|
356 DigitType d[] = { WesternDigit, ArabicIndicDigit, EasternArabicIndicDigit, DevanagariDigit, ThaiDigit }; |
|
357 int i = 0; |
|
358 int num = sizeof(d)/sizeof(d[0]); |
|
359 while(i<num) { |
|
360 if (ch>QChar(d[i]) && ch<QChar(d[i]+10)) { return d[i]; } |
|
361 i++; |
|
362 } |
|
363 return ch; |
|
364 } |
|
365 |
|
366 /*! |
|
367 Converts digits to native digits based on current UI language. |
|
368 \param str digits to be converted. |
|
369 */ |
|
370 QString HbStringUtil::convertDigits( const QString str ) |
|
371 { |
|
372 HbExtendedLocale locale = HbExtendedLocale::system(); |
|
373 DigitType digitType = WesternDigit; |
|
374 if (locale.language() == HbExtendedLocale::Arabic) { |
|
375 digitType = ArabicIndicDigit; |
|
376 } |
|
377 if (locale.language() == HbExtendedLocale::Persian) { |
|
378 digitType = EasternArabicIndicDigit; |
|
379 } |
|
380 if (locale.language() == HbExtendedLocale::Urdu) { |
|
381 digitType = EasternArabicIndicDigit; |
|
382 } |
|
383 QString converted = HbStringUtil::convertDigitsTo(str, digitType); |
|
384 return converted; |
|
385 } |
|
386 |
|
387 /*! |
|
388 Converts the digit from Latin to native or native to latin or native to native |
|
389 \param str digits to be converted. |
|
390 \param digitType type of the digit to be converted to |
|
391 */ |
|
392 QString HbStringUtil::convertDigitsTo( const QString str, const DigitType digitType ) |
|
393 { |
|
394 QString convDigit; |
|
395 int length = str.length(); |
|
396 for(int i=0; i<length; i++) |
|
397 { |
|
398 ushort digit = str[i].unicode(); |
|
399 ushort digitBase = nativeDigitBase(str[i]).unicode(); |
|
400 ushort convertedDigit = 0; |
|
401 switch (digitBase) |
|
402 { |
|
403 case WesternDigit: |
|
404 case ArabicIndicDigit: |
|
405 case EasternArabicIndicDigit: |
|
406 case DevanagariDigit: |
|
407 case ThaiDigit: |
|
408 convertedDigit += digitType + digit - digitBase; |
|
409 convDigit[i] = QChar(convertedDigit); |
|
410 break; |
|
411 default: |
|
412 convDigit[i] = QChar(digit); |
|
413 break; |
|
414 }; |
|
415 } |
|
416 return convDigit; |
|
417 } |
|
418 |
|
419 /*! |
|
420 Sorts QStrings into alphabetically order (overwrites the strList's original content) |
|
421 |
|
422 \param strList List of QStrings which need to be sorted. |
|
423 |
|
424 Example |
|
425 \snippet{unittest_hbstringutil/unittest_hbstringutil.cpp,7} |
|
426 */ |
|
427 void HbStringUtil::sort( QStringList &strList ) |
|
428 { |
|
429 if ( strList.size() > 1 ) { |
|
430 qSort(strList.begin(), strList.end(), hbStringUtil_SortHelper); |
|
431 } |
|
432 } |
|
433 |
|
434 bool hbStringUtil_SortHelper( const QString &s1, const QString &s2 ) |
|
435 { |
|
436 if ( HbStringUtil::compareC(s1, s2) < 0 ) { |
|
437 // s1 is before s2 |
|
438 return true; |
|
439 } else { |
|
440 // s1 is after s2 (or they are equal) |
|
441 return false; |
|
442 } |
|
443 } |