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