tizen beta release
[framework/web/webkit-efl.git] / Source / JavaScriptCore / wtf / unicode / qt4 / UnicodeQt4.h
1 /*
2  *  Copyright (C) 2006 George Staikos <staikos@kde.org>
3  *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
4  *  Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #ifndef WTF_UNICODE_QT4_H
24 #define WTF_UNICODE_QT4_H
25
26 #include "ScriptCodesFromICU.h"
27 #include "UnicodeMacrosFromICU.h"
28
29 #include <QChar>
30 #include <QString>
31
32 #include <config.h>
33
34 #include <stdint.h>
35 #if USE(ICU_UNICODE)
36 #include <unicode/ubrk.h>
37 #endif
38
39 QT_BEGIN_NAMESPACE
40 namespace QUnicodeTables {
41     struct Properties {
42         ushort category : 8;
43         ushort line_break_class : 8;
44         ushort direction : 8;
45         ushort combiningClass :8;
46         ushort joining : 2;
47         signed short digitValue : 6; /* 5 needed */
48         ushort unicodeVersion : 4;
49         ushort lowerCaseSpecial : 1;
50         ushort upperCaseSpecial : 1;
51         ushort titleCaseSpecial : 1;
52         ushort caseFoldSpecial : 1; /* currently unused */
53         signed short mirrorDiff : 16;
54         signed short lowerCaseDiff : 16;
55         signed short upperCaseDiff : 16;
56         signed short titleCaseDiff : 16;
57         signed short caseFoldDiff : 16;
58     };
59     Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4);
60     Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2);
61 }
62 QT_END_NAMESPACE
63
64 // ugly hack to make UChar compatible with JSChar in API/JSStringRef.h
65 #if defined(Q_OS_WIN) || (COMPILER(RVCT) && !OS(LINUX))
66 typedef wchar_t UChar;
67 #else
68 typedef uint16_t UChar;
69 #endif
70
71 #if !USE(ICU_UNICODE)
72 typedef uint32_t UChar32;
73 #endif
74
75 namespace WTF {
76 namespace Unicode {
77
78 enum Direction {
79     LeftToRight = QChar::DirL,
80     RightToLeft = QChar::DirR,
81     EuropeanNumber = QChar::DirEN,
82     EuropeanNumberSeparator = QChar::DirES,
83     EuropeanNumberTerminator = QChar::DirET,
84     ArabicNumber = QChar::DirAN,
85     CommonNumberSeparator = QChar::DirCS,
86     BlockSeparator = QChar::DirB,
87     SegmentSeparator = QChar::DirS,
88     WhiteSpaceNeutral = QChar::DirWS,
89     OtherNeutral = QChar::DirON,
90     LeftToRightEmbedding = QChar::DirLRE,
91     LeftToRightOverride = QChar::DirLRO,
92     RightToLeftArabic = QChar::DirAL,
93     RightToLeftEmbedding = QChar::DirRLE,
94     RightToLeftOverride = QChar::DirRLO,
95     PopDirectionalFormat = QChar::DirPDF,
96     NonSpacingMark = QChar::DirNSM,
97     BoundaryNeutral = QChar::DirBN
98 };
99
100 enum DecompositionType {
101     DecompositionNone = QChar::NoDecomposition,
102     DecompositionCanonical = QChar::Canonical,
103     DecompositionCompat = QChar::Compat,
104     DecompositionCircle = QChar::Circle,
105     DecompositionFinal = QChar::Final,
106     DecompositionFont = QChar::Font,
107     DecompositionFraction = QChar::Fraction,
108     DecompositionInitial = QChar::Initial,
109     DecompositionIsolated = QChar::Isolated,
110     DecompositionMedial = QChar::Medial,
111     DecompositionNarrow = QChar::Narrow,
112     DecompositionNoBreak = QChar::NoBreak,
113     DecompositionSmall = QChar::Small,
114     DecompositionSquare = QChar::Square,
115     DecompositionSub = QChar::Sub,
116     DecompositionSuper = QChar::Super,
117     DecompositionVertical = QChar::Vertical,
118     DecompositionWide = QChar::Wide
119 };
120
121 enum CharCategory {
122     NoCategory = 0,
123     Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing),
124     Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining),
125     Mark_Enclosing = U_MASK(QChar::Mark_Enclosing),
126     Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit),
127     Number_Letter = U_MASK(QChar::Number_Letter),
128     Number_Other = U_MASK(QChar::Number_Other),
129     Separator_Space = U_MASK(QChar::Separator_Space),
130     Separator_Line = U_MASK(QChar::Separator_Line),
131     Separator_Paragraph = U_MASK(QChar::Separator_Paragraph),
132     Other_Control = U_MASK(QChar::Other_Control),
133     Other_Format = U_MASK(QChar::Other_Format),
134     Other_Surrogate = U_MASK(QChar::Other_Surrogate),
135     Other_PrivateUse = U_MASK(QChar::Other_PrivateUse),
136     Other_NotAssigned = U_MASK(QChar::Other_NotAssigned),
137     Letter_Uppercase = U_MASK(QChar::Letter_Uppercase),
138     Letter_Lowercase = U_MASK(QChar::Letter_Lowercase),
139     Letter_Titlecase = U_MASK(QChar::Letter_Titlecase),
140     Letter_Modifier = U_MASK(QChar::Letter_Modifier),
141     Letter_Other = U_MASK(QChar::Letter_Other),
142     Punctuation_Connector = U_MASK(QChar::Punctuation_Connector),
143     Punctuation_Dash = U_MASK(QChar::Punctuation_Dash),
144     Punctuation_Open = U_MASK(QChar::Punctuation_Open),
145     Punctuation_Close = U_MASK(QChar::Punctuation_Close),
146     Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote),
147     Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote),
148     Punctuation_Other = U_MASK(QChar::Punctuation_Other),
149     Symbol_Math = U_MASK(QChar::Symbol_Math),
150     Symbol_Currency = U_MASK(QChar::Symbol_Currency),
151     Symbol_Modifier = U_MASK(QChar::Symbol_Modifier),
152     Symbol_Other = U_MASK(QChar::Symbol_Other)
153 };
154
155
156 // FIXME: handle surrogates correctly in all methods
157
158 inline UChar32 toLower(UChar32 ch)
159 {
160     return QChar::toLower(uint32_t(ch));
161 }
162
163 inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
164 {
165     const UChar *e = src + srcLength;
166     const UChar *s = src;
167     UChar *r = result;
168     uint rindex = 0;
169
170     // this avoids one out of bounds check in the loop
171     if (s < e && QChar(*s).isLowSurrogate()) {
172         if (r)
173             r[rindex] = *s++;
174         ++rindex;
175     }
176
177     int needed = 0;
178     while (s < e && (rindex < uint(resultLength) || !r)) {
179         uint c = *s;
180         if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
181             c = QChar::surrogateToUcs4(*(s - 1), c);
182         const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
183         if (prop->lowerCaseSpecial) {
184             QString qstring;
185             if (c < 0x10000) {
186                 qstring += QChar(c);
187             } else {
188                 qstring += QChar(*(s-1));
189                 qstring += QChar(*s);
190             }
191             qstring = qstring.toLower();
192             for (int i = 0; i < qstring.length(); ++i) {
193                 if (rindex >= uint(resultLength)) {
194                     needed += qstring.length() - i;
195                     break;
196                 }
197                 if (r)
198                     r[rindex] = qstring.at(i).unicode();
199                 ++rindex;
200             }
201         } else {
202             if (r)
203                 r[rindex] = *s + prop->lowerCaseDiff;
204             ++rindex;
205         }
206         ++s;
207     }
208     if (s < e)
209         needed += e - s;
210     *error = (needed != 0);
211     if (rindex < uint(resultLength))
212         r[rindex] = 0;
213     return rindex + needed;
214 }
215
216 inline UChar32 toUpper(UChar32 c)
217 {
218     return QChar::toUpper(uint32_t(c));
219 }
220
221 inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
222 {
223     const UChar *e = src + srcLength;
224     const UChar *s = src;
225     UChar *r = result;
226     int rindex = 0;
227
228     // this avoids one out of bounds check in the loop
229     if (s < e && QChar(*s).isLowSurrogate()) {
230         if (r)
231             r[rindex] = *s++;
232         ++rindex;
233     }
234
235     int needed = 0;
236     while (s < e && (rindex < resultLength || !r)) {
237         uint c = *s;
238         if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
239             c = QChar::surrogateToUcs4(*(s - 1), c);
240         const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
241         if (prop->upperCaseSpecial) {
242             QString qstring;
243             if (c < 0x10000) {
244                 qstring += QChar(c);
245             } else {
246                 qstring += QChar(*(s-1));
247                 qstring += QChar(*s);
248             }
249             qstring = qstring.toUpper();
250             for (int i = 0; i < qstring.length(); ++i) {
251                 if (rindex >= resultLength) {
252                     needed += qstring.length() - i;
253                     break;
254                 }
255                 if (r)
256                     r[rindex] = qstring.at(i).unicode();
257                 ++rindex;
258             }
259         } else {
260             if (r)
261                 r[rindex] = *s + prop->upperCaseDiff;
262             ++rindex;
263         }
264         ++s;
265     }
266     if (s < e)
267         needed += e - s;
268     *error = (needed != 0);
269     if (rindex < resultLength)
270         r[rindex] = 0;
271     return rindex + needed;
272 }
273
274 inline int toTitleCase(UChar32 c)
275 {
276     return QChar::toTitleCase(uint32_t(c));
277 }
278
279 inline UChar32 foldCase(UChar32 c)
280 {
281     return QChar::toCaseFolded(uint32_t(c));
282 }
283
284 inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
285 {
286     // FIXME: handle special casing. Easiest with some low level API in Qt
287     *error = false;
288     if (resultLength < srcLength) {
289         *error = true;
290         return srcLength;
291     }
292     for (int i = 0; i < srcLength; ++i)
293         result[i] = QChar::toCaseFolded(ushort(src[i]));
294     return srcLength;
295 }
296
297 inline bool isArabicChar(UChar32 c)
298 {
299     return c >= 0x0600 && c <= 0x06FF;
300 }
301
302 inline bool isPrintableChar(UChar32 c)
303 {
304     const uint test = U_MASK(QChar::Other_Control) |
305                       U_MASK(QChar::Other_NotAssigned);
306     return !(U_MASK(QChar::category(uint32_t(c))) & test);
307 }
308
309 inline bool isSeparatorSpace(UChar32 c)
310 {
311     return QChar::category(uint32_t(c)) == QChar::Separator_Space;
312 }
313
314 inline bool isPunct(UChar32 c)
315 {
316     const uint test = U_MASK(QChar::Punctuation_Connector) |
317                       U_MASK(QChar::Punctuation_Dash) |
318                       U_MASK(QChar::Punctuation_Open) |
319                       U_MASK(QChar::Punctuation_Close) |
320                       U_MASK(QChar::Punctuation_InitialQuote) |
321                       U_MASK(QChar::Punctuation_FinalQuote) |
322                       U_MASK(QChar::Punctuation_Other);
323     return U_MASK(QChar::category(uint32_t(c))) & test;
324 }
325
326 inline bool isLower(UChar32 c)
327 {
328     return QChar::category(uint32_t(c)) == QChar::Letter_Lowercase;
329 }
330
331 inline bool hasLineBreakingPropertyComplexContext(UChar32)
332 {
333     // FIXME: Implement this to return whether the character has line breaking property SA (Complex Context).
334     return false;
335 }
336
337 inline UChar32 mirroredChar(UChar32 c)
338 {
339     return QChar::mirroredChar(uint32_t(c));
340 }
341
342 inline uint8_t combiningClass(UChar32 c)
343 {
344     return QChar::combiningClass(uint32_t(c));
345 }
346
347 inline DecompositionType decompositionType(UChar32 c)
348 {
349     return (DecompositionType)QChar::decompositionTag(c);
350 }
351
352 inline int umemcasecmp(const UChar* a, const UChar* b, int len)
353 {
354     // handle surrogates correctly
355     for (int i = 0; i < len; ++i) {
356         uint c1 = QChar::toCaseFolded(ushort(a[i]));
357         uint c2 = QChar::toCaseFolded(ushort(b[i]));
358         if (c1 != c2)
359             return c1 - c2;
360     }
361     return 0;
362 }
363
364 inline Direction direction(UChar32 c)
365 {
366     return (Direction)QChar::direction(uint32_t(c));
367 }
368
369 inline CharCategory category(UChar32 c)
370 {
371     return (CharCategory) U_MASK(QChar::category(uint32_t(c)));
372 }
373
374 } // namespace Unicode
375 } // namespace WTF
376
377 #endif // WTF_UNICODE_QT4_H