add return values (!!)
[WebKit-https.git] / JavaScriptCore / wtf / unicode / qt4 / UnicodeQt4.h
1 /*
2  *  This file is part of the KDE libraries
3  *  Copyright (C) 2006 George Staikos <staikos@kde.org>
4  *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
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 KJS_UNICODE_QT4_H
24 #define KJS_UNICODE_QT4_H
25
26 #include <QChar>
27 #include <QString>
28
29 #include <config.h>
30
31 #include <stdint.h>
32
33 typedef uint16_t UChar;
34 typedef uint32_t UChar32;
35
36 // some defines from ICU needed one or two places
37
38 #define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800)
39 #define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00)
40 #define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000)
41 #define U16_GET_SUPPLEMENTARY(lead, trail) \
42     (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET)
43
44 #define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0)
45 #define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00)
46
47 #define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800)
48 #define U16_IS_SURROGATE(c) U_IS_SURROGATE(c)
49 #define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0)
50
51 #define U16_NEXT(s, i, length, c) { \
52     (c)=(s)[(i)++]; \
53     if(U16_IS_LEAD(c)) { \
54         uint16_t __c2; \
55         if((i)<(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \
56             ++(i); \
57             (c)=U16_GET_SUPPLEMENTARY((c), __c2); \
58         } \
59     } \
60 }
61
62 #define U_MASK(x) ((uint32_t)1<<(x))
63
64 namespace WTF {
65   namespace Unicode {
66
67     enum Direction {
68       LeftToRight = QChar::DirL,
69       RightToLeft = QChar::DirR,
70       EuropeanNumber = QChar::DirEN,
71       EuropeanNumberSeparator = QChar::DirES,
72       EuropeanNumberTerminator = QChar::DirET,
73       ArabicNumber = QChar::DirAN,
74       CommonNumberSeparator = QChar::DirCS,
75       BlockSeparator = QChar::DirB,
76       SegmentSeparator = QChar::DirS,
77       WhiteSpaceNeutral = QChar::DirWS,
78       OtherNeutral = QChar::DirON,
79       LeftToRightEmbedding = QChar::DirLRE,
80       LeftToRightOverride = QChar::DirLRO,
81       RightToLeftArabic = QChar::DirAL,
82       RightToLeftEmbedding = QChar::DirRLE,
83       RightToLeftOverride = QChar::DirRLO,
84       PopDirectionalFormat = QChar::DirPDF,
85       NonSpacingMark = QChar::DirNSM,
86       BoundaryNeutral = QChar::DirBN
87     };
88
89     enum DecompositionType {
90       DecompositionNone = QChar::NoDecomposition,
91       DecompositionCanonical = QChar::Canonical,
92       DecompositionCompat = QChar::Compat,
93       DecompositionCircle = QChar::Circle,
94       DecompositionFinal = QChar::Final,
95       DecompositionFont = QChar::Font,
96       DecompositionFraction = QChar::Fraction,
97       DecompositionInitial = QChar::Initial,
98       DecompositionIsolated = QChar::Isolated,
99       DecompositionMedial = QChar::Medial,
100       DecompositionNarrow = QChar::Narrow,
101       DecompositionNoBreak = QChar::NoBreak,
102       DecompositionSmall = QChar::Small,
103       DecompositionSquare = QChar::Square,
104       DecompositionSub = QChar::Sub,
105       DecompositionSuper = QChar::Super,
106       DecompositionVertical = QChar::Vertical,
107       DecompositionWide = QChar::Wide
108     };
109
110     enum CharCategory {
111       NoCategory = 0,
112       Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing),
113       Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining),
114       Mark_Enclosing = U_MASK(QChar::Mark_Enclosing),
115       Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit),
116       Number_Letter = U_MASK(QChar::Number_Letter),
117       Number_Other = U_MASK(QChar::Number_Other),
118       Separator_Space = U_MASK(QChar::Separator_Space),
119       Separator_Line = U_MASK(QChar::Separator_Line),
120       Separator_Paragraph = U_MASK(QChar::Separator_Paragraph),
121       Other_Control = U_MASK(QChar::Other_Control),
122       Other_Format = U_MASK(QChar::Other_Format),
123       Other_Surrogate = U_MASK(QChar::Other_Surrogate),
124       Other_PrivateUse = U_MASK(QChar::Other_PrivateUse),
125       Other_NotAssigned = U_MASK(QChar::Other_NotAssigned),
126       Letter_Uppercase = U_MASK(QChar::Letter_Uppercase),
127       Letter_Lowercase = U_MASK(QChar::Letter_Lowercase),
128       Letter_Titlecase = U_MASK(QChar::Letter_Titlecase),
129       Letter_Modifier = U_MASK(QChar::Letter_Modifier),
130       Letter_Other = U_MASK(QChar::Letter_Other),
131       Punctuation_Connector = U_MASK(QChar::Punctuation_Connector),
132       Punctuation_Dash = U_MASK(QChar::Punctuation_Dash),
133       Punctuation_Open = U_MASK(QChar::Punctuation_Open),
134       Punctuation_Close = U_MASK(QChar::Punctuation_Close),
135       Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote),
136       Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote),
137       Punctuation_Other = U_MASK(QChar::Punctuation_Other),
138       Symbol_Math = U_MASK(QChar::Symbol_Math),
139       Symbol_Currency = U_MASK(QChar::Symbol_Currency),
140       Symbol_Modifier = U_MASK(QChar::Symbol_Modifier),
141       Symbol_Other = U_MASK(QChar::Symbol_Other),
142     };
143
144
145 #if QT_VERSION >= 0x040300
146     // FIXME: handle surrogates correctly in all methods
147     
148     inline int toLower(UChar* str, int strLength, UChar*& destIfNeeded)
149     {
150       destIfNeeded = 0;
151
152       // FIXME: handle special casing. Easiest with some low level API in Qt
153       for (int i = 0; i < strLength; ++i)
154         str[i] = QChar::toLower(str[i]);
155
156       return strLength;
157     }
158
159     inline UChar32 toLower(UChar32 ch)
160     {
161       return QChar::toLower(ch);
162     }
163
164     inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
165     {
166       // FIXME: handle special casing. Easiest with some low level API in Qt
167       *error = false;
168       if (resultLength < srcLength) {
169         *error = true;
170         return srcLength;
171       }
172       for (int i = 0; i < srcLength; ++i)
173         result[i] = QChar::toLower(src[i]);
174       return srcLength;
175     }
176
177     inline int toUpper(UChar* str, int strLength, UChar*& destIfNeeded)
178     {
179       // FIXME: handle special casing. Easiest with some low level API in Qt
180       destIfNeeded = 0;
181
182       for (int i = 0; i < strLength; ++i)
183         str[i] = QChar::toUpper(str[i]);
184
185       return strLength;
186     }
187
188     inline UChar32 toUpper(UChar32 ch)
189     {
190       return QChar::toUpper(ch);
191     }
192
193     inline int toUpper(UChar* result, int resultLength, UChar* src, int srcLength,  bool* error)
194     {
195       // FIXME: handle special casing. Easiest with some low level API in Qt
196       *error = false;
197       if (resultLength < srcLength) {
198         *error = true;
199         return srcLength;
200       }
201       for (int i = 0; i < srcLength; ++i)
202         result[i] = QChar::toUpper(src[i]);
203       return srcLength;
204     }
205
206     inline int toTitleCase(UChar32 c)
207     {
208       return QChar::toTitleCase(c);
209     }
210
211     inline UChar32 foldCase(UChar32 c)
212     {
213       return QChar::toCaseFolded(c);
214     }
215
216     inline int foldCase(UChar* result, int resultLength, UChar* src, int srcLength,  bool* error)
217     {
218       // FIXME: handle special casing. Easiest with some low level API in Qt
219       *error = false;
220       if (resultLength < srcLength) {
221         *error = true;
222         return srcLength;
223       }
224       for (int i = 0; i < srcLength; ++i)
225         result[i] = QChar::toCaseFolded(src[i]);
226       return srcLength;
227     }
228
229     inline bool isFormatChar(UChar32 c)
230     {
231       return QChar::category(c) == QChar::Other_Format;
232     }
233
234     inline bool isPrintableChar(UChar32 c)
235     {
236       const uint test = U_MASK(QChar::Other_Control) |
237                         U_MASK(QChar::Other_NotAssigned);
238       return !(U_MASK(QChar::category(c)) & test);
239     }
240
241     inline bool isSeparatorSpace(UChar32 c)
242     {
243       return QChar::category(c) == QChar::Separator_Space;
244     }
245
246     inline bool isPunct(UChar32 c)
247     {
248       const uint test = U_MASK(QChar::Punctuation_Connector) |
249                         U_MASK(QChar::Punctuation_Dash) |
250                         U_MASK(QChar::Punctuation_Open) |
251                         U_MASK(QChar::Punctuation_Close) |
252                         U_MASK(QChar::Punctuation_InitialQuote) |
253                         U_MASK(QChar::Punctuation_FinalQuote) |
254                         U_MASK(QChar::Punctuation_Other);
255       return U_MASK(QChar::category(c)) & test;
256     }
257
258     inline bool isDigit(UChar32 c)
259     {
260       return QChar::category(c) == QChar::Number_DecimalDigit;
261     }
262
263     inline bool isLower(UChar32 c)
264     {
265       return QChar::category(c) == QChar::Letter_Lowercase;
266     }
267
268     inline bool isUpper(UChar32 c)
269     {
270       return QChar::category(c) == QChar::Letter_Uppercase;
271     }
272
273     inline int digitValue(UChar32 c)
274     {
275       return QChar::digitValue(c);
276     }
277
278     inline UChar32 mirroredChar(UChar32 c)
279     {
280       return QChar::mirroredChar(c);
281     }
282
283     inline uint8_t combiningClass(UChar32 c)
284     {
285       return QChar::combiningClass(c);
286     }
287
288     inline DecompositionType decompositionType(UChar32 c)
289     {
290       return (DecompositionType)QChar::decompositionTag(c);
291     }
292
293     inline int umemcasecmp(const UChar* a, const UChar* b, int len)
294     {
295       // handle surrogates correctly
296       for (int i = 0; i < len; ++i) {
297         QChar c1 = QChar(a[i]).toCaseFolded();
298         QChar c2 = QChar(b[i]).toCaseFolded();
299         if (c1 != c2)
300           return c1 < c2;
301       }
302       return 0;
303     }
304
305     inline Direction direction(UChar32 c)
306     {
307       return (Direction)QChar::direction(c);
308     }
309
310     inline CharCategory category(UChar32 c)
311     {
312       return (CharCategory) U_MASK(QChar::category(c));
313     }
314     
315 #else
316
317     inline int toLower(UChar* str, int strLength, UChar*& destIfNeeded)
318     {
319       destIfNeeded = 0;
320
321       for (int i = 0; i < strLength; ++i)
322         str[i] = QChar(str[i]).toLower().unicode();
323
324       return strLength;
325     }
326
327     inline UChar32 toLower(UChar32 ch)
328     {
329       if (ch > 0xffff)
330         return ch;
331       return QChar((unsigned short)ch).toLower().unicode();
332     }
333
334     inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
335     {
336       *error = false;
337       if (resultLength < srcLength) {
338         *error = true;
339         return srcLength;
340       }
341       for (int i = 0; i < srcLength; ++i)
342         result[i] = QChar(src[i]).toLower().unicode();
343       return srcLength;
344     }
345
346     inline int toUpper(UChar* str, int strLength, UChar*& destIfNeeded)
347     {
348       destIfNeeded = 0;
349
350       for (int i = 0; i < strLength; ++i)
351         str[i] = QChar(str[i]).toUpper().unicode();
352
353       return strLength;
354     }
355
356     inline UChar32 toUpper(UChar32 ch)
357     {
358       if (ch > 0xffff)
359         return ch;
360       return QChar((unsigned short)ch).toUpper().unicode();
361     }
362
363     inline int toUpper(UChar* result, int resultLength, UChar* src, int srcLength,  bool* error)
364     {
365       *error = false;
366       if (resultLength < srcLength) {
367         *error = true;
368         return srcLength;
369       }
370       for (int i = 0; i < srcLength; ++i)
371         result[i] = QChar(src[i]).toUpper().unicode();
372       return srcLength;
373     }
374
375     inline int toTitleCase(UChar32 c)
376     {
377       if (c > 0xffff)
378         return c;
379       return QChar((unsigned short)c).toUpper().unicode();
380     }
381
382     inline UChar32 foldCase(UChar32 c)
383     {
384       if (c > 0xffff)
385         return c;
386       return QChar((unsigned short)c).toLower().unicode();
387     }
388
389     inline int foldCase(UChar* result, int resultLength, UChar* src, int srcLength,  bool* error)
390     {
391       return toLower(result, resultLength, src, srcLength, error);
392     }
393
394     inline bool isFormatChar(UChar32 c)
395     {
396       return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Other_Format;
397     }
398
399     inline bool isPrintableChar(UChar32 c)
400     {
401       return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPrint();
402     }
403
404     inline bool isSeparatorSpace(UChar32 c)
405     {
406       return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Separator_Space;
407     }
408
409     inline bool isPunct(UChar32 c)
410     {
411       return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPunct();
412     }
413
414     inline bool isDigit(UChar32 c)
415     {
416       return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isDigit();
417     }
418
419     inline bool isLower(UChar32 c)
420     {
421       return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Letter_Lowercase;
422     }
423
424     inline bool isUpper(UChar32 c)
425     {
426       return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Letter_Uppercase;
427     }
428
429     inline int digitValue(UChar32 c)
430     {
431       if (c > 0xffff)
432         return 0;
433       return QChar(c).digitValue();
434     }
435
436     inline UChar32 mirroredChar(UChar32 c)
437     {
438       if (c > 0xffff)
439         return c;
440       return QChar(c).mirroredChar().unicode();
441     }
442
443     inline uint8_t combiningClass(UChar32 c)
444     {
445       if (c > 0xffff)
446         return 0;
447       return QChar((unsigned short)c).combiningClass();
448     }
449
450     inline DecompositionType decompositionType(UChar32 c)
451     {
452       if (c > 0xffff)
453         return DecompositionNone;
454       return (DecompositionType)QChar(c).decompositionTag();
455     }
456
457     inline int umemcasecmp(const UChar* a, const UChar* b, int len)
458     {
459       for (int i = 0; i < len; ++i) {
460         QChar c1 = QChar(a[i]).toLower();
461         QChar c2 = QChar(b[i]).toLower();
462         if (c1 != c2)
463           return c1 < c2;
464       }
465       return 0;
466     }
467
468     inline Direction direction(UChar32 c)
469     {
470       if (c > 0xffff)
471         return LeftToRight;
472       return (Direction)QChar(c).direction();
473     }
474
475     inline CharCategory category(UChar32 c)
476     {
477       if (c > 0xffff)
478         return NoCategory;
479       return (CharCategory) U_MASK(QChar(c).category());
480     }
481
482 #endif
483     
484   }
485 }
486
487 #endif
488 // vim: ts=2 sw=2 et