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