source: trunk/src/corelib/io/qurl.cpp@ 477

Last change on this file since 477 was 172, checked in by Dmitry A. Kuminov, 16 years ago

corelib/io, gui/dialogs: Handle DOS-like filesystem details (drives, slashes) on OS/2 similarly to Win32.

File size: 198.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*!
43 \class QUrl
44
45 \brief The QUrl class provides a convenient interface for working
46 with URLs.
47
48 \reentrant
49 \ingroup io
50 \ingroup misc
51 \ingroup shared
52 \mainclass
53
54 It can parse and construct URLs in both encoded and unencoded
55 form. QUrl also has support for internationalized domain names
56 (IDNs).
57
58 The most common way to use QUrl is to initialize it via the
59 constructor by passing a QString. Otherwise, setUrl() and
60 setEncodedUrl() can also be used.
61
62 URLs can be represented in two forms: encoded or unencoded. The
63 unencoded representation is suitable for showing to users, but
64 the encoded representation is typically what you would send to
65 a web server. For example, the unencoded URL
66 "http://b\uuml\c{}hler.example.com" would be sent to the server as
67 "http://xn--bhler-kva.example.com/List%20of%20applicants.xml".
68
69 A URL can also be constructed piece by piece by calling
70 setScheme(), setUserName(), setPassword(), setHost(), setPort(),
71 setPath(), setEncodedQuery() and setFragment(). Some convenience
72 functions are also available: setAuthority() sets the user name,
73 password, host and port. setUserInfo() sets the user name and
74 password at once.
75
76 Call isValid() to check if the URL is valid. This can be done at
77 any point during the constructing of a URL.
78
79 Constructing a query is particularly convenient through the use
80 of setQueryItems(), addQueryItem() and removeQueryItem(). Use
81 setQueryDelimiters() to customize the delimiters used for
82 generating the query string.
83
84 For the convenience of generating encoded URL strings or query
85 strings, there are two static functions called
86 fromPercentEncoding() and toPercentEncoding() which deal with
87 percent encoding and decoding of QStrings.
88
89 Calling isRelative() will tell whether or not the URL is
90 relative. A relative URL can be resolved by passing it as argument
91 to resolved(), which returns an absolute URL. isParentOf() is used
92 for determining whether one URL is a parent of another.
93
94 fromLocalFile() constructs a QUrl by parsing a local
95 file path. toLocalFile() converts a URL to a local file path.
96
97 The human readable representation of the URL is fetched with
98 toString(). This representation is appropriate for displaying a
99 URL to a user in unencoded form. The encoded form however, as
100 returned by toEncoded(), is for internal use, passing to web
101 servers, mail clients and so on.
102
103 QUrl conforms to the URI specification from
104 \l{RFC 3986} (Uniform Resource Identifier: Generic Syntax), and includes
105 scheme extensions from \l{RFC 1738} (Uniform Resource Locators). Case
106 folding rules in QUrl conform to \l{RFC 3491} (Nameprep: A Stringprep
107 Profile for Internationalized Domain Names (IDN)).
108
109 \sa QUrlInfo
110*/
111
112/*!
113 \enum QUrl::ParsingMode
114
115 The parsing mode controls the way QUrl parses strings.
116
117 \value TolerantMode QUrl will try to correct some common errors in URLs.
118 This mode is useful when processing URLs entered by
119 users.
120
121 \value StrictMode Only valid URLs are accepted. This mode is useful for
122 general URL validation.
123
124 In TolerantMode, the parser corrects the following invalid input:
125
126 \list
127
128 \o Spaces and "%20": If an encoded URL contains a space, this will be
129 replaced with "%20". If a decoded URL contains "%20", this will be
130 replaced with a single space before the URL is parsed.
131
132 \o Single "%" characters: Any occurrences of a percent character "%" not
133 followed by exactly two hexadecimal characters (e.g., "13% coverage.html")
134 will be replaced by "%25".
135
136 \o Reserved and unreserved characters: An encoded URL should only
137 contain a few characters as literals; all other characters should
138 be percent-encoded. In TolerantMode, these characters will be
139 automatically percent-encoded where they are not allowed:
140 space / double-quote / "<" / ">" / "[" / "\" /
141 "]" / "^" / "`" / "{" / "|" / "}"
142
143 \endlist
144*/
145
146/*!
147 \enum QUrl::FormattingOption
148
149 The formatting options define how the URL is formatted when written out
150 as text.
151
152 \value None The format of the URL is unchanged.
153 \value RemoveScheme The scheme is removed from the URL.
154 \value RemovePassword Any password in the URL is removed.
155 \value RemoveUserInfo Any user information in the URL is removed.
156 \value RemovePort Any specified port is removed from the URL.
157 \value RemoveAuthority
158 \value RemovePath The URL's path is removed, leaving only the scheme,
159 host address, and port (if present).
160 \value RemoveQuery The query part of the URL (following a '?' character)
161 is removed.
162 \value RemoveFragment
163 \value StripTrailingSlash The trailing slash is removed if one is present.
164
165 Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl
166 conforms to, require host names to always be converted to lower case,
167 regardless of the Qt::FormattingOptions used.
168*/
169
170#include "qplatformdefs.h"
171#include "qurl.h"
172#include "private/qunicodetables_p.h"
173#include "qatomic.h"
174#include "qbytearray.h"
175#include "qlist.h"
176#ifndef QT_NO_REGEXP
177#include "qregexp.h"
178#endif
179#include "qstring.h"
180#include "qstringlist.h"
181#include "qstack.h"
182#include "qvarlengtharray.h"
183#include "qdebug.h"
184#if defined QT3_SUPPORT
185#include "qfileinfo.h"
186#endif
187
188#if defined(Q_OS_WINCE_WM)
189#pragma optimize("g", off)
190#endif
191
192QT_BEGIN_NAMESPACE
193
194extern void q_normalizePercentEncoding(QByteArray *ba, const char *exclude);
195extern void q_toPercentEncoding(QByteArray *ba, const char *exclude, const char *include = 0);
196extern void q_fromPercentEncoding(QByteArray *ba);
197
198static QByteArray toPercentEncodingHelper(const QString &s, const char *exclude, const char *include = 0)
199{
200 if (s.isNull())
201 return QByteArray(); // null
202 QByteArray ba = s.toUtf8();
203 q_toPercentEncoding(&ba, exclude, include);
204 return ba;
205}
206
207static QString fromPercentEncodingHelper(const QByteArray &ba)
208{
209 if (ba.isNull())
210 return QString(); // null
211 QByteArray copy = ba;
212 q_fromPercentEncoding(&copy);
213 return QString::fromUtf8(copy.constData(), copy.length());
214}
215
216static QString fromPercentEncodingMutable(QByteArray *ba)
217{
218 if (ba->isNull())
219 return QString(); // null
220 q_fromPercentEncoding(ba);
221 return QString::fromUtf8(ba->constData(), ba->length());
222}
223
224// ### Qt 5: Consider accepting empty strings as valid. See task 144227.
225
226//#define QURL_DEBUG
227
228// implemented in qvsnprintf.cpp
229Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...);
230
231// needed by the punycode encoder/decoder
232#define Q_MAXINT ((uint)((uint)(-1)>>1))
233static const uint base = 36;
234static const uint tmin = 1;
235static const uint tmax = 26;
236static const uint skew = 38;
237static const uint damp = 700;
238static const uint initial_bias = 72;
239static const uint initial_n = 128;
240
241#define QURL_SETFLAG(a, b) { (a) |= (b); }
242#define QURL_UNSETFLAG(a, b) { (a) &= ~(b); }
243#define QURL_HASFLAG(a, b) (((a) & (b)) == (b))
244
245struct QUrlErrorInfo {
246 inline QUrlErrorInfo() : _source(0), _message(0), _expected(0), _found(0)
247 { }
248
249 const char *_source;
250 const char *_message;
251 char _expected;
252 char _found;
253
254 inline void setParams(const char *source, const char *message, char expected, char found)
255 {
256 _source = source;
257 _message = message;
258 _expected = expected;
259 _found = found;
260 }
261};
262
263struct QUrlParseData
264{
265 const char *scheme;
266 int schemeLength;
267
268 const char *userInfo;
269 int userInfoDelimIndex;
270 int userInfoLength;
271
272 const char *host;
273 int hostLength;
274 int port;
275
276 const char *path;
277 int pathLength;
278 const char *query;
279 int queryLength;
280 const char *fragment;
281 int fragmentLength;
282};
283
284
285class QUrlPrivate
286{
287public:
288 QUrlPrivate();
289 QUrlPrivate(const QUrlPrivate &other);
290
291 bool setUrl(const QString &url);
292
293 QString canonicalHost() const;
294 void ensureEncodedParts() const;
295 QString authority(QUrl::FormattingOptions options = QUrl::None) const;
296 void setAuthority(const QString &auth);
297 void setUserInfo(const QString &userInfo);
298 QString userInfo(QUrl::FormattingOptions options = QUrl::None) const;
299 void setEncodedAuthority(const QByteArray &authority);
300 void setEncodedUserInfo(const QUrlParseData *parseData);
301
302 QByteArray mergePaths(const QByteArray &relativePath) const;
303
304 void queryItem(int pos, int *value, int *end);
305
306 enum ParseOptions {
307 ParseAndSet,
308 ParseOnly
309 };
310
311 void validate() const;
312 void parse(ParseOptions parseOptions = ParseAndSet) const;
313 void clear();
314
315 QByteArray toEncoded(QUrl::FormattingOptions options = QUrl::None) const;
316
317 QAtomicInt ref;
318
319 QString scheme;
320 QString userName;
321 QString password;
322 QString host;
323 QString path;
324 QByteArray query;
325 QString fragment;
326
327 QByteArray encodedOriginal;
328 QByteArray encodedUserName;
329 QByteArray encodedPassword;
330 QByteArray encodedPath;
331 QByteArray encodedFragment;
332
333 int port;
334 QUrl::ParsingMode parsingMode;
335
336 bool hasQuery;
337 bool hasFragment;
338 bool isValid;
339
340 char valueDelimiter;
341 char pairDelimiter;
342
343 enum State {
344 Parsed = 0x1,
345 Validated = 0x2,
346 Normalized = 0x4,
347 HostCanonicalized = 0x8
348 };
349 int stateFlags;
350
351 QByteArray encodedNormalized;
352 const QByteArray & normalized();
353
354 mutable QUrlErrorInfo errorInfo;
355 QString createErrorString();
356};
357
358
359static bool QT_FASTCALL _HEXDIG(const char **ptr)
360{
361 char ch = **ptr;
362 if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
363 ++(*ptr);
364 return true;
365 }
366
367 return false;
368}
369
370// pct-encoded = "%" HEXDIG HEXDIG
371static bool QT_FASTCALL _pctEncoded(const char **ptr)
372{
373 const char *ptrBackup = *ptr;
374
375 if (**ptr != '%')
376 return false;
377 ++(*ptr);
378
379 if (!_HEXDIG(ptr)) {
380 *ptr = ptrBackup;
381 return false;
382 }
383 if (!_HEXDIG(ptr)) {
384 *ptr = ptrBackup;
385 return false;
386 }
387
388 return true;
389}
390
391#if 0
392// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
393static bool QT_FASTCALL _genDelims(const char **ptr, char *c)
394{
395 char ch = **ptr;
396 switch (ch) {
397 case ':': case '/': case '?': case '#':
398 case '[': case ']': case '@':
399 *c = ch;
400 ++(*ptr);
401 return true;
402 default:
403 return false;
404 }
405}
406#endif
407
408// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
409// / "*" / "+" / "," / ";" / "="
410static bool QT_FASTCALL _subDelims(const char **ptr)
411{
412 char ch = **ptr;
413 switch (ch) {
414 case '!': case '$': case '&': case '\'':
415 case '(': case ')': case '*': case '+':
416 case ',': case ';': case '=':
417 ++(*ptr);
418 return true;
419 default:
420 return false;
421 }
422}
423
424// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
425static bool QT_FASTCALL _unreserved(const char **ptr)
426{
427 char ch = **ptr;
428 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
429 || (ch >= '0' && ch <= '9')
430 || ch == '-' || ch == '.' || ch == '_' || ch == '~') {
431 ++(*ptr);
432 return true;
433 }
434 return false;
435}
436
437// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
438static void QT_FASTCALL _scheme(const char **ptr, QUrlParseData *parseData)
439{
440 bool first = true;
441
442 parseData->scheme = *ptr;
443 for (;;) {
444 char ch = **ptr;
445 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
446 ;
447 } else if (!first && ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.')) {
448 ;
449 } else {
450 break;
451 }
452
453 ++(*ptr);
454 first = false;
455 }
456
457 if (**ptr != ':') {
458 *ptr = parseData->scheme;
459 } else {
460 parseData->schemeLength = *ptr - parseData->scheme;
461 ++(*ptr); // skip ':'
462 }
463}
464
465// IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
466static bool QT_FASTCALL _IPvFuture(const char **ptr)
467{
468 if (**ptr != 'v')
469 return false;
470
471 const char *ptrBackup = *ptr;
472 ++(*ptr);
473
474 if (!_HEXDIG(ptr)) {
475 *ptr = ptrBackup;
476 return false;
477 }
478
479 while (_HEXDIG(ptr))
480 ;
481
482 if (**ptr != '.') {
483 *ptr = ptrBackup;
484 return false;
485 }
486 ++(*ptr);
487
488 if (!_unreserved(ptr) && !_subDelims(ptr) && *((*ptr)++) != ':') {
489 *ptr = ptrBackup;
490 return false;
491 }
492
493
494 while (_unreserved(ptr) || _subDelims(ptr) || *((*ptr)++) == ':')
495 ;
496
497 return true;
498}
499
500// h16 = 1*4HEXDIG
501// ; 16 bits of address represented in hexadecimal
502static bool QT_FASTCALL _h16(const char **ptr)
503{
504 int i = 0;
505 for (; i < 4; ++i) {
506 if (!_HEXDIG(ptr))
507 break;
508 }
509 return (i != 0);
510}
511
512// dec-octet = DIGIT ; 0-9
513// / %x31-39 DIGIT ; 10-99
514// / "1" 2DIGIT ; 100-199
515// / "2" %x30-34 DIGIT ; 200-249
516// / "25" %x30-35 ; 250-255
517static bool QT_FASTCALL _decOctet(const char **ptr)
518{
519 const char *ptrBackup = *ptr;
520 char c1 = **ptr;
521
522 if (c1 < '0' || c1 > '9')
523 return false;
524
525 ++(*ptr);
526
527 if (c1 == '0')
528 return true;
529
530 char c2 = **ptr;
531
532 if (c2 < '0' || c2 > '9')
533 return true;
534
535 ++(*ptr);
536
537 char c3 = **ptr;
538 if (c3 < '0' || c3 > '9')
539 return true;
540
541 // If there is a three digit number larger than 255, reject the
542 // whole token.
543 if (c1 >= '2' && c2 >= '5' && c3 > '5') {
544 *ptr = ptrBackup;
545 return false;
546 }
547
548 ++(*ptr);
549
550 return true;
551}
552
553// IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
554static bool QT_FASTCALL _IPv4Address(const char **ptr)
555{
556 const char *ptrBackup = *ptr;
557
558 if (!_decOctet(ptr)) {
559 *ptr = ptrBackup;
560 return false;
561 }
562
563 for (int i = 0; i < 3; ++i) {
564 char ch = *((*ptr)++);
565 if (ch != '.') {
566 *ptr = ptrBackup;
567 return false;
568 }
569
570 if (!_decOctet(ptr)) {
571 *ptr = ptrBackup;
572 return false;
573 }
574 }
575
576 return true;
577}
578
579// ls32 = ( h16 ":" h16 ) / IPv4address
580// ; least-significant 32 bits of address
581static bool QT_FASTCALL _ls32(const char **ptr)
582{
583 const char *ptrBackup = *ptr;
584 if (_h16(ptr) && *((*ptr)++) == ':' && _h16(ptr))
585 return true;
586
587 *ptr = ptrBackup;
588 return _IPv4Address(ptr);
589}
590
591// IPv6address = 6( h16 ":" ) ls32 // case 1
592// / "::" 5( h16 ":" ) ls32 // case 2
593// / [ h16 ] "::" 4( h16 ":" ) ls32 // case 3
594// / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 // case 4
595// / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 // case 5
596// / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 // case 6
597// / [ *4( h16 ":" ) h16 ] "::" ls32 // case 7
598// / [ *5( h16 ":" ) h16 ] "::" h16 // case 8
599// / [ *6( h16 ":" ) h16 ] "::" // case 9
600static bool QT_FASTCALL _IPv6Address(const char **ptr)
601{
602 const char *ptrBackup = *ptr;
603
604 // count of (h16 ":") to the left of and including ::
605 int leftHexColons = 0;
606 // count of (h16 ":") to the right of ::
607 int rightHexColons = 0;
608
609 // first count the number of (h16 ":") on the left of ::
610 while (_h16(ptr)) {
611
612 // an h16 not followed by a colon is considered an
613 // error.
614 if (**ptr != ':') {
615 *ptr = ptrBackup;
616 return false;
617 }
618 ++(*ptr);
619 ++leftHexColons;
620
621 // check for case 1, the only time when there can be no ::
622 if (leftHexColons == 6 && _ls32(ptr)) {
623 return true;
624 }
625 }
626
627 // check for case 2 where the address starts with a :
628 if (leftHexColons == 0 && *((*ptr)++) != ':') {
629 *ptr = ptrBackup;
630 return false;
631 }
632
633 // check for the second colon in ::
634 if (*((*ptr)++) != ':') {
635 *ptr = ptrBackup;
636 return false;
637 }
638
639 int canBeCase = -1;
640 bool ls32WasRead = false;
641
642 const char *tmpBackup = *ptr;
643
644 // count the number of (h16 ":") on the right of ::
645 for (;;) {
646 tmpBackup = *ptr;
647 if (!_h16(ptr)) {
648 if (!_ls32(ptr)) {
649 if (rightHexColons != 0) {
650 *ptr = ptrBackup;
651 return false;
652 }
653
654 // the address ended with :: (case 9)
655 // only valid if 1 <= leftHexColons <= 7
656 canBeCase = 9;
657 } else {
658 ls32WasRead = true;
659 }
660 break;
661 }
662 ++rightHexColons;
663 if (**ptr != ':') {
664 // no colon could mean that what was read as an h16
665 // was in fact the first part of an ls32. we backtrack
666 // and retry.
667 const char *pb = *ptr;
668 *ptr = tmpBackup;
669 if (_ls32(ptr)) {
670 ls32WasRead = true;
671 --rightHexColons;
672 } else {
673 *ptr = pb;
674 // address ends with only 1 h16 after :: (case 8)
675 if (rightHexColons == 1)
676 canBeCase = 8;
677 }
678 break;
679 }
680 ++(*ptr);
681 }
682
683 // determine which case it is based on the number of rightHexColons
684 if (canBeCase == -1) {
685
686 // check if a ls32 was read. If it wasn't and rightHexColons >= 2 then the
687 // last 2 HexColons are in fact a ls32
688 if (!ls32WasRead && rightHexColons >= 2)
689 rightHexColons -= 2;
690
691 canBeCase = 7 - rightHexColons;
692 }
693
694 // based on the case we need to check that the number of leftHexColons is valid
695 if (leftHexColons > (canBeCase - 2)) {
696 *ptr = ptrBackup;
697 return false;
698 }
699
700 return true;
701}
702
703// IP-literal = "[" ( IPv6address / IPvFuture ) "]"
704static bool QT_FASTCALL _IPLiteral(const char **ptr)
705{
706 const char *ptrBackup = *ptr;
707 if (**ptr != '[')
708 return false;
709 ++(*ptr);
710
711 if (!_IPv6Address(ptr) && !_IPvFuture(ptr)) {
712 *ptr = ptrBackup;
713 return false;
714 }
715
716 if (**ptr != ']') {
717 *ptr = ptrBackup;
718 return false;
719 }
720 ++(*ptr);
721
722 return true;
723}
724
725// reg-name = *( unreserved / pct-encoded / sub-delims )
726static void QT_FASTCALL _regName(const char **ptr)
727{
728 for (;;) {
729 if (!_unreserved(ptr) && !_subDelims(ptr)) {
730 if (!_pctEncoded(ptr))
731 break;
732 }
733 }
734}
735
736// host = IP-literal / IPv4address / reg-name
737static void QT_FASTCALL _host(const char **ptr, QUrlParseData *parseData)
738{
739 parseData->host = *ptr;
740 if (!_IPLiteral(ptr)) {
741 if (_IPv4Address(ptr)) {
742 char ch = **ptr;
743 if (ch && ch != ':' && ch != '/') {
744 // reset
745 *ptr = parseData->host;
746 _regName(ptr);
747 }
748 } else {
749 _regName(ptr);
750 }
751 }
752 parseData->hostLength = *ptr - parseData->host;
753}
754
755// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
756static void QT_FASTCALL _userInfo(const char **ptr, QUrlParseData *parseData)
757{
758 parseData->userInfo = *ptr;
759 for (;;) {
760 if (_unreserved(ptr) || _subDelims(ptr)) {
761 ;
762 } else {
763 if (_pctEncoded(ptr)) {
764 ;
765 } else if (**ptr == ':') {
766 parseData->userInfoDelimIndex = *ptr - parseData->userInfo;
767 ++(*ptr);
768 } else {
769 break;
770 }
771 }
772 }
773 if (**ptr != '@') {
774 *ptr = parseData->userInfo;
775 parseData->userInfoDelimIndex = -1;
776 return;
777 }
778 parseData->userInfoLength = *ptr - parseData->userInfo;
779 ++(*ptr);
780}
781
782// port = *DIGIT
783static void QT_FASTCALL _port(const char **ptr, int *port)
784{
785 bool first = true;
786
787 for (;;) {
788 const char *ptrBackup = *ptr;
789 char ch = *((*ptr)++);
790 if (ch < '0' || ch > '9') {
791 *ptr = ptrBackup;
792 break;
793 }
794
795 if (first) {
796 first = false;
797 *port = 0;
798 }
799
800 *port *= 10;
801 *port += ch - '0';
802 }
803}
804
805// authority = [ userinfo "@" ] host [ ":" port ]
806static void QT_FASTCALL _authority(const char **ptr, QUrlParseData *parseData)
807{
808 _userInfo(ptr, parseData);
809 _host(ptr, parseData);
810
811 if (**ptr != ':')
812 return;
813
814 ++(*ptr);
815 _port(ptr, &parseData->port);
816}
817
818// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
819static bool QT_FASTCALL _pchar(const char **ptr)
820{
821 char c = *(*ptr);
822
823 switch (c) {
824 case '!': case '$': case '&': case '\'': case '(': case ')': case '*':
825 case '+': case ',': case ';': case '=': case ':': case '@':
826 case '-': case '.': case '_': case '~':
827 ++(*ptr);
828 return true;
829 default:
830 break;
831 };
832
833 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) {
834 ++(*ptr);
835 return true;
836 }
837
838 if (_pctEncoded(ptr))
839 return true;
840
841 return false;
842}
843
844// segment = *pchar
845static bool QT_FASTCALL _segmentNZ(const char **ptr)
846{
847 if (!_pchar(ptr))
848 return false;
849
850 while(_pchar(ptr))
851 ;
852
853 return true;
854}
855
856// path-abempty = *( "/" segment )
857static void QT_FASTCALL _pathAbEmpty(const char **ptr)
858{
859 for (;;) {
860 if (**ptr != '/')
861 break;
862 ++(*ptr);
863
864 while (_pchar(ptr))
865 ;
866 }
867}
868
869// path-abs = "/" [ segment-nz *( "/" segment ) ]
870static bool QT_FASTCALL _pathAbs(const char **ptr)
871{
872 // **ptr == '/' already checked in caller
873 ++(*ptr);
874
875 // we might be able to unnest this to gain some performance.
876 if (!_segmentNZ(ptr))
877 return true;
878
879 _pathAbEmpty(ptr);
880
881 return true;
882}
883
884// path-rootless = segment-nz *( "/" segment )
885static bool QT_FASTCALL _pathRootless(const char **ptr)
886{
887 // we might be able to unnest this to gain some performance.
888 if (!_segmentNZ(ptr))
889 return false;
890
891 _pathAbEmpty(ptr);
892
893 return true;
894}
895
896
897// hier-part = "//" authority path-abempty
898// / path-abs
899// / path-rootless
900// / path-empty
901static void QT_FASTCALL _hierPart(const char **ptr, QUrlParseData *parseData)
902{
903 const char *ptrBackup = *ptr;
904 const char *pathStart = 0;
905 if (*((*ptr)++) == '/' && *((*ptr)++) == '/') {
906 _authority(ptr, parseData);
907 pathStart = *ptr;
908 _pathAbEmpty(ptr);
909 } else {
910 *ptr = ptrBackup;
911 pathStart = *ptr;
912 if (**ptr == '/')
913 _pathAbs(ptr);
914 else
915 _pathRootless(ptr);
916 }
917 parseData->path = pathStart;
918 parseData->pathLength = *ptr - pathStart;
919}
920
921// query = *( pchar / "/" / "?" )
922static void QT_FASTCALL _query(const char **ptr, QUrlParseData *parseData)
923{
924 parseData->query = *ptr;
925 for (;;) {
926 if (_pchar(ptr)) {
927 ;
928 } else if (**ptr == '/' || **ptr == '?') {
929 ++(*ptr);
930 } else {
931 break;
932 }
933 }
934 parseData->queryLength = *ptr - parseData->query;
935}
936
937// fragment = *( pchar / "/" / "?" )
938static void QT_FASTCALL _fragment(const char **ptr, QUrlParseData *parseData)
939{
940 parseData->fragment = *ptr;
941 for (;;) {
942 if (_pchar(ptr)) {
943 ;
944 } else if (**ptr == '/' || **ptr == '?' || **ptr == '#') {
945 ++(*ptr);
946 } else {
947 break;
948 }
949 }
950 parseData->fragmentLength = *ptr - parseData->fragment;
951}
952
953struct NameprepCaseFoldingEntry {
954 int uc;
955 ushort mapping[4];
956};
957
958inline bool operator<(int one, const NameprepCaseFoldingEntry &other)
959{ return one < other.uc; }
960
961inline bool operator<(const NameprepCaseFoldingEntry &one, int other)
962{ return one.uc < other; }
963
964static const NameprepCaseFoldingEntry NameprepCaseFolding[] = {
965/* { 0x0041, { 0x0061, 0x0000, 0x0000, 0x0000 } },
966 { 0x0042, { 0x0062, 0x0000, 0x0000, 0x0000 } },
967 { 0x0043, { 0x0063, 0x0000, 0x0000, 0x0000 } },
968 { 0x0044, { 0x0064, 0x0000, 0x0000, 0x0000 } },
969 { 0x0045, { 0x0065, 0x0000, 0x0000, 0x0000 } },
970 { 0x0046, { 0x0066, 0x0000, 0x0000, 0x0000 } },
971 { 0x0047, { 0x0067, 0x0000, 0x0000, 0x0000 } },
972 { 0x0048, { 0x0068, 0x0000, 0x0000, 0x0000 } },
973 { 0x0049, { 0x0069, 0x0000, 0x0000, 0x0000 } },
974 { 0x004A, { 0x006A, 0x0000, 0x0000, 0x0000 } },
975 { 0x004B, { 0x006B, 0x0000, 0x0000, 0x0000 } },
976 { 0x004C, { 0x006C, 0x0000, 0x0000, 0x0000 } },
977 { 0x004D, { 0x006D, 0x0000, 0x0000, 0x0000 } },
978 { 0x004E, { 0x006E, 0x0000, 0x0000, 0x0000 } },
979 { 0x004F, { 0x006F, 0x0000, 0x0000, 0x0000 } },
980 { 0x0050, { 0x0070, 0x0000, 0x0000, 0x0000 } },
981 { 0x0051, { 0x0071, 0x0000, 0x0000, 0x0000 } },
982 { 0x0052, { 0x0072, 0x0000, 0x0000, 0x0000 } },
983 { 0x0053, { 0x0073, 0x0000, 0x0000, 0x0000 } },
984 { 0x0054, { 0x0074, 0x0000, 0x0000, 0x0000 } },
985 { 0x0055, { 0x0075, 0x0000, 0x0000, 0x0000 } },
986 { 0x0056, { 0x0076, 0x0000, 0x0000, 0x0000 } },
987 { 0x0057, { 0x0077, 0x0000, 0x0000, 0x0000 } },
988 { 0x0058, { 0x0078, 0x0000, 0x0000, 0x0000 } },
989 { 0x0059, { 0x0079, 0x0000, 0x0000, 0x0000 } },
990 { 0x005A, { 0x007A, 0x0000, 0x0000, 0x0000 } },*/
991 { 0x00B5, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
992 { 0x00C0, { 0x00E0, 0x0000, 0x0000, 0x0000 } },
993 { 0x00C1, { 0x00E1, 0x0000, 0x0000, 0x0000 } },
994 { 0x00C2, { 0x00E2, 0x0000, 0x0000, 0x0000 } },
995 { 0x00C3, { 0x00E3, 0x0000, 0x0000, 0x0000 } },
996 { 0x00C4, { 0x00E4, 0x0000, 0x0000, 0x0000 } },
997 { 0x00C5, { 0x00E5, 0x0000, 0x0000, 0x0000 } },
998 { 0x00C6, { 0x00E6, 0x0000, 0x0000, 0x0000 } },
999 { 0x00C7, { 0x00E7, 0x0000, 0x0000, 0x0000 } },
1000 { 0x00C8, { 0x00E8, 0x0000, 0x0000, 0x0000 } },
1001 { 0x00C9, { 0x00E9, 0x0000, 0x0000, 0x0000 } },
1002 { 0x00CA, { 0x00EA, 0x0000, 0x0000, 0x0000 } },
1003 { 0x00CB, { 0x00EB, 0x0000, 0x0000, 0x0000 } },
1004 { 0x00CC, { 0x00EC, 0x0000, 0x0000, 0x0000 } },
1005 { 0x00CD, { 0x00ED, 0x0000, 0x0000, 0x0000 } },
1006 { 0x00CE, { 0x00EE, 0x0000, 0x0000, 0x0000 } },
1007 { 0x00CF, { 0x00EF, 0x0000, 0x0000, 0x0000 } },
1008 { 0x00D0, { 0x00F0, 0x0000, 0x0000, 0x0000 } },
1009 { 0x00D1, { 0x00F1, 0x0000, 0x0000, 0x0000 } },
1010 { 0x00D2, { 0x00F2, 0x0000, 0x0000, 0x0000 } },
1011 { 0x00D3, { 0x00F3, 0x0000, 0x0000, 0x0000 } },
1012 { 0x00D4, { 0x00F4, 0x0000, 0x0000, 0x0000 } },
1013 { 0x00D5, { 0x00F5, 0x0000, 0x0000, 0x0000 } },
1014 { 0x00D6, { 0x00F6, 0x0000, 0x0000, 0x0000 } },
1015 { 0x00D8, { 0x00F8, 0x0000, 0x0000, 0x0000 } },
1016 { 0x00D9, { 0x00F9, 0x0000, 0x0000, 0x0000 } },
1017 { 0x00DA, { 0x00FA, 0x0000, 0x0000, 0x0000 } },
1018 { 0x00DB, { 0x00FB, 0x0000, 0x0000, 0x0000 } },
1019 { 0x00DC, { 0x00FC, 0x0000, 0x0000, 0x0000 } },
1020 { 0x00DD, { 0x00FD, 0x0000, 0x0000, 0x0000 } },
1021 { 0x00DE, { 0x00FE, 0x0000, 0x0000, 0x0000 } },
1022 { 0x00DF, { 0x0073, 0x0073, 0x0000, 0x0000 } },
1023 { 0x0100, { 0x0101, 0x0000, 0x0000, 0x0000 } },
1024 { 0x0102, { 0x0103, 0x0000, 0x0000, 0x0000 } },
1025 { 0x0104, { 0x0105, 0x0000, 0x0000, 0x0000 } },
1026 { 0x0106, { 0x0107, 0x0000, 0x0000, 0x0000 } },
1027 { 0x0108, { 0x0109, 0x0000, 0x0000, 0x0000 } },
1028 { 0x010A, { 0x010B, 0x0000, 0x0000, 0x0000 } },
1029 { 0x010C, { 0x010D, 0x0000, 0x0000, 0x0000 } },
1030 { 0x010E, { 0x010F, 0x0000, 0x0000, 0x0000 } },
1031 { 0x0110, { 0x0111, 0x0000, 0x0000, 0x0000 } },
1032 { 0x0112, { 0x0113, 0x0000, 0x0000, 0x0000 } },
1033 { 0x0114, { 0x0115, 0x0000, 0x0000, 0x0000 } },
1034 { 0x0116, { 0x0117, 0x0000, 0x0000, 0x0000 } },
1035 { 0x0118, { 0x0119, 0x0000, 0x0000, 0x0000 } },
1036 { 0x011A, { 0x011B, 0x0000, 0x0000, 0x0000 } },
1037 { 0x011C, { 0x011D, 0x0000, 0x0000, 0x0000 } },
1038 { 0x011E, { 0x011F, 0x0000, 0x0000, 0x0000 } },
1039 { 0x0120, { 0x0121, 0x0000, 0x0000, 0x0000 } },
1040 { 0x0122, { 0x0123, 0x0000, 0x0000, 0x0000 } },
1041 { 0x0124, { 0x0125, 0x0000, 0x0000, 0x0000 } },
1042 { 0x0126, { 0x0127, 0x0000, 0x0000, 0x0000 } },
1043 { 0x0128, { 0x0129, 0x0000, 0x0000, 0x0000 } },
1044 { 0x012A, { 0x012B, 0x0000, 0x0000, 0x0000 } },
1045 { 0x012C, { 0x012D, 0x0000, 0x0000, 0x0000 } },
1046 { 0x012E, { 0x012F, 0x0000, 0x0000, 0x0000 } },
1047 { 0x0130, { 0x0069, 0x0307, 0x0000, 0x0000 } },
1048 { 0x0132, { 0x0133, 0x0000, 0x0000, 0x0000 } },
1049 { 0x0134, { 0x0135, 0x0000, 0x0000, 0x0000 } },
1050 { 0x0136, { 0x0137, 0x0000, 0x0000, 0x0000 } },
1051 { 0x0139, { 0x013A, 0x0000, 0x0000, 0x0000 } },
1052 { 0x013B, { 0x013C, 0x0000, 0x0000, 0x0000 } },
1053 { 0x013D, { 0x013E, 0x0000, 0x0000, 0x0000 } },
1054 { 0x013F, { 0x0140, 0x0000, 0x0000, 0x0000 } },
1055 { 0x0141, { 0x0142, 0x0000, 0x0000, 0x0000 } },
1056 { 0x0143, { 0x0144, 0x0000, 0x0000, 0x0000 } },
1057 { 0x0145, { 0x0146, 0x0000, 0x0000, 0x0000 } },
1058 { 0x0147, { 0x0148, 0x0000, 0x0000, 0x0000 } },
1059 { 0x0149, { 0x02BC, 0x006E, 0x0000, 0x0000 } },
1060 { 0x014A, { 0x014B, 0x0000, 0x0000, 0x0000 } },
1061 { 0x014C, { 0x014D, 0x0000, 0x0000, 0x0000 } },
1062 { 0x014E, { 0x014F, 0x0000, 0x0000, 0x0000 } },
1063 { 0x0150, { 0x0151, 0x0000, 0x0000, 0x0000 } },
1064 { 0x0152, { 0x0153, 0x0000, 0x0000, 0x0000 } },
1065 { 0x0154, { 0x0155, 0x0000, 0x0000, 0x0000 } },
1066 { 0x0156, { 0x0157, 0x0000, 0x0000, 0x0000 } },
1067 { 0x0158, { 0x0159, 0x0000, 0x0000, 0x0000 } },
1068 { 0x015A, { 0x015B, 0x0000, 0x0000, 0x0000 } },
1069 { 0x015C, { 0x015D, 0x0000, 0x0000, 0x0000 } },
1070 { 0x015E, { 0x015F, 0x0000, 0x0000, 0x0000 } },
1071 { 0x0160, { 0x0161, 0x0000, 0x0000, 0x0000 } },
1072 { 0x0162, { 0x0163, 0x0000, 0x0000, 0x0000 } },
1073 { 0x0164, { 0x0165, 0x0000, 0x0000, 0x0000 } },
1074 { 0x0166, { 0x0167, 0x0000, 0x0000, 0x0000 } },
1075 { 0x0168, { 0x0169, 0x0000, 0x0000, 0x0000 } },
1076 { 0x016A, { 0x016B, 0x0000, 0x0000, 0x0000 } },
1077 { 0x016C, { 0x016D, 0x0000, 0x0000, 0x0000 } },
1078 { 0x016E, { 0x016F, 0x0000, 0x0000, 0x0000 } },
1079 { 0x0170, { 0x0171, 0x0000, 0x0000, 0x0000 } },
1080 { 0x0172, { 0x0173, 0x0000, 0x0000, 0x0000 } },
1081 { 0x0174, { 0x0175, 0x0000, 0x0000, 0x0000 } },
1082 { 0x0176, { 0x0177, 0x0000, 0x0000, 0x0000 } },
1083 { 0x0178, { 0x00FF, 0x0000, 0x0000, 0x0000 } },
1084 { 0x0179, { 0x017A, 0x0000, 0x0000, 0x0000 } },
1085 { 0x017B, { 0x017C, 0x0000, 0x0000, 0x0000 } },
1086 { 0x017D, { 0x017E, 0x0000, 0x0000, 0x0000 } },
1087 { 0x017F, { 0x0073, 0x0000, 0x0000, 0x0000 } },
1088 { 0x0181, { 0x0253, 0x0000, 0x0000, 0x0000 } },
1089 { 0x0182, { 0x0183, 0x0000, 0x0000, 0x0000 } },
1090 { 0x0184, { 0x0185, 0x0000, 0x0000, 0x0000 } },
1091 { 0x0186, { 0x0254, 0x0000, 0x0000, 0x0000 } },
1092 { 0x0187, { 0x0188, 0x0000, 0x0000, 0x0000 } },
1093 { 0x0189, { 0x0256, 0x0000, 0x0000, 0x0000 } },
1094 { 0x018A, { 0x0257, 0x0000, 0x0000, 0x0000 } },
1095 { 0x018B, { 0x018C, 0x0000, 0x0000, 0x0000 } },
1096 { 0x018E, { 0x01DD, 0x0000, 0x0000, 0x0000 } },
1097 { 0x018F, { 0x0259, 0x0000, 0x0000, 0x0000 } },
1098 { 0x0190, { 0x025B, 0x0000, 0x0000, 0x0000 } },
1099 { 0x0191, { 0x0192, 0x0000, 0x0000, 0x0000 } },
1100 { 0x0193, { 0x0260, 0x0000, 0x0000, 0x0000 } },
1101 { 0x0194, { 0x0263, 0x0000, 0x0000, 0x0000 } },
1102 { 0x0196, { 0x0269, 0x0000, 0x0000, 0x0000 } },
1103 { 0x0197, { 0x0268, 0x0000, 0x0000, 0x0000 } },
1104 { 0x0198, { 0x0199, 0x0000, 0x0000, 0x0000 } },
1105 { 0x019C, { 0x026F, 0x0000, 0x0000, 0x0000 } },
1106 { 0x019D, { 0x0272, 0x0000, 0x0000, 0x0000 } },
1107 { 0x019F, { 0x0275, 0x0000, 0x0000, 0x0000 } },
1108 { 0x01A0, { 0x01A1, 0x0000, 0x0000, 0x0000 } },
1109 { 0x01A2, { 0x01A3, 0x0000, 0x0000, 0x0000 } },
1110 { 0x01A4, { 0x01A5, 0x0000, 0x0000, 0x0000 } },
1111 { 0x01A6, { 0x0280, 0x0000, 0x0000, 0x0000 } },
1112 { 0x01A7, { 0x01A8, 0x0000, 0x0000, 0x0000 } },
1113 { 0x01A9, { 0x0283, 0x0000, 0x0000, 0x0000 } },
1114 { 0x01AC, { 0x01AD, 0x0000, 0x0000, 0x0000 } },
1115 { 0x01AE, { 0x0288, 0x0000, 0x0000, 0x0000 } },
1116 { 0x01AF, { 0x01B0, 0x0000, 0x0000, 0x0000 } },
1117 { 0x01B1, { 0x028A, 0x0000, 0x0000, 0x0000 } },
1118 { 0x01B2, { 0x028B, 0x0000, 0x0000, 0x0000 } },
1119 { 0x01B3, { 0x01B4, 0x0000, 0x0000, 0x0000 } },
1120 { 0x01B5, { 0x01B6, 0x0000, 0x0000, 0x0000 } },
1121 { 0x01B7, { 0x0292, 0x0000, 0x0000, 0x0000 } },
1122 { 0x01B8, { 0x01B9, 0x0000, 0x0000, 0x0000 } },
1123 { 0x01BC, { 0x01BD, 0x0000, 0x0000, 0x0000 } },
1124 { 0x01C4, { 0x01C6, 0x0000, 0x0000, 0x0000 } },
1125 { 0x01C5, { 0x01C6, 0x0000, 0x0000, 0x0000 } },
1126 { 0x01C7, { 0x01C9, 0x0000, 0x0000, 0x0000 } },
1127 { 0x01C8, { 0x01C9, 0x0000, 0x0000, 0x0000 } },
1128 { 0x01CA, { 0x01CC, 0x0000, 0x0000, 0x0000 } },
1129 { 0x01CB, { 0x01CC, 0x0000, 0x0000, 0x0000 } },
1130 { 0x01CD, { 0x01CE, 0x0000, 0x0000, 0x0000 } },
1131 { 0x01CF, { 0x01D0, 0x0000, 0x0000, 0x0000 } },
1132 { 0x01D1, { 0x01D2, 0x0000, 0x0000, 0x0000 } },
1133 { 0x01D3, { 0x01D4, 0x0000, 0x0000, 0x0000 } },
1134 { 0x01D5, { 0x01D6, 0x0000, 0x0000, 0x0000 } },
1135 { 0x01D7, { 0x01D8, 0x0000, 0x0000, 0x0000 } },
1136 { 0x01D9, { 0x01DA, 0x0000, 0x0000, 0x0000 } },
1137 { 0x01DB, { 0x01DC, 0x0000, 0x0000, 0x0000 } },
1138 { 0x01DE, { 0x01DF, 0x0000, 0x0000, 0x0000 } },
1139 { 0x01E0, { 0x01E1, 0x0000, 0x0000, 0x0000 } },
1140 { 0x01E2, { 0x01E3, 0x0000, 0x0000, 0x0000 } },
1141 { 0x01E4, { 0x01E5, 0x0000, 0x0000, 0x0000 } },
1142 { 0x01E6, { 0x01E7, 0x0000, 0x0000, 0x0000 } },
1143 { 0x01E8, { 0x01E9, 0x0000, 0x0000, 0x0000 } },
1144 { 0x01EA, { 0x01EB, 0x0000, 0x0000, 0x0000 } },
1145 { 0x01EC, { 0x01ED, 0x0000, 0x0000, 0x0000 } },
1146 { 0x01EE, { 0x01EF, 0x0000, 0x0000, 0x0000 } },
1147 { 0x01F0, { 0x006A, 0x030C, 0x0000, 0x0000 } },
1148 { 0x01F1, { 0x01F3, 0x0000, 0x0000, 0x0000 } },
1149 { 0x01F2, { 0x01F3, 0x0000, 0x0000, 0x0000 } },
1150 { 0x01F4, { 0x01F5, 0x0000, 0x0000, 0x0000 } },
1151 { 0x01F6, { 0x0195, 0x0000, 0x0000, 0x0000 } },
1152 { 0x01F7, { 0x01BF, 0x0000, 0x0000, 0x0000 } },
1153 { 0x01F8, { 0x01F9, 0x0000, 0x0000, 0x0000 } },
1154 { 0x01FA, { 0x01FB, 0x0000, 0x0000, 0x0000 } },
1155 { 0x01FC, { 0x01FD, 0x0000, 0x0000, 0x0000 } },
1156 { 0x01FE, { 0x01FF, 0x0000, 0x0000, 0x0000 } },
1157 { 0x0200, { 0x0201, 0x0000, 0x0000, 0x0000 } },
1158 { 0x0202, { 0x0203, 0x0000, 0x0000, 0x0000 } },
1159 { 0x0204, { 0x0205, 0x0000, 0x0000, 0x0000 } },
1160 { 0x0206, { 0x0207, 0x0000, 0x0000, 0x0000 } },
1161 { 0x0208, { 0x0209, 0x0000, 0x0000, 0x0000 } },
1162 { 0x020A, { 0x020B, 0x0000, 0x0000, 0x0000 } },
1163 { 0x020C, { 0x020D, 0x0000, 0x0000, 0x0000 } },
1164 { 0x020E, { 0x020F, 0x0000, 0x0000, 0x0000 } },
1165 { 0x0210, { 0x0211, 0x0000, 0x0000, 0x0000 } },
1166 { 0x0212, { 0x0213, 0x0000, 0x0000, 0x0000 } },
1167 { 0x0214, { 0x0215, 0x0000, 0x0000, 0x0000 } },
1168 { 0x0216, { 0x0217, 0x0000, 0x0000, 0x0000 } },
1169 { 0x0218, { 0x0219, 0x0000, 0x0000, 0x0000 } },
1170 { 0x021A, { 0x021B, 0x0000, 0x0000, 0x0000 } },
1171 { 0x021C, { 0x021D, 0x0000, 0x0000, 0x0000 } },
1172 { 0x021E, { 0x021F, 0x0000, 0x0000, 0x0000 } },
1173 { 0x0220, { 0x019E, 0x0000, 0x0000, 0x0000 } },
1174 { 0x0222, { 0x0223, 0x0000, 0x0000, 0x0000 } },
1175 { 0x0224, { 0x0225, 0x0000, 0x0000, 0x0000 } },
1176 { 0x0226, { 0x0227, 0x0000, 0x0000, 0x0000 } },
1177 { 0x0228, { 0x0229, 0x0000, 0x0000, 0x0000 } },
1178 { 0x022A, { 0x022B, 0x0000, 0x0000, 0x0000 } },
1179 { 0x022C, { 0x022D, 0x0000, 0x0000, 0x0000 } },
1180 { 0x022E, { 0x022F, 0x0000, 0x0000, 0x0000 } },
1181 { 0x0230, { 0x0231, 0x0000, 0x0000, 0x0000 } },
1182 { 0x0232, { 0x0233, 0x0000, 0x0000, 0x0000 } },
1183 { 0x0345, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
1184 { 0x037A, { 0x0020, 0x03B9, 0x0000, 0x0000 } },
1185 { 0x0386, { 0x03AC, 0x0000, 0x0000, 0x0000 } },
1186 { 0x0388, { 0x03AD, 0x0000, 0x0000, 0x0000 } },
1187 { 0x0389, { 0x03AE, 0x0000, 0x0000, 0x0000 } },
1188 { 0x038A, { 0x03AF, 0x0000, 0x0000, 0x0000 } },
1189 { 0x038C, { 0x03CC, 0x0000, 0x0000, 0x0000 } },
1190 { 0x038E, { 0x03CD, 0x0000, 0x0000, 0x0000 } },
1191 { 0x038F, { 0x03CE, 0x0000, 0x0000, 0x0000 } },
1192 { 0x0390, { 0x03B9, 0x0308, 0x0301, 0x0000 } },
1193 { 0x0391, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
1194 { 0x0392, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
1195 { 0x0393, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
1196 { 0x0394, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
1197 { 0x0395, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
1198 { 0x0396, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
1199 { 0x0397, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
1200 { 0x0398, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
1201 { 0x0399, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
1202 { 0x039A, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
1203 { 0x039B, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
1204 { 0x039C, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
1205 { 0x039D, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
1206 { 0x039E, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
1207 { 0x039F, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
1208 { 0x03A0, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
1209 { 0x03A1, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
1210 { 0x03A3, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
1211 { 0x03A4, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
1212 { 0x03A5, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
1213 { 0x03A6, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
1214 { 0x03A7, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
1215 { 0x03A8, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
1216 { 0x03A9, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
1217 { 0x03AA, { 0x03CA, 0x0000, 0x0000, 0x0000 } },
1218 { 0x03AB, { 0x03CB, 0x0000, 0x0000, 0x0000 } },
1219 { 0x03B0, { 0x03C5, 0x0308, 0x0301, 0x0000 } },
1220 { 0x03C2, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
1221 { 0x03D0, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
1222 { 0x03D1, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
1223 { 0x03D2, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
1224 { 0x03D3, { 0x03CD, 0x0000, 0x0000, 0x0000 } },
1225 { 0x03D4, { 0x03CB, 0x0000, 0x0000, 0x0000 } },
1226 { 0x03D5, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
1227 { 0x03D6, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
1228 { 0x03D8, { 0x03D9, 0x0000, 0x0000, 0x0000 } },
1229 { 0x03DA, { 0x03DB, 0x0000, 0x0000, 0x0000 } },
1230 { 0x03DC, { 0x03DD, 0x0000, 0x0000, 0x0000 } },
1231 { 0x03DE, { 0x03DF, 0x0000, 0x0000, 0x0000 } },
1232 { 0x03E0, { 0x03E1, 0x0000, 0x0000, 0x0000 } },
1233 { 0x03E2, { 0x03E3, 0x0000, 0x0000, 0x0000 } },
1234 { 0x03E4, { 0x03E5, 0x0000, 0x0000, 0x0000 } },
1235 { 0x03E6, { 0x03E7, 0x0000, 0x0000, 0x0000 } },
1236 { 0x03E8, { 0x03E9, 0x0000, 0x0000, 0x0000 } },
1237 { 0x03EA, { 0x03EB, 0x0000, 0x0000, 0x0000 } },
1238 { 0x03EC, { 0x03ED, 0x0000, 0x0000, 0x0000 } },
1239 { 0x03EE, { 0x03EF, 0x0000, 0x0000, 0x0000 } },
1240 { 0x03F0, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
1241 { 0x03F1, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
1242 { 0x03F2, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
1243 { 0x03F4, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
1244 { 0x03F5, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
1245 { 0x0400, { 0x0450, 0x0000, 0x0000, 0x0000 } },
1246 { 0x0401, { 0x0451, 0x0000, 0x0000, 0x0000 } },
1247 { 0x0402, { 0x0452, 0x0000, 0x0000, 0x0000 } },
1248 { 0x0403, { 0x0453, 0x0000, 0x0000, 0x0000 } },
1249 { 0x0404, { 0x0454, 0x0000, 0x0000, 0x0000 } },
1250 { 0x0405, { 0x0455, 0x0000, 0x0000, 0x0000 } },
1251 { 0x0406, { 0x0456, 0x0000, 0x0000, 0x0000 } },
1252 { 0x0407, { 0x0457, 0x0000, 0x0000, 0x0000 } },
1253 { 0x0408, { 0x0458, 0x0000, 0x0000, 0x0000 } },
1254 { 0x0409, { 0x0459, 0x0000, 0x0000, 0x0000 } },
1255 { 0x040A, { 0x045A, 0x0000, 0x0000, 0x0000 } },
1256 { 0x040B, { 0x045B, 0x0000, 0x0000, 0x0000 } },
1257 { 0x040C, { 0x045C, 0x0000, 0x0000, 0x0000 } },
1258 { 0x040D, { 0x045D, 0x0000, 0x0000, 0x0000 } },
1259 { 0x040E, { 0x045E, 0x0000, 0x0000, 0x0000 } },
1260 { 0x040F, { 0x045F, 0x0000, 0x0000, 0x0000 } },
1261 { 0x0410, { 0x0430, 0x0000, 0x0000, 0x0000 } },
1262 { 0x0411, { 0x0431, 0x0000, 0x0000, 0x0000 } },
1263 { 0x0412, { 0x0432, 0x0000, 0x0000, 0x0000 } },
1264 { 0x0413, { 0x0433, 0x0000, 0x0000, 0x0000 } },
1265 { 0x0414, { 0x0434, 0x0000, 0x0000, 0x0000 } },
1266 { 0x0415, { 0x0435, 0x0000, 0x0000, 0x0000 } },
1267 { 0x0416, { 0x0436, 0x0000, 0x0000, 0x0000 } },
1268 { 0x0417, { 0x0437, 0x0000, 0x0000, 0x0000 } },
1269 { 0x0418, { 0x0438, 0x0000, 0x0000, 0x0000 } },
1270 { 0x0419, { 0x0439, 0x0000, 0x0000, 0x0000 } },
1271 { 0x041A, { 0x043A, 0x0000, 0x0000, 0x0000 } },
1272 { 0x041B, { 0x043B, 0x0000, 0x0000, 0x0000 } },
1273 { 0x041C, { 0x043C, 0x0000, 0x0000, 0x0000 } },
1274 { 0x041D, { 0x043D, 0x0000, 0x0000, 0x0000 } },
1275 { 0x041E, { 0x043E, 0x0000, 0x0000, 0x0000 } },
1276 { 0x041F, { 0x043F, 0x0000, 0x0000, 0x0000 } },
1277 { 0x0420, { 0x0440, 0x0000, 0x0000, 0x0000 } },
1278 { 0x0421, { 0x0441, 0x0000, 0x0000, 0x0000 } },
1279 { 0x0422, { 0x0442, 0x0000, 0x0000, 0x0000 } },
1280 { 0x0423, { 0x0443, 0x0000, 0x0000, 0x0000 } },
1281 { 0x0424, { 0x0444, 0x0000, 0x0000, 0x0000 } },
1282 { 0x0425, { 0x0445, 0x0000, 0x0000, 0x0000 } },
1283 { 0x0426, { 0x0446, 0x0000, 0x0000, 0x0000 } },
1284 { 0x0427, { 0x0447, 0x0000, 0x0000, 0x0000 } },
1285 { 0x0428, { 0x0448, 0x0000, 0x0000, 0x0000 } },
1286 { 0x0429, { 0x0449, 0x0000, 0x0000, 0x0000 } },
1287 { 0x042A, { 0x044A, 0x0000, 0x0000, 0x0000 } },
1288 { 0x042B, { 0x044B, 0x0000, 0x0000, 0x0000 } },
1289 { 0x042C, { 0x044C, 0x0000, 0x0000, 0x0000 } },
1290 { 0x042D, { 0x044D, 0x0000, 0x0000, 0x0000 } },
1291 { 0x042E, { 0x044E, 0x0000, 0x0000, 0x0000 } },
1292 { 0x042F, { 0x044F, 0x0000, 0x0000, 0x0000 } },
1293 { 0x0460, { 0x0461, 0x0000, 0x0000, 0x0000 } },
1294 { 0x0462, { 0x0463, 0x0000, 0x0000, 0x0000 } },
1295 { 0x0464, { 0x0465, 0x0000, 0x0000, 0x0000 } },
1296 { 0x0466, { 0x0467, 0x0000, 0x0000, 0x0000 } },
1297 { 0x0468, { 0x0469, 0x0000, 0x0000, 0x0000 } },
1298 { 0x046A, { 0x046B, 0x0000, 0x0000, 0x0000 } },
1299 { 0x046C, { 0x046D, 0x0000, 0x0000, 0x0000 } },
1300 { 0x046E, { 0x046F, 0x0000, 0x0000, 0x0000 } },
1301 { 0x0470, { 0x0471, 0x0000, 0x0000, 0x0000 } },
1302 { 0x0472, { 0x0473, 0x0000, 0x0000, 0x0000 } },
1303 { 0x0474, { 0x0475, 0x0000, 0x0000, 0x0000 } },
1304 { 0x0476, { 0x0477, 0x0000, 0x0000, 0x0000 } },
1305 { 0x0478, { 0x0479, 0x0000, 0x0000, 0x0000 } },
1306 { 0x047A, { 0x047B, 0x0000, 0x0000, 0x0000 } },
1307 { 0x047C, { 0x047D, 0x0000, 0x0000, 0x0000 } },
1308 { 0x047E, { 0x047F, 0x0000, 0x0000, 0x0000 } },
1309 { 0x0480, { 0x0481, 0x0000, 0x0000, 0x0000 } },
1310 { 0x048A, { 0x048B, 0x0000, 0x0000, 0x0000 } },
1311 { 0x048C, { 0x048D, 0x0000, 0x0000, 0x0000 } },
1312 { 0x048E, { 0x048F, 0x0000, 0x0000, 0x0000 } },
1313 { 0x0490, { 0x0491, 0x0000, 0x0000, 0x0000 } },
1314 { 0x0492, { 0x0493, 0x0000, 0x0000, 0x0000 } },
1315 { 0x0494, { 0x0495, 0x0000, 0x0000, 0x0000 } },
1316 { 0x0496, { 0x0497, 0x0000, 0x0000, 0x0000 } },
1317 { 0x0498, { 0x0499, 0x0000, 0x0000, 0x0000 } },
1318 { 0x049A, { 0x049B, 0x0000, 0x0000, 0x0000 } },
1319 { 0x049C, { 0x049D, 0x0000, 0x0000, 0x0000 } },
1320 { 0x049E, { 0x049F, 0x0000, 0x0000, 0x0000 } },
1321 { 0x04A0, { 0x04A1, 0x0000, 0x0000, 0x0000 } },
1322 { 0x04A2, { 0x04A3, 0x0000, 0x0000, 0x0000 } },
1323 { 0x04A4, { 0x04A5, 0x0000, 0x0000, 0x0000 } },
1324 { 0x04A6, { 0x04A7, 0x0000, 0x0000, 0x0000 } },
1325 { 0x04A8, { 0x04A9, 0x0000, 0x0000, 0x0000 } },
1326 { 0x04AA, { 0x04AB, 0x0000, 0x0000, 0x0000 } },
1327 { 0x04AC, { 0x04AD, 0x0000, 0x0000, 0x0000 } },
1328 { 0x04AE, { 0x04AF, 0x0000, 0x0000, 0x0000 } },
1329 { 0x04B0, { 0x04B1, 0x0000, 0x0000, 0x0000 } },
1330 { 0x04B2, { 0x04B3, 0x0000, 0x0000, 0x0000 } },
1331 { 0x04B4, { 0x04B5, 0x0000, 0x0000, 0x0000 } },
1332 { 0x04B6, { 0x04B7, 0x0000, 0x0000, 0x0000 } },
1333 { 0x04B8, { 0x04B9, 0x0000, 0x0000, 0x0000 } },
1334 { 0x04BA, { 0x04BB, 0x0000, 0x0000, 0x0000 } },
1335 { 0x04BC, { 0x04BD, 0x0000, 0x0000, 0x0000 } },
1336 { 0x04BE, { 0x04BF, 0x0000, 0x0000, 0x0000 } },
1337 { 0x04C1, { 0x04C2, 0x0000, 0x0000, 0x0000 } },
1338 { 0x04C3, { 0x04C4, 0x0000, 0x0000, 0x0000 } },
1339 { 0x04C5, { 0x04C6, 0x0000, 0x0000, 0x0000 } },
1340 { 0x04C7, { 0x04C8, 0x0000, 0x0000, 0x0000 } },
1341 { 0x04C9, { 0x04CA, 0x0000, 0x0000, 0x0000 } },
1342 { 0x04CB, { 0x04CC, 0x0000, 0x0000, 0x0000 } },
1343 { 0x04CD, { 0x04CE, 0x0000, 0x0000, 0x0000 } },
1344 { 0x04D0, { 0x04D1, 0x0000, 0x0000, 0x0000 } },
1345 { 0x04D2, { 0x04D3, 0x0000, 0x0000, 0x0000 } },
1346 { 0x04D4, { 0x04D5, 0x0000, 0x0000, 0x0000 } },
1347 { 0x04D6, { 0x04D7, 0x0000, 0x0000, 0x0000 } },
1348 { 0x04D8, { 0x04D9, 0x0000, 0x0000, 0x0000 } },
1349 { 0x04DA, { 0x04DB, 0x0000, 0x0000, 0x0000 } },
1350 { 0x04DC, { 0x04DD, 0x0000, 0x0000, 0x0000 } },
1351 { 0x04DE, { 0x04DF, 0x0000, 0x0000, 0x0000 } },
1352 { 0x04E0, { 0x04E1, 0x0000, 0x0000, 0x0000 } },
1353 { 0x04E2, { 0x04E3, 0x0000, 0x0000, 0x0000 } },
1354 { 0x04E4, { 0x04E5, 0x0000, 0x0000, 0x0000 } },
1355 { 0x04E6, { 0x04E7, 0x0000, 0x0000, 0x0000 } },
1356 { 0x04E8, { 0x04E9, 0x0000, 0x0000, 0x0000 } },
1357 { 0x04EA, { 0x04EB, 0x0000, 0x0000, 0x0000 } },
1358 { 0x04EC, { 0x04ED, 0x0000, 0x0000, 0x0000 } },
1359 { 0x04EE, { 0x04EF, 0x0000, 0x0000, 0x0000 } },
1360 { 0x04F0, { 0x04F1, 0x0000, 0x0000, 0x0000 } },
1361 { 0x04F2, { 0x04F3, 0x0000, 0x0000, 0x0000 } },
1362 { 0x04F4, { 0x04F5, 0x0000, 0x0000, 0x0000 } },
1363 { 0x04F8, { 0x04F9, 0x0000, 0x0000, 0x0000 } },
1364 { 0x0500, { 0x0501, 0x0000, 0x0000, 0x0000 } },
1365 { 0x0502, { 0x0503, 0x0000, 0x0000, 0x0000 } },
1366 { 0x0504, { 0x0505, 0x0000, 0x0000, 0x0000 } },
1367 { 0x0506, { 0x0507, 0x0000, 0x0000, 0x0000 } },
1368 { 0x0508, { 0x0509, 0x0000, 0x0000, 0x0000 } },
1369 { 0x050A, { 0x050B, 0x0000, 0x0000, 0x0000 } },
1370 { 0x050C, { 0x050D, 0x0000, 0x0000, 0x0000 } },
1371 { 0x050E, { 0x050F, 0x0000, 0x0000, 0x0000 } },
1372 { 0x0531, { 0x0561, 0x0000, 0x0000, 0x0000 } },
1373 { 0x0532, { 0x0562, 0x0000, 0x0000, 0x0000 } },
1374 { 0x0533, { 0x0563, 0x0000, 0x0000, 0x0000 } },
1375 { 0x0534, { 0x0564, 0x0000, 0x0000, 0x0000 } },
1376 { 0x0535, { 0x0565, 0x0000, 0x0000, 0x0000 } },
1377 { 0x0536, { 0x0566, 0x0000, 0x0000, 0x0000 } },
1378 { 0x0537, { 0x0567, 0x0000, 0x0000, 0x0000 } },
1379 { 0x0538, { 0x0568, 0x0000, 0x0000, 0x0000 } },
1380 { 0x0539, { 0x0569, 0x0000, 0x0000, 0x0000 } },
1381 { 0x053A, { 0x056A, 0x0000, 0x0000, 0x0000 } },
1382 { 0x053B, { 0x056B, 0x0000, 0x0000, 0x0000 } },
1383 { 0x053C, { 0x056C, 0x0000, 0x0000, 0x0000 } },
1384 { 0x053D, { 0x056D, 0x0000, 0x0000, 0x0000 } },
1385 { 0x053E, { 0x056E, 0x0000, 0x0000, 0x0000 } },
1386 { 0x053F, { 0x056F, 0x0000, 0x0000, 0x0000 } },
1387 { 0x0540, { 0x0570, 0x0000, 0x0000, 0x0000 } },
1388 { 0x0541, { 0x0571, 0x0000, 0x0000, 0x0000 } },
1389 { 0x0542, { 0x0572, 0x0000, 0x0000, 0x0000 } },
1390 { 0x0543, { 0x0573, 0x0000, 0x0000, 0x0000 } },
1391 { 0x0544, { 0x0574, 0x0000, 0x0000, 0x0000 } },
1392 { 0x0545, { 0x0575, 0x0000, 0x0000, 0x0000 } },
1393 { 0x0546, { 0x0576, 0x0000, 0x0000, 0x0000 } },
1394 { 0x0547, { 0x0577, 0x0000, 0x0000, 0x0000 } },
1395 { 0x0548, { 0x0578, 0x0000, 0x0000, 0x0000 } },
1396 { 0x0549, { 0x0579, 0x0000, 0x0000, 0x0000 } },
1397 { 0x054A, { 0x057A, 0x0000, 0x0000, 0x0000 } },
1398 { 0x054B, { 0x057B, 0x0000, 0x0000, 0x0000 } },
1399 { 0x054C, { 0x057C, 0x0000, 0x0000, 0x0000 } },
1400 { 0x054D, { 0x057D, 0x0000, 0x0000, 0x0000 } },
1401 { 0x054E, { 0x057E, 0x0000, 0x0000, 0x0000 } },
1402 { 0x054F, { 0x057F, 0x0000, 0x0000, 0x0000 } },
1403 { 0x0550, { 0x0580, 0x0000, 0x0000, 0x0000 } },
1404 { 0x0551, { 0x0581, 0x0000, 0x0000, 0x0000 } },
1405 { 0x0552, { 0x0582, 0x0000, 0x0000, 0x0000 } },
1406 { 0x0553, { 0x0583, 0x0000, 0x0000, 0x0000 } },
1407 { 0x0554, { 0x0584, 0x0000, 0x0000, 0x0000 } },
1408 { 0x0555, { 0x0585, 0x0000, 0x0000, 0x0000 } },
1409 { 0x0556, { 0x0586, 0x0000, 0x0000, 0x0000 } },
1410 { 0x0587, { 0x0565, 0x0582, 0x0000, 0x0000 } },
1411 { 0x1E00, { 0x1E01, 0x0000, 0x0000, 0x0000 } },
1412 { 0x1E02, { 0x1E03, 0x0000, 0x0000, 0x0000 } },
1413 { 0x1E04, { 0x1E05, 0x0000, 0x0000, 0x0000 } },
1414 { 0x1E06, { 0x1E07, 0x0000, 0x0000, 0x0000 } },
1415 { 0x1E08, { 0x1E09, 0x0000, 0x0000, 0x0000 } },
1416 { 0x1E0A, { 0x1E0B, 0x0000, 0x0000, 0x0000 } },
1417 { 0x1E0C, { 0x1E0D, 0x0000, 0x0000, 0x0000 } },
1418 { 0x1E0E, { 0x1E0F, 0x0000, 0x0000, 0x0000 } },
1419 { 0x1E10, { 0x1E11, 0x0000, 0x0000, 0x0000 } },
1420 { 0x1E12, { 0x1E13, 0x0000, 0x0000, 0x0000 } },
1421 { 0x1E14, { 0x1E15, 0x0000, 0x0000, 0x0000 } },
1422 { 0x1E16, { 0x1E17, 0x0000, 0x0000, 0x0000 } },
1423 { 0x1E18, { 0x1E19, 0x0000, 0x0000, 0x0000 } },
1424 { 0x1E1A, { 0x1E1B, 0x0000, 0x0000, 0x0000 } },
1425 { 0x1E1C, { 0x1E1D, 0x0000, 0x0000, 0x0000 } },
1426 { 0x1E1E, { 0x1E1F, 0x0000, 0x0000, 0x0000 } },
1427 { 0x1E20, { 0x1E21, 0x0000, 0x0000, 0x0000 } },
1428 { 0x1E22, { 0x1E23, 0x0000, 0x0000, 0x0000 } },
1429 { 0x1E24, { 0x1E25, 0x0000, 0x0000, 0x0000 } },
1430 { 0x1E26, { 0x1E27, 0x0000, 0x0000, 0x0000 } },
1431 { 0x1E28, { 0x1E29, 0x0000, 0x0000, 0x0000 } },
1432 { 0x1E2A, { 0x1E2B, 0x0000, 0x0000, 0x0000 } },
1433 { 0x1E2C, { 0x1E2D, 0x0000, 0x0000, 0x0000 } },
1434 { 0x1E2E, { 0x1E2F, 0x0000, 0x0000, 0x0000 } },
1435 { 0x1E30, { 0x1E31, 0x0000, 0x0000, 0x0000 } },
1436 { 0x1E32, { 0x1E33, 0x0000, 0x0000, 0x0000 } },
1437 { 0x1E34, { 0x1E35, 0x0000, 0x0000, 0x0000 } },
1438 { 0x1E36, { 0x1E37, 0x0000, 0x0000, 0x0000 } },
1439 { 0x1E38, { 0x1E39, 0x0000, 0x0000, 0x0000 } },
1440 { 0x1E3A, { 0x1E3B, 0x0000, 0x0000, 0x0000 } },
1441 { 0x1E3C, { 0x1E3D, 0x0000, 0x0000, 0x0000 } },
1442 { 0x1E3E, { 0x1E3F, 0x0000, 0x0000, 0x0000 } },
1443 { 0x1E40, { 0x1E41, 0x0000, 0x0000, 0x0000 } },
1444 { 0x1E42, { 0x1E43, 0x0000, 0x0000, 0x0000 } },
1445 { 0x1E44, { 0x1E45, 0x0000, 0x0000, 0x0000 } },
1446 { 0x1E46, { 0x1E47, 0x0000, 0x0000, 0x0000 } },
1447 { 0x1E48, { 0x1E49, 0x0000, 0x0000, 0x0000 } },
1448 { 0x1E4A, { 0x1E4B, 0x0000, 0x0000, 0x0000 } },
1449 { 0x1E4C, { 0x1E4D, 0x0000, 0x0000, 0x0000 } },
1450 { 0x1E4E, { 0x1E4F, 0x0000, 0x0000, 0x0000 } },
1451 { 0x1E50, { 0x1E51, 0x0000, 0x0000, 0x0000 } },
1452 { 0x1E52, { 0x1E53, 0x0000, 0x0000, 0x0000 } },
1453 { 0x1E54, { 0x1E55, 0x0000, 0x0000, 0x0000 } },
1454 { 0x1E56, { 0x1E57, 0x0000, 0x0000, 0x0000 } },
1455 { 0x1E58, { 0x1E59, 0x0000, 0x0000, 0x0000 } },
1456 { 0x1E5A, { 0x1E5B, 0x0000, 0x0000, 0x0000 } },
1457 { 0x1E5C, { 0x1E5D, 0x0000, 0x0000, 0x0000 } },
1458 { 0x1E5E, { 0x1E5F, 0x0000, 0x0000, 0x0000 } },
1459 { 0x1E60, { 0x1E61, 0x0000, 0x0000, 0x0000 } },
1460 { 0x1E62, { 0x1E63, 0x0000, 0x0000, 0x0000 } },
1461 { 0x1E64, { 0x1E65, 0x0000, 0x0000, 0x0000 } },
1462 { 0x1E66, { 0x1E67, 0x0000, 0x0000, 0x0000 } },
1463 { 0x1E68, { 0x1E69, 0x0000, 0x0000, 0x0000 } },
1464 { 0x1E6A, { 0x1E6B, 0x0000, 0x0000, 0x0000 } },
1465 { 0x1E6C, { 0x1E6D, 0x0000, 0x0000, 0x0000 } },
1466 { 0x1E6E, { 0x1E6F, 0x0000, 0x0000, 0x0000 } },
1467 { 0x1E70, { 0x1E71, 0x0000, 0x0000, 0x0000 } },
1468 { 0x1E72, { 0x1E73, 0x0000, 0x0000, 0x0000 } },
1469 { 0x1E74, { 0x1E75, 0x0000, 0x0000, 0x0000 } },
1470 { 0x1E76, { 0x1E77, 0x0000, 0x0000, 0x0000 } },
1471 { 0x1E78, { 0x1E79, 0x0000, 0x0000, 0x0000 } },
1472 { 0x1E7A, { 0x1E7B, 0x0000, 0x0000, 0x0000 } },
1473 { 0x1E7C, { 0x1E7D, 0x0000, 0x0000, 0x0000 } },
1474 { 0x1E7E, { 0x1E7F, 0x0000, 0x0000, 0x0000 } },
1475 { 0x1E80, { 0x1E81, 0x0000, 0x0000, 0x0000 } },
1476 { 0x1E82, { 0x1E83, 0x0000, 0x0000, 0x0000 } },
1477 { 0x1E84, { 0x1E85, 0x0000, 0x0000, 0x0000 } },
1478 { 0x1E86, { 0x1E87, 0x0000, 0x0000, 0x0000 } },
1479 { 0x1E88, { 0x1E89, 0x0000, 0x0000, 0x0000 } },
1480 { 0x1E8A, { 0x1E8B, 0x0000, 0x0000, 0x0000 } },
1481 { 0x1E8C, { 0x1E8D, 0x0000, 0x0000, 0x0000 } },
1482 { 0x1E8E, { 0x1E8F, 0x0000, 0x0000, 0x0000 } },
1483 { 0x1E90, { 0x1E91, 0x0000, 0x0000, 0x0000 } },
1484 { 0x1E92, { 0x1E93, 0x0000, 0x0000, 0x0000 } },
1485 { 0x1E94, { 0x1E95, 0x0000, 0x0000, 0x0000 } },
1486 { 0x1E96, { 0x0068, 0x0331, 0x0000, 0x0000 } },
1487 { 0x1E97, { 0x0074, 0x0308, 0x0000, 0x0000 } },
1488 { 0x1E98, { 0x0077, 0x030A, 0x0000, 0x0000 } },
1489 { 0x1E99, { 0x0079, 0x030A, 0x0000, 0x0000 } },
1490 { 0x1E9A, { 0x0061, 0x02BE, 0x0000, 0x0000 } },
1491 { 0x1E9B, { 0x1E61, 0x0000, 0x0000, 0x0000 } },
1492 { 0x1EA0, { 0x1EA1, 0x0000, 0x0000, 0x0000 } },
1493 { 0x1EA2, { 0x1EA3, 0x0000, 0x0000, 0x0000 } },
1494 { 0x1EA4, { 0x1EA5, 0x0000, 0x0000, 0x0000 } },
1495 { 0x1EA6, { 0x1EA7, 0x0000, 0x0000, 0x0000 } },
1496 { 0x1EA8, { 0x1EA9, 0x0000, 0x0000, 0x0000 } },
1497 { 0x1EAA, { 0x1EAB, 0x0000, 0x0000, 0x0000 } },
1498 { 0x1EAC, { 0x1EAD, 0x0000, 0x0000, 0x0000 } },
1499 { 0x1EAE, { 0x1EAF, 0x0000, 0x0000, 0x0000 } },
1500 { 0x1EB0, { 0x1EB1, 0x0000, 0x0000, 0x0000 } },
1501 { 0x1EB2, { 0x1EB3, 0x0000, 0x0000, 0x0000 } },
1502 { 0x1EB4, { 0x1EB5, 0x0000, 0x0000, 0x0000 } },
1503 { 0x1EB6, { 0x1EB7, 0x0000, 0x0000, 0x0000 } },
1504 { 0x1EB8, { 0x1EB9, 0x0000, 0x0000, 0x0000 } },
1505 { 0x1EBA, { 0x1EBB, 0x0000, 0x0000, 0x0000 } },
1506 { 0x1EBC, { 0x1EBD, 0x0000, 0x0000, 0x0000 } },
1507 { 0x1EBE, { 0x1EBF, 0x0000, 0x0000, 0x0000 } },
1508 { 0x1EC0, { 0x1EC1, 0x0000, 0x0000, 0x0000 } },
1509 { 0x1EC2, { 0x1EC3, 0x0000, 0x0000, 0x0000 } },
1510 { 0x1EC4, { 0x1EC5, 0x0000, 0x0000, 0x0000 } },
1511 { 0x1EC6, { 0x1EC7, 0x0000, 0x0000, 0x0000 } },
1512 { 0x1EC8, { 0x1EC9, 0x0000, 0x0000, 0x0000 } },
1513 { 0x1ECA, { 0x1ECB, 0x0000, 0x0000, 0x0000 } },
1514 { 0x1ECC, { 0x1ECD, 0x0000, 0x0000, 0x0000 } },
1515 { 0x1ECE, { 0x1ECF, 0x0000, 0x0000, 0x0000 } },
1516 { 0x1ED0, { 0x1ED1, 0x0000, 0x0000, 0x0000 } },
1517 { 0x1ED2, { 0x1ED3, 0x0000, 0x0000, 0x0000 } },
1518 { 0x1ED4, { 0x1ED5, 0x0000, 0x0000, 0x0000 } },
1519 { 0x1ED6, { 0x1ED7, 0x0000, 0x0000, 0x0000 } },
1520 { 0x1ED8, { 0x1ED9, 0x0000, 0x0000, 0x0000 } },
1521 { 0x1EDA, { 0x1EDB, 0x0000, 0x0000, 0x0000 } },
1522 { 0x1EDC, { 0x1EDD, 0x0000, 0x0000, 0x0000 } },
1523 { 0x1EDE, { 0x1EDF, 0x0000, 0x0000, 0x0000 } },
1524 { 0x1EE0, { 0x1EE1, 0x0000, 0x0000, 0x0000 } },
1525 { 0x1EE2, { 0x1EE3, 0x0000, 0x0000, 0x0000 } },
1526 { 0x1EE4, { 0x1EE5, 0x0000, 0x0000, 0x0000 } },
1527 { 0x1EE6, { 0x1EE7, 0x0000, 0x0000, 0x0000 } },
1528 { 0x1EE8, { 0x1EE9, 0x0000, 0x0000, 0x0000 } },
1529 { 0x1EEA, { 0x1EEB, 0x0000, 0x0000, 0x0000 } },
1530 { 0x1EEC, { 0x1EED, 0x0000, 0x0000, 0x0000 } },
1531 { 0x1EEE, { 0x1EEF, 0x0000, 0x0000, 0x0000 } },
1532 { 0x1EF0, { 0x1EF1, 0x0000, 0x0000, 0x0000 } },
1533 { 0x1EF2, { 0x1EF3, 0x0000, 0x0000, 0x0000 } },
1534 { 0x1EF4, { 0x1EF5, 0x0000, 0x0000, 0x0000 } },
1535 { 0x1EF6, { 0x1EF7, 0x0000, 0x0000, 0x0000 } },
1536 { 0x1EF8, { 0x1EF9, 0x0000, 0x0000, 0x0000 } },
1537 { 0x1F08, { 0x1F00, 0x0000, 0x0000, 0x0000 } },
1538 { 0x1F09, { 0x1F01, 0x0000, 0x0000, 0x0000 } },
1539 { 0x1F0A, { 0x1F02, 0x0000, 0x0000, 0x0000 } },
1540 { 0x1F0B, { 0x1F03, 0x0000, 0x0000, 0x0000 } },
1541 { 0x1F0C, { 0x1F04, 0x0000, 0x0000, 0x0000 } },
1542 { 0x1F0D, { 0x1F05, 0x0000, 0x0000, 0x0000 } },
1543 { 0x1F0E, { 0x1F06, 0x0000, 0x0000, 0x0000 } },
1544 { 0x1F0F, { 0x1F07, 0x0000, 0x0000, 0x0000 } },
1545 { 0x1F18, { 0x1F10, 0x0000, 0x0000, 0x0000 } },
1546 { 0x1F19, { 0x1F11, 0x0000, 0x0000, 0x0000 } },
1547 { 0x1F1A, { 0x1F12, 0x0000, 0x0000, 0x0000 } },
1548 { 0x1F1B, { 0x1F13, 0x0000, 0x0000, 0x0000 } },
1549 { 0x1F1C, { 0x1F14, 0x0000, 0x0000, 0x0000 } },
1550 { 0x1F1D, { 0x1F15, 0x0000, 0x0000, 0x0000 } },
1551 { 0x1F28, { 0x1F20, 0x0000, 0x0000, 0x0000 } },
1552 { 0x1F29, { 0x1F21, 0x0000, 0x0000, 0x0000 } },
1553 { 0x1F2A, { 0x1F22, 0x0000, 0x0000, 0x0000 } },
1554 { 0x1F2B, { 0x1F23, 0x0000, 0x0000, 0x0000 } },
1555 { 0x1F2C, { 0x1F24, 0x0000, 0x0000, 0x0000 } },
1556 { 0x1F2D, { 0x1F25, 0x0000, 0x0000, 0x0000 } },
1557 { 0x1F2E, { 0x1F26, 0x0000, 0x0000, 0x0000 } },
1558 { 0x1F2F, { 0x1F27, 0x0000, 0x0000, 0x0000 } },
1559 { 0x1F38, { 0x1F30, 0x0000, 0x0000, 0x0000 } },
1560 { 0x1F39, { 0x1F31, 0x0000, 0x0000, 0x0000 } },
1561 { 0x1F3A, { 0x1F32, 0x0000, 0x0000, 0x0000 } },
1562 { 0x1F3B, { 0x1F33, 0x0000, 0x0000, 0x0000 } },
1563 { 0x1F3C, { 0x1F34, 0x0000, 0x0000, 0x0000 } },
1564 { 0x1F3D, { 0x1F35, 0x0000, 0x0000, 0x0000 } },
1565 { 0x1F3E, { 0x1F36, 0x0000, 0x0000, 0x0000 } },
1566 { 0x1F3F, { 0x1F37, 0x0000, 0x0000, 0x0000 } },
1567 { 0x1F48, { 0x1F40, 0x0000, 0x0000, 0x0000 } },
1568 { 0x1F49, { 0x1F41, 0x0000, 0x0000, 0x0000 } },
1569 { 0x1F4A, { 0x1F42, 0x0000, 0x0000, 0x0000 } },
1570 { 0x1F4B, { 0x1F43, 0x0000, 0x0000, 0x0000 } },
1571 { 0x1F4C, { 0x1F44, 0x0000, 0x0000, 0x0000 } },
1572 { 0x1F4D, { 0x1F45, 0x0000, 0x0000, 0x0000 } },
1573 { 0x1F50, { 0x03C5, 0x0313, 0x0000, 0x0000 } },
1574 { 0x1F52, { 0x03C5, 0x0313, 0x0300, 0x0000 } },
1575 { 0x1F54, { 0x03C5, 0x0313, 0x0301, 0x0000 } },
1576 { 0x1F56, { 0x03C5, 0x0313, 0x0342, 0x0000 } },
1577 { 0x1F59, { 0x1F51, 0x0000, 0x0000, 0x0000 } },
1578 { 0x1F5B, { 0x1F53, 0x0000, 0x0000, 0x0000 } },
1579 { 0x1F5D, { 0x1F55, 0x0000, 0x0000, 0x0000 } },
1580 { 0x1F5F, { 0x1F57, 0x0000, 0x0000, 0x0000 } },
1581 { 0x1F68, { 0x1F60, 0x0000, 0x0000, 0x0000 } },
1582 { 0x1F69, { 0x1F61, 0x0000, 0x0000, 0x0000 } },
1583 { 0x1F6A, { 0x1F62, 0x0000, 0x0000, 0x0000 } },
1584 { 0x1F6B, { 0x1F63, 0x0000, 0x0000, 0x0000 } },
1585 { 0x1F6C, { 0x1F64, 0x0000, 0x0000, 0x0000 } },
1586 { 0x1F6D, { 0x1F65, 0x0000, 0x0000, 0x0000 } },
1587 { 0x1F6E, { 0x1F66, 0x0000, 0x0000, 0x0000 } },
1588 { 0x1F6F, { 0x1F67, 0x0000, 0x0000, 0x0000 } },
1589 { 0x1F80, { 0x1F00, 0x03B9, 0x0000, 0x0000 } },
1590 { 0x1F81, { 0x1F01, 0x03B9, 0x0000, 0x0000 } },
1591 { 0x1F82, { 0x1F02, 0x03B9, 0x0000, 0x0000 } },
1592 { 0x1F83, { 0x1F03, 0x03B9, 0x0000, 0x0000 } },
1593 { 0x1F84, { 0x1F04, 0x03B9, 0x0000, 0x0000 } },
1594 { 0x1F85, { 0x1F05, 0x03B9, 0x0000, 0x0000 } },
1595 { 0x1F86, { 0x1F06, 0x03B9, 0x0000, 0x0000 } },
1596 { 0x1F87, { 0x1F07, 0x03B9, 0x0000, 0x0000 } },
1597 { 0x1F88, { 0x1F00, 0x03B9, 0x0000, 0x0000 } },
1598 { 0x1F89, { 0x1F01, 0x03B9, 0x0000, 0x0000 } },
1599 { 0x1F8A, { 0x1F02, 0x03B9, 0x0000, 0x0000 } },
1600 { 0x1F8B, { 0x1F03, 0x03B9, 0x0000, 0x0000 } },
1601 { 0x1F8C, { 0x1F04, 0x03B9, 0x0000, 0x0000 } },
1602 { 0x1F8D, { 0x1F05, 0x03B9, 0x0000, 0x0000 } },
1603 { 0x1F8E, { 0x1F06, 0x03B9, 0x0000, 0x0000 } },
1604 { 0x1F8F, { 0x1F07, 0x03B9, 0x0000, 0x0000 } },
1605 { 0x1F90, { 0x1F20, 0x03B9, 0x0000, 0x0000 } },
1606 { 0x1F91, { 0x1F21, 0x03B9, 0x0000, 0x0000 } },
1607 { 0x1F92, { 0x1F22, 0x03B9, 0x0000, 0x0000 } },
1608 { 0x1F93, { 0x1F23, 0x03B9, 0x0000, 0x0000 } },
1609 { 0x1F94, { 0x1F24, 0x03B9, 0x0000, 0x0000 } },
1610 { 0x1F95, { 0x1F25, 0x03B9, 0x0000, 0x0000 } },
1611 { 0x1F96, { 0x1F26, 0x03B9, 0x0000, 0x0000 } },
1612 { 0x1F97, { 0x1F27, 0x03B9, 0x0000, 0x0000 } },
1613 { 0x1F98, { 0x1F20, 0x03B9, 0x0000, 0x0000 } },
1614 { 0x1F99, { 0x1F21, 0x03B9, 0x0000, 0x0000 } },
1615 { 0x1F9A, { 0x1F22, 0x03B9, 0x0000, 0x0000 } },
1616 { 0x1F9B, { 0x1F23, 0x03B9, 0x0000, 0x0000 } },
1617 { 0x1F9C, { 0x1F24, 0x03B9, 0x0000, 0x0000 } },
1618 { 0x1F9D, { 0x1F25, 0x03B9, 0x0000, 0x0000 } },
1619 { 0x1F9E, { 0x1F26, 0x03B9, 0x0000, 0x0000 } },
1620 { 0x1F9F, { 0x1F27, 0x03B9, 0x0000, 0x0000 } },
1621 { 0x1FA0, { 0x1F60, 0x03B9, 0x0000, 0x0000 } },
1622 { 0x1FA1, { 0x1F61, 0x03B9, 0x0000, 0x0000 } },
1623 { 0x1FA2, { 0x1F62, 0x03B9, 0x0000, 0x0000 } },
1624 { 0x1FA3, { 0x1F63, 0x03B9, 0x0000, 0x0000 } },
1625 { 0x1FA4, { 0x1F64, 0x03B9, 0x0000, 0x0000 } },
1626 { 0x1FA5, { 0x1F65, 0x03B9, 0x0000, 0x0000 } },
1627 { 0x1FA6, { 0x1F66, 0x03B9, 0x0000, 0x0000 } },
1628 { 0x1FA7, { 0x1F67, 0x03B9, 0x0000, 0x0000 } },
1629 { 0x1FA8, { 0x1F60, 0x03B9, 0x0000, 0x0000 } },
1630 { 0x1FA9, { 0x1F61, 0x03B9, 0x0000, 0x0000 } },
1631 { 0x1FAA, { 0x1F62, 0x03B9, 0x0000, 0x0000 } },
1632 { 0x1FAB, { 0x1F63, 0x03B9, 0x0000, 0x0000 } },
1633 { 0x1FAC, { 0x1F64, 0x03B9, 0x0000, 0x0000 } },
1634 { 0x1FAD, { 0x1F65, 0x03B9, 0x0000, 0x0000 } },
1635 { 0x1FAE, { 0x1F66, 0x03B9, 0x0000, 0x0000 } },
1636 { 0x1FAF, { 0x1F67, 0x03B9, 0x0000, 0x0000 } },
1637 { 0x1FB2, { 0x1F70, 0x03B9, 0x0000, 0x0000 } },
1638 { 0x1FB3, { 0x03B1, 0x03B9, 0x0000, 0x0000 } },
1639 { 0x1FB4, { 0x03AC, 0x03B9, 0x0000, 0x0000 } },
1640 { 0x1FB6, { 0x03B1, 0x0342, 0x0000, 0x0000 } },
1641 { 0x1FB7, { 0x03B1, 0x0342, 0x03B9, 0x0000 } },
1642 { 0x1FB8, { 0x1FB0, 0x0000, 0x0000, 0x0000 } },
1643 { 0x1FB9, { 0x1FB1, 0x0000, 0x0000, 0x0000 } },
1644 { 0x1FBA, { 0x1F70, 0x0000, 0x0000, 0x0000 } },
1645 { 0x1FBB, { 0x1F71, 0x0000, 0x0000, 0x0000 } },
1646 { 0x1FBC, { 0x03B1, 0x03B9, 0x0000, 0x0000 } },
1647 { 0x1FBE, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
1648 { 0x1FC2, { 0x1F74, 0x03B9, 0x0000, 0x0000 } },
1649 { 0x1FC3, { 0x03B7, 0x03B9, 0x0000, 0x0000 } },
1650 { 0x1FC4, { 0x03AE, 0x03B9, 0x0000, 0x0000 } },
1651 { 0x1FC6, { 0x03B7, 0x0342, 0x0000, 0x0000 } },
1652 { 0x1FC7, { 0x03B7, 0x0342, 0x03B9, 0x0000 } },
1653 { 0x1FC8, { 0x1F72, 0x0000, 0x0000, 0x0000 } },
1654 { 0x1FC9, { 0x1F73, 0x0000, 0x0000, 0x0000 } },
1655 { 0x1FCA, { 0x1F74, 0x0000, 0x0000, 0x0000 } },
1656 { 0x1FCB, { 0x1F75, 0x0000, 0x0000, 0x0000 } },
1657 { 0x1FCC, { 0x03B7, 0x03B9, 0x0000, 0x0000 } },
1658 { 0x1FD2, { 0x03B9, 0x0308, 0x0300, 0x0000 } },
1659 { 0x1FD3, { 0x03B9, 0x0308, 0x0301, 0x0000 } },
1660 { 0x1FD6, { 0x03B9, 0x0342, 0x0000, 0x0000 } },
1661 { 0x1FD7, { 0x03B9, 0x0308, 0x0342, 0x0000 } },
1662 { 0x1FD8, { 0x1FD0, 0x0000, 0x0000, 0x0000 } },
1663 { 0x1FD9, { 0x1FD1, 0x0000, 0x0000, 0x0000 } },
1664 { 0x1FDA, { 0x1F76, 0x0000, 0x0000, 0x0000 } },
1665 { 0x1FDB, { 0x1F77, 0x0000, 0x0000, 0x0000 } },
1666 { 0x1FE2, { 0x03C5, 0x0308, 0x0300, 0x0000 } },
1667 { 0x1FE3, { 0x03C5, 0x0308, 0x0301, 0x0000 } },
1668 { 0x1FE4, { 0x03C1, 0x0313, 0x0000, 0x0000 } },
1669 { 0x1FE6, { 0x03C5, 0x0342, 0x0000, 0x0000 } },
1670 { 0x1FE7, { 0x03C5, 0x0308, 0x0342, 0x0000 } },
1671 { 0x1FE8, { 0x1FE0, 0x0000, 0x0000, 0x0000 } },
1672 { 0x1FE9, { 0x1FE1, 0x0000, 0x0000, 0x0000 } },
1673 { 0x1FEA, { 0x1F7A, 0x0000, 0x0000, 0x0000 } },
1674 { 0x1FEB, { 0x1F7B, 0x0000, 0x0000, 0x0000 } },
1675 { 0x1FEC, { 0x1FE5, 0x0000, 0x0000, 0x0000 } },
1676 { 0x1FF2, { 0x1F7C, 0x03B9, 0x0000, 0x0000 } },
1677 { 0x1FF3, { 0x03C9, 0x03B9, 0x0000, 0x0000 } },
1678 { 0x1FF4, { 0x03CE, 0x03B9, 0x0000, 0x0000 } },
1679 { 0x1FF6, { 0x03C9, 0x0342, 0x0000, 0x0000 } },
1680 { 0x1FF7, { 0x03C9, 0x0342, 0x03B9, 0x0000 } },
1681 { 0x1FF8, { 0x1F78, 0x0000, 0x0000, 0x0000 } },
1682 { 0x1FF9, { 0x1F79, 0x0000, 0x0000, 0x0000 } },
1683 { 0x1FFA, { 0x1F7C, 0x0000, 0x0000, 0x0000 } },
1684 { 0x1FFB, { 0x1F7D, 0x0000, 0x0000, 0x0000 } },
1685 { 0x1FFC, { 0x03C9, 0x03B9, 0x0000, 0x0000 } },
1686 { 0x20A8, { 0x0072, 0x0073, 0x0000, 0x0000 } },
1687 { 0x2102, { 0x0063, 0x0000, 0x0000, 0x0000 } },
1688 { 0x2103, { 0x00B0, 0x0063, 0x0000, 0x0000 } },
1689 { 0x2107, { 0x025B, 0x0000, 0x0000, 0x0000 } },
1690 { 0x2109, { 0x00B0, 0x0066, 0x0000, 0x0000 } },
1691 { 0x210B, { 0x0068, 0x0000, 0x0000, 0x0000 } },
1692 { 0x210C, { 0x0068, 0x0000, 0x0000, 0x0000 } },
1693 { 0x210D, { 0x0068, 0x0000, 0x0000, 0x0000 } },
1694 { 0x2110, { 0x0069, 0x0000, 0x0000, 0x0000 } },
1695 { 0x2111, { 0x0069, 0x0000, 0x0000, 0x0000 } },
1696 { 0x2112, { 0x006C, 0x0000, 0x0000, 0x0000 } },
1697 { 0x2115, { 0x006E, 0x0000, 0x0000, 0x0000 } },
1698 { 0x2116, { 0x006E, 0x006F, 0x0000, 0x0000 } },
1699 { 0x2119, { 0x0070, 0x0000, 0x0000, 0x0000 } },
1700 { 0x211A, { 0x0071, 0x0000, 0x0000, 0x0000 } },
1701 { 0x211B, { 0x0072, 0x0000, 0x0000, 0x0000 } },
1702 { 0x211C, { 0x0072, 0x0000, 0x0000, 0x0000 } },
1703 { 0x211D, { 0x0072, 0x0000, 0x0000, 0x0000 } },
1704 { 0x2120, { 0x0073, 0x006D, 0x0000, 0x0000 } },
1705 { 0x2121, { 0x0074, 0x0065, 0x006C, 0x0000 } },
1706 { 0x2122, { 0x0074, 0x006D, 0x0000, 0x0000 } },
1707 { 0x2124, { 0x007A, 0x0000, 0x0000, 0x0000 } },
1708 { 0x2126, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
1709 { 0x2128, { 0x007A, 0x0000, 0x0000, 0x0000 } },
1710 { 0x212A, { 0x006B, 0x0000, 0x0000, 0x0000 } },
1711 { 0x212B, { 0x00E5, 0x0000, 0x0000, 0x0000 } },
1712 { 0x212C, { 0x0062, 0x0000, 0x0000, 0x0000 } },
1713 { 0x212D, { 0x0063, 0x0000, 0x0000, 0x0000 } },
1714 { 0x2130, { 0x0065, 0x0000, 0x0000, 0x0000 } },
1715 { 0x2131, { 0x0066, 0x0000, 0x0000, 0x0000 } },
1716 { 0x2133, { 0x006D, 0x0000, 0x0000, 0x0000 } },
1717 { 0x213E, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
1718 { 0x213F, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
1719 { 0x2145, { 0x0064, 0x0000, 0x0000, 0x0000 } },
1720 { 0x2160, { 0x2170, 0x0000, 0x0000, 0x0000 } },
1721 { 0x2161, { 0x2171, 0x0000, 0x0000, 0x0000 } },
1722 { 0x2162, { 0x2172, 0x0000, 0x0000, 0x0000 } },
1723 { 0x2163, { 0x2173, 0x0000, 0x0000, 0x0000 } },
1724 { 0x2164, { 0x2174, 0x0000, 0x0000, 0x0000 } },
1725 { 0x2165, { 0x2175, 0x0000, 0x0000, 0x0000 } },
1726 { 0x2166, { 0x2176, 0x0000, 0x0000, 0x0000 } },
1727 { 0x2167, { 0x2177, 0x0000, 0x0000, 0x0000 } },
1728 { 0x2168, { 0x2178, 0x0000, 0x0000, 0x0000 } },
1729 { 0x2169, { 0x2179, 0x0000, 0x0000, 0x0000 } },
1730 { 0x216A, { 0x217A, 0x0000, 0x0000, 0x0000 } },
1731 { 0x216B, { 0x217B, 0x0000, 0x0000, 0x0000 } },
1732 { 0x216C, { 0x217C, 0x0000, 0x0000, 0x0000 } },
1733 { 0x216D, { 0x217D, 0x0000, 0x0000, 0x0000 } },
1734 { 0x216E, { 0x217E, 0x0000, 0x0000, 0x0000 } },
1735 { 0x216F, { 0x217F, 0x0000, 0x0000, 0x0000 } },
1736 { 0x24B6, { 0x24D0, 0x0000, 0x0000, 0x0000 } },
1737 { 0x24B7, { 0x24D1, 0x0000, 0x0000, 0x0000 } },
1738 { 0x24B8, { 0x24D2, 0x0000, 0x0000, 0x0000 } },
1739 { 0x24B9, { 0x24D3, 0x0000, 0x0000, 0x0000 } },
1740 { 0x24BA, { 0x24D4, 0x0000, 0x0000, 0x0000 } },
1741 { 0x24BB, { 0x24D5, 0x0000, 0x0000, 0x0000 } },
1742 { 0x24BC, { 0x24D6, 0x0000, 0x0000, 0x0000 } },
1743 { 0x24BD, { 0x24D7, 0x0000, 0x0000, 0x0000 } },
1744 { 0x24BE, { 0x24D8, 0x0000, 0x0000, 0x0000 } },
1745 { 0x24BF, { 0x24D9, 0x0000, 0x0000, 0x0000 } },
1746 { 0x24C0, { 0x24DA, 0x0000, 0x0000, 0x0000 } },
1747 { 0x24C1, { 0x24DB, 0x0000, 0x0000, 0x0000 } },
1748 { 0x24C2, { 0x24DC, 0x0000, 0x0000, 0x0000 } },
1749 { 0x24C3, { 0x24DD, 0x0000, 0x0000, 0x0000 } },
1750 { 0x24C4, { 0x24DE, 0x0000, 0x0000, 0x0000 } },
1751 { 0x24C5, { 0x24DF, 0x0000, 0x0000, 0x0000 } },
1752 { 0x24C6, { 0x24E0, 0x0000, 0x0000, 0x0000 } },
1753 { 0x24C7, { 0x24E1, 0x0000, 0x0000, 0x0000 } },
1754 { 0x24C8, { 0x24E2, 0x0000, 0x0000, 0x0000 } },
1755 { 0x24C9, { 0x24E3, 0x0000, 0x0000, 0x0000 } },
1756 { 0x24CA, { 0x24E4, 0x0000, 0x0000, 0x0000 } },
1757 { 0x24CB, { 0x24E5, 0x0000, 0x0000, 0x0000 } },
1758 { 0x24CC, { 0x24E6, 0x0000, 0x0000, 0x0000 } },
1759 { 0x24CD, { 0x24E7, 0x0000, 0x0000, 0x0000 } },
1760 { 0x24CE, { 0x24E8, 0x0000, 0x0000, 0x0000 } },
1761 { 0x24CF, { 0x24E9, 0x0000, 0x0000, 0x0000 } },
1762 { 0x3371, { 0x0068, 0x0070, 0x0061, 0x0000 } },
1763 { 0x3373, { 0x0061, 0x0075, 0x0000, 0x0000 } },
1764 { 0x3375, { 0x006F, 0x0076, 0x0000, 0x0000 } },
1765 { 0x3380, { 0x0070, 0x0061, 0x0000, 0x0000 } },
1766 { 0x3381, { 0x006E, 0x0061, 0x0000, 0x0000 } },
1767 { 0x3382, { 0x03BC, 0x0061, 0x0000, 0x0000 } },
1768 { 0x3383, { 0x006D, 0x0061, 0x0000, 0x0000 } },
1769 { 0x3384, { 0x006B, 0x0061, 0x0000, 0x0000 } },
1770 { 0x3385, { 0x006B, 0x0062, 0x0000, 0x0000 } },
1771 { 0x3386, { 0x006D, 0x0062, 0x0000, 0x0000 } },
1772 { 0x3387, { 0x0067, 0x0062, 0x0000, 0x0000 } },
1773 { 0x338A, { 0x0070, 0x0066, 0x0000, 0x0000 } },
1774 { 0x338B, { 0x006E, 0x0066, 0x0000, 0x0000 } },
1775 { 0x338C, { 0x03BC, 0x0066, 0x0000, 0x0000 } },
1776 { 0x3390, { 0x0068, 0x007A, 0x0000, 0x0000 } },
1777 { 0x3391, { 0x006B, 0x0068, 0x007A, 0x0000 } },
1778 { 0x3392, { 0x006D, 0x0068, 0x007A, 0x0000 } },
1779 { 0x3393, { 0x0067, 0x0068, 0x007A, 0x0000 } },
1780 { 0x3394, { 0x0074, 0x0068, 0x007A, 0x0000 } },
1781 { 0x33A9, { 0x0070, 0x0061, 0x0000, 0x0000 } },
1782 { 0x33AA, { 0x006B, 0x0070, 0x0061, 0x0000 } },
1783 { 0x33AB, { 0x006D, 0x0070, 0x0061, 0x0000 } },
1784 { 0x33AC, { 0x0067, 0x0070, 0x0061, 0x0000 } },
1785 { 0x33B4, { 0x0070, 0x0076, 0x0000, 0x0000 } },
1786 { 0x33B5, { 0x006E, 0x0076, 0x0000, 0x0000 } },
1787 { 0x33B6, { 0x03BC, 0x0076, 0x0000, 0x0000 } },
1788 { 0x33B7, { 0x006D, 0x0076, 0x0000, 0x0000 } },
1789 { 0x33B8, { 0x006B, 0x0076, 0x0000, 0x0000 } },
1790 { 0x33B9, { 0x006D, 0x0076, 0x0000, 0x0000 } },
1791 { 0x33BA, { 0x0070, 0x0077, 0x0000, 0x0000 } },
1792 { 0x33BB, { 0x006E, 0x0077, 0x0000, 0x0000 } },
1793 { 0x33BC, { 0x03BC, 0x0077, 0x0000, 0x0000 } },
1794 { 0x33BD, { 0x006D, 0x0077, 0x0000, 0x0000 } },
1795 { 0x33BE, { 0x006B, 0x0077, 0x0000, 0x0000 } },
1796 { 0x33BF, { 0x006D, 0x0077, 0x0000, 0x0000 } },
1797 { 0x33C0, { 0x006B, 0x03C9, 0x0000, 0x0000 } },
1798 { 0x33C1, { 0x006D, 0x03C9, 0x0000, 0x0000 } },
1799 { 0x33C3, { 0x0062, 0x0071, 0x0000, 0x0000 } },
1800 { 0x33C6, { 0x0063, 0x2215, 0x006B, 0x0067 } },
1801 { 0x33C7, { 0x0063, 0x006F, 0x002E, 0x0000 } },
1802 { 0x33C8, { 0x0064, 0x0062, 0x0000, 0x0000 } },
1803 { 0x33C9, { 0x0067, 0x0079, 0x0000, 0x0000 } },
1804 { 0x33CB, { 0x0068, 0x0070, 0x0000, 0x0000 } },
1805 { 0x33CD, { 0x006B, 0x006B, 0x0000, 0x0000 } },
1806 { 0x33CE, { 0x006B, 0x006D, 0x0000, 0x0000 } },
1807 { 0x33D7, { 0x0070, 0x0068, 0x0000, 0x0000 } },
1808 { 0x33D9, { 0x0070, 0x0070, 0x006D, 0x0000 } },
1809 { 0x33DA, { 0x0070, 0x0072, 0x0000, 0x0000 } },
1810 { 0x33DC, { 0x0073, 0x0076, 0x0000, 0x0000 } },
1811 { 0x33DD, { 0x0077, 0x0062, 0x0000, 0x0000 } },
1812 { 0xFB00, { 0x0066, 0x0066, 0x0000, 0x0000 } },
1813 { 0xFB01, { 0x0066, 0x0069, 0x0000, 0x0000 } },
1814 { 0xFB02, { 0x0066, 0x006C, 0x0000, 0x0000 } },
1815 { 0xFB03, { 0x0066, 0x0066, 0x0069, 0x0000 } },
1816 { 0xFB04, { 0x0066, 0x0066, 0x006C, 0x0000 } },
1817 { 0xFB05, { 0x0073, 0x0074, 0x0000, 0x0000 } },
1818 { 0xFB06, { 0x0073, 0x0074, 0x0000, 0x0000 } },
1819 { 0xFB13, { 0x0574, 0x0576, 0x0000, 0x0000 } },
1820 { 0xFB14, { 0x0574, 0x0565, 0x0000, 0x0000 } },
1821 { 0xFB15, { 0x0574, 0x056B, 0x0000, 0x0000 } },
1822 { 0xFB16, { 0x057E, 0x0576, 0x0000, 0x0000 } },
1823 { 0xFB17, { 0x0574, 0x056D, 0x0000, 0x0000 } },
1824 { 0xFF21, { 0xFF41, 0x0000, 0x0000, 0x0000 } },
1825 { 0xFF22, { 0xFF42, 0x0000, 0x0000, 0x0000 } },
1826 { 0xFF23, { 0xFF43, 0x0000, 0x0000, 0x0000 } },
1827 { 0xFF24, { 0xFF44, 0x0000, 0x0000, 0x0000 } },
1828 { 0xFF25, { 0xFF45, 0x0000, 0x0000, 0x0000 } },
1829 { 0xFF26, { 0xFF46, 0x0000, 0x0000, 0x0000 } },
1830 { 0xFF27, { 0xFF47, 0x0000, 0x0000, 0x0000 } },
1831 { 0xFF28, { 0xFF48, 0x0000, 0x0000, 0x0000 } },
1832 { 0xFF29, { 0xFF49, 0x0000, 0x0000, 0x0000 } },
1833 { 0xFF2A, { 0xFF4A, 0x0000, 0x0000, 0x0000 } },
1834 { 0xFF2B, { 0xFF4B, 0x0000, 0x0000, 0x0000 } },
1835 { 0xFF2C, { 0xFF4C, 0x0000, 0x0000, 0x0000 } },
1836 { 0xFF2D, { 0xFF4D, 0x0000, 0x0000, 0x0000 } },
1837 { 0xFF2E, { 0xFF4E, 0x0000, 0x0000, 0x0000 } },
1838 { 0xFF2F, { 0xFF4F, 0x0000, 0x0000, 0x0000 } },
1839 { 0xFF30, { 0xFF50, 0x0000, 0x0000, 0x0000 } },
1840 { 0xFF31, { 0xFF51, 0x0000, 0x0000, 0x0000 } },
1841 { 0xFF32, { 0xFF52, 0x0000, 0x0000, 0x0000 } },
1842 { 0xFF33, { 0xFF53, 0x0000, 0x0000, 0x0000 } },
1843 { 0xFF34, { 0xFF54, 0x0000, 0x0000, 0x0000 } },
1844 { 0xFF35, { 0xFF55, 0x0000, 0x0000, 0x0000 } },
1845 { 0xFF36, { 0xFF56, 0x0000, 0x0000, 0x0000 } },
1846 { 0xFF37, { 0xFF57, 0x0000, 0x0000, 0x0000 } },
1847 { 0xFF38, { 0xFF58, 0x0000, 0x0000, 0x0000 } },
1848 { 0xFF39, { 0xFF59, 0x0000, 0x0000, 0x0000 } },
1849 { 0xFF3A, { 0xFF5A, 0x0000, 0x0000, 0x0000 } },
1850 // #####
1851/* { 0x10400, { 0x10428, 0x0000, 0x0000, 0x0000 } },
1852 { 0x10401, { 0x10429, 0x0000, 0x0000, 0x0000 } },
1853 { 0x10402, { 0x1042A, 0x0000, 0x0000, 0x0000 } },
1854 { 0x10403, { 0x1042B, 0x0000, 0x0000, 0x0000 } },
1855 { 0x10404, { 0x1042C, 0x0000, 0x0000, 0x0000 } },
1856 { 0x10405, { 0x1042D, 0x0000, 0x0000, 0x0000 } },
1857 { 0x10406, { 0x1042E, 0x0000, 0x0000, 0x0000 } },
1858 { 0x10407, { 0x1042F, 0x0000, 0x0000, 0x0000 } },
1859 { 0x10408, { 0x10430, 0x0000, 0x0000, 0x0000 } },
1860 { 0x10409, { 0x10431, 0x0000, 0x0000, 0x0000 } },
1861 { 0x1040A, { 0x10432, 0x0000, 0x0000, 0x0000 } },
1862 { 0x1040B, { 0x10433, 0x0000, 0x0000, 0x0000 } },
1863 { 0x1040C, { 0x10434, 0x0000, 0x0000, 0x0000 } },
1864 { 0x1040D, { 0x10435, 0x0000, 0x0000, 0x0000 } },
1865 { 0x1040E, { 0x10436, 0x0000, 0x0000, 0x0000 } },
1866 { 0x1040F, { 0x10437, 0x0000, 0x0000, 0x0000 } },
1867 { 0x10410, { 0x10438, 0x0000, 0x0000, 0x0000 } },
1868 { 0x10411, { 0x10439, 0x0000, 0x0000, 0x0000 } },
1869 { 0x10412, { 0x1043A, 0x0000, 0x0000, 0x0000 } },
1870 { 0x10413, { 0x1043B, 0x0000, 0x0000, 0x0000 } },
1871 { 0x10414, { 0x1043C, 0x0000, 0x0000, 0x0000 } },
1872 { 0x10415, { 0x1043D, 0x0000, 0x0000, 0x0000 } },
1873 { 0x10416, { 0x1043E, 0x0000, 0x0000, 0x0000 } },
1874 { 0x10417, { 0x1043F, 0x0000, 0x0000, 0x0000 } },
1875 { 0x10418, { 0x10440, 0x0000, 0x0000, 0x0000 } },
1876 { 0x10419, { 0x10441, 0x0000, 0x0000, 0x0000 } },
1877 { 0x1041A, { 0x10442, 0x0000, 0x0000, 0x0000 } },
1878 { 0x1041B, { 0x10443, 0x0000, 0x0000, 0x0000 } },
1879 { 0x1041C, { 0x10444, 0x0000, 0x0000, 0x0000 } },
1880 { 0x1041D, { 0x10445, 0x0000, 0x0000, 0x0000 } },
1881 { 0x1041E, { 0x10446, 0x0000, 0x0000, 0x0000 } },
1882 { 0x1041F, { 0x10447, 0x0000, 0x0000, 0x0000 } },
1883 { 0x10420, { 0x10448, 0x0000, 0x0000, 0x0000 } },
1884 { 0x10421, { 0x10449, 0x0000, 0x0000, 0x0000 } },
1885 { 0x10422, { 0x1044A, 0x0000, 0x0000, 0x0000 } },
1886 { 0x10423, { 0x1044B, 0x0000, 0x0000, 0x0000 } },
1887 { 0x10424, { 0x1044C, 0x0000, 0x0000, 0x0000 } },
1888 { 0x10425, { 0x1044D, 0x0000, 0x0000, 0x0000 } },*/
1889 { 0x1D400, { 0x0061, 0x0000, 0x0000, 0x0000 } },
1890 { 0x1D401, { 0x0062, 0x0000, 0x0000, 0x0000 } },
1891 { 0x1D402, { 0x0063, 0x0000, 0x0000, 0x0000 } },
1892 { 0x1D403, { 0x0064, 0x0000, 0x0000, 0x0000 } },
1893 { 0x1D404, { 0x0065, 0x0000, 0x0000, 0x0000 } },
1894 { 0x1D405, { 0x0066, 0x0000, 0x0000, 0x0000 } },
1895 { 0x1D406, { 0x0067, 0x0000, 0x0000, 0x0000 } },
1896 { 0x1D407, { 0x0068, 0x0000, 0x0000, 0x0000 } },
1897 { 0x1D408, { 0x0069, 0x0000, 0x0000, 0x0000 } },
1898 { 0x1D409, { 0x006A, 0x0000, 0x0000, 0x0000 } },
1899 { 0x1D40A, { 0x006B, 0x0000, 0x0000, 0x0000 } },
1900 { 0x1D40B, { 0x006C, 0x0000, 0x0000, 0x0000 } },
1901 { 0x1D40C, { 0x006D, 0x0000, 0x0000, 0x0000 } },
1902 { 0x1D40D, { 0x006E, 0x0000, 0x0000, 0x0000 } },
1903 { 0x1D40E, { 0x006F, 0x0000, 0x0000, 0x0000 } },
1904 { 0x1D40F, { 0x0070, 0x0000, 0x0000, 0x0000 } },
1905 { 0x1D410, { 0x0071, 0x0000, 0x0000, 0x0000 } },
1906 { 0x1D411, { 0x0072, 0x0000, 0x0000, 0x0000 } },
1907 { 0x1D412, { 0x0073, 0x0000, 0x0000, 0x0000 } },
1908 { 0x1D413, { 0x0074, 0x0000, 0x0000, 0x0000 } },
1909 { 0x1D414, { 0x0075, 0x0000, 0x0000, 0x0000 } },
1910 { 0x1D415, { 0x0076, 0x0000, 0x0000, 0x0000 } },
1911 { 0x1D416, { 0x0077, 0x0000, 0x0000, 0x0000 } },
1912 { 0x1D417, { 0x0078, 0x0000, 0x0000, 0x0000 } },
1913 { 0x1D418, { 0x0079, 0x0000, 0x0000, 0x0000 } },
1914 { 0x1D419, { 0x007A, 0x0000, 0x0000, 0x0000 } },
1915 { 0x1D434, { 0x0061, 0x0000, 0x0000, 0x0000 } },
1916 { 0x1D435, { 0x0062, 0x0000, 0x0000, 0x0000 } },
1917 { 0x1D436, { 0x0063, 0x0000, 0x0000, 0x0000 } },
1918 { 0x1D437, { 0x0064, 0x0000, 0x0000, 0x0000 } },
1919 { 0x1D438, { 0x0065, 0x0000, 0x0000, 0x0000 } },
1920 { 0x1D439, { 0x0066, 0x0000, 0x0000, 0x0000 } },
1921 { 0x1D43A, { 0x0067, 0x0000, 0x0000, 0x0000 } },
1922 { 0x1D43B, { 0x0068, 0x0000, 0x0000, 0x0000 } },
1923 { 0x1D43C, { 0x0069, 0x0000, 0x0000, 0x0000 } },
1924 { 0x1D43D, { 0x006A, 0x0000, 0x0000, 0x0000 } },
1925 { 0x1D43E, { 0x006B, 0x0000, 0x0000, 0x0000 } },
1926 { 0x1D43F, { 0x006C, 0x0000, 0x0000, 0x0000 } },
1927 { 0x1D440, { 0x006D, 0x0000, 0x0000, 0x0000 } },
1928 { 0x1D441, { 0x006E, 0x0000, 0x0000, 0x0000 } },
1929 { 0x1D442, { 0x006F, 0x0000, 0x0000, 0x0000 } },
1930 { 0x1D443, { 0x0070, 0x0000, 0x0000, 0x0000 } },
1931 { 0x1D444, { 0x0071, 0x0000, 0x0000, 0x0000 } },
1932 { 0x1D445, { 0x0072, 0x0000, 0x0000, 0x0000 } },
1933 { 0x1D446, { 0x0073, 0x0000, 0x0000, 0x0000 } },
1934 { 0x1D447, { 0x0074, 0x0000, 0x0000, 0x0000 } },
1935 { 0x1D448, { 0x0075, 0x0000, 0x0000, 0x0000 } },
1936 { 0x1D449, { 0x0076, 0x0000, 0x0000, 0x0000 } },
1937 { 0x1D44A, { 0x0077, 0x0000, 0x0000, 0x0000 } },
1938 { 0x1D44B, { 0x0078, 0x0000, 0x0000, 0x0000 } },
1939 { 0x1D44C, { 0x0079, 0x0000, 0x0000, 0x0000 } },
1940 { 0x1D44D, { 0x007A, 0x0000, 0x0000, 0x0000 } },
1941 { 0x1D468, { 0x0061, 0x0000, 0x0000, 0x0000 } },
1942 { 0x1D469, { 0x0062, 0x0000, 0x0000, 0x0000 } },
1943 { 0x1D46A, { 0x0063, 0x0000, 0x0000, 0x0000 } },
1944 { 0x1D46B, { 0x0064, 0x0000, 0x0000, 0x0000 } },
1945 { 0x1D46C, { 0x0065, 0x0000, 0x0000, 0x0000 } },
1946 { 0x1D46D, { 0x0066, 0x0000, 0x0000, 0x0000 } },
1947 { 0x1D46E, { 0x0067, 0x0000, 0x0000, 0x0000 } },
1948 { 0x1D46F, { 0x0068, 0x0000, 0x0000, 0x0000 } },
1949 { 0x1D470, { 0x0069, 0x0000, 0x0000, 0x0000 } },
1950 { 0x1D471, { 0x006A, 0x0000, 0x0000, 0x0000 } },
1951 { 0x1D472, { 0x006B, 0x0000, 0x0000, 0x0000 } },
1952 { 0x1D473, { 0x006C, 0x0000, 0x0000, 0x0000 } },
1953 { 0x1D474, { 0x006D, 0x0000, 0x0000, 0x0000 } },
1954 { 0x1D475, { 0x006E, 0x0000, 0x0000, 0x0000 } },
1955 { 0x1D476, { 0x006F, 0x0000, 0x0000, 0x0000 } },
1956 { 0x1D477, { 0x0070, 0x0000, 0x0000, 0x0000 } },
1957 { 0x1D478, { 0x0071, 0x0000, 0x0000, 0x0000 } },
1958 { 0x1D479, { 0x0072, 0x0000, 0x0000, 0x0000 } },
1959 { 0x1D47A, { 0x0073, 0x0000, 0x0000, 0x0000 } },
1960 { 0x1D47B, { 0x0074, 0x0000, 0x0000, 0x0000 } },
1961 { 0x1D47C, { 0x0075, 0x0000, 0x0000, 0x0000 } },
1962 { 0x1D47D, { 0x0076, 0x0000, 0x0000, 0x0000 } },
1963 { 0x1D47E, { 0x0077, 0x0000, 0x0000, 0x0000 } },
1964 { 0x1D47F, { 0x0078, 0x0000, 0x0000, 0x0000 } },
1965 { 0x1D480, { 0x0079, 0x0000, 0x0000, 0x0000 } },
1966 { 0x1D481, { 0x007A, 0x0000, 0x0000, 0x0000 } },
1967 { 0x1D49C, { 0x0061, 0x0000, 0x0000, 0x0000 } },
1968 { 0x1D49E, { 0x0063, 0x0000, 0x0000, 0x0000 } },
1969 { 0x1D49F, { 0x0064, 0x0000, 0x0000, 0x0000 } },
1970 { 0x1D4A2, { 0x0067, 0x0000, 0x0000, 0x0000 } },
1971 { 0x1D4A5, { 0x006A, 0x0000, 0x0000, 0x0000 } },
1972 { 0x1D4A6, { 0x006B, 0x0000, 0x0000, 0x0000 } },
1973 { 0x1D4A9, { 0x006E, 0x0000, 0x0000, 0x0000 } },
1974 { 0x1D4AA, { 0x006F, 0x0000, 0x0000, 0x0000 } },
1975 { 0x1D4AB, { 0x0070, 0x0000, 0x0000, 0x0000 } },
1976 { 0x1D4AC, { 0x0071, 0x0000, 0x0000, 0x0000 } },
1977 { 0x1D4AE, { 0x0073, 0x0000, 0x0000, 0x0000 } },
1978 { 0x1D4AF, { 0x0074, 0x0000, 0x0000, 0x0000 } },
1979 { 0x1D4B0, { 0x0075, 0x0000, 0x0000, 0x0000 } },
1980 { 0x1D4B1, { 0x0076, 0x0000, 0x0000, 0x0000 } },
1981 { 0x1D4B2, { 0x0077, 0x0000, 0x0000, 0x0000 } },
1982 { 0x1D4B3, { 0x0078, 0x0000, 0x0000, 0x0000 } },
1983 { 0x1D4B4, { 0x0079, 0x0000, 0x0000, 0x0000 } },
1984 { 0x1D4B5, { 0x007A, 0x0000, 0x0000, 0x0000 } },
1985 { 0x1D4D0, { 0x0061, 0x0000, 0x0000, 0x0000 } },
1986 { 0x1D4D1, { 0x0062, 0x0000, 0x0000, 0x0000 } },
1987 { 0x1D4D2, { 0x0063, 0x0000, 0x0000, 0x0000 } },
1988 { 0x1D4D3, { 0x0064, 0x0000, 0x0000, 0x0000 } },
1989 { 0x1D4D4, { 0x0065, 0x0000, 0x0000, 0x0000 } },
1990 { 0x1D4D5, { 0x0066, 0x0000, 0x0000, 0x0000 } },
1991 { 0x1D4D6, { 0x0067, 0x0000, 0x0000, 0x0000 } },
1992 { 0x1D4D7, { 0x0068, 0x0000, 0x0000, 0x0000 } },
1993 { 0x1D4D8, { 0x0069, 0x0000, 0x0000, 0x0000 } },
1994 { 0x1D4D9, { 0x006A, 0x0000, 0x0000, 0x0000 } },
1995 { 0x1D4DA, { 0x006B, 0x0000, 0x0000, 0x0000 } },
1996 { 0x1D4DB, { 0x006C, 0x0000, 0x0000, 0x0000 } },
1997 { 0x1D4DC, { 0x006D, 0x0000, 0x0000, 0x0000 } },
1998 { 0x1D4DD, { 0x006E, 0x0000, 0x0000, 0x0000 } },
1999 { 0x1D4DE, { 0x006F, 0x0000, 0x0000, 0x0000 } },
2000 { 0x1D4DF, { 0x0070, 0x0000, 0x0000, 0x0000 } },
2001 { 0x1D4E0, { 0x0071, 0x0000, 0x0000, 0x0000 } },
2002 { 0x1D4E1, { 0x0072, 0x0000, 0x0000, 0x0000 } },
2003 { 0x1D4E2, { 0x0073, 0x0000, 0x0000, 0x0000 } },
2004 { 0x1D4E3, { 0x0074, 0x0000, 0x0000, 0x0000 } },
2005 { 0x1D4E4, { 0x0075, 0x0000, 0x0000, 0x0000 } },
2006 { 0x1D4E5, { 0x0076, 0x0000, 0x0000, 0x0000 } },
2007 { 0x1D4E6, { 0x0077, 0x0000, 0x0000, 0x0000 } },
2008 { 0x1D4E7, { 0x0078, 0x0000, 0x0000, 0x0000 } },
2009 { 0x1D4E8, { 0x0079, 0x0000, 0x0000, 0x0000 } },
2010 { 0x1D4E9, { 0x007A, 0x0000, 0x0000, 0x0000 } },
2011 { 0x1D504, { 0x0061, 0x0000, 0x0000, 0x0000 } },
2012 { 0x1D505, { 0x0062, 0x0000, 0x0000, 0x0000 } },
2013 { 0x1D507, { 0x0064, 0x0000, 0x0000, 0x0000 } },
2014 { 0x1D508, { 0x0065, 0x0000, 0x0000, 0x0000 } },
2015 { 0x1D509, { 0x0066, 0x0000, 0x0000, 0x0000 } },
2016 { 0x1D50A, { 0x0067, 0x0000, 0x0000, 0x0000 } },
2017 { 0x1D50D, { 0x006A, 0x0000, 0x0000, 0x0000 } },
2018 { 0x1D50E, { 0x006B, 0x0000, 0x0000, 0x0000 } },
2019 { 0x1D50F, { 0x006C, 0x0000, 0x0000, 0x0000 } },
2020 { 0x1D510, { 0x006D, 0x0000, 0x0000, 0x0000 } },
2021 { 0x1D511, { 0x006E, 0x0000, 0x0000, 0x0000 } },
2022 { 0x1D512, { 0x006F, 0x0000, 0x0000, 0x0000 } },
2023 { 0x1D513, { 0x0070, 0x0000, 0x0000, 0x0000 } },
2024 { 0x1D514, { 0x0071, 0x0000, 0x0000, 0x0000 } },
2025 { 0x1D516, { 0x0073, 0x0000, 0x0000, 0x0000 } },
2026 { 0x1D517, { 0x0074, 0x0000, 0x0000, 0x0000 } },
2027 { 0x1D518, { 0x0075, 0x0000, 0x0000, 0x0000 } },
2028 { 0x1D519, { 0x0076, 0x0000, 0x0000, 0x0000 } },
2029 { 0x1D51A, { 0x0077, 0x0000, 0x0000, 0x0000 } },
2030 { 0x1D51B, { 0x0078, 0x0000, 0x0000, 0x0000 } },
2031 { 0x1D51C, { 0x0079, 0x0000, 0x0000, 0x0000 } },
2032 { 0x1D538, { 0x0061, 0x0000, 0x0000, 0x0000 } },
2033 { 0x1D539, { 0x0062, 0x0000, 0x0000, 0x0000 } },
2034 { 0x1D53B, { 0x0064, 0x0000, 0x0000, 0x0000 } },
2035 { 0x1D53C, { 0x0065, 0x0000, 0x0000, 0x0000 } },
2036 { 0x1D53D, { 0x0066, 0x0000, 0x0000, 0x0000 } },
2037 { 0x1D53E, { 0x0067, 0x0000, 0x0000, 0x0000 } },
2038 { 0x1D540, { 0x0069, 0x0000, 0x0000, 0x0000 } },
2039 { 0x1D541, { 0x006A, 0x0000, 0x0000, 0x0000 } },
2040 { 0x1D542, { 0x006B, 0x0000, 0x0000, 0x0000 } },
2041 { 0x1D543, { 0x006C, 0x0000, 0x0000, 0x0000 } },
2042 { 0x1D544, { 0x006D, 0x0000, 0x0000, 0x0000 } },
2043 { 0x1D546, { 0x006F, 0x0000, 0x0000, 0x0000 } },
2044 { 0x1D54A, { 0x0073, 0x0000, 0x0000, 0x0000 } },
2045 { 0x1D54B, { 0x0074, 0x0000, 0x0000, 0x0000 } },
2046 { 0x1D54C, { 0x0075, 0x0000, 0x0000, 0x0000 } },
2047 { 0x1D54D, { 0x0076, 0x0000, 0x0000, 0x0000 } },
2048 { 0x1D54E, { 0x0077, 0x0000, 0x0000, 0x0000 } },
2049 { 0x1D54F, { 0x0078, 0x0000, 0x0000, 0x0000 } },
2050 { 0x1D550, { 0x0079, 0x0000, 0x0000, 0x0000 } },
2051 { 0x1D56C, { 0x0061, 0x0000, 0x0000, 0x0000 } },
2052 { 0x1D56D, { 0x0062, 0x0000, 0x0000, 0x0000 } },
2053 { 0x1D56E, { 0x0063, 0x0000, 0x0000, 0x0000 } },
2054 { 0x1D56F, { 0x0064, 0x0000, 0x0000, 0x0000 } },
2055 { 0x1D570, { 0x0065, 0x0000, 0x0000, 0x0000 } },
2056 { 0x1D571, { 0x0066, 0x0000, 0x0000, 0x0000 } },
2057 { 0x1D572, { 0x0067, 0x0000, 0x0000, 0x0000 } },
2058 { 0x1D573, { 0x0068, 0x0000, 0x0000, 0x0000 } },
2059 { 0x1D574, { 0x0069, 0x0000, 0x0000, 0x0000 } },
2060 { 0x1D575, { 0x006A, 0x0000, 0x0000, 0x0000 } },
2061 { 0x1D576, { 0x006B, 0x0000, 0x0000, 0x0000 } },
2062 { 0x1D577, { 0x006C, 0x0000, 0x0000, 0x0000 } },
2063 { 0x1D578, { 0x006D, 0x0000, 0x0000, 0x0000 } },
2064 { 0x1D579, { 0x006E, 0x0000, 0x0000, 0x0000 } },
2065 { 0x1D57A, { 0x006F, 0x0000, 0x0000, 0x0000 } },
2066 { 0x1D57B, { 0x0070, 0x0000, 0x0000, 0x0000 } },
2067 { 0x1D57C, { 0x0071, 0x0000, 0x0000, 0x0000 } },
2068 { 0x1D57D, { 0x0072, 0x0000, 0x0000, 0x0000 } },
2069 { 0x1D57E, { 0x0073, 0x0000, 0x0000, 0x0000 } },
2070 { 0x1D57F, { 0x0074, 0x0000, 0x0000, 0x0000 } },
2071 { 0x1D580, { 0x0075, 0x0000, 0x0000, 0x0000 } },
2072 { 0x1D581, { 0x0076, 0x0000, 0x0000, 0x0000 } },
2073 { 0x1D582, { 0x0077, 0x0000, 0x0000, 0x0000 } },
2074 { 0x1D583, { 0x0078, 0x0000, 0x0000, 0x0000 } },
2075 { 0x1D584, { 0x0079, 0x0000, 0x0000, 0x0000 } },
2076 { 0x1D585, { 0x007A, 0x0000, 0x0000, 0x0000 } },
2077 { 0x1D5A0, { 0x0061, 0x0000, 0x0000, 0x0000 } },
2078 { 0x1D5A1, { 0x0062, 0x0000, 0x0000, 0x0000 } },
2079 { 0x1D5A2, { 0x0063, 0x0000, 0x0000, 0x0000 } },
2080 { 0x1D5A3, { 0x0064, 0x0000, 0x0000, 0x0000 } },
2081 { 0x1D5A4, { 0x0065, 0x0000, 0x0000, 0x0000 } },
2082 { 0x1D5A5, { 0x0066, 0x0000, 0x0000, 0x0000 } },
2083 { 0x1D5A6, { 0x0067, 0x0000, 0x0000, 0x0000 } },
2084 { 0x1D5A7, { 0x0068, 0x0000, 0x0000, 0x0000 } },
2085 { 0x1D5A8, { 0x0069, 0x0000, 0x0000, 0x0000 } },
2086 { 0x1D5A9, { 0x006A, 0x0000, 0x0000, 0x0000 } },
2087 { 0x1D5AA, { 0x006B, 0x0000, 0x0000, 0x0000 } },
2088 { 0x1D5AB, { 0x006C, 0x0000, 0x0000, 0x0000 } },
2089 { 0x1D5AC, { 0x006D, 0x0000, 0x0000, 0x0000 } },
2090 { 0x1D5AD, { 0x006E, 0x0000, 0x0000, 0x0000 } },
2091 { 0x1D5AE, { 0x006F, 0x0000, 0x0000, 0x0000 } },
2092 { 0x1D5AF, { 0x0070, 0x0000, 0x0000, 0x0000 } },
2093 { 0x1D5B0, { 0x0071, 0x0000, 0x0000, 0x0000 } },
2094 { 0x1D5B1, { 0x0072, 0x0000, 0x0000, 0x0000 } },
2095 { 0x1D5B2, { 0x0073, 0x0000, 0x0000, 0x0000 } },
2096 { 0x1D5B3, { 0x0074, 0x0000, 0x0000, 0x0000 } },
2097 { 0x1D5B4, { 0x0075, 0x0000, 0x0000, 0x0000 } },
2098 { 0x1D5B5, { 0x0076, 0x0000, 0x0000, 0x0000 } },
2099 { 0x1D5B6, { 0x0077, 0x0000, 0x0000, 0x0000 } },
2100 { 0x1D5B7, { 0x0078, 0x0000, 0x0000, 0x0000 } },
2101 { 0x1D5B8, { 0x0079, 0x0000, 0x0000, 0x0000 } },
2102 { 0x1D5B9, { 0x007A, 0x0000, 0x0000, 0x0000 } },
2103 { 0x1D5D4, { 0x0061, 0x0000, 0x0000, 0x0000 } },
2104 { 0x1D5D5, { 0x0062, 0x0000, 0x0000, 0x0000 } },
2105 { 0x1D5D6, { 0x0063, 0x0000, 0x0000, 0x0000 } },
2106 { 0x1D5D7, { 0x0064, 0x0000, 0x0000, 0x0000 } },
2107 { 0x1D5D8, { 0x0065, 0x0000, 0x0000, 0x0000 } },
2108 { 0x1D5D9, { 0x0066, 0x0000, 0x0000, 0x0000 } },
2109 { 0x1D5DA, { 0x0067, 0x0000, 0x0000, 0x0000 } },
2110 { 0x1D5DB, { 0x0068, 0x0000, 0x0000, 0x0000 } },
2111 { 0x1D5DC, { 0x0069, 0x0000, 0x0000, 0x0000 } },
2112 { 0x1D5DD, { 0x006A, 0x0000, 0x0000, 0x0000 } },
2113 { 0x1D5DE, { 0x006B, 0x0000, 0x0000, 0x0000 } },
2114 { 0x1D5DF, { 0x006C, 0x0000, 0x0000, 0x0000 } },
2115 { 0x1D5E0, { 0x006D, 0x0000, 0x0000, 0x0000 } },
2116 { 0x1D5E1, { 0x006E, 0x0000, 0x0000, 0x0000 } },
2117 { 0x1D5E2, { 0x006F, 0x0000, 0x0000, 0x0000 } },
2118 { 0x1D5E3, { 0x0070, 0x0000, 0x0000, 0x0000 } },
2119 { 0x1D5E4, { 0x0071, 0x0000, 0x0000, 0x0000 } },
2120 { 0x1D5E5, { 0x0072, 0x0000, 0x0000, 0x0000 } },
2121 { 0x1D5E6, { 0x0073, 0x0000, 0x0000, 0x0000 } },
2122 { 0x1D5E7, { 0x0074, 0x0000, 0x0000, 0x0000 } },
2123 { 0x1D5E8, { 0x0075, 0x0000, 0x0000, 0x0000 } },
2124 { 0x1D5E9, { 0x0076, 0x0000, 0x0000, 0x0000 } },
2125 { 0x1D5EA, { 0x0077, 0x0000, 0x0000, 0x0000 } },
2126 { 0x1D5EB, { 0x0078, 0x0000, 0x0000, 0x0000 } },
2127 { 0x1D5EC, { 0x0079, 0x0000, 0x0000, 0x0000 } },
2128 { 0x1D5ED, { 0x007A, 0x0000, 0x0000, 0x0000 } },
2129 { 0x1D608, { 0x0061, 0x0000, 0x0000, 0x0000 } },
2130 { 0x1D609, { 0x0062, 0x0000, 0x0000, 0x0000 } },
2131 { 0x1D60A, { 0x0063, 0x0000, 0x0000, 0x0000 } },
2132 { 0x1D60B, { 0x0064, 0x0000, 0x0000, 0x0000 } },
2133 { 0x1D60C, { 0x0065, 0x0000, 0x0000, 0x0000 } },
2134 { 0x1D60D, { 0x0066, 0x0000, 0x0000, 0x0000 } },
2135 { 0x1D60E, { 0x0067, 0x0000, 0x0000, 0x0000 } },
2136 { 0x1D60F, { 0x0068, 0x0000, 0x0000, 0x0000 } },
2137 { 0x1D610, { 0x0069, 0x0000, 0x0000, 0x0000 } },
2138 { 0x1D611, { 0x006A, 0x0000, 0x0000, 0x0000 } },
2139 { 0x1D612, { 0x006B, 0x0000, 0x0000, 0x0000 } },
2140 { 0x1D613, { 0x006C, 0x0000, 0x0000, 0x0000 } },
2141 { 0x1D614, { 0x006D, 0x0000, 0x0000, 0x0000 } },
2142 { 0x1D615, { 0x006E, 0x0000, 0x0000, 0x0000 } },
2143 { 0x1D616, { 0x006F, 0x0000, 0x0000, 0x0000 } },
2144 { 0x1D617, { 0x0070, 0x0000, 0x0000, 0x0000 } },
2145 { 0x1D618, { 0x0071, 0x0000, 0x0000, 0x0000 } },
2146 { 0x1D619, { 0x0072, 0x0000, 0x0000, 0x0000 } },
2147 { 0x1D61A, { 0x0073, 0x0000, 0x0000, 0x0000 } },
2148 { 0x1D61B, { 0x0074, 0x0000, 0x0000, 0x0000 } },
2149 { 0x1D61C, { 0x0075, 0x0000, 0x0000, 0x0000 } },
2150 { 0x1D61D, { 0x0076, 0x0000, 0x0000, 0x0000 } },
2151 { 0x1D61E, { 0x0077, 0x0000, 0x0000, 0x0000 } },
2152 { 0x1D61F, { 0x0078, 0x0000, 0x0000, 0x0000 } },
2153 { 0x1D620, { 0x0079, 0x0000, 0x0000, 0x0000 } },
2154 { 0x1D621, { 0x007A, 0x0000, 0x0000, 0x0000 } },
2155 { 0x1D63C, { 0x0061, 0x0000, 0x0000, 0x0000 } },
2156 { 0x1D63D, { 0x0062, 0x0000, 0x0000, 0x0000 } },
2157 { 0x1D63E, { 0x0063, 0x0000, 0x0000, 0x0000 } },
2158 { 0x1D63F, { 0x0064, 0x0000, 0x0000, 0x0000 } },
2159 { 0x1D640, { 0x0065, 0x0000, 0x0000, 0x0000 } },
2160 { 0x1D641, { 0x0066, 0x0000, 0x0000, 0x0000 } },
2161 { 0x1D642, { 0x0067, 0x0000, 0x0000, 0x0000 } },
2162 { 0x1D643, { 0x0068, 0x0000, 0x0000, 0x0000 } },
2163 { 0x1D644, { 0x0069, 0x0000, 0x0000, 0x0000 } },
2164 { 0x1D645, { 0x006A, 0x0000, 0x0000, 0x0000 } },
2165 { 0x1D646, { 0x006B, 0x0000, 0x0000, 0x0000 } },
2166 { 0x1D647, { 0x006C, 0x0000, 0x0000, 0x0000 } },
2167 { 0x1D648, { 0x006D, 0x0000, 0x0000, 0x0000 } },
2168 { 0x1D649, { 0x006E, 0x0000, 0x0000, 0x0000 } },
2169 { 0x1D64A, { 0x006F, 0x0000, 0x0000, 0x0000 } },
2170 { 0x1D64B, { 0x0070, 0x0000, 0x0000, 0x0000 } },
2171 { 0x1D64C, { 0x0071, 0x0000, 0x0000, 0x0000 } },
2172 { 0x1D64D, { 0x0072, 0x0000, 0x0000, 0x0000 } },
2173 { 0x1D64E, { 0x0073, 0x0000, 0x0000, 0x0000 } },
2174 { 0x1D64F, { 0x0074, 0x0000, 0x0000, 0x0000 } },
2175 { 0x1D650, { 0x0075, 0x0000, 0x0000, 0x0000 } },
2176 { 0x1D651, { 0x0076, 0x0000, 0x0000, 0x0000 } },
2177 { 0x1D652, { 0x0077, 0x0000, 0x0000, 0x0000 } },
2178 { 0x1D653, { 0x0078, 0x0000, 0x0000, 0x0000 } },
2179 { 0x1D654, { 0x0079, 0x0000, 0x0000, 0x0000 } },
2180 { 0x1D655, { 0x007A, 0x0000, 0x0000, 0x0000 } },
2181 { 0x1D670, { 0x0061, 0x0000, 0x0000, 0x0000 } },
2182 { 0x1D671, { 0x0062, 0x0000, 0x0000, 0x0000 } },
2183 { 0x1D672, { 0x0063, 0x0000, 0x0000, 0x0000 } },
2184 { 0x1D673, { 0x0064, 0x0000, 0x0000, 0x0000 } },
2185 { 0x1D674, { 0x0065, 0x0000, 0x0000, 0x0000 } },
2186 { 0x1D675, { 0x0066, 0x0000, 0x0000, 0x0000 } },
2187 { 0x1D676, { 0x0067, 0x0000, 0x0000, 0x0000 } },
2188 { 0x1D677, { 0x0068, 0x0000, 0x0000, 0x0000 } },
2189 { 0x1D678, { 0x0069, 0x0000, 0x0000, 0x0000 } },
2190 { 0x1D679, { 0x006A, 0x0000, 0x0000, 0x0000 } },
2191 { 0x1D67A, { 0x006B, 0x0000, 0x0000, 0x0000 } },
2192 { 0x1D67B, { 0x006C, 0x0000, 0x0000, 0x0000 } },
2193 { 0x1D67C, { 0x006D, 0x0000, 0x0000, 0x0000 } },
2194 { 0x1D67D, { 0x006E, 0x0000, 0x0000, 0x0000 } },
2195 { 0x1D67E, { 0x006F, 0x0000, 0x0000, 0x0000 } },
2196 { 0x1D67F, { 0x0070, 0x0000, 0x0000, 0x0000 } },
2197 { 0x1D680, { 0x0071, 0x0000, 0x0000, 0x0000 } },
2198 { 0x1D681, { 0x0072, 0x0000, 0x0000, 0x0000 } },
2199 { 0x1D682, { 0x0073, 0x0000, 0x0000, 0x0000 } },
2200 { 0x1D683, { 0x0074, 0x0000, 0x0000, 0x0000 } },
2201 { 0x1D684, { 0x0075, 0x0000, 0x0000, 0x0000 } },
2202 { 0x1D685, { 0x0076, 0x0000, 0x0000, 0x0000 } },
2203 { 0x1D686, { 0x0077, 0x0000, 0x0000, 0x0000 } },
2204 { 0x1D687, { 0x0078, 0x0000, 0x0000, 0x0000 } },
2205 { 0x1D688, { 0x0079, 0x0000, 0x0000, 0x0000 } },
2206 { 0x1D689, { 0x007A, 0x0000, 0x0000, 0x0000 } },
2207 { 0x1D6A8, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
2208 { 0x1D6A9, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
2209 { 0x1D6AA, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
2210 { 0x1D6AB, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
2211 { 0x1D6AC, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
2212 { 0x1D6AD, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
2213 { 0x1D6AE, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
2214 { 0x1D6AF, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2215 { 0x1D6B0, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
2216 { 0x1D6B1, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
2217 { 0x1D6B2, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
2218 { 0x1D6B3, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
2219 { 0x1D6B4, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
2220 { 0x1D6B5, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
2221 { 0x1D6B6, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
2222 { 0x1D6B7, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
2223 { 0x1D6B8, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
2224 { 0x1D6B9, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2225 { 0x1D6BA, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
2226 { 0x1D6BB, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
2227 { 0x1D6BC, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
2228 { 0x1D6BD, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
2229 { 0x1D6BE, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
2230 { 0x1D6BF, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
2231 { 0x1D6C0, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
2232 { 0x1D6D3, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
2233 { 0x1D6E2, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
2234 { 0x1D6E3, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
2235 { 0x1D6E4, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
2236 { 0x1D6E5, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
2237 { 0x1D6E6, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
2238 { 0x1D6E7, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
2239 { 0x1D6E8, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
2240 { 0x1D6E9, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2241 { 0x1D6EA, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
2242 { 0x1D6EB, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
2243 { 0x1D6EC, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
2244 { 0x1D6ED, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
2245 { 0x1D6EE, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
2246 { 0x1D6EF, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
2247 { 0x1D6F0, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
2248 { 0x1D6F1, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
2249 { 0x1D6F2, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
2250 { 0x1D6F3, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2251 { 0x1D6F4, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
2252 { 0x1D6F5, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
2253 { 0x1D6F6, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
2254 { 0x1D6F7, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
2255 { 0x1D6F8, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
2256 { 0x1D6F9, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
2257 { 0x1D6FA, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
2258 { 0x1D70D, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
2259 { 0x1D71C, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
2260 { 0x1D71D, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
2261 { 0x1D71E, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
2262 { 0x1D71F, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
2263 { 0x1D720, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
2264 { 0x1D721, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
2265 { 0x1D722, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
2266 { 0x1D723, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2267 { 0x1D724, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
2268 { 0x1D725, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
2269 { 0x1D726, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
2270 { 0x1D727, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
2271 { 0x1D728, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
2272 { 0x1D729, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
2273 { 0x1D72A, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
2274 { 0x1D72B, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
2275 { 0x1D72C, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
2276 { 0x1D72D, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2277 { 0x1D72E, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
2278 { 0x1D72F, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
2279 { 0x1D730, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
2280 { 0x1D731, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
2281 { 0x1D732, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
2282 { 0x1D733, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
2283 { 0x1D734, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
2284 { 0x1D747, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
2285 { 0x1D756, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
2286 { 0x1D757, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
2287 { 0x1D758, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
2288 { 0x1D759, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
2289 { 0x1D75A, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
2290 { 0x1D75B, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
2291 { 0x1D75C, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
2292 { 0x1D75D, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2293 { 0x1D75E, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
2294 { 0x1D75F, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
2295 { 0x1D760, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
2296 { 0x1D761, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
2297 { 0x1D762, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
2298 { 0x1D763, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
2299 { 0x1D764, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
2300 { 0x1D765, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
2301 { 0x1D766, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
2302 { 0x1D767, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2303 { 0x1D768, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
2304 { 0x1D769, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
2305 { 0x1D76A, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
2306 { 0x1D76B, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
2307 { 0x1D76C, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
2308 { 0x1D76D, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
2309 { 0x1D76E, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
2310 { 0x1D781, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
2311 { 0x1D790, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
2312 { 0x1D791, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
2313 { 0x1D792, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
2314 { 0x1D793, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
2315 { 0x1D794, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
2316 { 0x1D795, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
2317 { 0x1D796, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
2318 { 0x1D797, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2319 { 0x1D798, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
2320 { 0x1D799, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
2321 { 0x1D79A, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
2322 { 0x1D79B, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
2323 { 0x1D79C, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
2324 { 0x1D79D, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
2325 { 0x1D79E, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
2326 { 0x1D79F, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
2327 { 0x1D7A0, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
2328 { 0x1D7A1, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
2329 { 0x1D7A2, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
2330 { 0x1D7A3, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
2331 { 0x1D7A4, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
2332 { 0x1D7A5, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
2333 { 0x1D7A6, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
2334 { 0x1D7A7, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
2335 { 0x1D7A8, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
2336 { 0x1D7BB, { 0x03C3, 0x0000, 0x0000, 0x0000 } }
2337};
2338
2339static void mapToLowerCase(QString *str)
2340{
2341 int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]);
2342
2343 QChar *d = 0;
2344 for (int i = 0; i < str->size(); ++i) {
2345 int uc = str->at(i).unicode();
2346 if (uc < 0x80) {
2347 if (uc <= 'Z' && uc >= 'A') {
2348 uc |= 0x20;
2349 if (!d)
2350 d = str->data();
2351 d[i] = QChar(uc);
2352 }
2353 } else {
2354 const NameprepCaseFoldingEntry *entry = qBinaryFind(NameprepCaseFolding,
2355 NameprepCaseFolding + N,
2356 uc);
2357 if ((entry - NameprepCaseFolding) != N) {
2358 int l = 1;
2359 while (l < 4 && entry->mapping[l])
2360 ++l;
2361 if (l > 1) {
2362 str->replace(i, 1, (const QChar *)&entry->mapping[0], l);
2363 d = 0;
2364 } else {
2365 if (!d)
2366 d = str->data();
2367 d[i] = QChar(entry->mapping[0]);
2368 }
2369 }
2370 }
2371 }
2372}
2373
2374static bool isMappedToNothing(const QChar &ch)
2375{
2376 if (ch.unicode() < 0xad)
2377 return false;
2378 switch (ch.unicode()) {
2379 case 0x00AD: case 0x034F: case 0x1806: case 0x180B: case 0x180C: case 0x180D:
2380 case 0x200B: case 0x200C: case 0x200D: case 0x2060: case 0xFE00: case 0xFE01:
2381 case 0xFE02: case 0xFE03: case 0xFE04: case 0xFE05: case 0xFE06: case 0xFE07:
2382 case 0xFE08: case 0xFE09: case 0xFE0A: case 0xFE0B: case 0xFE0C: case 0xFE0D:
2383 case 0xFE0E: case 0xFE0F: case 0xFEFF:
2384 return true;
2385 default:
2386 return false;
2387 }
2388}
2389
2390
2391static void stripProhibitedOutput(QString *str)
2392{
2393 ushort *out = (ushort *)str->data();
2394 const ushort *in = out;
2395 const ushort *end = out + str->size();
2396 while (in < end) {
2397 ushort uc = *in;
2398 if (uc < 0x80 ||
2399 !(uc <= 0x009F
2400 || uc == 0x00A0
2401 || uc == 0x0340
2402 || uc == 0x0341
2403 || uc == 0x06DD
2404 || uc == 0x070F
2405 || uc == 0x1680
2406 || uc == 0x180E
2407 || (uc >= 0x2000 && uc <= 0x200B)
2408 || uc == 0x200C
2409 || uc == 0x200D
2410 || uc == 0x200E
2411 || uc == 0x200F
2412 || (uc >= 0x2028 && uc <= 0x202F)
2413 || uc == 0x205F
2414 || (uc >= 0x2060 && uc <= 0x2063)
2415 || uc == 0x206A
2416 || (uc >= 0x206A && uc <= 0x206F)
2417 || (uc >= 0x2FF0 && uc <= 0x2FFB)
2418 || uc == 0x3000
2419 || (uc >= 0xD800 && uc <= 0xDFFF)
2420 || (uc >= 0xE000 && uc <= 0xF8FF)
2421 || (uc >= 0xFDD0 && uc <= 0xFDEF)
2422 || uc == 0xFEFF
2423 || (uc >= 0xFFF9 && uc <= 0xFFFC)
2424 || (uc >= 0xFFFA && (uc <= 0xFFFE || uc == 0xFFFF))
2425 /* ### Add NAMEPREP support for surrogates
2426 || uc == 0xE0001
2427 || (uc >= 0x2FFFE && uc <= 0x2FFFF)
2428 || (uc >= 0x1D173 && uc <= 0x1D17A)
2429 || (uc >= 0x1FFFE && uc <= 0x1FFFF)
2430 || (uc >= 0x3FFFE && uc <= 0x3FFFF)
2431 || (uc >= 0x4FFFE && uc <= 0x4FFFF)
2432 || (uc >= 0x5FFFE && uc <= 0x5FFFF)
2433 || (uc >= 0x6FFFE && uc <= 0x6FFFF)
2434 || (uc >= 0x7FFFE && uc <= 0x7FFFF)
2435 || (uc >= 0x8FFFE && uc <= 0x8FFFF)
2436 || (uc >= 0x9FFFE && uc <= 0x9FFFF)
2437 || (uc >= 0xAFFFE && uc <= 0xAFFFF)
2438 || (uc >= 0xBFFFE && uc <= 0xBFFFF)
2439 || (uc >= 0xCFFFE && uc <= 0xCFFFF)
2440 || (uc >= 0xDFFFE && uc <= 0xDFFFF)
2441 || (uc >= 0xE0020 && uc <= 0xE007F)
2442 || (uc >= 0xEFFFE && uc <= 0xEFFFF)
2443 || (uc >= 0xF0000 && uc <= 0xFFFFD)
2444 || (uc >= 0xFFFFE && uc <= 0xFFFFF)
2445 || (uc >= 0x100000 && uc <= 0x10FFFD)
2446 || (uc >= 0x10FFFE && uc <= 0x10FFFF)*/))
2447 *out++ = *in;
2448 ++in;
2449 }
2450 if (in != out)
2451 str->truncate(out - str->utf16());
2452}
2453
2454static bool isBidirectionalRorAL(const QChar &c)
2455{
2456 ushort uc = c.unicode();
2457 if (uc < 0x5b0)
2458 return false;
2459 return uc == 0x05BE
2460 || uc == 0x05C0
2461 || uc == 0x05C3
2462 || (uc >= 0x05D0 && uc <= 0x05EA)
2463 || (uc >= 0x05F0 && uc <= 0x05F4)
2464 || uc == 0x061B
2465 || uc == 0x061F
2466 || (uc >= 0x0621 && uc <= 0x063A)
2467 || (uc >= 0x0640 && uc <= 0x064A)
2468 || (uc >= 0x066D && uc <= 0x066F)
2469 || (uc >= 0x0671 && uc <= 0x06D5)
2470 || uc == 0x06DD
2471 || (uc >= 0x06E5 && uc <= 0x06E6)
2472 || (uc >= 0x06FA && uc <= 0x06FE)
2473 || (uc >= 0x0700 && uc <= 0x070D)
2474 || uc == 0x0710
2475 || (uc >= 0x0712 && uc <= 0x072C)
2476 || (uc >= 0x0780 && uc <= 0x07A5)
2477 || uc == 0x07B1
2478 || uc == 0x200F
2479 || uc == 0xFB1D
2480 || (uc >= 0xFB1F && uc <= 0xFB28)
2481 || (uc >= 0xFB2A && uc <= 0xFB36)
2482 || (uc >= 0xFB38 && uc <= 0xFB3C)
2483 || uc == 0xFB3E
2484 || (uc >= 0xFB40 && uc <= 0xFB41)
2485 || (uc >= 0xFB43 && uc <= 0xFB44)
2486 || (uc >= 0xFB46 && uc <= 0xFBB1)
2487 || (uc >= 0xFBD3 && uc <= 0xFD3D)
2488 || (uc >= 0xFD50 && uc <= 0xFD8F)
2489 || (uc >= 0xFD92 && uc <= 0xFDC7)
2490 || (uc >= 0xFDF0 && uc <= 0xFDFC)
2491 || (uc >= 0xFE70 && uc <= 0xFE74)
2492 || (uc >= 0xFE76 && uc <= 0xFEFC);
2493}
2494
2495static bool isBidirectionalL(const QChar &ch)
2496{
2497 ushort uc = ch.unicode();
2498 if (uc < 0xaa)
2499 return (uc >= 0x0041 && uc <= 0x005A)
2500 || (uc >= 0x0061 && uc <= 0x007A);
2501
2502 if (uc == 0x00AA
2503 || uc == 0x00B5
2504 || uc == 0x00BA
2505 || (uc >= 0x00C0 && uc <= 0x00D6)
2506 || (uc >= 0x00D8 && uc <= 0x00F6)
2507 || (uc >= 0x00F8 && uc <= 0x0220)
2508 || (uc >= 0x0222 && uc <= 0x0233)
2509 || (uc >= 0x0250 && uc <= 0x02AD)
2510 || (uc >= 0x02B0 && uc <= 0x02B8)
2511 || (uc >= 0x02BB && uc <= 0x02C1)
2512 || (uc >= 0x02D0 && uc <= 0x02D1)
2513 || (uc >= 0x02E0 && uc <= 0x02E4)
2514 || uc == 0x02EE
2515 || uc == 0x037A
2516 || uc == 0x0386
2517 || (uc >= 0x0388 && uc <= 0x038A)) {
2518 return true;
2519 }
2520
2521 if (uc == 0x038C
2522 || (uc >= 0x038E && uc <= 0x03A1)
2523 || (uc >= 0x03A3 && uc <= 0x03CE)
2524 || (uc >= 0x03D0 && uc <= 0x03F5)
2525 || (uc >= 0x0400 && uc <= 0x0482)
2526 || (uc >= 0x048A && uc <= 0x04CE)
2527 || (uc >= 0x04D0 && uc <= 0x04F5)
2528 || (uc >= 0x04F8 && uc <= 0x04F9)
2529 || (uc >= 0x0500 && uc <= 0x050F)
2530 || (uc >= 0x0531 && uc <= 0x0556)
2531 || (uc >= 0x0559 && uc <= 0x055F)
2532 || (uc >= 0x0561 && uc <= 0x0587)
2533 || uc == 0x0589
2534 || uc == 0x0903
2535 || (uc >= 0x0905 && uc <= 0x0939)
2536 || (uc >= 0x093D && uc <= 0x0940)
2537 || (uc >= 0x0949 && uc <= 0x094C)
2538 || uc == 0x0950) {
2539 return true;
2540 }
2541
2542 if ((uc >= 0x0958 && uc <= 0x0961)
2543 || (uc >= 0x0964 && uc <= 0x0970)
2544 || (uc >= 0x0982 && uc <= 0x0983)
2545 || (uc >= 0x0985 && uc <= 0x098C)
2546 || (uc >= 0x098F && uc <= 0x0990)
2547 || (uc >= 0x0993 && uc <= 0x09A8)
2548 || (uc >= 0x09AA && uc <= 0x09B0)
2549 || uc == 0x09B2
2550 || (uc >= 0x09B6 && uc <= 0x09B9)
2551 || (uc >= 0x09BE && uc <= 0x09C0)
2552 || (uc >= 0x09C7 && uc <= 0x09C8)
2553 || (uc >= 0x09CB && uc <= 0x09CC)
2554 || uc == 0x09D7
2555 || (uc >= 0x09DC && uc <= 0x09DD)
2556 || (uc >= 0x09DF && uc <= 0x09E1)
2557 || (uc >= 0x09E6 && uc <= 0x09F1)
2558 || (uc >= 0x09F4 && uc <= 0x09FA)
2559 || (uc >= 0x0A05 && uc <= 0x0A0A)
2560 || (uc >= 0x0A0F && uc <= 0x0A10)
2561 || (uc >= 0x0A13 && uc <= 0x0A28)
2562 || (uc >= 0x0A2A && uc <= 0x0A30)
2563 || (uc >= 0x0A32 && uc <= 0x0A33)) {
2564 return true;
2565 }
2566
2567 if ((uc >= 0x0A35 && uc <= 0x0A36)
2568 || (uc >= 0x0A38 && uc <= 0x0A39)
2569 || (uc >= 0x0A3E && uc <= 0x0A40)
2570 || (uc >= 0x0A59 && uc <= 0x0A5C)
2571 || uc == 0x0A5E
2572 || (uc >= 0x0A66 && uc <= 0x0A6F)
2573 || (uc >= 0x0A72 && uc <= 0x0A74)
2574 || uc == 0x0A83
2575 || (uc >= 0x0A85 && uc <= 0x0A8B)
2576 || uc == 0x0A8D
2577 || (uc >= 0x0A8F && uc <= 0x0A91)
2578 || (uc >= 0x0A93 && uc <= 0x0AA8)
2579 || (uc >= 0x0AAA && uc <= 0x0AB0)
2580 || (uc >= 0x0AB2 && uc <= 0x0AB3)
2581 || (uc >= 0x0AB5 && uc <= 0x0AB9)
2582 || (uc >= 0x0ABD && uc <= 0x0AC0)
2583 || uc == 0x0AC9
2584 || (uc >= 0x0ACB && uc <= 0x0ACC)
2585 || uc == 0x0AD0
2586 || uc == 0x0AE0
2587 || (uc >= 0x0AE6 && uc <= 0x0AEF)
2588 || (uc >= 0x0B02 && uc <= 0x0B03)
2589 || (uc >= 0x0B05 && uc <= 0x0B0C)
2590 || (uc >= 0x0B0F && uc <= 0x0B10)
2591 || (uc >= 0x0B13 && uc <= 0x0B28)
2592 || (uc >= 0x0B2A && uc <= 0x0B30)) {
2593 return true;
2594 }
2595
2596 if ((uc >= 0x0B32 && uc <= 0x0B33)
2597 || (uc >= 0x0B36 && uc <= 0x0B39)
2598 || (uc >= 0x0B3D && uc <= 0x0B3E)
2599 || uc == 0x0B40
2600 || (uc >= 0x0B47 && uc <= 0x0B48)
2601 || (uc >= 0x0B4B && uc <= 0x0B4C)
2602 || uc == 0x0B57
2603 || (uc >= 0x0B5C && uc <= 0x0B5D)
2604 || (uc >= 0x0B5F && uc <= 0x0B61)
2605 || (uc >= 0x0B66 && uc <= 0x0B70)
2606 || uc == 0x0B83
2607 || (uc >= 0x0B85 && uc <= 0x0B8A)
2608 || (uc >= 0x0B8E && uc <= 0x0B90)
2609 || (uc >= 0x0B92 && uc <= 0x0B95)
2610 || (uc >= 0x0B99 && uc <= 0x0B9A)
2611 || uc == 0x0B9C
2612 || (uc >= 0x0B9E && uc <= 0x0B9F)
2613 || (uc >= 0x0BA3 && uc <= 0x0BA4)
2614 || (uc >= 0x0BA8 && uc <= 0x0BAA)
2615 || (uc >= 0x0BAE && uc <= 0x0BB5)
2616 || (uc >= 0x0BB7 && uc <= 0x0BB9)
2617 || (uc >= 0x0BBE && uc <= 0x0BBF)
2618 || (uc >= 0x0BC1 && uc <= 0x0BC2)
2619 || (uc >= 0x0BC6 && uc <= 0x0BC8)
2620 || (uc >= 0x0BCA && uc <= 0x0BCC)
2621 || uc == 0x0BD7
2622 || (uc >= 0x0BE7 && uc <= 0x0BF2)
2623 || (uc >= 0x0C01 && uc <= 0x0C03)
2624 || (uc >= 0x0C05 && uc <= 0x0C0C)
2625 || (uc >= 0x0C0E && uc <= 0x0C10)
2626 || (uc >= 0x0C12 && uc <= 0x0C28)
2627 || (uc >= 0x0C2A && uc <= 0x0C33)
2628 || (uc >= 0x0C35 && uc <= 0x0C39)) {
2629 return true;
2630 }
2631 if ((uc >= 0x0C41 && uc <= 0x0C44)
2632 || (uc >= 0x0C60 && uc <= 0x0C61)
2633 || (uc >= 0x0C66 && uc <= 0x0C6F)
2634 || (uc >= 0x0C82 && uc <= 0x0C83)
2635 || (uc >= 0x0C85 && uc <= 0x0C8C)
2636 || (uc >= 0x0C8E && uc <= 0x0C90)
2637 || (uc >= 0x0C92 && uc <= 0x0CA8)
2638 || (uc >= 0x0CAA && uc <= 0x0CB3)
2639 || (uc >= 0x0CB5 && uc <= 0x0CB9)
2640 || uc == 0x0CBE
2641 || (uc >= 0x0CC0 && uc <= 0x0CC4)
2642 || (uc >= 0x0CC7 && uc <= 0x0CC8)
2643 || (uc >= 0x0CCA && uc <= 0x0CCB)
2644 || (uc >= 0x0CD5 && uc <= 0x0CD6)
2645 || uc == 0x0CDE
2646 || (uc >= 0x0CE0 && uc <= 0x0CE1)
2647 || (uc >= 0x0CE6 && uc <= 0x0CEF)
2648 || (uc >= 0x0D02 && uc <= 0x0D03)
2649 || (uc >= 0x0D05 && uc <= 0x0D0C)
2650 || (uc >= 0x0D0E && uc <= 0x0D10)
2651 || (uc >= 0x0D12 && uc <= 0x0D28)
2652 || (uc >= 0x0D2A && uc <= 0x0D39)
2653 || (uc >= 0x0D3E && uc <= 0x0D40)
2654 || (uc >= 0x0D46 && uc <= 0x0D48)
2655 || (uc >= 0x0D4A && uc <= 0x0D4C)
2656 || uc == 0x0D57
2657 || (uc >= 0x0D60 && uc <= 0x0D61)
2658 || (uc >= 0x0D66 && uc <= 0x0D6F)
2659 || (uc >= 0x0D82 && uc <= 0x0D83)
2660 || (uc >= 0x0D85 && uc <= 0x0D96)
2661 || (uc >= 0x0D9A && uc <= 0x0DB1)
2662 || (uc >= 0x0DB3 && uc <= 0x0DBB)
2663 || uc == 0x0DBD) {
2664 return true;
2665 }
2666 if ((uc >= 0x0DC0 && uc <= 0x0DC6)
2667 || (uc >= 0x0DCF && uc <= 0x0DD1)
2668 || (uc >= 0x0DD8 && uc <= 0x0DDF)
2669 || (uc >= 0x0DF2 && uc <= 0x0DF4)
2670 || (uc >= 0x0E01 && uc <= 0x0E30)
2671 || (uc >= 0x0E32 && uc <= 0x0E33)
2672 || (uc >= 0x0E40 && uc <= 0x0E46)
2673 || (uc >= 0x0E4F && uc <= 0x0E5B)
2674 || (uc >= 0x0E81 && uc <= 0x0E82)
2675 || uc == 0x0E84
2676 || (uc >= 0x0E87 && uc <= 0x0E88)
2677 || uc == 0x0E8A
2678 || uc == 0x0E8D
2679 || (uc >= 0x0E94 && uc <= 0x0E97)
2680 || (uc >= 0x0E99 && uc <= 0x0E9F)
2681 || (uc >= 0x0EA1 && uc <= 0x0EA3)
2682 || uc == 0x0EA5
2683 || uc == 0x0EA7
2684 || (uc >= 0x0EAA && uc <= 0x0EAB)
2685 || (uc >= 0x0EAD && uc <= 0x0EB0)
2686 || (uc >= 0x0EB2 && uc <= 0x0EB3)
2687 || uc == 0x0EBD
2688 || (uc >= 0x0EC0 && uc <= 0x0EC4)
2689 || uc == 0x0EC6
2690 || (uc >= 0x0ED0 && uc <= 0x0ED9)
2691 || (uc >= 0x0EDC && uc <= 0x0EDD)
2692 || (uc >= 0x0F00 && uc <= 0x0F17)
2693 || (uc >= 0x0F1A && uc <= 0x0F34)
2694 || uc == 0x0F36
2695 || uc == 0x0F38
2696 || (uc >= 0x0F3E && uc <= 0x0F47)
2697 || (uc >= 0x0F49 && uc <= 0x0F6A)
2698 || uc == 0x0F7F
2699 || uc == 0x0F85
2700 || (uc >= 0x0F88 && uc <= 0x0F8B)
2701 || (uc >= 0x0FBE && uc <= 0x0FC5)
2702 || (uc >= 0x0FC7 && uc <= 0x0FCC)
2703 || uc == 0x0FCF) {
2704 return true;
2705 }
2706
2707 if ((uc >= 0x1000 && uc <= 0x1021)
2708 || (uc >= 0x1023 && uc <= 0x1027)
2709 || (uc >= 0x1029 && uc <= 0x102A)
2710 || uc == 0x102C
2711 || uc == 0x1031
2712 || uc == 0x1038
2713 || (uc >= 0x1040 && uc <= 0x1057)
2714 || (uc >= 0x10A0 && uc <= 0x10C5)
2715 || (uc >= 0x10D0 && uc <= 0x10F8)
2716 || uc == 0x10FB
2717 || (uc >= 0x1100 && uc <= 0x1159)
2718 || (uc >= 0x115F && uc <= 0x11A2)
2719 || (uc >= 0x11A8 && uc <= 0x11F9)
2720 || (uc >= 0x1200 && uc <= 0x1206)
2721 || (uc >= 0x1208 && uc <= 0x1246)
2722 || uc == 0x1248
2723 || (uc >= 0x124A && uc <= 0x124D)
2724 || (uc >= 0x1250 && uc <= 0x1256)
2725 || uc == 0x1258
2726 || (uc >= 0x125A && uc <= 0x125D)
2727 || (uc >= 0x1260 && uc <= 0x1286)
2728 || uc == 0x1288
2729 || (uc >= 0x128A && uc <= 0x128D)
2730 || (uc >= 0x1290 && uc <= 0x12AE)
2731 || uc == 0x12B0
2732 || (uc >= 0x12B2 && uc <= 0x12B5)
2733 || (uc >= 0x12B8 && uc <= 0x12BE)
2734 || uc == 0x12C0
2735 || (uc >= 0x12C2 && uc <= 0x12C5)
2736 || (uc >= 0x12C8 && uc <= 0x12CE)
2737 || (uc >= 0x12D0 && uc <= 0x12D6)
2738 || (uc >= 0x12D8 && uc <= 0x12EE)
2739 || (uc >= 0x12F0 && uc <= 0x130E)
2740 || uc == 0x1310) {
2741 return true;
2742 }
2743
2744 if ((uc >= 0x1312 && uc <= 0x1315)
2745 || (uc >= 0x1318 && uc <= 0x131E)
2746 || (uc >= 0x1320 && uc <= 0x1346)
2747 || (uc >= 0x1348 && uc <= 0x135A)
2748 || (uc >= 0x1361 && uc <= 0x137C)
2749 || (uc >= 0x13A0 && uc <= 0x13F4)
2750 || (uc >= 0x1401 && uc <= 0x1676)
2751 || (uc >= 0x1681 && uc <= 0x169A)
2752 || (uc >= 0x16A0 && uc <= 0x16F0)
2753 || (uc >= 0x1700 && uc <= 0x170C)
2754 || (uc >= 0x170E && uc <= 0x1711)
2755 || (uc >= 0x1720 && uc <= 0x1731)
2756 || (uc >= 0x1735 && uc <= 0x1736)
2757 || (uc >= 0x1740 && uc <= 0x1751)
2758 || (uc >= 0x1760 && uc <= 0x176C)
2759 || (uc >= 0x176E && uc <= 0x1770)
2760 || (uc >= 0x1780 && uc <= 0x17B6)
2761 || (uc >= 0x17BE && uc <= 0x17C5)
2762 || (uc >= 0x17C7 && uc <= 0x17C8)
2763 || (uc >= 0x17D4 && uc <= 0x17DA)
2764 || uc == 0x17DC
2765 || (uc >= 0x17E0 && uc <= 0x17E9)
2766 || (uc >= 0x1810 && uc <= 0x1819)
2767 || (uc >= 0x1820 && uc <= 0x1877)
2768 || (uc >= 0x1880 && uc <= 0x18A8)
2769 || (uc >= 0x1E00 && uc <= 0x1E9B)
2770 || (uc >= 0x1EA0 && uc <= 0x1EF9)
2771 || (uc >= 0x1F00 && uc <= 0x1F15)
2772 || (uc >= 0x1F18 && uc <= 0x1F1D)
2773 || (uc >= 0x1F20 && uc <= 0x1F45)
2774 || (uc >= 0x1F48 && uc <= 0x1F4D)
2775 || (uc >= 0x1F50 && uc <= 0x1F57)
2776 || uc == 0x1F59
2777 || uc == 0x1F5B
2778 || uc == 0x1F5D) {
2779 return true;
2780 }
2781
2782 if ((uc >= 0x1F5F && uc <= 0x1F7D)
2783 || (uc >= 0x1F80 && uc <= 0x1FB4)
2784 || (uc >= 0x1FB6 && uc <= 0x1FBC)
2785 || uc == 0x1FBE
2786 || (uc >= 0x1FC2 && uc <= 0x1FC4)
2787 || (uc >= 0x1FC6 && uc <= 0x1FCC)
2788 || (uc >= 0x1FD0 && uc <= 0x1FD3)
2789 || (uc >= 0x1FD6 && uc <= 0x1FDB)
2790 || (uc >= 0x1FE0 && uc <= 0x1FEC)
2791 || (uc >= 0x1FF2 && uc <= 0x1FF4)
2792 || (uc >= 0x1FF6 && uc <= 0x1FFC)
2793 || uc == 0x200E
2794 || uc == 0x2071
2795 || uc == 0x207F
2796 || uc == 0x2102
2797 || uc == 0x2107
2798 || (uc >= 0x210A && uc <= 0x2113)
2799 || uc == 0x2115
2800 || (uc >= 0x2119 && uc <= 0x211D)) {
2801 return true;
2802 }
2803
2804 if (uc == 0x2124
2805 || uc == 0x2126
2806 || uc == 0x2128
2807 || (uc >= 0x212A && uc <= 0x212D)
2808 || (uc >= 0x212F && uc <= 0x2131)
2809 || (uc >= 0x2133 && uc <= 0x2139)
2810 || (uc >= 0x213D && uc <= 0x213F)
2811 || (uc >= 0x2145 && uc <= 0x2149)
2812 || (uc >= 0x2160 && uc <= 0x2183)
2813 || (uc >= 0x2336 && uc <= 0x237A)
2814 || uc == 0x2395
2815 || (uc >= 0x249C && uc <= 0x24E9)
2816 || (uc >= 0x3005 && uc <= 0x3007)
2817 || (uc >= 0x3021 && uc <= 0x3029)
2818 || (uc >= 0x3031 && uc <= 0x3035)
2819 || (uc >= 0x3038 && uc <= 0x303C)
2820 || (uc >= 0x3041 && uc <= 0x3096)
2821 || (uc >= 0x309D && uc <= 0x309F)
2822 || (uc >= 0x30A1 && uc <= 0x30FA)) {
2823 return true;
2824 }
2825
2826 if ((uc >= 0x30FC && uc <= 0x30FF)
2827 || (uc >= 0x3105 && uc <= 0x312C)
2828 || (uc >= 0x3131 && uc <= 0x318E)
2829 || (uc >= 0x3190 && uc <= 0x31B7)
2830 || (uc >= 0x31F0 && uc <= 0x321C)
2831 || (uc >= 0x3220 && uc <= 0x3243)) {
2832 return true;
2833 }
2834
2835 if ((uc >= 0x3260 && uc <= 0x327B)
2836 || (uc >= 0x327F && uc <= 0x32B0)
2837 || (uc >= 0x32C0 && uc <= 0x32CB)
2838 || (uc >= 0x32D0 && uc <= 0x32FE)
2839 || (uc >= 0x3300 && uc <= 0x3376)
2840 || (uc >= 0x337B && uc <= 0x33DD)) {
2841 return true;
2842 }
2843 if ((uc >= 0x33E0 && uc <= 0x33FE)
2844 || (uc >= 0x3400 && uc <= 0x4DB5)
2845 || (uc >= 0x4E00 && uc <= 0x9FA5)
2846 || (uc >= 0xA000 && uc <= 0xA48C)
2847 || (uc >= 0xAC00 && uc <= 0xD7A3)
2848 || (uc >= 0xD800 && uc <= 0xFA2D)
2849 || (uc >= 0xFA30 && uc <= 0xFA6A)
2850 || (uc >= 0xFB00 && uc <= 0xFB06)
2851 || (uc >= 0xFB13 && uc <= 0xFB17)
2852 || (uc >= 0xFF21 && uc <= 0xFF3A)
2853 || (uc >= 0xFF41 && uc <= 0xFF5A)
2854 || (uc >= 0xFF66 && uc <= 0xFFBE)
2855 || (uc >= 0xFFC2 && uc <= 0xFFC7)
2856 || (uc >= 0xFFCA && uc <= 0xFFCF)
2857 || (uc >= 0xFFD2 && uc <= 0xFFD7)
2858 || (uc >= 0xFFDA && uc <= 0xFFDC)) {
2859 return true;
2860 }
2861
2862 /* ### Add NAMEPREP support for surrogates
2863 || (uc >= 0x10300 && uc <= 0x1031E)
2864 || (uc >= 0x10320 && uc <= 0x10323)
2865 || (uc >= 0x10330 && uc <= 0x1034A)
2866 || (uc >= 0x10400 && uc <= 0x10425)
2867 || (uc >= 0x10428 && uc <= 0x1044D)
2868 || (uc >= 0x1D000 && uc <= 0x1D0F5)
2869 || (uc >= 0x1D100 && uc <= 0x1D126)
2870 || (uc >= 0x1D12A && uc <= 0x1D166)
2871 || (uc >= 0x1D16A && uc <= 0x1D172)
2872 || (uc >= 0x1D183 && uc <= 0x1D184)
2873 || (uc >= 0x1D18C && uc <= 0x1D1A9)
2874 || (uc >= 0x1D1AE && uc <= 0x1D1DD)
2875 || (uc >= 0x1D400 && uc <= 0x1D454)
2876 || (uc >= 0x1D456 && uc <= 0x1D49C)
2877 || (uc >= 0x1D49E && uc <= 0x1D49F)
2878 || uc == 0x1D4A2
2879 || (uc >= 0x1D4A5 && uc <= 0x1D4A6)
2880 || (uc >= 0x1D4A9 && uc <= 0x1D4AC)
2881 || (uc >= 0x1D4AE && uc <= 0x1D4B9)
2882 || uc == 0x1D4BB
2883 || (uc >= 0x1D4BD && uc <= 0x1D4C0)
2884 || (uc >= 0x1D4C2 && uc <= 0x1D4C3)
2885 || (uc >= 0x1D4C5 && uc <= 0x1D505)
2886 || (uc >= 0x1D507 && uc <= 0x1D50A)
2887 || (uc >= 0x1D50D && uc <= 0x1D514)
2888 || (uc >= 0x1D516 && uc <= 0x1D51C)
2889 || (uc >= 0x1D51E && uc <= 0x1D539)
2890 || (uc >= 0x1D53B && uc <= 0x1D53E)
2891 || (uc >= 0x1D540 && uc <= 0x1D544)
2892 || uc == 0x1D546
2893 || (uc >= 0x1D54A && uc <= 0x1D550)
2894 || (uc >= 0x1D552 && uc <= 0x1D6A3)
2895 || (uc >= 0x1D6A8 && uc <= 0x1D7C9)
2896 || (uc >= 0x20000 && uc <= 0x2A6D6)
2897 || (uc >= 0x2F800 && uc <= 0x2FA1D)
2898 || (uc >= 0xF0000 && uc <= 0xFFFFD)
2899 || (uc >= 0x100000 && uc <= 0x10FFFD)*/
2900
2901 return false;
2902}
2903
2904
2905Q_AUTOTEST_EXPORT QString qt_nameprep(const QString &source)
2906{
2907 QString mapped = source;
2908
2909 bool simple = true;
2910 for (int i = 0; i < mapped.size(); ++i) {
2911 ushort uc = mapped.at(i).unicode();
2912 if (uc > 0x80) {
2913 simple = false;
2914 break;
2915 } else if (uc >= 'A' && uc <= 'Z') {
2916 mapped[i] = QChar(uc | 0x20);
2917 }
2918 }
2919 if (simple)
2920 return mapped;
2921
2922 // Characters commonly mapped to nothing are simply removed
2923 // (Table B.1)
2924 QChar *out = mapped.data();
2925 const QChar *in = out;
2926 const QChar *e = in + mapped.size();
2927 while (in < e) {
2928 if (!isMappedToNothing(*in))
2929 *out++ = *in;
2930 ++in;
2931 }
2932 if (out != in)
2933 mapped.truncate(out - mapped.constData());
2934
2935 // Map to lowercase (Table B.2)
2936 mapToLowerCase(&mapped);
2937
2938 // Normalize to Unicode 3.2 form KC
2939 mapped = mapped.normalized(QString::NormalizationForm_KC, QChar::Unicode_3_2);
2940
2941 // Strip prohibited output
2942 stripProhibitedOutput(&mapped);
2943
2944 // Check for valid bidirectional characters
2945 bool containsLCat = false;
2946 bool containsRandALCat = false;
2947 for (int j = 0; j < mapped.size() && (!containsLCat || !containsRandALCat); ++j) {
2948 if (isBidirectionalL(mapped.at(j)))
2949 containsLCat = true;
2950 else if (isBidirectionalRorAL(mapped.at(j)))
2951 containsRandALCat = true;
2952 }
2953 if (containsRandALCat) {
2954 if (containsLCat || (!isBidirectionalRorAL(mapped.at(0))
2955 || !isBidirectionalRorAL(mapped.at(mapped.size() - 1))))
2956 mapped.clear();
2957 }
2958
2959 return mapped;
2960}
2961
2962
2963static inline char encodeDigit(uint digit)
2964{
2965 return digit + 22 + 75 * (digit < 26);
2966}
2967
2968static inline uint adapt(uint delta, uint numpoints, bool firsttime)
2969{
2970 delta /= (firsttime ? damp : 2);
2971 delta += (delta / numpoints);
2972
2973 uint k = 0;
2974 for (; delta > ((base - tmin) * tmax) / 2; k += base)
2975 delta /= (base - tmin);
2976
2977 return k + (((base - tmin + 1) * delta) / (delta + skew));
2978}
2979
2980static inline void appendEncode(QByteArray* output, uint& delta, uint& bias, uint& b, uint& h)
2981{
2982 uint qq;
2983 uint k;
2984 uint t;
2985
2986 // insert the variable length delta integer; fail on
2987 // overflow.
2988 for (qq = delta, k = base;; k += base) {
2989 // stop generating digits when the threshold is
2990 // detected.
2991 t = (k <= bias) ? tmin : (k >= bias + tmax) ? tmax : k - bias;
2992 if (qq < t) break;
2993
2994 *output += encodeDigit(t + (qq - t) % (base - t));
2995 qq = (qq - t) / (base - t);
2996 }
2997
2998 *output += encodeDigit(qq);
2999 bias = adapt(delta, h + 1, h == b);
3000 delta = 0;
3001 ++h;
3002}
3003
3004static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output)
3005{
3006 uint n = initial_n;
3007 uint delta = 0;
3008 uint bias = initial_bias;
3009
3010 int outLen = output->length();
3011 output->resize(outLen + ucLength);
3012
3013 char *d = output->data() + outLen;
3014 bool skipped = false;
3015 // copy all basic code points verbatim to output.
3016 for (uint j = 0; j < (uint) ucLength; ++j) {
3017 ushort js = s[j].unicode();
3018 if (js < 0x80)
3019 *d++ = js;
3020 else
3021 skipped = true;
3022 }
3023
3024 // if there were only basic code points, just return them
3025 // directly; don't do any encoding.
3026 if (!skipped)
3027 return;
3028
3029 output->truncate(d - output->constData());
3030 int copied = output->size() - outLen;
3031
3032 // h and b now contain the number of basic code points in input.
3033 uint b = copied;
3034 uint h = copied;
3035
3036 // if basic code points were copied, add the delimiter character.
3037 if (h > 0)
3038 *output += 0x2d;
3039
3040 // while there are still unprocessed non-basic code points left in
3041 // the input string...
3042 while (h < (uint) ucLength) {
3043 // find the character in the input string with the lowest
3044 // unicode value.
3045 uint m = Q_MAXINT;
3046 uint j;
3047 for (j = 0; j < (uint) ucLength; ++j) {
3048 if (s[j].unicode() >= n && s[j].unicode() < m)
3049 m = (uint) s[j].unicode();
3050 }
3051
3052 // reject out-of-bounds unicode characters
3053 if (m - n > (Q_MAXINT - delta) / (h + 1)) {
3054 output->truncate(outLen);
3055 return; // punycode_overflow
3056 }
3057
3058 delta += (m - n) * (h + 1);
3059 n = m;
3060
3061 // for each code point in the input string
3062 for (j = 0; j < (uint) ucLength; ++j) {
3063
3064 // increase delta until we reach the character with the
3065 // lowest unicode code. fail if delta overflows.
3066 if (s[j].unicode() < n) {
3067 ++delta;
3068 if (!delta) {
3069 output->truncate(outLen);
3070 return; // punycode_overflow
3071 }
3072 }
3073
3074 // if j is the index of the character with the lowest
3075 // unicode code...
3076 if (s[j].unicode() == n) {
3077 appendEncode(output, delta, bias, b, h);
3078 }
3079 }
3080
3081 ++delta;
3082 ++n;
3083 }
3084
3085 // prepend ACE prefix
3086 output->insert(outLen, "xn--");
3087 return;
3088}
3089
3090
3091static const char * const idn_whitelist[] = {
3092 "ac", "at",
3093 "br",
3094 "cat", "ch", "cl", "cn",
3095 "de", "dk",
3096 "fi",
3097 "gr",
3098 "hu",
3099 "info", "io", "is",
3100 "jp",
3101 "kr",
3102 "li", "lt",
3103 "museum",
3104 "no",
3105 "org",
3106 "se", "sh",
3107 "th", "tm", "tw",
3108 "vn",
3109};
3110
3111static QStringList *user_idn_whitelist = 0;
3112
3113static bool lessThan(const QChar *a, int l, const char *c)
3114{
3115 const ushort *uc = (const ushort *)a;
3116 const ushort *e = uc + l;
3117
3118 if (!c || *c == 0)
3119 return false;
3120
3121 while (*c) {
3122 if (uc == e || *uc != *c)
3123 break;
3124 ++uc;
3125 ++c;
3126 }
3127 return (uc == e ? *c : *uc < *c);
3128}
3129
3130static bool equal(const QChar *a, int l, const char *b)
3131{
3132 while (l && a->unicode() && *b) {
3133 if (*a != QLatin1Char(*b))
3134 return false;
3135 ++a;
3136 ++b;
3137 --l;
3138 }
3139 return l == 0;
3140}
3141
3142static bool qt_is_idn_enabled(const QString &domain)
3143{
3144 int idx = domain.lastIndexOf(QLatin1Char('.'));
3145 if (idx == -1)
3146 return false;
3147 const QChar *tld = domain.constData() + idx + 1;
3148 int len = domain.size() - idx - 1;
3149
3150 if (user_idn_whitelist)
3151 return user_idn_whitelist->contains(QString(tld, len));
3152
3153 int l = 0;
3154 int r = sizeof(idn_whitelist)/sizeof(const char *) - 1;
3155 int i = (l + r + 1) / 2;
3156
3157 while (r != l) {
3158 if (lessThan(tld, len, idn_whitelist[i]))
3159 r = i - 1;
3160 else
3161 l = i;
3162 i = (l + r + 1) / 2;
3163 }
3164 return equal(tld, len, idn_whitelist[i]);
3165}
3166
3167static QString qt_from_ACE(const QString &domainMC)
3168{
3169 QString domain = domainMC.toLower();
3170 int idx = domain.indexOf(QLatin1Char('.'));
3171 if (idx != -1) {
3172 if (!domain.contains(QLatin1String("xn--"))) {
3173 bool simple = true;
3174 for (int i = 0; i < domain.size(); ++i) {
3175 ushort ch = domain.at(i).unicode();
3176 if (ch > 'z' || ch < '-' || ch == '/' || (ch > '9' && ch < 'A') || (ch > 'Z' && ch < 'a')) {
3177 simple = false;
3178 break;
3179 }
3180 }
3181 if (simple)
3182 return domain;
3183 }
3184
3185 const bool isIdnEnabled = qt_is_idn_enabled(domain);
3186 int lastIdx = 0;
3187 QString result;
3188 while (1) {
3189 // Nameprep the host. If the labels in the hostname are Punycode
3190 // encoded, we decode them immediately, then nameprep them.
3191 QByteArray label;
3192 toPunycodeHelper(domain.constData() + lastIdx, idx - lastIdx, &label);
3193 result += qt_nameprep(isIdnEnabled ? QUrl::fromPunycode(label) : QString::fromLatin1(label));
3194 lastIdx = idx + 1;
3195 if (lastIdx < domain.size() + 1)
3196 result += QLatin1Char('.');
3197 else
3198 break;
3199 idx = domain.indexOf(QLatin1Char('.'), lastIdx);
3200 if (idx == -1)
3201 idx = domain.size();
3202 }
3203 return result;
3204 } else {
3205 return qt_nameprep(domain);
3206 }
3207}
3208
3209
3210QUrlPrivate::QUrlPrivate()
3211{
3212 ref = 1;
3213 port = -1;
3214 isValid = false;
3215 parsingMode = QUrl::TolerantMode;
3216 valueDelimiter = '=';
3217 pairDelimiter = '&';
3218 stateFlags = 0;
3219 hasFragment = false;
3220 hasQuery = false;
3221}
3222
3223QUrlPrivate::QUrlPrivate(const QUrlPrivate &copy)
3224 : scheme(copy.scheme),
3225 userName(copy.userName),
3226 password(copy.password),
3227 host(copy.host),
3228 path(copy.path),
3229 query(copy.query),
3230 fragment(copy.fragment),
3231 encodedOriginal(copy.encodedOriginal),
3232 encodedUserName(copy.encodedUserName),
3233 encodedPassword(copy.encodedPassword),
3234 encodedPath(copy.encodedPath),
3235 encodedFragment(copy.encodedFragment),
3236 port(copy.port),
3237 parsingMode(copy.parsingMode),
3238 hasQuery(copy.hasQuery),
3239 hasFragment(copy.hasFragment),
3240 isValid(copy.isValid),
3241 valueDelimiter(copy.valueDelimiter),
3242 pairDelimiter(copy.pairDelimiter),
3243 stateFlags(copy.stateFlags),
3244 encodedNormalized(copy.encodedNormalized)
3245{ ref = 1; }
3246
3247QString QUrlPrivate::canonicalHost() const
3248{
3249 if (QURL_HASFLAG(stateFlags, HostCanonicalized))
3250 return host;
3251
3252 QUrlPrivate *that = const_cast<QUrlPrivate *>(this);
3253 QURL_SETFLAG(that->stateFlags, HostCanonicalized);
3254 that->host = qt_from_ACE(host);
3255 return that->host;
3256}
3257
3258// From RFC 3896, Appendix A Collected ABNF for URI
3259// authority = [ userinfo "@" ] host [ ":" port ]
3260// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
3261// host = IP-literal / IPv4address / reg-name
3262// port = *DIGIT
3263//[...]
3264// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
3265//
3266// query = *( pchar / "/" / "?" )
3267//
3268// fragment = *( pchar / "/" / "?" )
3269//
3270// pct-encoded = "%" HEXDIG HEXDIG
3271//
3272// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
3273// reserved = gen-delims / sub-delims
3274// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
3275// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
3276// / "*" / "+" / "," / ";" / "="
3277
3278// use defines for concatenation:
3279#define ABNF_sub_delims "!$&'()*+,;="
3280#define ABNF_gen_delims ":/?#[]@"
3281#define ABNF_pchar ABNF_sub_delims ":@"
3282#define ABNF_reserved ABNF_sub_delims ABNF_gen_delims
3283
3284// list the characters that don't have to be converted according to the list above.
3285// "unreserved" is already automatically not encoded, so we don't have to list it.
3286// the path component has a complex ABNF that basically boils down to
3287// slash-separated segments of "pchar"
3288
3289static const char userNameExcludeChars[] = ABNF_sub_delims;
3290static const char passwordExcludeChars[] = ABNF_sub_delims ":";
3291static const char pathExcludeChars[] = ABNF_pchar "/";
3292static const char queryExcludeChars[] = ABNF_pchar "/?";
3293static const char fragmentExcludeChars[] = ABNF_pchar "/?";
3294
3295void QUrlPrivate::ensureEncodedParts() const
3296{
3297 QUrlPrivate *that = const_cast<QUrlPrivate *>(this);
3298
3299 if (encodedUserName.isNull())
3300 // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
3301 that->encodedUserName = toPercentEncodingHelper(userName, userNameExcludeChars);
3302 if (encodedPassword.isNull())
3303 // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
3304 that->encodedPassword = toPercentEncodingHelper(password, passwordExcludeChars);
3305 if (encodedPath.isNull())
3306 // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" ... also "/"
3307 that->encodedPath = toPercentEncodingHelper(path, pathExcludeChars);
3308 if (encodedFragment.isNull())
3309 // fragment = *( pchar / "/" / "?" )
3310 that->encodedFragment = toPercentEncodingHelper(fragment, fragmentExcludeChars);
3311}
3312
3313QString QUrlPrivate::authority(QUrl::FormattingOptions options) const
3314{
3315 if ((options & QUrl::RemoveAuthority) == QUrl::RemoveAuthority)
3316 return QString();
3317
3318 QString tmp = userInfo(options);
3319 if (!tmp.isEmpty())
3320 tmp += QLatin1Char('@');
3321 tmp += canonicalHost();
3322 if (!(options & QUrl::RemovePort) && port != -1)
3323 tmp += QLatin1Char(':') + QString::number(port);
3324
3325 return tmp;
3326}
3327
3328void QUrlPrivate::setAuthority(const QString &auth)
3329{
3330 if (auth.isEmpty())
3331 return;
3332
3333 // find the port section of the authority by searching from the
3334 // end towards the beginning for numbers until a ':' is reached.
3335 int portIndex = auth.length() - 1;
3336 if (portIndex == 0) {
3337 portIndex = -1;
3338 } else {
3339 short c = auth.at(portIndex--).unicode();
3340 if (c < '0' || c > '9') {
3341 portIndex = -1;
3342 } else while (portIndex >= 0) {
3343 c = auth.at(portIndex).unicode();
3344 if (c == ':') {
3345 break;
3346 } else if (c == '.') {
3347 portIndex = -1;
3348 break;
3349 }
3350 --portIndex;
3351 }
3352 }
3353
3354 if (portIndex != -1) {
3355 port = 0;
3356 for (int i = portIndex + 1; i < auth.length(); ++i)
3357 port = (port * 10) + (auth.at(i).unicode() - '0');
3358 } else {
3359 port = -1;
3360 }
3361
3362 int userInfoIndex = auth.indexOf(QLatin1Char('@'));
3363 if (userInfoIndex != -1 && (portIndex == -1 || userInfoIndex < portIndex))
3364 setUserInfo(auth.left(userInfoIndex));
3365
3366 int hostIndex = 0;
3367 if (userInfoIndex != -1)
3368 hostIndex = userInfoIndex + 1;
3369 int hostLength = auth.length() - hostIndex;
3370 if (portIndex != -1)
3371 hostLength -= (auth.length() - portIndex);
3372
3373 host = auth.mid(hostIndex, hostLength).trimmed();
3374}
3375
3376void QUrlPrivate::setUserInfo(const QString &userInfo)
3377{
3378 encodedUserName.clear();
3379 encodedPassword.clear();
3380
3381 int delimIndex = userInfo.indexOf(QLatin1Char(':'));
3382 if (delimIndex == -1) {
3383 userName = userInfo;
3384 password.clear();
3385 return;
3386 }
3387 userName = userInfo.left(delimIndex);
3388 password = userInfo.right(userInfo.length() - delimIndex - 1);
3389}
3390
3391void QUrlPrivate::setEncodedUserInfo(const QUrlParseData *parseData)
3392{
3393 userName.clear();
3394 password.clear();
3395 if (!parseData->userInfoLength) {
3396 encodedUserName.clear();
3397 encodedPassword.clear();
3398 } else if (parseData->userInfoDelimIndex == -1) {
3399 encodedUserName = QByteArray(parseData->userInfo, parseData->userInfoLength);
3400 encodedPassword.clear();
3401 } else {
3402 encodedUserName = QByteArray(parseData->userInfo, parseData->userInfoDelimIndex);
3403 encodedPassword = QByteArray(parseData->userInfo + parseData->userInfoDelimIndex + 1,
3404 parseData->userInfoLength - parseData->userInfoDelimIndex - 1);
3405 }
3406}
3407
3408QString QUrlPrivate::userInfo(QUrl::FormattingOptions options) const
3409{
3410 if ((options & QUrl::RemoveUserInfo) == QUrl::RemoveUserInfo)
3411 return QString();
3412
3413 QUrlPrivate *that = const_cast<QUrlPrivate *>(this);
3414 if (userName.isNull())
3415 that->userName = fromPercentEncodingHelper(encodedUserName);
3416 if (password.isNull())
3417 that->password = fromPercentEncodingHelper(encodedPassword);
3418
3419 QString tmp = userName;
3420
3421 if (!(options & QUrl::RemovePassword) && !password.isEmpty()) {
3422 tmp += QLatin1Char(':');
3423 tmp += password;
3424 }
3425
3426 return tmp;
3427}
3428
3429/*
3430 From http://www.ietf.org/rfc/rfc3986.txt, 5.2.3: Merge paths
3431
3432 Returns a merge of the current path with the relative path passed
3433 as argument.
3434*/
3435QByteArray QUrlPrivate::mergePaths(const QByteArray &relativePath) const
3436{
3437 if (encodedPath.isNull())
3438 ensureEncodedParts();
3439
3440 // If the base URI has a defined authority component and an empty
3441 // path, then return a string consisting of "/" concatenated with
3442 // the reference's path; otherwise,
3443 if (!authority().isEmpty() && encodedPath.isEmpty())
3444 return '/' + relativePath;
3445
3446 // Return a string consisting of the reference's path component
3447 // appended to all but the last segment of the base URI's path
3448 // (i.e., excluding any characters after the right-most "/" in the
3449 // base URI path, or excluding the entire base URI path if it does
3450 // not contain any "/" characters).
3451 QByteArray newPath;
3452 if (!encodedPath.contains('/'))
3453 newPath = relativePath;
3454 else
3455 newPath = encodedPath.left(encodedPath.lastIndexOf('/') + 1) + relativePath;
3456
3457 return newPath;
3458}
3459
3460void QUrlPrivate::queryItem(int pos, int *value, int *end)
3461{
3462 *end = query.indexOf(pairDelimiter, pos);
3463 if (*end == -1)
3464 *end = query.size();
3465 *value = pos;
3466 while (*value < *end) {
3467 if (query[*value] == valueDelimiter)
3468 break;
3469 ++*value;
3470 }
3471}
3472
3473/*
3474 From http://www.ietf.org/rfc/rfc3986.txt, 5.2.4: Remove dot segments
3475
3476 Removes unnecessary ../ and ./ from the path. Used for normalizing
3477 the URL.
3478*/
3479static void removeDotsFromPath(QByteArray *path)
3480{
3481 // The input buffer is initialized with the now-appended path
3482 // components and the output buffer is initialized to the empty
3483 // string.
3484 char *out = path->data();
3485 const char *in = out;
3486 const char *end = out + path->size();
3487
3488 // If the input buffer consists only of
3489 // "." or "..", then remove that from the input
3490 // buffer;
3491 if (path->size() == 1 && in[0] == '.')
3492 ++in;
3493 else if (path->size() == 2 && in[0] == '.' && in[1] == '.')
3494 in += 2;
3495 // While the input buffer is not empty, loop:
3496 while (in < end) {
3497
3498 // otherwise, if the input buffer begins with a prefix of "../" or "./",
3499 // then remove that prefix from the input buffer;
3500 if (path->size() >= 2 && in[0] == '.' && in[1] == '/')
3501 in += 2;
3502 else if (path->size() >= 3 && in[0] == '.' && in[1] == '.' && in[2] == '/')
3503 in += 3;
3504
3505 // otherwise, if the input buffer begins with a prefix of
3506 // "/./" or "/.", where "." is a complete path segment,
3507 // then replace that prefix with "/" in the input buffer;
3508 if (in <= end - 3 && in[0] == '/' && in[1] == '.' && in[2] == '/') {
3509 in += 2;
3510 continue;
3511 } else if (in == end - 2 && in[0] == '/' && in[1] == '.') {
3512 *out++ = '/';
3513 in += 2;
3514 break;
3515 }
3516
3517 // otherwise, if the input buffer begins with a prefix
3518 // of "/../" or "/..", where ".." is a complete path
3519 // segment, then replace that prefix with "/" in the
3520 // input buffer and remove the last //segment and its
3521 // preceding "/" (if any) from the output buffer;
3522 if (in <= end - 4 && in[0] == '/' && in[1] == '.' && in[2] == '.' && in[3] == '/') {
3523 while (out > path->constData() && *(--out) != '/')
3524 ;
3525 if (out == path->constData() && *out != '/')
3526 ++in;
3527 in += 3;
3528 continue;
3529 } else if (in == end - 3 && in[0] == '/' && in[1] == '.' && in[2] == '.') {
3530 while (out > path->constData() && *(--out) != '/')
3531 ;
3532 if (*out == '/')
3533 ++out;
3534 in += 3;
3535 break;
3536 }
3537
3538 // otherwise move the first path segment in
3539 // the input buffer to the end of the output
3540 // buffer, including the initial "/" character
3541 // (if any) and any subsequent characters up
3542 // to, but not including, the next "/"
3543 // character or the end of the input buffer.
3544 *out++ = *in++;
3545 while (in < end && *in != '/')
3546 *out++ = *in++;
3547 }
3548 path->truncate(out - path->constData());
3549}
3550
3551void QUrlPrivate::validate() const
3552{
3553 QUrlPrivate *that = (QUrlPrivate *)this;
3554 that->encodedOriginal = that->toEncoded(); // may detach
3555 parse(ParseOnly);
3556
3557 QURL_SETFLAG(that->stateFlags, Validated);
3558
3559 if (!isValid)
3560 return;
3561
3562 QString auth = authority(); // causes the non-encoded forms to be valid
3563
3564 if (scheme == QLatin1String("mailto")) {
3565 if (!host.isEmpty() || port != -1 || !userName.isEmpty() || !password.isEmpty()) {
3566 that->isValid = false;
3567 that->errorInfo.setParams(0, QT_TRANSLATE_NOOP(QUrl, "expected empty host, username,"
3568 "port and password"),
3569 0, 0);
3570 }
3571 } else if (scheme == QLatin1String("ftp") || scheme == QLatin1String("http")) {
3572 if (host.isEmpty() && !(path.isEmpty() && encodedPath.isEmpty())) {
3573 that->isValid = false;
3574 that->errorInfo.setParams(0, QT_TRANSLATE_NOOP(QUrl, "the host is empty, but not the path"),
3575 0, 0);
3576 }
3577 }
3578}
3579
3580void QUrlPrivate::parse(ParseOptions parseOptions) const
3581{
3582 QUrlPrivate *that = (QUrlPrivate *)this;
3583 that->errorInfo.setParams(0, 0, 0, 0);
3584 if (encodedOriginal.isEmpty()) {
3585 that->isValid = false;
3586 that->errorInfo.setParams(0, QT_TRANSLATE_NOOP(QUrl, "empty"),
3587 0, 0);
3588 QURL_SETFLAG(that->stateFlags, Validated | Parsed);
3589 return;
3590 }
3591
3592
3593 QUrlParseData parseData;
3594 memset(&parseData, 0, sizeof(parseData));
3595 parseData.userInfoDelimIndex = -1;
3596 parseData.port = -1;
3597
3598 const char *pptr = (char *) encodedOriginal.constData();
3599 const char **ptr = &pptr;
3600
3601#if defined (QURL_DEBUG)
3602 qDebug("QUrlPrivate::parse(), parsing \"%s\"", pptr);
3603#endif
3604
3605 // optional scheme
3606 _scheme(ptr, &parseData);
3607
3608 // hierpart
3609 _hierPart(ptr, &parseData);
3610
3611 // optional query
3612 char ch = *((*ptr)++);
3613 if (ch == '?') {
3614 that->hasQuery = true;
3615 _query(ptr, &parseData);
3616 ch = *((*ptr)++);
3617 }
3618
3619 // optional fragment
3620 if (ch == '#') {
3621 that->hasFragment = true;
3622 _fragment(ptr, &parseData);
3623 } else if (ch != '\0') {
3624 that->isValid = false;
3625 that->errorInfo.setParams(*ptr, QT_TRANSLATE_NOOP(QUrl, "expected end of URL"),
3626 0, ch);
3627 QURL_SETFLAG(that->stateFlags, Validated | Parsed);
3628#if defined (QURL_DEBUG)
3629 qDebug("QUrlPrivate::parse(), unrecognized: %c%s", ch, *ptr);
3630#endif
3631 return;
3632 }
3633
3634 // when doing lazy validation, this function is called after
3635 // encodedOriginal has been constructed from the individual parts,
3636 // only to see if the constructed URL can be parsed. in that case,
3637 // parse() is called in ParseOnly mode; we don't want to set all
3638 // the members over again.
3639 if (parseOptions == ParseAndSet) {
3640 QURL_UNSETFLAG(that->stateFlags, HostCanonicalized);
3641
3642 if (parseData.scheme) {
3643 QByteArray s(parseData.scheme, parseData.schemeLength);
3644 that->scheme = fromPercentEncodingMutable(&s);
3645 }
3646
3647 that->setEncodedUserInfo(&parseData);
3648
3649 QByteArray h(parseData.host, parseData.hostLength);
3650 that->host = fromPercentEncodingMutable(&h);
3651 that->port = parseData.port;
3652
3653 that->path.clear();
3654 that->encodedPath = QByteArray(parseData.path, parseData.pathLength);
3655
3656 if (that->hasQuery)
3657 that->query = QByteArray(parseData.query, parseData.queryLength);
3658 else
3659 that->query.clear();
3660
3661 that->fragment.clear();
3662 if (that->hasFragment) {
3663 that->encodedFragment = QByteArray(parseData.fragment, parseData.fragmentLength);
3664 } else {
3665 that->encodedFragment.clear();
3666 }
3667 }
3668
3669 that->isValid = true;
3670 QURL_SETFLAG(that->stateFlags, Parsed);
3671
3672#if defined (QURL_DEBUG)
3673 qDebug("QUrl::setUrl(), scheme = %s", that->scheme.toLatin1().constData());
3674 qDebug("QUrl::setUrl(), userInfo = %s", that->userInfo.toLatin1().constData());
3675 qDebug("QUrl::setUrl(), host = %s", that->host.toLatin1().constData());
3676 qDebug("QUrl::setUrl(), port = %i", that->port);
3677 qDebug("QUrl::setUrl(), path = %s", fromPercentEncodingHelper(__path).toLatin1().constData());
3678 qDebug("QUrl::setUrl(), query = %s", __query.constData());
3679 qDebug("QUrl::setUrl(), fragment = %s", fromPercentEncodingHelper(__fragment).toLatin1().constData());
3680#endif
3681}
3682
3683void QUrlPrivate::clear()
3684{
3685 scheme.clear();
3686 userName.clear();
3687 password.clear();
3688 host.clear();
3689 port = -1;
3690 path.clear();
3691 query.clear();
3692 fragment.clear();
3693
3694 encodedOriginal.clear();
3695 encodedUserName.clear();
3696 encodedPassword.clear();
3697 encodedPath.clear();
3698 encodedFragment.clear();
3699 encodedNormalized.clear();
3700
3701 isValid = false;
3702 hasQuery = false;
3703 hasFragment = false;
3704
3705 valueDelimiter = '=';
3706 pairDelimiter = '&';
3707
3708 QURL_UNSETFLAG(stateFlags, Parsed | Validated | Normalized | HostCanonicalized);
3709}
3710
3711QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const
3712{
3713 if (!QURL_HASFLAG(stateFlags, Parsed)) parse();
3714 else ensureEncodedParts();
3715
3716 QByteArray url;
3717
3718 if (!(options & QUrl::RemoveScheme) && !scheme.isEmpty()) {
3719 url += scheme.toLatin1();
3720 url += ':';
3721 }
3722 QString auth = authority();
3723 bool doFileScheme = scheme == QLatin1String("file") && encodedPath.startsWith('/');
3724 if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority && (!auth.isEmpty() || doFileScheme)) {
3725 if (doFileScheme && !encodedPath.startsWith('/'))
3726 url += '/';
3727 url += "//";
3728
3729 if ((options & QUrl::RemoveUserInfo) != QUrl::RemoveUserInfo) {
3730 if (!userName.isEmpty()) {
3731 url += encodedUserName;
3732 if (!(options & QUrl::RemovePassword) && !password.isEmpty()) {
3733 url += ':';
3734 url += encodedPassword;
3735 }
3736 url += '@';
3737 }
3738 }
3739
3740 url += QUrl::toAce(host);
3741 if (!(options & QUrl::RemovePort) && port != -1) {
3742 url += ':';
3743 url += QString::number(port).toAscii();
3744 }
3745 }
3746
3747 if (!(options & QUrl::RemovePath)) {
3748 // check if we need to insert a slash
3749 if (!encodedPath.isEmpty() && !auth.isEmpty()) {
3750 if (!encodedPath.startsWith('/'))
3751 url += '/';
3752 }
3753 url += encodedPath;
3754
3755 // check if we need to remove trailing slashes
3756 while ((options & QUrl::StripTrailingSlash) && url.endsWith('/'))
3757 url.chop(1);
3758 }
3759
3760 if (!(options & QUrl::RemoveQuery) && hasQuery) {
3761 url += '?';
3762 url += query;
3763 }
3764 if (!(options & QUrl::RemoveFragment) && hasFragment) {
3765 url += '#';
3766 url += encodedFragment;
3767 }
3768
3769 return url;
3770}
3771
3772#define qToLower(ch) (((ch|32) >= 'a' && (ch|32) <= 'z') ? (ch|32) : ch)
3773
3774const QByteArray &QUrlPrivate::normalized()
3775{
3776 if (QURL_HASFLAG(stateFlags, QUrlPrivate::Normalized))
3777 return encodedNormalized;
3778
3779 QURL_SETFLAG(stateFlags, QUrlPrivate::Normalized);
3780
3781 QUrlPrivate tmp = *this;
3782 tmp.scheme = tmp.scheme.toLower();
3783 tmp.host = tmp.canonicalHost();
3784
3785 // ensure the encoded and normalized parts of the URL
3786 tmp.ensureEncodedParts();
3787 if (tmp.encodedUserName.contains('%'))
3788 q_normalizePercentEncoding(&tmp.encodedUserName, userNameExcludeChars);
3789 if (tmp.encodedPassword.contains('%'))
3790 q_normalizePercentEncoding(&tmp.encodedPassword, passwordExcludeChars);
3791 if (tmp.encodedFragment.contains('%'))
3792 q_normalizePercentEncoding(&tmp.encodedFragment, fragmentExcludeChars);
3793
3794 if (tmp.encodedPath.contains('%')) {
3795 // the path is a bit special:
3796 // the slashes shouldn't be encoded or decoded.
3797 // They should remain exactly like they are right now
3798 //
3799 // treat the path as a slash-separated sequence of pchar
3800 QByteArray result;
3801 result.reserve(tmp.encodedPath.length());
3802 if (tmp.encodedPath.startsWith('/'))
3803 result.append('/');
3804
3805 const char *data = tmp.encodedPath.constData();
3806 int lastSlash = 0;
3807 int nextSlash;
3808 do {
3809 ++lastSlash;
3810 nextSlash = tmp.encodedPath.indexOf('/', lastSlash);
3811 int len;
3812 if (nextSlash == -1)
3813 len = tmp.encodedPath.length() - lastSlash;
3814 else
3815 len = nextSlash - lastSlash;
3816
3817 if (memchr(data + lastSlash, '%', len)) {
3818 // there's at least one percent before the next slash
3819 QByteArray block = QByteArray(data + lastSlash, len);
3820 q_normalizePercentEncoding(&block, pathExcludeChars);
3821 result.append(block);
3822 } else {
3823 // no percents in this path segment, append wholesale
3824 result.append(data + lastSlash, len);
3825 }
3826
3827 // append the slash too, if it's there
3828 if (nextSlash != -1)
3829 result.append('/');
3830
3831 lastSlash = nextSlash;
3832 } while (lastSlash != -1);
3833
3834 tmp.encodedPath = result;
3835 }
3836
3837 if (!tmp.scheme.isEmpty()) // relative test
3838 removeDotsFromPath(&tmp.encodedPath);
3839
3840 int qLen = tmp.query.length();
3841 for (int i = 0; i < qLen; i++) {
3842 if (qLen - i > 2 && tmp.query.at(i) == '%') {
3843 ++i;
3844 tmp.query[i] = qToLower(tmp.query.at(i));
3845 ++i;
3846 tmp.query[i] = qToLower(tmp.query.at(i));
3847 }
3848 }
3849 encodedNormalized = tmp.toEncoded();
3850
3851 return encodedNormalized;
3852}
3853
3854QString QUrlPrivate::createErrorString()
3855{
3856 if (isValid)
3857 return QString();
3858
3859 QString errorString(QLatin1String(QT_TRANSLATE_NOOP(QUrl, "Invalid URL \"")));
3860 errorString += QLatin1String(encodedOriginal.constData());
3861 errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, "\""));
3862
3863 if (errorInfo._source) {
3864 int position = encodedOriginal.indexOf(errorInfo._source) - 1;
3865 if (position > 0) {
3866 errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ": error at position "));
3867 errorString += QString::number(position);
3868 } else {
3869 errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ": "));
3870 errorString += QLatin1String(errorInfo._source);
3871 }
3872 }
3873
3874 if (errorInfo._expected) {
3875 errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ": expected \'"));
3876 errorString += QLatin1Char(errorInfo._expected);
3877 errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, "\'"));
3878 } else {
3879 errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ": "));
3880 errorString += QLatin1String(errorInfo._message);
3881 }
3882 if (errorInfo._found) {
3883 errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ", but found \'"));
3884 errorString += QLatin1Char(errorInfo._found);
3885 errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, "\'"));
3886 }
3887 return errorString;
3888}
3889
3890/*!
3891 Constructs a URL by parsing \a url. \a url is assumed to be in human
3892 readable representation, with no percent encoding. QUrl will automatically
3893 percent encode all characters that are not allowed in a URL.
3894
3895 Example:
3896
3897 \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 0
3898
3899 To construct a URL from an encoded string, call fromEncoded():
3900
3901 \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 1
3902
3903 \sa setUrl(), setEncodedUrl(), fromEncoded(), TolerantMode
3904*/
3905QUrl::QUrl(const QString &url) : d(new QUrlPrivate)
3906{
3907 if (!url.isEmpty())
3908 setUrl(url);
3909}
3910
3911/*!
3912 \overload
3913
3914 Parses the \a url using the parser mode \a parsingMode.
3915
3916 \sa setUrl()
3917*/
3918QUrl::QUrl(const QString &url, ParsingMode parsingMode) : d(new QUrlPrivate)
3919{
3920 if (!url.isEmpty())
3921 setUrl(url, parsingMode);
3922 else
3923 d->parsingMode = parsingMode;
3924}
3925
3926/*!
3927 Constructs an empty QUrl object.
3928*/
3929QUrl::QUrl() : d(new QUrlPrivate)
3930{
3931}
3932
3933/*!
3934 Constructs a copy of \a other.
3935*/
3936QUrl::QUrl(const QUrl &other) : d(other.d)
3937{
3938 d->ref.ref();
3939}
3940
3941/*!
3942 Destructor; called immediately before the object is deleted.
3943*/
3944QUrl::~QUrl()
3945{
3946 if (!d->ref.deref())
3947 delete d;
3948}
3949
3950/*!
3951 Returns true if the URL is valid; otherwise returns false.
3952
3953 The URL is run through a conformance test. Every part of the URL
3954 must conform to the standard encoding rules of the URI standard
3955 for the URL to be reported as valid.
3956
3957 \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 2
3958*/
3959bool QUrl::isValid() const
3960{
3961 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
3962 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Validated)) d->validate();
3963
3964 return d->isValid;
3965}
3966
3967/*!
3968 Returns true if the URL has no data; otherwise returns false.
3969*/
3970bool QUrl::isEmpty() const
3971{
3972 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed))
3973 return d->encodedOriginal.isEmpty();
3974 else
3975 return d->scheme.isEmpty() // no encodedScheme
3976 && d->userName.isEmpty() && d->encodedUserName.isEmpty()
3977 && d->password.isEmpty() && d->encodedPassword.isEmpty()
3978 && d->host.isEmpty() // no encodedHost
3979 && d->port == -1
3980 && d->path.isEmpty() && d->encodedPath.isEmpty()
3981 && d->query.isEmpty()
3982 && d->fragment.isEmpty() && d->encodedFragment.isEmpty();
3983}
3984
3985/*!
3986 Resets the content of the QUrl. After calling this function, the
3987 QUrl is equal to one that has been constructed with the default
3988 empty constructor.
3989*/
3990void QUrl::clear()
3991{
3992 detach();
3993 d->clear();
3994}
3995
3996/*!
3997 Constructs a URL by parsing the contents of \a url.
3998
3999 \a url is assumed to be in unicode format, with no percent
4000 encoding.
4001
4002 Calling isValid() will tell whether or not a valid URL was
4003 constructed.
4004
4005 \sa setEncodedUrl()
4006*/
4007void QUrl::setUrl(const QString &url)
4008{
4009 setUrl(url, TolerantMode);
4010}
4011
4012/*!
4013 \overload
4014
4015 Parses \a url using the parsing mode \a parsingMode.
4016
4017 \sa setEncodedUrl()
4018*/
4019void QUrl::setUrl(const QString &url, ParsingMode parsingMode)
4020{
4021 // escape all reserved characters and delimiters
4022 // reserved = gen-delims / sub-delims
4023 if (parsingMode != TolerantMode) {
4024 setEncodedUrl(toPercentEncodingHelper(url, ABNF_reserved), parsingMode);
4025 return;
4026 }
4027
4028 // Tolerant preprocessing
4029 QString tmp = url;
4030
4031 // Allow %20 in the QString variant
4032 tmp.replace(QLatin1String("%20"), QLatin1String(" "));
4033
4034 // Percent-encode unsafe ASCII characters after host part
4035 int start = tmp.indexOf(QLatin1String("//"));
4036 if (start != -1) {
4037 // Has host part, find delimiter
4038 start += 2; // skip "//"
4039 const char delims[] = "/#?";
4040 const char *d = delims;
4041 int hostEnd = -1;
4042 while (*d && (hostEnd = tmp.indexOf(QLatin1Char(*d), start)) == -1)
4043 ++d;
4044 start = (hostEnd == -1) ? -1 : hostEnd + 1;
4045 } else {
4046 start = 0; // Has no host part
4047 }
4048 QByteArray encodedUrl;
4049 if (start != -1) {
4050 QString hostPart = tmp.left(start);
4051 QString otherPart = tmp.mid(start);
4052 encodedUrl = toPercentEncodingHelper(hostPart, ":/?#[]@!$&'()*+,;=")
4053 + toPercentEncodingHelper(otherPart, ":/?#@!$&'()*+,;=");
4054 } else {
4055 encodedUrl = toPercentEncodingHelper(tmp, ABNF_reserved);
4056 }
4057 setEncodedUrl(encodedUrl, StrictMode);
4058}
4059
4060/*!
4061 Constructs a URL by parsing the contents of \a encodedUrl.
4062
4063 \a encodedUrl is assumed to be a URL string in percent encoded
4064 form, containing only ASCII characters.
4065
4066 Use isValid() to determine if a valid URL was constructed.
4067
4068 \sa setUrl()
4069*/
4070void QUrl::setEncodedUrl(const QByteArray &encodedUrl)
4071{
4072 setEncodedUrl(encodedUrl, TolerantMode);
4073}
4074
4075inline static bool isHex(char c)
4076{
4077 c |= 0x20;
4078 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
4079}
4080
4081static inline char toHex(quint8 c)
4082{
4083 return c > 9 ? c - 10 + 'A' : c + '0';
4084}
4085
4086/*!
4087 Constructs a URL by parsing the contents of \a encodedUrl using
4088 the given \a parsingMode.
4089*/
4090void QUrl::setEncodedUrl(const QByteArray &encodedUrl, ParsingMode parsingMode)
4091{
4092 clear();
4093 QByteArray tmp = encodedUrl;
4094 if ((d->parsingMode = parsingMode) == TolerantMode) {
4095 // Replace stray % with %25
4096 QByteArray copy = tmp;
4097 for (int i = 0, j = 0; i < copy.size(); ++i, ++j) {
4098 if (copy.at(i) == '%') {
4099 if (i + 2 >= copy.size() || !isHex(copy.at(i + 1)) || !isHex(copy.at(i + 2))) {
4100 tmp.replace(j, 1, "%25");
4101 j += 2;
4102 }
4103 }
4104 }
4105
4106 // Find the host part
4107 int hostStart = tmp.indexOf("//");
4108 int hostEnd = -1;
4109 if (hostStart != -1) {
4110 // Has host part, find delimiter
4111 hostStart += 2; // skip "//"
4112 hostEnd = tmp.indexOf('/', hostStart);
4113 if (hostEnd == -1)
4114 hostEnd = tmp.indexOf('#', hostStart);
4115 if (hostEnd == -1)
4116 hostEnd = tmp.indexOf('?');
4117 if (hostEnd == -1)
4118 hostEnd = tmp.length() - 1;
4119 }
4120
4121 // Reserved and unreserved characters are fine
4122// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
4123// reserved = gen-delims / sub-delims
4124// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
4125// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
4126// / "*" / "+" / "," / ";" / "="
4127 // Replace everything else with percent encoding
4128 static const char doEncode[] = " \"<>[\\]^`{|}";
4129 static const char doEncodeHost[] = " \"<>\\^`{|}";
4130 for (int i = 0; i < tmp.size(); ++i) {
4131 quint8 c = quint8(tmp.at(i));
4132 if (c < 32 || c > 127 ||
4133 strchr(hostStart <= i && i <= hostEnd ? doEncodeHost : doEncode, c)) {
4134 char buf[4];
4135 buf[0] = '%';
4136 buf[1] = toHex(c >> 4);
4137 buf[2] = toHex(c & 0xf);
4138 buf[3] = '\0';
4139 tmp.replace(i, 1, buf);
4140 i += 2;
4141 }
4142 }
4143 }
4144
4145 d->encodedOriginal = tmp;
4146}
4147
4148/*!
4149 Sets the scheme of the URL to \a scheme. As a scheme can only
4150 contain ASCII characters, no conversion or encoding is done on the
4151 input.
4152
4153 The scheme describes the type (or protocol) of the URL. It's
4154 represented by one or more ASCII characters at the start the URL,
4155 and is followed by a ':'. The following example shows a URL where
4156 the scheme is "ftp":
4157
4158 \img qurl-authority2.png
4159
4160 The scheme can also be empty, in which case the URL is interpreted
4161 as relative.
4162
4163 \sa scheme(), isRelative()
4164*/
4165void QUrl::setScheme(const QString &scheme)
4166{
4167 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4168 detach();
4169 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4170
4171 d->scheme = scheme;
4172}
4173
4174/*!
4175 Returns the scheme of the URL. If an empty string is returned,
4176 this means the scheme is undefined and the URL is then relative.
4177
4178 \sa setScheme(), isRelative()
4179*/
4180QString QUrl::scheme() const
4181{
4182 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4183
4184 return d->scheme;
4185}
4186
4187/*!
4188 Sets the authority of the URL to \a authority.
4189
4190 The authority of a URL is the combination of user info, a host
4191 name and a port. All of these elements are optional; an empty
4192 authority is therefore valid.
4193
4194 The user info and host are separated by a '@', and the host and
4195 port are separated by a ':'. If the user info is empty, the '@'
4196 must be omitted; although a stray ':' is permitted if the port is
4197 empty.
4198
4199 The following example shows a valid authority string:
4200
4201 \img qurl-authority.png
4202*/
4203void QUrl::setAuthority(const QString &authority)
4204{
4205 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4206 detach();
4207 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4208
4209 d->setAuthority(authority);
4210}
4211
4212/*!
4213 Returns the authority of the URL if it is defined; otherwise
4214 an empty string is returned.
4215
4216 \sa setAuthority()
4217*/
4218QString QUrl::authority() const
4219{
4220 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4221
4222 return d->authority();
4223}
4224
4225/*!
4226 Sets the user info of the URL to \a userInfo. The user info is an
4227 optional part of the authority of the URL, as described in
4228 setAuthority().
4229
4230 The user info consists of a user name and optionally a password,
4231 separated by a ':'. If the password is empty, the colon must be
4232 omitted. The following example shows a valid user info string:
4233
4234 \img qurl-authority3.png
4235
4236 \sa userInfo(), setUserName(), setPassword(), setAuthority()
4237*/
4238void QUrl::setUserInfo(const QString &userInfo)
4239{
4240 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4241 detach();
4242 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4243
4244 d->setUserInfo(userInfo.trimmed());
4245}
4246
4247/*!
4248 Returns the user info of the URL, or an empty string if the user
4249 info is undefined.
4250*/
4251QString QUrl::userInfo() const
4252{
4253 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4254
4255 return d->userInfo();
4256}
4257
4258/*!
4259 Sets the URL's user name to \a userName. The \a userName is part
4260 of the user info element in the authority of the URL, as described
4261 in setUserInfo().
4262
4263 \sa setEncodedUserName(), userName(), setUserInfo()
4264*/
4265void QUrl::setUserName(const QString &userName)
4266{
4267 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4268 detach();
4269 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4270
4271 d->userName = userName;
4272 d->encodedUserName.clear();
4273}
4274
4275/*!
4276 Returns the user name of the URL if it is defined; otherwise
4277 an empty string is returned.
4278
4279 \sa setUserName(), encodedUserName()
4280*/
4281QString QUrl::userName() const
4282{
4283 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4284
4285 d->userInfo(); // causes the unencoded form to be set
4286 return d->userName;
4287}
4288
4289/*!
4290 \since 4.4
4291
4292 Sets the URL's user name to the percent-encoded \a userName. The \a
4293 userName is part of the user info element in the authority of the
4294 URL, as described in setUserInfo().
4295
4296 Note: this function does not verify that \a userName is properly
4297 encoded. It is the caller's responsibility to ensure that the any
4298 delimiters (such as colons or slashes) are properly encoded.
4299
4300 \sa setUserName(), encodedUserName(), setUserInfo()
4301*/
4302void QUrl::setEncodedUserName(const QByteArray &userName)
4303{
4304 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4305 detach();
4306 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4307
4308 d->encodedUserName = userName;
4309 d->userName.clear();
4310}
4311
4312/*!
4313 \since 4.4
4314
4315 Returns the user name of the URL if it is defined; otherwise
4316 an empty string is returned. The returned value will have its
4317 non-ASCII and other control characters percent-encoded, as in
4318 toEncoded().
4319
4320 \sa setEncodedUserName()
4321*/
4322QByteArray QUrl::encodedUserName() const
4323{
4324 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4325
4326 d->ensureEncodedParts();
4327 return d->encodedUserName;
4328}
4329
4330/*!
4331 Sets the URL's password to \a password. The \a password is part of
4332 the user info element in the authority of the URL, as described in
4333 setUserInfo().
4334
4335 \sa password(), setUserInfo()
4336*/
4337void QUrl::setPassword(const QString &password)
4338{
4339 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4340 detach();
4341 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4342
4343 d->password = password;
4344 d->encodedPassword.clear();
4345}
4346
4347/*!
4348 Returns the password of the URL if it is defined; otherwise
4349 an empty string is returned.
4350
4351 \sa setPassword()
4352*/
4353QString QUrl::password() const
4354{
4355 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4356
4357 d->userInfo(); // causes the unencoded form to be set
4358 return d->password;
4359}
4360
4361/*!
4362 \since 4.4
4363
4364 Sets the URL's password to the percent-encoded \a password. The \a
4365 password is part of the user info element in the authority of the
4366 URL, as described in setUserInfo().
4367
4368 Note: this function does not verify that \a password is properly
4369 encoded. It is the caller's responsibility to ensure that the any
4370 delimiters (such as colons or slashes) are properly encoded.
4371
4372 \sa setPassword(), encodedPassword(), setUserInfo()
4373*/
4374void QUrl::setEncodedPassword(const QByteArray &password)
4375{
4376 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4377 detach();
4378 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4379
4380 d->encodedPassword = password;
4381 d->password.clear();
4382}
4383
4384/*!
4385 \since 4.4
4386
4387 Returns the password of the URL if it is defined; otherwise an
4388 empty string is returned. The returned value will have its
4389 non-ASCII and other control characters percent-encoded, as in
4390 toEncoded().
4391
4392 \sa setEncodedPassword(), toEncoded()
4393*/
4394QByteArray QUrl::encodedPassword() const
4395{
4396 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4397
4398 d->ensureEncodedParts();
4399 return d->encodedPassword;
4400}
4401
4402/*!
4403 Sets the host of the URL to \a host. The host is part of the
4404 authority.
4405
4406 \sa host(), setAuthority()
4407*/
4408void QUrl::setHost(const QString &host)
4409{
4410 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4411 detach();
4412 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized | QUrlPrivate::HostCanonicalized);
4413
4414 d->host = host;
4415 if (d->host.contains(QLatin1Char(':')))
4416 d->host = QLatin1Char('[') + d->host + QLatin1Char(']');
4417}
4418
4419/*!
4420 Returns the host of the URL if it is defined; otherwise
4421 an empty string is returned.
4422*/
4423QString QUrl::host() const
4424{
4425 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4426
4427 if (d->host.isEmpty() || d->host.at(0) != QLatin1Char('['))
4428 return d->canonicalHost();
4429 QString tmp = d->host.mid(1);
4430 tmp.truncate(tmp.length() - 1);
4431 return tmp;
4432}
4433
4434/*!
4435 \since 4.4
4436
4437 Sets the URL's host to the ACE- or percent-encoded \a host. The \a
4438 host is part of the user info element in the authority of the
4439 URL, as described in setAuthority().
4440
4441 \sa setHost(), encodedHost(), setAuthority(), fromAce()
4442*/
4443void QUrl::setEncodedHost(const QByteArray &host)
4444{
4445 setHost(fromPercentEncodingHelper(host));
4446}
4447
4448/*!
4449 \since 4.4
4450
4451 Returns the host part of the URL if it is defined; otherwise
4452 an empty string is returned.
4453
4454 Note: encodedHost() does not return percent-encoded hostnames. Instead,
4455 the ACE-encoded (bare ASCII in Punycode encoding) form will be
4456 returned for any non-ASCII hostname.
4457
4458 This function is equivalent to calling QUrl::toAce() on the return
4459 value of host().
4460
4461 \sa setEncodedHost()
4462*/
4463QByteArray QUrl::encodedHost() const
4464{
4465 // should we cache this in d->encodedHost?
4466 return QUrl::toAce(host());
4467}
4468
4469/*!
4470 Sets the port of the URL to \a port. The port is part of the
4471 authority of the URL, as described in setAuthority().
4472
4473 \a port must be between 0 and 65535 inclusive. Setting the
4474 port to -1 indicates that the port is unspecified.
4475*/
4476void QUrl::setPort(int port)
4477{
4478 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4479 detach();
4480 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4481
4482 if (port < -1 || port > 65535) {
4483 qWarning("QUrl::setPort: Out of range");
4484 port = -1;
4485 }
4486
4487 d->port = port;
4488}
4489
4490/*!
4491 Returns the port of the URL, or -1 if the port is unspecified.
4492*/
4493int QUrl::port() const
4494{
4495 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4496 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Validated)) d->validate();
4497 return d->port;
4498}
4499
4500/*!
4501 \overload
4502 \since 4.1
4503
4504 Returns the port of the URL, or \a defaultPort if the port is
4505 unspecified.
4506
4507 Example:
4508
4509 \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 3
4510*/
4511int QUrl::port(int defaultPort) const
4512{
4513 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4514 return d->port == -1 ? defaultPort : d->port;
4515}
4516
4517/*!
4518 Sets the path of the URL to \a path. The path is the part of the
4519 URL that comes after the authority but before the query string.
4520
4521 \img qurl-ftppath.png
4522
4523 For non-hierarchical schemes, the path will be everything
4524 following the scheme declaration, as in the following example:
4525
4526 \img qurl-mailtopath.png
4527
4528 \sa path()
4529*/
4530void QUrl::setPath(const QString &path)
4531{
4532 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4533 detach();
4534 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4535
4536 d->path = path;
4537 d->encodedPath.clear();
4538}
4539
4540/*!
4541 Returns the path of the URL.
4542
4543 \sa setPath()
4544*/
4545QString QUrl::path() const
4546{
4547 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4548
4549 if (d->path.isNull()) {
4550 QUrlPrivate *that = const_cast<QUrlPrivate *>(d);
4551 that->path = fromPercentEncodingHelper(d->encodedPath);
4552 }
4553 return d->path;
4554}
4555
4556/*!
4557 \since 4.4
4558
4559 Sets the URL's path to the percent-encoded \a path. The path is
4560 the part of the URL that comes after the authority but before the
4561 query string.
4562
4563 \img qurl-ftppath.png
4564
4565 For non-hierarchical schemes, the path will be everything
4566 following the scheme declaration, as in the following example:
4567
4568 \img qurl-mailtopath.png
4569
4570 Note: this function does not verify that \a path is properly
4571 encoded. It is the caller's responsibility to ensure that the any
4572 delimiters (such as '?' and '#') are properly encoded.
4573
4574 \sa setPath(), encodedPath(), setUserInfo()
4575*/
4576void QUrl::setEncodedPath(const QByteArray &path)
4577{
4578 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4579 detach();
4580 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4581
4582 d->encodedPath = path;
4583 d->path.clear();
4584}
4585
4586/*!
4587 \since 4.4
4588
4589 Returns the path of the URL if it is defined; otherwise an
4590 empty string is returned. The returned value will have its
4591 non-ASCII and other control characters percent-encoded, as in
4592 toEncoded().
4593
4594 \sa setEncodedPath(), toEncoded()
4595*/
4596QByteArray QUrl::encodedPath() const
4597{
4598 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4599
4600 d->ensureEncodedParts();
4601 return d->encodedPath;
4602}
4603
4604/*!
4605 \since 4.2
4606
4607 Returns true if this URL contains a Query (i.e., if ? was seen on it).
4608
4609 \sa hasQueryItem(), encodedQuery()
4610*/
4611bool QUrl::hasQuery() const
4612{
4613 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4614
4615 return d->hasQuery;
4616}
4617
4618/*!
4619 Sets the characters used for delimiting between keys and values,
4620 and between key-value pairs in the URL's query string. The default
4621 value delimiter is '=' and the default pair delimiter is '&'.
4622
4623 \img qurl-querystring.png
4624
4625 \a valueDelimiter will be used for separating keys from values,
4626 and \a pairDelimiter will be used to separate key-value pairs.
4627 Any occurrences of these delimiting characters in the encoded
4628 representation of the keys and values of the query string are
4629 percent encoded.
4630
4631 If \a valueDelimiter is set to '-' and \a pairDelimiter is '/',
4632 the above query string would instead be represented like this:
4633
4634 \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 4
4635
4636 Calling this function does not change the delimiters of the
4637 current query string. It only affects queryItems(),
4638 setQueryItems() and addQueryItems().
4639*/
4640void QUrl::setQueryDelimiters(char valueDelimiter, char pairDelimiter)
4641{
4642 detach();
4643
4644 d->valueDelimiter = valueDelimiter;
4645 d->pairDelimiter = pairDelimiter;
4646}
4647
4648/*!
4649 Returns the character used to delimit between key-value pairs in
4650 the query string of the URL.
4651*/
4652char QUrl::queryPairDelimiter() const
4653{
4654 return d->pairDelimiter;
4655}
4656
4657/*!
4658 Returns the character used to delimit between keys and values in
4659 the query string of the URL.
4660*/
4661char QUrl::queryValueDelimiter() const
4662{
4663 return d->valueDelimiter;
4664}
4665
4666/*!
4667 Sets the query string of the URL to \a query. The string is
4668 inserted as-is, and no further encoding is performed when calling
4669 toEncoded().
4670
4671 This function is useful if you need to pass a query string that
4672 does not fit into the key-value pattern, or that uses a different
4673 scheme for encoding special characters than what is suggested by
4674 QUrl.
4675
4676 Passing a value of QByteArray() to \a query (a null QByteArray) unsets
4677 the query completely. However, passing a value of QByteArray("")
4678 will set the query to an empty value, as if the original URL
4679 had a lone "?".
4680
4681 \sa encodedQuery(), hasQuery()
4682*/
4683void QUrl::setEncodedQuery(const QByteArray &query)
4684{
4685 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4686 detach();
4687 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
4688
4689 d->query = query;
4690 d->hasQuery = !query.isNull();
4691}
4692
4693/*!
4694 Sets the query string of the URL to an encoded version of \a
4695 query. The contents of \a query are converted to a string
4696 internally, each pair delimited by the character returned by
4697 pairDelimiter(), and the key and value are delimited by
4698 valueDelimiter().
4699
4700 \sa setQueryDelimiters(), queryItems(), setEncodedQueryItems()
4701*/
4702void QUrl::setQueryItems(const QList<QPair<QString, QString> > &query)
4703{
4704 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4705 detach();
4706
4707 char alsoEncode[3];
4708 alsoEncode[0] = d->valueDelimiter;
4709 alsoEncode[1] = d->pairDelimiter;
4710 alsoEncode[2] = 0;
4711
4712 QByteArray queryTmp;
4713 for (int i = 0; i < query.size(); i++) {
4714 if (i) queryTmp += d->pairDelimiter;
4715 // query = *( pchar / "/" / "?" )
4716 queryTmp += toPercentEncodingHelper(query.at(i).first, queryExcludeChars, alsoEncode);
4717 queryTmp += d->valueDelimiter;
4718 // query = *( pchar / "/" / "?" )
4719 queryTmp += toPercentEncodingHelper(query.at(i).second, queryExcludeChars, alsoEncode);
4720 }
4721
4722 d->query = queryTmp;
4723 d->hasQuery = !query.isEmpty();
4724}
4725
4726/*!
4727 \since 4.4
4728
4729 Sets the query string of the URL to the encoded version of \a
4730 query. The contents of \a query are converted to a string
4731 internally, each pair delimited by the character returned by
4732 pairDelimiter(), and the key and value are delimited by
4733 valueDelimiter().
4734
4735 Note: this function does not verify that the key-value pairs
4736 are properly encoded. It is the caller's responsibility to ensure
4737 that the query delimiters are properly encoded, if any.
4738
4739 \sa setQueryDelimiters(), encodedQueryItems(), setQueryItems()
4740*/
4741void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query)
4742{
4743 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4744 detach();
4745
4746 QByteArray queryTmp;
4747 for (int i = 0; i < query.size(); i++) {
4748 if (i) queryTmp += d->pairDelimiter;
4749 queryTmp += query.at(i).first;
4750 queryTmp += d->valueDelimiter;
4751 queryTmp += query.at(i).second;
4752 }
4753
4754 d->query = queryTmp;
4755 d->hasQuery = !query.isEmpty();
4756}
4757
4758/*!
4759 Inserts the pair \a key = \a value into the query string of the
4760 URL.
4761
4762 \sa addEncodedQueryItem()
4763*/
4764void QUrl::addQueryItem(const QString &key, const QString &value)
4765{
4766 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4767 detach();
4768
4769 char alsoEncode[3];
4770 alsoEncode[0] = d->valueDelimiter;
4771 alsoEncode[1] = d->pairDelimiter;
4772 alsoEncode[2] = 0;
4773
4774 if (!d->query.isEmpty())
4775 d->query += d->pairDelimiter;
4776
4777 // query = *( pchar / "/" / "?" )
4778 d->query += toPercentEncodingHelper(key, queryExcludeChars, alsoEncode);
4779 d->query += d->valueDelimiter;
4780 // query = *( pchar / "/" / "?" )
4781 d->query += toPercentEncodingHelper(value, queryExcludeChars, alsoEncode);
4782
4783 d->hasQuery = !d->query.isEmpty();
4784}
4785
4786/*!
4787 \since 4.4
4788
4789 Inserts the pair \a key = \a value into the query string of the
4790 URL.
4791
4792 Note: this function does not verify that either \a key or \a value
4793 are properly encoded. It is the caller's responsibility to ensure
4794 that the query delimiters are properly encoded, if any.
4795
4796 \sa addQueryItem(), setQueryDelimiters()
4797*/
4798void QUrl::addEncodedQueryItem(const QByteArray &key, const QByteArray &value)
4799{
4800 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4801 detach();
4802
4803 if (!d->query.isEmpty())
4804 d->query += d->pairDelimiter;
4805
4806 d->query += key;
4807 d->query += d->valueDelimiter;
4808 d->query += value;
4809
4810 d->hasQuery = !d->query.isEmpty();
4811}
4812
4813/*!
4814 Returns the query string of the URL, as a map of keys and values.
4815
4816 \sa setQueryItems(), setEncodedQuery()
4817*/
4818QList<QPair<QString, QString> > QUrl::queryItems() const
4819{
4820 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4821
4822 QList<QPair<QString, QString> > itemMap;
4823
4824 int pos = 0;
4825 const char *query = d->query.constData();
4826 while (pos < d->query.size()) {
4827 int valuedelim, end;
4828 d->queryItem(pos, &valuedelim, &end);
4829 QByteArray q(query + pos, valuedelim - pos);
4830 if (valuedelim < end) {
4831 QByteArray v(query + valuedelim + 1, end - valuedelim - 1);
4832 itemMap += qMakePair(fromPercentEncodingMutable(&q),
4833 fromPercentEncodingMutable(&v));
4834 } else {
4835 itemMap += qMakePair(fromPercentEncodingMutable(&q), QString());
4836 }
4837 pos = end + 1;
4838 }
4839
4840 return itemMap;
4841}
4842
4843/*!
4844 \since 4.4
4845
4846 Returns the query string of the URL, as a map of encoded keys and values.
4847
4848 \sa setEncodedQueryItems(), setQueryItems(), setEncodedQuery()
4849*/
4850QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const
4851{
4852 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4853
4854 QList<QPair<QByteArray, QByteArray> > itemMap;
4855
4856 int pos = 0;
4857 const char *query = d->query.constData();
4858 while (pos < d->query.size()) {
4859 int valuedelim, end;
4860 d->queryItem(pos, &valuedelim, &end);
4861 if (valuedelim < end)
4862 itemMap += qMakePair(QByteArray(query + pos, valuedelim - pos),
4863 QByteArray(query + valuedelim + 1, end - valuedelim - 1));
4864 else
4865 itemMap += qMakePair(QByteArray(query + pos, valuedelim - pos), QByteArray());
4866 pos = end + 1;
4867 }
4868
4869 return itemMap;
4870}
4871
4872/*!
4873 Returns true if there is a query string pair whose key is equal
4874 to \a key from the URL.
4875
4876 \sa hasEncodedQueryItem()
4877*/
4878bool QUrl::hasQueryItem(const QString &key) const
4879{
4880 return hasEncodedQueryItem(toPercentEncoding(key, queryExcludeChars));
4881}
4882
4883/*!
4884 \since 4.4
4885
4886 Returns true if there is a query string pair whose key is equal
4887 to \a key from the URL.
4888
4889 Note: if the encoded \a key does not match the encoded version of
4890 the query, this function will return false. That is, if the
4891 encoded query of this URL is "search=Qt%20Rules", calling this
4892 function with \a key = "%73earch" will return false.
4893
4894 \sa hasQueryItem()
4895*/
4896bool QUrl::hasEncodedQueryItem(const QByteArray &key) const
4897{
4898 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4899
4900 int pos = 0;
4901 const char *query = d->query.constData();
4902 while (pos < d->query.size()) {
4903 int valuedelim, end;
4904 d->queryItem(pos, &valuedelim, &end);
4905 if (key == QByteArray::fromRawData(query + pos, valuedelim - pos))
4906 return true;
4907 pos = end + 1;
4908 }
4909 return false;
4910}
4911
4912/*!
4913 Returns the first query string value whose key is equal to \a key
4914 from the URL.
4915
4916 \sa allQueryItemValues()
4917*/
4918QString QUrl::queryItemValue(const QString &key) const
4919{
4920 QByteArray tmp = encodedQueryItemValue(toPercentEncoding(key, queryExcludeChars));
4921 return fromPercentEncodingMutable(&tmp);
4922}
4923
4924/*!
4925 \since 4.4
4926
4927 Returns the first query string value whose key is equal to \a key
4928 from the URL.
4929
4930 Note: if the encoded \a key does not match the encoded version of
4931 the query, this function will not work. That is, if the
4932 encoded query of this URL is "search=Qt%20Rules", calling this
4933 function with \a key = "%73earch" will return an empty string.
4934
4935 \sa queryItemValue(), allQueryItemValues()
4936*/
4937QByteArray QUrl::encodedQueryItemValue(const QByteArray &key) const
4938{
4939 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4940
4941 int pos = 0;
4942 const char *query = d->query.constData();
4943 while (pos < d->query.size()) {
4944 int valuedelim, end;
4945 d->queryItem(pos, &valuedelim, &end);
4946 if (key == QByteArray::fromRawData(query + pos, valuedelim - pos))
4947 return valuedelim < end ?
4948 QByteArray(query + valuedelim + 1, end - valuedelim - 1) : QByteArray();
4949 pos = end + 1;
4950 }
4951 return QByteArray();
4952}
4953
4954/*!
4955 Returns the a list of query string values whose key is equal to
4956 \a key from the URL.
4957
4958 \sa queryItemValue()
4959*/
4960QStringList QUrl::allQueryItemValues(const QString &key) const
4961{
4962 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
4963
4964 QByteArray encodedKey = toPercentEncoding(key, queryExcludeChars);
4965 QStringList values;
4966
4967 int pos = 0;
4968 const char *query = d->query.constData();
4969 while (pos < d->query.size()) {
4970 int valuedelim, end;
4971 d->queryItem(pos, &valuedelim, &end);
4972 if (encodedKey == QByteArray::fromRawData(query + pos, valuedelim - pos)) {
4973 QByteArray v(query + valuedelim + 1, end - valuedelim - 1);
4974 values += valuedelim < end ?
4975 fromPercentEncodingMutable(&v)
4976 : QString();
4977 }
4978 pos = end + 1;
4979 }
4980
4981 return values;
4982}
4983
4984/*!
4985 \since 4.4
4986
4987 Returns the a list of query string values whose key is equal to
4988 \a key from the URL.
4989
4990 Note: if the encoded \a key does not match the encoded version of
4991 the query, this function will not work. That is, if the
4992 encoded query of this URL is "search=Qt%20Rules", calling this
4993 function with \a key = "%73earch" will return an empty list.
4994
4995 \sa allQueryItemValues(), queryItemValue(), encodedQueryItemValue()
4996*/
4997QList<QByteArray> QUrl::allEncodedQueryItemValues(const QByteArray &key) const
4998{
4999 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5000
5001 QList<QByteArray> values;
5002
5003 int pos = 0;
5004 const char *query = d->query.constData();
5005 while (pos < d->query.size()) {
5006 int valuedelim, end;
5007 d->queryItem(pos, &valuedelim, &end);
5008 if (key == QByteArray::fromRawData(query + pos, valuedelim - pos))
5009 values += valuedelim < end ?
5010 QByteArray(query + valuedelim + 1, end - valuedelim - 1)
5011 : QByteArray();
5012 pos = end + 1;
5013 }
5014
5015 return values;
5016}
5017
5018/*!
5019 Removes the first query string pair whose key is equal to \a key
5020 from the URL.
5021
5022 \sa removeAllQueryItems()
5023*/
5024void QUrl::removeQueryItem(const QString &key)
5025{
5026 removeEncodedQueryItem(toPercentEncoding(key, queryExcludeChars));
5027}
5028
5029/*!
5030 \since 4.4
5031
5032 Removes the first query string pair whose key is equal to \a key
5033 from the URL.
5034
5035 Note: if the encoded \a key does not match the encoded version of
5036 the query, this function will not work. That is, if the
5037 encoded query of this URL is "search=Qt%20Rules", calling this
5038 function with \a key = "%73earch" will do nothing.
5039
5040 \sa removeQueryItem(), removeAllQueryItems()
5041*/
5042void QUrl::removeEncodedQueryItem(const QByteArray &key)
5043{
5044 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5045 detach();
5046
5047 int pos = 0;
5048 const char *query = d->query.constData();
5049 while (pos < d->query.size()) {
5050 int valuedelim, end;
5051 d->queryItem(pos, &valuedelim, &end);
5052 if (key == QByteArray::fromRawData(query + pos, valuedelim - pos)) {
5053 if (end < d->query.size())
5054 ++end; // remove additional '%'
5055 d->query.remove(pos, end - pos);
5056 return;
5057 }
5058 pos = end + 1;
5059 }
5060}
5061
5062/*!
5063 Removes all the query string pairs whose key is equal to \a key
5064 from the URL.
5065
5066 \sa removeQueryItem()
5067*/
5068void QUrl::removeAllQueryItems(const QString &key)
5069{
5070 removeAllEncodedQueryItems(toPercentEncoding(key, queryExcludeChars));
5071}
5072
5073/*!
5074 \since 4.4
5075
5076 Removes all the query string pairs whose key is equal to \a key
5077 from the URL.
5078
5079 Note: if the encoded \a key does not match the encoded version of
5080 the query, this function will not work. That is, if the
5081 encoded query of this URL is "search=Qt%20Rules", calling this
5082 function with \a key = "%73earch" will do nothing.
5083
5084 \sa removeQueryItem()
5085*/
5086void QUrl::removeAllEncodedQueryItems(const QByteArray &key)
5087{
5088 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5089 detach();
5090
5091 int pos = 0;
5092 const char *query = d->query.constData();
5093 while (pos < d->query.size()) {
5094 int valuedelim, end;
5095 d->queryItem(pos, &valuedelim, &end);
5096 if (key == QByteArray::fromRawData(query + pos, valuedelim - pos)) {
5097 if (end < d->query.size())
5098 ++end; // remove additional '%'
5099 d->query.remove(pos, end - pos);
5100 } else {
5101 pos = end + 1;
5102 }
5103 }
5104}
5105
5106/*!
5107 Returns the query string of the URL in percent encoded form.
5108*/
5109QByteArray QUrl::encodedQuery() const
5110{
5111 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5112
5113 return d->query;
5114}
5115
5116/*!
5117 Sets the fragment of the URL to \a fragment. The fragment is the
5118 last part of the URL, represented by a '#' followed by a string of
5119 characters. It is typically used in HTTP for referring to a
5120 certain link or point on a page:
5121
5122 \img qurl-fragment.png
5123
5124 The fragment is sometimes also referred to as the URL "reference".
5125
5126 Passing an argument of QString() (a null QString) will unset the fragment.
5127 Passing an argument of QString("") (an empty but not null QString)
5128 will set the fragment to an empty string (as if the original URL
5129 had a lone "#").
5130
5131 \sa fragment(), hasFragment()
5132*/
5133void QUrl::setFragment(const QString &fragment)
5134{
5135 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5136 detach();
5137 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
5138
5139 d->fragment = fragment;
5140 d->hasFragment = !fragment.isNull();
5141 d->encodedFragment.clear();
5142}
5143
5144/*!
5145 Returns the fragment of the URL.
5146
5147 \sa setFragment()
5148*/
5149QString QUrl::fragment() const
5150{
5151 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5152
5153 if (d->fragment.isNull() && !d->encodedFragment.isNull()) {
5154 QUrlPrivate *that = const_cast<QUrlPrivate *>(d);
5155 that->fragment = fromPercentEncodingHelper(d->encodedFragment);
5156 }
5157 return d->fragment;
5158}
5159
5160/*!
5161 \since 4.4
5162
5163 Sets the URL's fragment to the percent-encoded \a fragment. The fragment is the
5164 last part of the URL, represented by a '#' followed by a string of
5165 characters. It is typically used in HTTP for referring to a
5166 certain link or point on a page:
5167
5168 \img qurl-fragment.png
5169
5170 The fragment is sometimes also referred to as the URL "reference".
5171
5172 Passing an argument of QByteArray() (a null QByteArray) will unset
5173 the fragment. Passing an argument of QByteArray("") (an empty but
5174 not null QByteArray) will set the fragment to an empty string (as
5175 if the original URL had a lone "#").
5176
5177 \sa setFragment(), encodedFragment()
5178*/
5179void QUrl::setEncodedFragment(const QByteArray &fragment)
5180{
5181 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5182 detach();
5183 QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized);
5184
5185 d->encodedFragment = fragment;
5186 d->hasFragment = !fragment.isNull();
5187 d->fragment.clear();
5188}
5189
5190/*!
5191 \since 4.4
5192
5193 Returns the fragment of the URL if it is defined; otherwise an
5194 empty string is returned. The returned value will have its
5195 non-ASCII and other control characters percent-encoded, as in
5196 toEncoded().
5197
5198 \sa setEncodedFragment(), toEncoded()
5199*/
5200QByteArray QUrl::encodedFragment() const
5201{
5202 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5203
5204 d->ensureEncodedParts();
5205 return d->encodedFragment;
5206}
5207
5208/*!
5209 \since 4.2
5210
5211 Returns true if this URL contains a fragment (i.e., if # was seen on it).
5212
5213 \sa fragment(), setFragment()
5214*/
5215bool QUrl::hasFragment() const
5216{
5217 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5218
5219 return d->hasFragment;
5220}
5221
5222/*!
5223 Returns the result of the merge of this URL with \a relative. This
5224 URL is used as a base to convert \a relative to an absolute URL.
5225
5226 If \a relative is not a relative URL, this function will return \a
5227 relative directly. Otherwise, the paths of the two URLs are
5228 merged, and the new URL returned has the scheme and authority of
5229 the base URL, but with the merged path, as in the following
5230 example:
5231
5232 \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 5
5233
5234 Calling resolved() with ".." returns a QUrl whose directory is
5235 one level higher than the original. Similarly, calling resolved()
5236 with "../.." removes two levels from the path. If \a relative is
5237 "/", the path becomes "/".
5238
5239 \sa isRelative()
5240*/
5241QUrl QUrl::resolved(const QUrl &relative) const
5242{
5243 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5244
5245 if (!QURL_HASFLAG(relative.d->stateFlags, QUrlPrivate::Parsed))
5246 relative.d->parse();
5247
5248 d->ensureEncodedParts();
5249 relative.d->ensureEncodedParts();
5250
5251 QUrl t;
5252 // be non strict and allow scheme in relative url
5253 if (!relative.d->scheme.isEmpty() && relative.d->scheme != d->scheme) {
5254 t = relative;
5255 } else {
5256 if (!relative.authority().isEmpty()) {
5257 t = relative;
5258 } else {
5259 if (relative.d->encodedPath.isEmpty()) {
5260 t.d->encodedPath = d->encodedPath;
5261 t.setEncodedQuery(relative.d->hasQuery ? relative.d->query : d->query);
5262 } else {
5263 t.d->encodedPath = relative.d->encodedPath.at(0) == '/'
5264 ? relative.d->encodedPath
5265 : d->mergePaths(relative.d->encodedPath);
5266 t.setEncodedQuery(relative.d->query);
5267 }
5268 t.d->encodedUserName = d->encodedUserName;
5269 t.d->encodedPassword = d->encodedPassword;
5270 t.d->host = d->host;
5271 t.d->port = d->port;
5272 }
5273 t.setScheme(d->scheme);
5274 }
5275 t.setFragment(relative.fragment());
5276 removeDotsFromPath(&t.d->encodedPath);
5277 t.d->path.clear();
5278
5279 return t;
5280}
5281
5282/*!
5283 Returns true if the URL is relative; otherwise returns false. A
5284 URL is relative if its scheme is undefined; this function is
5285 therefore equivalent to calling scheme().isEmpty().
5286*/
5287bool QUrl::isRelative() const
5288{
5289 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5290
5291 return d->scheme.isEmpty();
5292}
5293
5294/*!
5295 Returns the human-displayable string representation of the
5296 URL. The output can be customized by passing flags with \a
5297 options.
5298
5299 \sa FormattingOptions, toEncoded()
5300*/
5301QString QUrl::toString(FormattingOptions options) const
5302{
5303 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5304
5305 QString url;
5306
5307 if (!(options & QUrl::RemoveScheme) && !d->scheme.isEmpty())
5308 url += d->scheme + QLatin1Char(':');
5309 QString ourPath = path();
5310 if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority) {
5311 bool doFileScheme = d->scheme == QLatin1String("file") && ourPath.startsWith(QLatin1Char('/'));
5312 QString tmp = d->authority(options);
5313 if (!tmp.isEmpty() || doFileScheme) {
5314 if (doFileScheme && !ourPath.startsWith(QLatin1Char('/')))
5315 url += QLatin1Char('/');
5316 url += QLatin1String("//");
5317 url += tmp;
5318 }
5319 }
5320 if (!(options & QUrl::RemovePath)) {
5321 // check if we need to insert a slash
5322 if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority
5323 && !d->authority(options).isEmpty() && !ourPath.isEmpty() && ourPath.at(0) != QLatin1Char('/'))
5324 url += QLatin1Char('/');
5325 url += ourPath;
5326 // check if we need to remove trailing slashes
5327 while ((options & StripTrailingSlash) && url.right(1) == QLatin1String("/"))
5328 url.chop(1);
5329 }
5330
5331 if (!(options & QUrl::RemoveQuery) && d->hasQuery) {
5332 url += QLatin1Char('?');
5333 url += fromPercentEncoding(d->query);
5334 }
5335 if (!(options & QUrl::RemoveFragment) && d->hasFragment) {
5336 url += QLatin1Char('#');
5337 url += fragment();
5338 }
5339
5340 return url;
5341}
5342
5343/*!
5344 Returns the encoded representation of the URL if it's valid;
5345 otherwise an empty QByteArray is returned. The output can be
5346 customized by passing flags with \a options.
5347
5348 The user info, path and fragment are all converted to UTF-8, and
5349 all non-ASCII characters are then percent encoded. The host name
5350 is encoded using Punycode.
5351*/
5352QByteArray QUrl::toEncoded(FormattingOptions options) const
5353{
5354 return d->toEncoded(options);
5355}
5356
5357/*!
5358 Parses \a input and returns the corresponding QUrl. \a input is
5359 assumed to be in encoded form, containing only ASCII characters.
5360
5361 The URL is parsed using TolerantMode.
5362
5363 \sa toEncoded(), setUrl()
5364*/
5365QUrl QUrl::fromEncoded(const QByteArray &input)
5366{
5367 QUrl tmp;
5368 tmp.setEncodedUrl(input, TolerantMode);
5369 return tmp;
5370}
5371
5372/*!
5373 \overload
5374
5375 Parses the URL using \a parsingMode.
5376
5377 \sa toEncoded(), setUrl()
5378*/
5379QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode parsingMode)
5380{
5381 QUrl tmp;
5382 tmp.setEncodedUrl(input, parsingMode);
5383 return tmp;
5384}
5385
5386/*!
5387 Returns a decoded copy of \a input. \a input is first decoded from
5388 percent encoding, then converted from UTF-8 to unicode.
5389*/
5390QString QUrl::fromPercentEncoding(const QByteArray &input)
5391{
5392 return fromPercentEncodingHelper(input);
5393}
5394
5395/*!
5396 Returns an encoded copy of \a input. \a input is first converted
5397 to UTF-8, and all ASCII-characters that are not in the unreserved group
5398 are percent encoded. To prevent characters from being percent encoded
5399 pass them to \a exclude. To force characters to be percent encoded pass
5400 them to \a include.
5401
5402 Unreserved is defined as:
5403 ALPHA / DIGIT / "-" / "." / "_" / "~"
5404
5405 \snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 6
5406*/
5407QByteArray QUrl::toPercentEncoding(const QString &input, const QByteArray &exclude, const QByteArray &include)
5408{
5409 return toPercentEncodingHelper(input, exclude.constData(), include.constData());
5410}
5411
5412/*!
5413 \obsolete
5414 Returns a \a uc in Punycode encoding.
5415
5416 Punycode is a Unicode encoding used for internationalized domain
5417 names, as defined in RFC3492. If you want to convert a domain name from
5418 Unicode to its ASCII-compatible representation, use toAce().
5419*/
5420QByteArray QUrl::toPunycode(const QString &uc)
5421{
5422 QByteArray output;
5423 toPunycodeHelper(uc.constData(), uc.size(), &output);
5424 return output;
5425}
5426
5427/*!
5428 \obsolete
5429 Returns the Punycode decoded representation of \a pc.
5430
5431 Punycode is a Unicode encoding used for internationalized domain
5432 names, as defined in RFC3492. If you want to convert a domain from
5433 its ASCII-compatible encoding to the Unicode representation, use
5434 fromAce().
5435*/
5436QString QUrl::fromPunycode(const QByteArray &pc)
5437{
5438 uint n = initial_n;
5439 uint i = 0;
5440 uint bias = initial_bias;
5441
5442 // strip any ACE prefix
5443 int start = pc.startsWith("xn--") ? 4 : 0;
5444 if (!start)
5445 return QString::fromLatin1(pc);
5446
5447 // find the last delimiter character '-' in the input array. copy
5448 // all data before this delimiter directly to the output array.
5449 int delimiterPos = pc.lastIndexOf(0x2d);
5450 QString output = delimiterPos < 4 ?
5451 QString() : QString::fromLatin1(pc.constData() + start, delimiterPos - start);
5452
5453 // if a delimiter was found, skip to the position after it;
5454 // otherwise start at the front of the input string. everything
5455 // before the delimiter is assumed to be basic code points.
5456 uint cnt = delimiterPos + 1;
5457
5458 // loop through the rest of the input string, inserting non-basic
5459 // characters into output as we go.
5460 while (cnt < (uint) pc.size()) {
5461 uint oldi = i;
5462 uint w = 1;
5463
5464 // find the next index for inserting a non-basic character.
5465 for (uint k = base; cnt < (uint) pc.size(); k += base) {
5466 // grab a character from the punycode input and find its
5467 // delta digit (each digit code is part of the
5468 // variable-length integer delta)
5469 uint digit = pc.at(cnt++);
5470 if (digit - 48 < 10) digit -= 22;
5471 else if (digit - 65 < 26) digit -= 65;
5472 else if (digit - 97 < 26) digit -= 97;
5473 else digit = base;
5474
5475 // reject out of range digits
5476 if (digit >= base || digit > (Q_MAXINT - i) / w)
5477 return QLatin1String("");
5478
5479 i += (digit * w);
5480
5481 // detect threshold to stop reading delta digits
5482 uint t;
5483 if (k <= bias) t = tmin;
5484 else if (k >= bias + tmax) t = tmax;
5485 else t = k - bias;
5486 if (digit < t) break;
5487
5488 w *= (base - t);
5489 }
5490
5491 // find new bias and calculate the next non-basic code
5492 // character.
5493 bias = adapt(i - oldi, output.length() + 1, oldi == 0);
5494 n += i / (output.length() + 1);
5495
5496 // allow the deltas to wrap around
5497 i %= (output.length() + 1);
5498
5499 // insert the character n at position i
5500 output.insert((uint) i, QChar((ushort) n));
5501 ++i;
5502 }
5503
5504 return output;
5505}
5506
5507/*!
5508 \since 4.2
5509
5510 Returns the Unicode form of the given domain name
5511 \a domain, which is encoded in the ASCII Compatible Encoding (ACE).
5512 The result of this function is considered equivalent to \a domain.
5513
5514 If the value in \a domain cannot be encoded, it will be converted
5515 to QString and returned.
5516
5517 The ASCII Compatible Encoding (ACE) is defined by RFC 3490, RFC 3491
5518 and RFC 3492. It is part of the Internationalizing Domain Names in
5519 Applications (IDNA) specification, which allows for domain names
5520 (like \c "qtsoftware.com") to be written using international
5521 characters.
5522*/
5523QString QUrl::fromAce(const QByteArray &domain)
5524{
5525 return qt_from_ACE(QString::fromLatin1(domain));
5526}
5527
5528/*!
5529 \since 4.2
5530
5531 Returns the ASCII Compatible Encoding of the given domain name \a domain.
5532 The result of this function is considered equivalent to \a domain.
5533
5534 The ASCII-Compatible Encoding (ACE) is defined by RFC 3490, RFC 3491
5535 and RFC 3492. It is part of the Internationalizing Domain Names in
5536 Applications (IDNA) specification, which allows for domain names
5537 (like \c "qtsoftware.com") to be written using international
5538 characters.
5539*/
5540QByteArray QUrl::toAce(const QString &domain)
5541{
5542 // IDNA / rfc3490 describes these four delimiters used for
5543 // separating labels in unicode international domain
5544 // names.
5545 QString nameprepped = qt_nameprep(domain);
5546 int lastIdx = 0;
5547 QByteArray result;
5548 for (int i = 0; i < nameprepped.size(); ++i) {
5549 ushort uc = nameprepped.at(i).unicode();
5550 if (uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61) {
5551 if (lastIdx)
5552 result += '.';
5553 toPunycodeHelper(nameprepped.constData() + lastIdx, i - lastIdx, &result);
5554 lastIdx = i + 1;
5555 }
5556 }
5557 if (lastIdx)
5558 result += '.';
5559 toPunycodeHelper(nameprepped.constData() + lastIdx, nameprepped.size() - lastIdx, &result);
5560
5561 return result;
5562}
5563
5564/*!
5565 \since 4.2
5566
5567 Returns the current whitelist of top-level domains that are allowed
5568 to have non-ASCII characters in their compositions.
5569
5570 See setIdnWhitelist() for the rationale of this list.
5571*/
5572QStringList QUrl::idnWhitelist()
5573{
5574 if (user_idn_whitelist)
5575 return *user_idn_whitelist;
5576 QStringList list;
5577 unsigned int i = 0;
5578 while (i < sizeof(idn_whitelist)/sizeof(const char *)) {
5579 list << QLatin1String(idn_whitelist[i]);
5580 ++i;
5581 }
5582 return list;
5583}
5584
5585/*!
5586 \since 4.2
5587
5588 Sets the whitelist of Top-Level Domains (TLDs) that are allowed to have
5589 non-ASCII characters in domains to the value of \a list.
5590
5591 Qt has comes a default list that contains the Internet top-level domains
5592 that have published support for Internationalized Domain Names (IDNs)
5593 and rules to guarantee that no deception can happen between similarly-looking
5594 characters (such as the Latin lowercase letter \c 'a' and the Cyrillic
5595 equivalent, which in most fonts are visually identical).
5596
5597 This list is periodically maintained, as registrars publish new rules.
5598
5599 This function is provided for those who need to manipulate the list, in
5600 order to add or remove a TLD. It is not recommended to change its value
5601 for purposes other than testing, as it may expose users to security risks.
5602*/
5603void QUrl::setIdnWhitelist(const QStringList &list)
5604{
5605 if (!user_idn_whitelist)
5606 user_idn_whitelist = new QStringList;
5607 *user_idn_whitelist = list;
5608}
5609
5610/*!
5611 \internal
5612
5613 Returns true if this URL is "less than" the given \a url. This
5614 provides a means of ordering URLs.
5615*/
5616bool QUrl::operator <(const QUrl &url) const
5617{
5618 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5619 if (!QURL_HASFLAG(url.d->stateFlags, QUrlPrivate::Parsed)) url.d->parse();
5620 return d->normalized() < url.d->normalized();
5621}
5622
5623/*!
5624 Returns true if this URL and the given \a url are equal;
5625 otherwise returns false.
5626*/
5627bool QUrl::operator ==(const QUrl &url) const
5628{
5629 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5630 if (!QURL_HASFLAG(url.d->stateFlags, QUrlPrivate::Parsed)) url.d->parse();
5631 return d->normalized() == url.d->normalized();
5632}
5633
5634/*!
5635 Returns true if this URL and the given \a url are not equal;
5636 otherwise returns false.
5637*/
5638bool QUrl::operator !=(const QUrl &url) const
5639{
5640 return !(*this == url);
5641}
5642
5643/*!
5644 Assigns the specified \a url to this object.
5645*/
5646QUrl &QUrl::operator =(const QUrl &url)
5647{
5648 qAtomicAssign(d, url.d);
5649 return *this;
5650}
5651
5652/*!
5653 Assigns the specified \a url to this object.
5654*/
5655QUrl &QUrl::operator =(const QString &url)
5656{
5657 QUrl tmp(url);
5658 qAtomicAssign(d, tmp.d);
5659 return *this;
5660}
5661
5662/*! \internal
5663
5664 Forces a detach.
5665*/
5666void QUrl::detach()
5667{ qAtomicDetach(d); }
5668
5669/*!
5670 \internal
5671*/
5672bool QUrl::isDetached() const
5673{
5674 return d->ref == 1;
5675}
5676
5677
5678/*!
5679 Returns a QUrl representation of \a localFile, interpreted as a
5680 local file.
5681
5682 \sa toLocalFile()
5683*/
5684QUrl QUrl::fromLocalFile(const QString &localFile)
5685{
5686 QUrl url;
5687 url.setScheme(QLatin1String("file"));
5688 QString deslashified = localFile;
5689 deslashified.replace(QLatin1Char('\\'), QLatin1Char('/'));
5690
5691
5692
5693 // magic for drives on windows
5694 if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) {
5695 url.setPath(QLatin1String("/") + deslashified);
5696 // magic for shared drive on windows
5697 } else if (deslashified.startsWith(QLatin1String("//"))) {
5698 int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2);
5699 url.setHost(deslashified.mid(2, indexOfPath - 2));
5700 if (indexOfPath > 2)
5701 url.setPath(deslashified.right(deslashified.length() - indexOfPath));
5702 } else {
5703 url.setPath(deslashified);
5704 }
5705
5706 return url;
5707}
5708
5709/*!
5710 Returns the path of this URL formatted as a local file path.
5711
5712 \sa fromLocalFile()
5713*/
5714QString QUrl::toLocalFile() const
5715{
5716 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5717
5718 QString tmp;
5719 QString ourPath = path();
5720 if (d->scheme.isEmpty() || d->scheme.toLower() == QLatin1String("file")) {
5721
5722 // magic for shared drive on windows
5723 if (!d->host.isEmpty()) {
5724 tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/')
5725 ? QLatin1String("/") + ourPath : ourPath);
5726 } else {
5727 tmp = ourPath;
5728 // magic for drives on windows
5729 if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':'))
5730 tmp.remove(0, 1);
5731 }
5732 }
5733
5734 return tmp;
5735}
5736
5737/*!
5738 Returns true if this URL is a parent of \a childUrl. \a childUrl is a child
5739 of this URL if the two URLs share the same scheme and authority,
5740 and this URL's path is a parent of the path of \a childUrl.
5741*/
5742bool QUrl::isParentOf(const QUrl &childUrl) const
5743{
5744 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
5745
5746 QString childPath = childUrl.path();
5747 QString ourPath = path();
5748
5749 return ((childUrl.scheme().isEmpty() || d->scheme == childUrl.scheme())
5750 && (childUrl.authority().isEmpty() || d->authority() == childUrl.authority())
5751 && childPath.startsWith(ourPath)
5752 && ((ourPath.endsWith(QLatin1Char('/')) && childPath.length() > ourPath.length())
5753 || (!ourPath.endsWith(QLatin1Char('/'))
5754 && childPath.length() > ourPath.length() && childPath.at(ourPath.length()) == QLatin1Char('/'))));
5755}
5756
5757/*!
5758 \fn void QUrl::setProtocol(const QString &s)
5759
5760 Use setScheme() instead.
5761*/
5762
5763/*!
5764 \fn void QUrl::setUser(const QString &s)
5765
5766 Use setUserName() instead.
5767*/
5768
5769/*!
5770 \fn bool QUrl::hasUser() const
5771
5772 Use !userName().isEmpty() instead.
5773*/
5774
5775/*!
5776 \fn bool QUrl::hasPassword() const
5777
5778 Use !password().isEmpty() instead.
5779*/
5780
5781/*!
5782 \fn bool QUrl::hasHost() const
5783
5784 Use !host().isEmpty() instead.
5785*/
5786
5787/*!
5788 \fn bool QUrl::hasPort() const
5789
5790 Use port() != -1 instead.
5791*/
5792
5793/*!
5794 \fn bool QUrl::hasPath() const
5795
5796 Use !path().isEmpty() instead.
5797*/
5798
5799/*!
5800 \fn void QUrl::setQuery(const QString &txt)
5801
5802 Use setEncodedQuery() instead.
5803*/
5804
5805/*!
5806 \fn void QUrl::setRef(const QString &txt)
5807
5808 Use setFragment() instead.
5809*/
5810
5811/*!
5812 \fn bool QUrl::hasRef() const
5813
5814 Use !fragment().isEmpty() instead.
5815*/
5816
5817/*!
5818 \fn void QUrl::addPath(const QString &p)
5819
5820 Use setPath() instead.
5821*/
5822
5823/*!
5824 \fn void QUrl::setFileName(const QString &txt)
5825
5826 Use setPath() instead.
5827*/
5828
5829/*!
5830 \fn void QUrl::decode(QString &url)
5831
5832 Use fromPercentEncoding() instead.
5833*/
5834
5835/*!
5836 \fn void QUrl::encode(QString &url)
5837
5838 Use toPercentEncoding() instead.
5839*/
5840
5841/*!
5842 \fn bool QUrl::cdUp()
5843
5844 Use resolved("..") instead.
5845
5846 \oldcode
5847 QUrl url("http://qtsoftware.com/Developer/");
5848 url.cdUp();
5849 \newcode
5850 QUrl url("http://qtsoftware.com/Developer/");
5851 url = url.resolved("..");
5852 \endcode
5853*/
5854
5855/*!
5856 \fn bool QUrl::isRelativeUrl(const QString &url)
5857
5858 Use isRelative() instead.
5859*/
5860
5861/*!
5862 \fn void QUrl::reset()
5863
5864 Use clear() instead.
5865*/
5866
5867/*!
5868 \fn QUrl::operator QString() const
5869
5870 Use toString() instead.
5871*/
5872
5873/*!
5874 \fn QString QUrl::protocol() const
5875
5876 Use scheme() instead.
5877*/
5878
5879/*!
5880 \fn QString QUrl::user() const
5881
5882 Use userName() instead.
5883*/
5884
5885/*!
5886 \fn QString QUrl::query() const
5887
5888 Use encodedQuery() instead.
5889*/
5890
5891/*!
5892 \fn QString QUrl::ref() const
5893
5894 Use fragment() instead.
5895*/
5896
5897/*!
5898 \fn QString QUrl::fileName() const
5899
5900 Use QFileInfo(path()).fileName() instead.
5901*/
5902
5903/*!
5904 \fn QString QUrl::dirPath() const
5905
5906 Use QFileInfo(path()).absolutePath() or QFileInfo(path()) instead.
5907*/
5908
5909#ifdef QT3_SUPPORT
5910void QUrl::setFileName(const QString &txt)
5911{
5912 QFileInfo fileInfo(path());
5913 fileInfo.setFile(txt);
5914 setPath(fileInfo.filePath());
5915}
5916
5917QString QUrl::fileName() const
5918{
5919 QFileInfo fileInfo(path());
5920 return fileInfo.fileName();
5921}
5922
5923QString QUrl::dirPath() const
5924{
5925 QFileInfo fileInfo(path());
5926 if (fileInfo.isAbsolute()) {
5927 QString absPath = fileInfo.absolutePath();
5928#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
5929 if (absPath.size() > 1 && absPath.at(1) == QLatin1Char(':'))
5930 absPath = absPath.mid(2);
5931#endif
5932 return absPath;
5933 }
5934 return fileInfo.path();
5935}
5936#endif
5937
5938
5939#ifndef QT_NO_DATASTREAM
5940/*! \relates QUrl
5941
5942 Writes url \a url to the stream \a out and returns a reference
5943 to the stream.
5944
5945 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
5946*/
5947QDataStream &operator<<(QDataStream &out, const QUrl &url)
5948{
5949 QByteArray u = url.toEncoded();
5950 out << u;
5951 return out;
5952}
5953
5954/*! \relates QUrl
5955
5956 Reads a url into \a url from the stream \a in and returns a
5957 reference to the stream.
5958
5959 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
5960*/
5961QDataStream &operator>>(QDataStream &in, QUrl &url)
5962{
5963 QByteArray u;
5964 in >> u;
5965 url = QUrl::fromEncoded(u);
5966 return in;
5967}
5968#endif // QT_NO_DATASTREAM
5969
5970#ifndef QT_NO_DEBUG_STREAM
5971QDebug operator<<(QDebug d, const QUrl &url)
5972{
5973 d.maybeSpace() << "QUrl(" << url.toString() << ")";
5974 return d.space();
5975}
5976#endif
5977
5978/*!
5979 \since 4.2
5980
5981 Returns a text string that explains why an URL is invalid in the case being;
5982 otherwise returns an empty string.
5983*/
5984QString QUrl::errorString() const
5985{
5986 return d->createErrorString();
5987}
5988
5989/*!
5990 \typedef QUrl::DataPtr
5991 \internal
5992*/
5993
5994/*!
5995 \fn DataPtr &QUrl::data_ptr()
5996 \internal
5997*/
5998
5999QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.