Coverage Report

Created: 2024-02-11 06:14

/src/qtbase/src/corelib/text/qlocale.cpp
Line
Count
Source (jump to first uncovered line)
1
/****************************************************************************
2
**
3
** Copyright (C) 2020 The Qt Company Ltd.
4
** Copyright (C) 2019 Intel Corporation.
5
** Contact: https://www.qt.io/licensing/
6
**
7
** This file is part of the QtCore module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** Commercial License Usage
11
** Licensees holding valid commercial Qt licenses may use this file in
12
** accordance with the commercial license agreement provided with the
13
** Software or, alternatively, in accordance with the terms contained in
14
** a written agreement between you and The Qt Company. For licensing terms
15
** and conditions see https://www.qt.io/terms-conditions. For further
16
** information use the contact form at https://www.qt.io/contact-us.
17
**
18
** GNU Lesser General Public License Usage
19
** Alternatively, this file may be used under the terms of the GNU Lesser
20
** General Public License version 3 as published by the Free Software
21
** Foundation and appearing in the file LICENSE.LGPL3 included in the
22
** packaging of this file. Please review the following information to
23
** ensure the GNU Lesser General Public License version 3 requirements
24
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25
**
26
** GNU General Public License Usage
27
** Alternatively, this file may be used under the terms of the GNU
28
** General Public License version 2.0 or (at your option) the GNU General
29
** Public license version 3 or any later version approved by the KDE Free
30
** Qt Foundation. The licenses are as published by the Free Software
31
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32
** included in the packaging of this file. Please review the following
33
** information to ensure the GNU General Public License requirements will
34
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35
** https://www.gnu.org/licenses/gpl-3.0.html.
36
**
37
** $QT_END_LICENSE$
38
**
39
****************************************************************************/
40
41
#include "qglobal.h"
42
43
#if !defined(QWS) && defined(Q_OS_MAC)
44
#   include "private/qcore_mac_p.h"
45
#   include <CoreFoundation/CoreFoundation.h>
46
#endif
47
48
#include "qplatformdefs.h"
49
50
#include "qdatastream.h"
51
#include "qdebug.h"
52
#include "qhashfunctions.h"
53
#include "qstring.h"
54
#include "qlocale.h"
55
#include "qlocale_p.h"
56
#include "qlocale_tools_p.h"
57
#if QT_CONFIG(datetimeparser)
58
#include "private/qdatetimeparser_p.h"
59
#endif
60
#include "qnamespace.h"
61
#include "qdatetime.h"
62
#include "qstringlist.h"
63
#include "qvariant.h"
64
#include "qstringbuilder.h"
65
#include "private/qnumeric_p.h"
66
#include <cmath>
67
#ifndef QT_NO_SYSTEMLOCALE
68
#   include "qmutex.h"
69
#endif
70
#ifdef Q_OS_WIN
71
#   include <qt_windows.h>
72
#   include <time.h>
73
#endif
74
75
#include "private/qcalendarbackend_p.h"
76
#include "private/qgregoriancalendar_p.h"
77
#include "qcalendar.h"
78
79
QT_BEGIN_NAMESPACE
80
81
#ifndef QT_NO_SYSTEMLOCALE
82
static QSystemLocale *_systemLocale = nullptr;
83
class QSystemLocaleSingleton: public QSystemLocale
84
{
85
public:
86
1
    QSystemLocaleSingleton() : QSystemLocale(true) {}
87
};
88
89
Q_GLOBAL_STATIC(QSystemLocaleSingleton, QSystemLocale_globalSystemLocale)
90
static QLocaleData globalLocaleData;
91
#endif
92
93
/******************************************************************************
94
** Helpers for accessing Qt locale database
95
*/
96
97
QT_BEGIN_INCLUDE_NAMESPACE
98
#include "qlocale_data_p.h"
99
QT_END_INCLUDE_NAMESPACE
100
101
QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) noexcept
102
0
{
103
0
    const auto len = code.size();
104
0
    if (len != 2 && len != 3)
105
0
        return QLocale::C;
106
0
    ushort uc1 = code[0].toLower().unicode();
107
0
    ushort uc2 = code[1].toLower().unicode();
108
0
    ushort uc3 = len > 2 ? code[2].toLower().unicode() : 0;
109
110
0
    const unsigned char *c = language_code_list;
111
0
    for (; *c != 0; c += 3) {
112
0
        if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
113
0
            return QLocale::Language((c - language_code_list)/3);
114
0
    }
115
116
0
    if (uc3 == 0) {
117
        // legacy codes
118
0
        if (uc1 == 'n' && uc2 == 'o') // no -> nb
119
0
            return QLocale::NorwegianBokmal;
120
0
        if (uc1 == 't' && uc2 == 'l') // tl -> fil
121
0
            return QLocale::Filipino;
122
0
        if (uc1 == 's' && uc2 == 'h') // sh -> sr[_Latn]
123
0
            return QLocale::Serbian;
124
0
        if (uc1 == 'm' && uc2 == 'o') // mo -> ro
125
0
            return QLocale::Romanian;
126
        // Android uses the following deprecated codes
127
0
        if (uc1 == 'i' && uc2 == 'w') // iw -> he
128
0
            return QLocale::Hebrew;
129
0
        if (uc1 == 'i' && uc2 == 'n') // in -> id
130
0
            return QLocale::Indonesian;
131
0
        if (uc1 == 'j' && uc2 == 'i') // ji -> yi
132
0
            return QLocale::Yiddish;
133
0
    }
134
0
    return QLocale::C;
135
0
}
136
137
QLocale::Script QLocalePrivate::codeToScript(QStringView code) noexcept
138
0
{
139
0
    const auto len = code.size();
140
0
    if (len != 4)
141
0
        return QLocale::AnyScript;
142
143
    // script is titlecased in our data
144
0
    unsigned char c0 = code[0].toUpper().toLatin1();
145
0
    unsigned char c1 = code[1].toLower().toLatin1();
146
0
    unsigned char c2 = code[2].toLower().toLatin1();
147
0
    unsigned char c3 = code[3].toLower().toLatin1();
148
149
0
    const unsigned char *c = script_code_list;
150
0
    for (int i = 0; i < QLocale::LastScript; ++i, c += 4) {
151
0
        if (c0 == c[0] && c1 == c[1] && c2 == c[2] && c3 == c[3])
152
0
            return QLocale::Script(i);
153
0
    }
154
0
    return QLocale::AnyScript;
155
0
}
156
157
QLocale::Country QLocalePrivate::codeToCountry(QStringView code) noexcept
158
0
{
159
0
    const auto len = code.size();
160
0
    if (len != 2 && len != 3)
161
0
        return QLocale::AnyCountry;
162
163
0
    ushort uc1 = code[0].toUpper().unicode();
164
0
    ushort uc2 = code[1].toUpper().unicode();
165
0
    ushort uc3 = len > 2 ? code[2].toUpper().unicode() : 0;
166
167
0
    const unsigned char *c = country_code_list;
168
0
    for (; *c != 0; c += 3) {
169
0
        if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
170
0
            return QLocale::Country((c - country_code_list)/3);
171
0
    }
172
173
0
    return QLocale::AnyCountry;
174
0
}
175
176
QLatin1String QLocalePrivate::languageToCode(QLocale::Language language)
177
0
{
178
0
    if (language == QLocale::AnyLanguage)
179
0
        return QLatin1String();
180
0
    if (language == QLocale::C)
181
0
        return QLatin1String("C");
182
183
0
    const unsigned char *c = language_code_list + 3*(uint(language));
184
185
0
    return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
186
187
0
}
188
189
QLatin1String QLocalePrivate::scriptToCode(QLocale::Script script)
190
0
{
191
0
    if (script == QLocale::AnyScript || script > QLocale::LastScript)
192
0
        return QLatin1String();
193
0
    const unsigned char *c = script_code_list + 4*(uint(script));
194
0
    return QLatin1String(reinterpret_cast<const char *>(c), 4);
195
0
}
196
197
QLatin1String QLocalePrivate::countryToCode(QLocale::Country country)
198
0
{
199
0
    if (country == QLocale::AnyCountry)
200
0
        return QLatin1String();
201
202
0
    const unsigned char *c = country_code_list + 3*(uint(country));
203
204
0
    return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
205
0
}
206
207
// http://www.unicode.org/reports/tr35/#Likely_Subtags
208
static bool addLikelySubtags(QLocaleId &localeId)
209
4
{
210
    // ### optimize with bsearch
211
4
    const int likely_subtags_count = sizeof(likely_subtags) / sizeof(likely_subtags[0]);
212
4
    const QLocaleId *p = likely_subtags;
213
4
    const QLocaleId *const e = p + likely_subtags_count;
214
3.23k
    for ( ; p < e; p += 2) {
215
3.23k
        if (localeId == p[0]) {
216
0
            localeId = p[1];
217
0
            return true;
218
0
        }
219
3.23k
    }
220
4
    return false;
221
4
}
222
223
QLocaleId QLocaleId::withLikelySubtagsAdded() const
224
2
{
225
    // language_script_region
226
2
    if (language_id || script_id || country_id) {
227
2
        QLocaleId id = QLocaleId::fromIds(language_id, script_id, country_id);
228
2
        if (addLikelySubtags(id))
229
0
            return id;
230
2
    }
231
    // language_region
232
2
    if (script_id) {
233
0
        QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id);
234
0
        if (addLikelySubtags(id)) {
235
0
            id.script_id = script_id;
236
0
            return id;
237
0
        }
238
0
    }
239
    // language_script
240
2
    if (country_id) {
241
0
        QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0);
242
0
        if (addLikelySubtags(id)) {
243
0
            id.country_id = country_id;
244
0
            return id;
245
0
        }
246
0
    }
247
    // language
248
2
    if (script_id && country_id) {
249
0
        QLocaleId id = QLocaleId::fromIds(language_id, 0, 0);
250
0
        if (addLikelySubtags(id)) {
251
0
            id.script_id = script_id;
252
0
            id.country_id = country_id;
253
0
            return id;
254
0
        }
255
0
    }
256
    // und_script
257
2
    if (language_id) {
258
2
        QLocaleId id = QLocaleId::fromIds(0, script_id, 0);
259
2
        if (addLikelySubtags(id)) {
260
0
            id.language_id = language_id;
261
0
            return id;
262
0
        }
263
2
    }
264
2
    return *this;
265
2
}
266
267
QLocaleId QLocaleId::withLikelySubtagsRemoved() const
268
0
{
269
0
    QLocaleId max = withLikelySubtagsAdded();
270
    // language
271
0
    {
272
0
        QLocaleId id = QLocaleId::fromIds(language_id, 0, 0);
273
0
        if (id.withLikelySubtagsAdded() == max)
274
0
            return id;
275
0
    }
276
    // language_region
277
0
    if (country_id) {
278
0
        QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id);
279
0
        if (id.withLikelySubtagsAdded() == max)
280
0
            return id;
281
0
    }
282
    // language_script
283
0
    if (script_id) {
284
0
        QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0);
285
0
        if (id.withLikelySubtagsAdded() == max)
286
0
            return id;
287
0
    }
288
0
    return max;
289
0
}
290
291
QByteArray QLocaleId::name(char separator) const
292
0
{
293
0
    if (language_id == QLocale::AnyLanguage)
294
0
        return QByteArray();
295
0
    if (language_id == QLocale::C)
296
0
        return QByteArrayLiteral("C");
297
298
0
    const unsigned char *lang = language_code_list + 3 * language_id;
299
0
    const unsigned char *script =
300
0
            (script_id != QLocale::AnyScript ? script_code_list + 4 * script_id : nullptr);
301
0
    const unsigned char *country =
302
0
            (country_id != QLocale::AnyCountry ? country_code_list + 3 * country_id : nullptr);
303
0
    char len = (lang[2] != 0 ? 3 : 2) + (script ? 4 + 1 : 0)
304
0
        + (country ? (country[2] != 0 ? 3 : 2) + 1 : 0);
305
0
    QByteArray name(len, Qt::Uninitialized);
306
0
    char *uc = name.data();
307
0
    *uc++ = lang[0];
308
0
    *uc++ = lang[1];
309
0
    if (lang[2] != 0)
310
0
        *uc++ = lang[2];
311
0
    if (script) {
312
0
        *uc++ = separator;
313
0
        *uc++ = script[0];
314
0
        *uc++ = script[1];
315
0
        *uc++ = script[2];
316
0
        *uc++ = script[3];
317
0
    }
318
0
    if (country) {
319
0
        *uc++ = separator;
320
0
        *uc++ = country[0];
321
0
        *uc++ = country[1];
322
0
        if (country[2] != 0)
323
0
            *uc++ = country[2];
324
0
    }
325
0
    return name;
326
0
}
327
328
QByteArray QLocalePrivate::bcp47Name(char separator) const
329
0
{
330
0
    if (m_data->m_language_id == QLocale::AnyLanguage)
331
0
        return QByteArray();
332
0
    if (m_data->m_language_id == QLocale::C)
333
0
        return QByteArrayLiteral("en");
334
335
0
    QLocaleId localeId = QLocaleId::fromIds(m_data->m_language_id, m_data->m_script_id,
336
0
                                            m_data->m_country_id);
337
0
    return localeId.withLikelySubtagsRemoved().name(separator);
338
0
}
339
340
static const QLocaleData *findLocaleDataById(const QLocaleId &localeId)
341
2
{
342
2
    const uint idx = locale_index[localeId.language_id];
343
344
2
    const QLocaleData *data = locale_data + idx;
345
346
    // If there are no locales for specified language (so we we've got the
347
    // default language, which has no associated script or country), give up:
348
2
    if (localeId.language_id && idx == 0)
349
2
        return data;
350
351
0
    Q_ASSERT(localeId.language_id
352
0
             ? data->m_language_id == localeId.language_id
353
0
             : data->m_language_id);
354
355
0
    if (localeId.script_id == QLocale::AnyScript && localeId.country_id == QLocale::AnyCountry)
356
0
        return data;
357
358
0
    if (localeId.script_id == QLocale::AnyScript) {
359
0
        do {
360
0
            if (data->m_country_id == localeId.country_id)
361
0
                return data;
362
0
            ++data;
363
0
        } while (localeId.language_id
364
0
                 ? data->m_language_id == localeId.language_id
365
0
                 : data->m_language_id);
366
0
    } else if (localeId.country_id == QLocale::AnyCountry) {
367
0
        do {
368
0
            if (data->m_script_id == localeId.script_id)
369
0
                return data;
370
0
            ++data;
371
0
        } while (localeId.language_id
372
0
                 ? data->m_language_id == localeId.language_id
373
0
                 : data->m_language_id);;
374
0
    } else {
375
0
        do {
376
0
            if (data->m_script_id == localeId.script_id
377
0
                && data->m_country_id == localeId.country_id) {
378
0
                return data;
379
0
            }
380
0
            ++data;
381
0
        } while (localeId.language_id
382
0
                 ? data->m_language_id == localeId.language_id
383
0
                 : data->m_language_id);;
384
0
    }
385
386
0
    return nullptr;
387
0
}
388
389
const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script,
390
                                               QLocale::Country country)
391
2
{
392
2
    QLocaleId localeId = QLocaleId::fromIds(language, script, country);
393
2
    QLocaleId likelyId = localeId.withLikelySubtagsAdded();
394
395
2
    const uint idx = locale_index[likelyId.language_id];
396
397
    // Try a straight match with the likely data:
398
2
    if (const QLocaleData *const data = findLocaleDataById(likelyId))
399
2
        return data;
400
0
    QList<QLocaleId> tried;
401
0
    tried.push_back(likelyId);
402
403
    // No match; try again with raw data:
404
0
    if (!tried.contains(localeId)) {
405
0
        if (const QLocaleData *const data = findLocaleDataById(localeId))
406
0
            return data;
407
0
        tried.push_back(localeId);
408
0
    }
409
410
    // No match; try again with likely country
411
0
    if (country != QLocale::AnyCountry
412
0
        && (language != QLocale::AnyLanguage || script != QLocale::AnyScript)) {
413
0
        localeId = QLocaleId::fromIds(language, script, QLocale::AnyCountry);
414
0
        likelyId = localeId.withLikelySubtagsAdded();
415
0
        if (!tried.contains(likelyId)) {
416
0
            if (const QLocaleData *const data = findLocaleDataById(likelyId))
417
0
                return data;
418
0
            tried.push_back(likelyId);
419
0
        }
420
421
        // No match; try again with any country
422
0
        if (!tried.contains(localeId)) {
423
0
            if (const QLocaleData *const data = findLocaleDataById(localeId))
424
0
                return data;
425
0
            tried.push_back(localeId);
426
0
        }
427
0
    }
428
429
    // No match; try again with likely script
430
0
    if (script != QLocale::AnyScript
431
0
        && (language != QLocale::AnyLanguage || country != QLocale::AnyCountry)) {
432
0
        localeId = QLocaleId::fromIds(language, QLocale::AnyScript, country);
433
0
        likelyId = localeId.withLikelySubtagsAdded();
434
0
        if (!tried.contains(likelyId)) {
435
0
            if (const QLocaleData *const data = findLocaleDataById(likelyId))
436
0
                return data;
437
0
            tried.push_back(likelyId);
438
0
        }
439
440
        // No match; try again with any script
441
0
        if (!tried.contains(localeId)) {
442
0
            if (const QLocaleData *const data = findLocaleDataById(localeId))
443
0
                return data;
444
0
            tried.push_back(localeId);
445
0
        }
446
0
    }
447
448
    // No match; return data at original index
449
0
    return locale_data + idx;
450
0
}
451
452
uint QLocaleData::findLocaleOffset(QLocale::Language language, QLocale::Script script,
453
                                   QLocale::Country country)
454
1
{
455
1
    return findLocaleData(language, script, country) - locale_data;
456
1
}
457
458
static bool parse_locale_tag(const QString &input, int &i, QString *result,
459
                             const QString &separators)
460
0
{
461
0
    *result = QString(8, Qt::Uninitialized); // worst case according to BCP47
462
0
    QChar *pch = result->data();
463
0
    const QChar *uc = input.data() + i;
464
0
    const int l = input.length();
465
0
    int size = 0;
466
0
    for (; i < l && size < 8; ++i, ++size) {
467
0
        if (separators.contains(*uc))
468
0
            break;
469
0
        if (! ((uc->unicode() >= 'a' && uc->unicode() <= 'z') ||
470
0
               (uc->unicode() >= 'A' && uc->unicode() <= 'Z') ||
471
0
               (uc->unicode() >= '0' && uc->unicode() <= '9')) ) // latin only
472
0
            return false;
473
0
        *pch++ = *uc++;
474
0
    }
475
0
    result->truncate(size);
476
0
    return true;
477
0
}
478
479
bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry)
480
2
{
481
2
    const int length = name.length();
482
483
2
    lang = script = cntry = QString();
484
485
2
    const QString separators = QStringLiteral("_-.@");
486
2
    enum ParserState { NoState, LangState, ScriptState, CountryState };
487
2
    ParserState state = LangState;
488
2
    for (int i = 0; i < length && state != NoState; ) {
489
0
        QString value;
490
0
        if (!parse_locale_tag(name, i, &value, separators) ||value.isEmpty())
491
0
            break;
492
0
        QChar sep = i < length ? name.at(i) : QChar();
493
0
        switch (state) {
494
0
        case LangState:
495
0
            if (!sep.isNull() && !separators.contains(sep)) {
496
0
                state = NoState;
497
0
                break;
498
0
            }
499
0
            lang = value;
500
0
            if (i == length) {
501
                // just language was specified
502
0
                state = NoState;
503
0
                break;
504
0
            }
505
0
            state = ScriptState;
506
0
            break;
507
0
        case ScriptState: {
508
0
            QString scripts = QString::fromLatin1((const char *)script_code_list,
509
0
                                                  sizeof(script_code_list) - 1);
510
0
            if (value.length() == 4 && scripts.indexOf(value) % 4 == 0) {
511
                // script name is always 4 characters
512
0
                script = value;
513
0
                state = CountryState;
514
0
            } else {
515
                // it wasn't a script, maybe it is a country then?
516
0
                cntry = value;
517
0
                state = NoState;
518
0
            }
519
0
            break;
520
0
        }
521
0
        case CountryState:
522
0
            cntry = value;
523
0
            state = NoState;
524
0
            break;
525
0
        case NoState:
526
            // shouldn't happen
527
0
            qWarning("QLocale: This should never happen");
528
0
            break;
529
0
        }
530
0
        ++i;
531
0
    }
532
2
    return lang.length() == 2 || lang.length() == 3;
533
2
}
534
535
void QLocalePrivate::getLangAndCountry(const QString &name, QLocale::Language &lang,
536
                                       QLocale::Script &script, QLocale::Country &cntry)
537
2
{
538
2
    lang = QLocale::C;
539
2
    script = QLocale::AnyScript;
540
2
    cntry = QLocale::AnyCountry;
541
542
2
    QString lang_code;
543
2
    QString script_code;
544
2
    QString cntry_code;
545
2
    if (!qt_splitLocaleName(name, lang_code, script_code, cntry_code))
546
2
        return;
547
548
0
    lang = QLocalePrivate::codeToLanguage(lang_code);
549
0
    if (lang == QLocale::C)
550
0
        return;
551
0
    script = QLocalePrivate::codeToScript(script_code);
552
0
    cntry = QLocalePrivate::codeToCountry(cntry_code);
553
0
}
554
555
static const QLocaleData *findLocaleData(const QString &name)
556
1
{
557
1
    QLocale::Language lang;
558
1
    QLocale::Script script;
559
1
    QLocale::Country cntry;
560
1
    QLocalePrivate::getLangAndCountry(name, lang, script, cntry);
561
562
1
    return QLocaleData::findLocaleData(lang, script, cntry);
563
1
}
564
565
static uint findLocaleOffset(const QString &name)
566
1
{
567
1
    QLocale::Language lang;
568
1
    QLocale::Script script;
569
1
    QLocale::Country cntry;
570
1
    QLocalePrivate::getLangAndCountry(name, lang, script, cntry);
571
572
1
    return QLocaleData::findLocaleOffset(lang, script, cntry);
573
1
}
574
575
QString qt_readEscapedFormatString(QStringView format, int *idx)
576
0
{
577
0
    int &i = *idx;
578
579
0
    Q_ASSERT(format.at(i) == QLatin1Char('\''));
580
0
    ++i;
581
0
    if (i == format.size())
582
0
        return QString();
583
0
    if (format.at(i).unicode() == '\'') { // "''" outside of a quoted stirng
584
0
        ++i;
585
0
        return QLatin1String("'");
586
0
    }
587
588
0
    QString result;
589
590
0
    while (i < format.size()) {
591
0
        if (format.at(i).unicode() == '\'') {
592
0
            if (format.mid(i + 1).startsWith(QLatin1Char('\''))) {
593
                // "''" inside a quoted string
594
0
                result.append(QLatin1Char('\''));
595
0
                i += 2;
596
0
            } else {
597
0
                break;
598
0
            }
599
0
        } else {
600
0
            result.append(format.at(i++));
601
0
        }
602
0
    }
603
0
    if (i < format.size())
604
0
        ++i;
605
606
0
    return result;
607
0
}
608
609
/*!
610
    \internal
611
612
    Counts the number of identical leading characters in \a s.
613
614
    If \a s is empty, returns 0.
615
616
    Otherwise, returns the number of consecutive \c{s.front()}
617
    characters at the start of \a s.
618
619
    \code
620
    qt_repeatCount(u"a");   // == 1
621
    qt_repeatCount(u"ab");  // == 1
622
    qt_repeatCount(u"aab"); // == 2
623
    \endcode
624
*/
625
int qt_repeatCount(QStringView s)
626
0
{
627
0
    if (s.isEmpty())
628
0
        return 0;
629
0
    const QChar c = s.front();
630
0
    qsizetype j = 1;
631
0
    while (j < s.size() && s.at(j) == c)
632
0
        ++j;
633
0
    return int(j);
634
0
}
635
636
static const QLocaleData *default_data = nullptr;
637
638
static const QLocaleData *const c_data = locale_data;
639
static QLocalePrivate *c_private()
640
74.3k
{
641
74.3k
    static QLocalePrivate c_locale{
642
74.3k
            c_data, Q_BASIC_ATOMIC_INITIALIZER(1), 0, QLocale::OmitGroupSeparator };
643
74.3k
    return &c_locale;
644
74.3k
}
645
646
static const QLocaleData *systemData();
647
static QLocale::NumberOptions system_number_options = QLocale::DefaultNumberOptions;
648
Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<QLocalePrivate>, systemLocalePrivate,
649
                          (QLocalePrivate::create(systemData(), system_number_options)))
650
651
#ifndef QT_NO_SYSTEMLOCALE
652
/******************************************************************************
653
** Default system locale behavior
654
*/
655
656
/*!
657
  Constructs a QSystemLocale object.
658
659
  The constructor will automatically install this object as the system locale,
660
  if there's not one active.  It also resets the flag that'll prompt
661
  QLocale::system() to re-initialize its data, so that instantiating a
662
  QSystemLocale transiently (doesn't install the transient as system locale if
663
  there was one already and) triggers an update to the system locale's data.
664
*/
665
QSystemLocale::QSystemLocale()
666
0
{
667
0
    if (!_systemLocale)
668
0
        _systemLocale = this;
669
670
0
    globalLocaleData.m_language_id = 0;
671
0
}
672
673
/*!
674
    \internal
675
*/
676
QSystemLocale::QSystemLocale(bool)
677
1
{ }
678
679
/*!
680
  Deletes the object.
681
*/
682
QSystemLocale::~QSystemLocale()
683
1
{
684
1
    if (_systemLocale == this) {
685
0
        _systemLocale = nullptr;
686
687
0
        globalLocaleData.m_language_id = 0;
688
0
    }
689
1
}
690
691
static const QSystemLocale *systemLocale()
692
1
{
693
1
    if (_systemLocale)
694
0
        return _systemLocale;
695
1
    return QSystemLocale_globalSystemLocale();
696
1
}
697
698
static void updateSystemPrivate()
699
1
{
700
    // This function is NOT thread-safe!
701
    // It *should not* be called by anything but systemData()
702
    // It *is* called before {system,default}LocalePrivate exist.
703
1
    const QSystemLocale *sys_locale = systemLocale();
704
705
    // tell the object that the system locale has changed.
706
1
    sys_locale->query(QSystemLocale::LocaleChanged, QVariant());
707
708
    // Populate global with fallback as basis:
709
1
    globalLocaleData = *sys_locale->fallbackUiLocaleData();
710
1
    system_number_options = QLocale::DefaultNumberOptions;
711
712
1
    QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
713
1
    if (!res.isNull()) {
714
0
        globalLocaleData.m_language_id = res.toInt();
715
0
        globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
716
0
        if (globalLocaleData.m_language_id == QLocale::C)
717
0
            system_number_options = QLocale::OmitGroupSeparator;
718
0
    }
719
1
    res = sys_locale->query(QSystemLocale::CountryId, QVariant());
720
1
    if (!res.isNull()) {
721
0
        globalLocaleData.m_country_id = res.toInt();
722
0
        globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
723
0
    }
724
1
    res = sys_locale->query(QSystemLocale::ScriptId, QVariant());
725
1
    if (!res.isNull())
726
0
        globalLocaleData.m_script_id = res.toInt();
727
728
1
    res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant());
729
1
    if (!res.isNull() && !res.toString().isEmpty())
730
1
        globalLocaleData.m_decimal = res.toString().at(0).unicode();
731
732
    // System may supply empty group separator to say we should omit grouping;
733
    // and it makes no sense to use the same separator for decimal and grouping
734
    // (which might happen by system supplying, as decimal, what CLDR has given
735
    // us for grouping; or the other way round). Assume, at least, that each of
736
    // system and CLDR has decimal != group, all the same.
737
1
    res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant());
738
1
    if (res.isNull()) {
739
        // The case where system over-rides decimal but not group, and its
740
        // decimal clashes with CLDR's group.
741
0
        if (globalLocaleData.m_group == globalLocaleData.m_decimal)
742
0
            system_number_options |= QLocale::OmitGroupSeparator;
743
1
    } else if (res.toString().isEmpty()) {
744
0
        system_number_options |= QLocale::OmitGroupSeparator;
745
1
    } else {
746
1
        const ushort group = res.toString().at(0).unicode();
747
1
        if (group != globalLocaleData.m_decimal)
748
1
            globalLocaleData.m_group = group;
749
1
    }
750
751
1
    res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant());
752
1
    if (!res.isNull() && !res.toString().isEmpty())
753
1
        globalLocaleData.m_zero = res.toString().at(0).unicode();
754
755
1
    res = sys_locale->query(QSystemLocale::NegativeSign, QVariant());
756
1
    if (!res.isNull() && !res.toString().isEmpty())
757
1
        globalLocaleData.m_minus = res.toString().at(0).unicode();
758
759
1
    res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
760
1
    if (!res.isNull() && !res.toString().isEmpty())
761
1
        globalLocaleData.m_plus = res.toString().at(0).unicode();
762
763
1
    if (systemLocalePrivate.exists())
764
0
        systemLocalePrivate->data()->m_numberOptions = system_number_options;
765
    // else: system_number_options will be passed to create() when constructing.
766
1
}
767
#endif // !QT_NO_SYSTEMLOCALE
768
769
static const QLocaleData *systemData()
770
3
{
771
3
#ifndef QT_NO_SYSTEMLOCALE
772
    /*
773
      Copy over the information from the fallback locale and modify.
774
775
      This modifies (cross-thread) global state, so take care to only call it in
776
      one thread.
777
    */
778
3
    {
779
3
        static QBasicMutex systemDataMutex;
780
3
        systemDataMutex.lock();
781
3
        if (globalLocaleData.m_language_id == 0)
782
1
            updateSystemPrivate();
783
3
        systemDataMutex.unlock();
784
3
    }
785
786
3
    return &globalLocaleData;
787
#else
788
    return locale_data;
789
#endif
790
3
}
791
792
static const QLocaleData *defaultData()
793
1
{
794
1
    if (!default_data)
795
1
        default_data = systemData();
796
1
    return default_data;
797
1
}
798
799
const QLocaleData *QLocaleData::c()
800
1
{
801
1
    Q_ASSERT(locale_index[QLocale::C] == 0);
802
1
    return c_data;
803
1
}
804
805
static inline QString getLocaleData(const ushort *data, int size)
806
0
{
807
0
    return size > 0 ? QString::fromRawData(reinterpret_cast<const QChar *>(data), size) : QString();
808
0
}
809
810
static QString getLocaleListData(const ushort *data, int size, int index)
811
0
{
812
0
    static const ushort separator = ';';
813
0
    while (index && size > 0) {
814
0
        while (*data != separator)
815
0
            ++data, --size;
816
0
        --index;
817
0
        ++data;
818
0
        --size;
819
0
    }
820
0
    const ushort *end = data;
821
0
    while (size > 0 && *end != separator)
822
0
        ++end, --size;
823
0
    return getLocaleData(data, end - data);
824
0
}
825
826
827
#ifndef QT_NO_DATASTREAM
828
QDataStream &operator<<(QDataStream &ds, const QLocale &l)
829
0
{
830
0
    ds << l.name();
831
0
    return ds;
832
0
}
833
834
QDataStream &operator>>(QDataStream &ds, QLocale &l)
835
0
{
836
0
    QString s;
837
0
    ds >> s;
838
0
    l = QLocale(s);
839
0
    return ds;
840
0
}
841
#endif // QT_NO_DATASTREAM
842
843
844
static const int locale_data_size = sizeof(locale_data)/sizeof(QLocaleData) - 1;
845
846
Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate,
847
                          (QLocalePrivate::create(defaultData())))
848
849
static QLocalePrivate *localePrivateByName(const QString &name)
850
9
{
851
9
    if (name == QLatin1String("C"))
852
8
        return c_private();
853
    // TODO: Remove this version, and use offset everywhere
854
1
    const QLocaleData *data = findLocaleData(name);
855
1
    return QLocalePrivate::create(data, findLocaleOffset(name),
856
1
                                  data->m_language_id == QLocale::C
857
1
                                  ? QLocale::OmitGroupSeparator : QLocale::DefaultNumberOptions);
858
9
}
859
860
static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Script script,
861
                                         QLocale::Country country)
862
74.3k
{
863
74.3k
    if (language == QLocale::C)
864
74.3k
        return c_private();
865
866
    // TODO: Remove pointer, use index instead
867
0
    const QLocaleData *data = QLocaleData::findLocaleData(language, script, country);
868
0
    const uint offset = QLocaleData::findLocaleOffset(language, script, country);
869
870
0
    QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions;
871
872
    // If not found, should default to system
873
0
    if (data->m_language_id == QLocale::C) {
874
0
        if (defaultLocalePrivate.exists())
875
0
            numberOptions = defaultLocalePrivate->data()->m_numberOptions;
876
0
        data = defaultData();
877
0
    }
878
0
    return QLocalePrivate::create(data, offset, numberOptions);
879
74.3k
}
880
881
882
/*!
883
 \internal
884
*/
885
QLocale::QLocale(QLocalePrivate &dd)
886
    : d(&dd)
887
0
{}
888
889
890
/*!
891
    Constructs a QLocale object with the specified \a name,
892
    which has the format
893
    "language[_script][_country][.codeset][@modifier]" or "C", where:
894
895
    \list
896
    \li language is a lowercase, two-letter, ISO 639 language code (also some
897
        three-letter codes),
898
    \li script is a titlecase, four-letter, ISO 15924 script code,
899
    \li country is an uppercase, two-letter, ISO 3166 country code
900
        (also "419" as defined by United Nations),
901
    \li and codeset and modifier are ignored.
902
    \endlist
903
904
    The separator can be either underscore or a minus sign.
905
906
    If the string violates the locale format, or language is not
907
    a valid ISO 639 code, the "C" locale is used instead. If country
908
    is not present, or is not a valid ISO 3166 code, the most
909
    appropriate country is chosen for the specified language.
910
911
    The language, script and country codes are converted to their respective
912
    \c Language, \c Script and \c Country enums. After this conversion is
913
    performed, the constructor behaves exactly like QLocale(Country, Script,
914
    Language).
915
916
    This constructor is much slower than QLocale(Country, Script, Language).
917
918
    \sa bcp47Name()
919
*/
920
921
QLocale::QLocale(const QString &name)
922
    : d(localePrivateByName(name))
923
9
{
924
9
}
925
926
/*!
927
    Constructs a QLocale object initialized with the default locale. If
928
    no default locale was set using setDefault(), this locale will
929
    be the same as the one returned by system().
930
931
    \sa setDefault()
932
*/
933
934
QLocale::QLocale()
935
    : d(*defaultLocalePrivate)
936
2
{
937
    // Make sure system data is up to date
938
2
    systemData();
939
2
}
940
941
/*!
942
    Constructs a QLocale object with the specified \a language and \a
943
    country.
944
945
    \list
946
    \li If the language/country pair is found in the database, it is used.
947
    \li If the language is found but the country is not, or if the country
948
       is \c AnyCountry, the language is used with the most
949
       appropriate available country (for example, Germany for German),
950
    \li If neither the language nor the country are found, QLocale
951
       defaults to the default locale (see setDefault()).
952
    \endlist
953
954
    The language and country that are actually used can be queried
955
    using language() and country().
956
957
    \sa setDefault(), language(), country()
958
*/
959
960
QLocale::QLocale(Language language, Country country)
961
    : d(findLocalePrivate(language, QLocale::AnyScript, country))
962
74.3k
{
963
74.3k
}
964
965
/*!
966
    \since 4.8
967
968
    Constructs a QLocale object with the specified \a language, \a script and
969
    \a country.
970
971
    \list
972
    \li If the language/script/country is found in the database, it is used.
973
    \li If both \a script is AnyScript and \a country is AnyCountry, the
974
       language is used with the most appropriate available script and country
975
       (for example, Germany for German),
976
    \li If either \a script is AnyScript or \a country is AnyCountry, the
977
       language is used with the first locale that matches the given \a script
978
       and \a country.
979
    \li If neither the language nor the country are found, QLocale
980
       defaults to the default locale (see setDefault()).
981
    \endlist
982
983
    The language, script and country that are actually used can be queried
984
    using language(), script() and country().
985
986
    \sa setDefault(), language(), script(), country()
987
*/
988
989
QLocale::QLocale(Language language, Script script, Country country)
990
    : d(findLocalePrivate(language, script, country))
991
0
{
992
0
}
993
994
/*!
995
    Constructs a QLocale object as a copy of \a other.
996
*/
997
998
QLocale::QLocale(const QLocale &other)
999
0
{
1000
0
    d = other.d;
1001
0
}
1002
1003
/*!
1004
    Destructor
1005
*/
1006
1007
QLocale::~QLocale()
1008
74.4k
{
1009
74.4k
}
1010
1011
/*!
1012
    Assigns \a other to this QLocale object and returns a reference
1013
    to this QLocale object.
1014
*/
1015
1016
QLocale &QLocale::operator=(const QLocale &other)
1017
1
{
1018
1
    d = other.d;
1019
1
    return *this;
1020
1
}
1021
1022
bool QLocale::operator==(const QLocale &other) const
1023
0
{
1024
0
    return d->m_data == other.d->m_data && d->m_numberOptions == other.d->m_numberOptions;
1025
0
}
1026
1027
bool QLocale::operator!=(const QLocale &other) const
1028
0
{
1029
0
    return d->m_data != other.d->m_data || d->m_numberOptions != other.d->m_numberOptions;
1030
0
}
1031
1032
/*!
1033
    \fn void QLocale::swap(QLocale &other)
1034
    \since 5.6
1035
1036
    Swaps locale \a other with this locale. This operation is very fast and
1037
    never fails.
1038
*/
1039
1040
/*!
1041
    \since 5.6
1042
    \relates QLocale
1043
1044
    Returns the hash value for \a key, using
1045
    \a seed to seed the calculation.
1046
*/
1047
uint qHash(const QLocale &key, uint seed) noexcept
1048
0
{
1049
0
    QtPrivate::QHashCombine hash;
1050
0
    seed = hash(seed, key.d->m_data);
1051
0
    seed = hash(seed, key.d->m_numberOptions);
1052
0
    return seed;
1053
0
}
1054
1055
/*!
1056
    \since 4.2
1057
1058
    Sets the \a options related to number conversions for this
1059
    QLocale instance.
1060
1061
    \sa numberOptions()
1062
*/
1063
void QLocale::setNumberOptions(NumberOptions options)
1064
0
{
1065
0
    d->m_numberOptions = options;
1066
0
}
1067
1068
/*!
1069
    \since 4.2
1070
1071
    Returns the options related to number conversions for this
1072
    QLocale instance.
1073
1074
    By default, no options are set for the standard locales, except
1075
    for the "C" locale, which has OmitGroupSeparator set by default.
1076
1077
    \sa setNumberOptions(), toString(), groupSeparator()
1078
*/
1079
QLocale::NumberOptions QLocale::numberOptions() const
1080
0
{
1081
0
    return static_cast<NumberOptions>(d->m_numberOptions);
1082
0
}
1083
1084
/*!
1085
    \since 4.8
1086
1087
    Returns \a str quoted according to the current locale using the given
1088
    quotation \a style.
1089
*/
1090
QString QLocale::quoteString(const QString &str, QuotationStyle style) const
1091
0
{
1092
0
    return quoteString(QStringRef(&str), style);
1093
0
}
1094
1095
/*!
1096
    \since 4.8
1097
1098
    \overload
1099
*/
1100
QString QLocale::quoteString(const QStringRef &str, QuotationStyle style) const
1101
0
{
1102
0
#ifndef QT_NO_SYSTEMLOCALE
1103
0
    if (d->m_data == systemData()) {
1104
0
        QVariant res;
1105
0
        if (style == QLocale::AlternateQuotation)
1106
0
            res = systemLocale()->query(QSystemLocale::StringToAlternateQuotation,
1107
0
                                        QVariant::fromValue(str));
1108
0
        if (res.isNull() || style == QLocale::StandardQuotation)
1109
0
            res = systemLocale()->query(QSystemLocale::StringToStandardQuotation,
1110
0
                                        QVariant::fromValue(str));
1111
0
        if (!res.isNull())
1112
0
            return res.toString();
1113
0
    }
1114
0
#endif
1115
1116
0
    if (style == QLocale::StandardQuotation)
1117
0
        return QChar(d->m_data->m_quotation_start) % str % QChar(d->m_data->m_quotation_end);
1118
1119
0
    return QChar(d->m_data->m_alternate_quotation_start)
1120
0
        % str % QChar(d->m_data->m_alternate_quotation_end);
1121
0
}
1122
1123
/*!
1124
    \since 4.8
1125
1126
    Returns a string that represents a join of a given \a list of strings with
1127
    a separator defined by the locale.
1128
*/
1129
QString QLocale::createSeparatedList(const QStringList &list) const
1130
0
{
1131
0
#ifndef QT_NO_SYSTEMLOCALE
1132
0
    if (d->m_data == systemData()) {
1133
0
        QVariant res =
1134
0
            systemLocale()->query(QSystemLocale::ListToSeparatedString, QVariant::fromValue(list));
1135
1136
0
        if (!res.isNull())
1137
0
            return res.toString();
1138
0
    }
1139
0
#endif
1140
1141
0
    const int size = list.size();
1142
0
    if (size == 1) {
1143
0
        return list.at(0);
1144
0
    } else if (size == 2) {
1145
0
        QString format = getLocaleData(
1146
0
            list_pattern_part_data + d->m_data->m_list_pattern_part_two_idx,
1147
0
            d->m_data->m_list_pattern_part_two_size);
1148
0
        return format.arg(list.at(0), list.at(1));
1149
0
    } else if (size > 2) {
1150
0
        QString formatStart = getLocaleData(
1151
0
            list_pattern_part_data + d->m_data->m_list_pattern_part_start_idx,
1152
0
            d->m_data->m_list_pattern_part_start_size);
1153
0
        QString formatMid = getLocaleData(
1154
0
            list_pattern_part_data + d->m_data->m_list_pattern_part_mid_idx,
1155
0
            d->m_data->m_list_pattern_part_mid_size);
1156
0
        QString formatEnd = getLocaleData(
1157
0
            list_pattern_part_data + d->m_data->m_list_pattern_part_end_idx,
1158
0
            d->m_data->m_list_pattern_part_end_size);
1159
0
        QString result = formatStart.arg(list.at(0), list.at(1));
1160
0
        for (int i = 2; i < size - 1; ++i)
1161
0
            result = formatMid.arg(result, list.at(i));
1162
0
        result = formatEnd.arg(result, list.at(size - 1));
1163
0
        return result;
1164
0
    }
1165
1166
0
    return QString();
1167
0
}
1168
1169
/*!
1170
    \nonreentrant
1171
1172
    Sets the global default locale to \a locale. These
1173
    values are used when a QLocale object is constructed with
1174
    no arguments. If this function is not called, the system's
1175
    locale is used.
1176
1177
    \warning In a multithreaded application, the default locale
1178
    should be set at application startup, before any non-GUI threads
1179
    are created.
1180
1181
    \sa system(), c()
1182
*/
1183
1184
void QLocale::setDefault(const QLocale &locale)
1185
0
{
1186
0
    default_data = locale.d->m_data;
1187
1188
0
    if (defaultLocalePrivate.isDestroyed())
1189
0
        return; // avoid crash on exit
1190
0
    if (!defaultLocalePrivate.exists()) {
1191
        // Force it to exist; see QTBUG-83016
1192
0
        QLocale ignoreme;
1193
0
        Q_ASSERT(defaultLocalePrivate.exists());
1194
0
    }
1195
1196
    // update the cached private
1197
0
    *defaultLocalePrivate = locale.d;
1198
0
}
1199
1200
/*!
1201
    Returns the language of this locale.
1202
1203
    \sa script(), country(), languageToString(), bcp47Name()
1204
*/
1205
QLocale::Language QLocale::language() const
1206
0
{
1207
0
    return Language(d->languageId());
1208
0
}
1209
1210
/*!
1211
    \since 4.8
1212
1213
    Returns the script of this locale.
1214
1215
    \sa language(), country(), languageToString(), scriptToString(), bcp47Name()
1216
*/
1217
QLocale::Script QLocale::script() const
1218
0
{
1219
0
    return Script(d->m_data->m_script_id);
1220
0
}
1221
1222
/*!
1223
    Returns the country of this locale.
1224
1225
    \sa language(), script(), countryToString(), bcp47Name()
1226
*/
1227
QLocale::Country QLocale::country() const
1228
0
{
1229
0
    return Country(d->countryId());
1230
0
}
1231
1232
/*!
1233
    Returns the language and country of this locale as a
1234
    string of the form "language_country", where
1235
    language is a lowercase, two-letter ISO 639 language code,
1236
    and country is an uppercase, two- or three-letter ISO 3166 country code.
1237
1238
    Note that even if QLocale object was constructed with an explicit script,
1239
    name() will not contain it for compatibility reasons. Use bcp47Name() instead
1240
    if you need a full locale name.
1241
1242
    \sa QLocale(), language(), script(), country(), bcp47Name()
1243
*/
1244
1245
QString QLocale::name() const
1246
0
{
1247
0
    Language l = language();
1248
0
    if (l == C)
1249
0
        return d->languageCode();
1250
1251
0
    Country c = country();
1252
0
    if (c == AnyCountry)
1253
0
        return d->languageCode();
1254
1255
0
    return d->languageCode() + QLatin1Char('_') + d->countryCode();
1256
0
}
1257
1258
static qlonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok,
1259
                                   QLocale::NumberOptions mode, qlonglong)
1260
0
{
1261
0
    return d->stringToLongLong(str, 10, ok, mode);
1262
0
}
1263
1264
static qulonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok,
1265
                                    QLocale::NumberOptions mode, qulonglong)
1266
0
{
1267
0
    return d->stringToUnsLongLong(str, 10, ok, mode);
1268
0
}
1269
1270
template <typename T> static inline
1271
T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok)
1272
0
{
1273
0
    using Int64 =
1274
0
        typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type;
1275
1276
    // we select the right overload by the last, unused parameter
1277
0
    Int64 val = toIntegral_helper(d->m_data, str, ok, d->m_numberOptions, Int64());
1278
0
    if (T(val) != val) {
1279
0
        if (ok != nullptr)
1280
0
            *ok = false;
1281
0
        val = 0;
1282
0
    }
1283
0
    return T(val);
1284
0
}
Unexecuted instantiation: qlocale.cpp:short toIntegral_helper<short>(QLocalePrivate const*, QStringView, bool*)
Unexecuted instantiation: qlocale.cpp:unsigned short toIntegral_helper<unsigned short>(QLocalePrivate const*, QStringView, bool*)
Unexecuted instantiation: qlocale.cpp:int toIntegral_helper<int>(QLocalePrivate const*, QStringView, bool*)
Unexecuted instantiation: qlocale.cpp:unsigned int toIntegral_helper<unsigned int>(QLocalePrivate const*, QStringView, bool*)
Unexecuted instantiation: qlocale.cpp:long toIntegral_helper<long>(QLocalePrivate const*, QStringView, bool*)
Unexecuted instantiation: qlocale.cpp:unsigned long toIntegral_helper<unsigned long>(QLocalePrivate const*, QStringView, bool*)
Unexecuted instantiation: qlocale.cpp:long long toIntegral_helper<long long>(QLocalePrivate const*, QStringView, bool*)
Unexecuted instantiation: qlocale.cpp:unsigned long long toIntegral_helper<unsigned long long>(QLocalePrivate const*, QStringView, bool*)
1285
1286
1287
/*!
1288
    \since 4.8
1289
1290
    Returns the dash-separated language, script and country (and possibly other
1291
    BCP47 fields) of this locale as a string.
1292
1293
    Unlike the uiLanguages() the returned value of the bcp47Name() represents
1294
    the locale name of the QLocale data but not the language the user-interface
1295
    should be in.
1296
1297
    This function tries to conform the locale name to BCP47.
1298
1299
    \sa language(), country(), script(), uiLanguages()
1300
*/
1301
QString QLocale::bcp47Name() const
1302
0
{
1303
0
    return QString::fromLatin1(d->bcp47Name());
1304
0
}
1305
1306
/*!
1307
    Returns a QString containing the name of \a language.
1308
1309
    \sa countryToString(), scriptToString(), bcp47Name()
1310
*/
1311
1312
QString QLocale::languageToString(Language language)
1313
0
{
1314
0
    if (uint(language) > uint(QLocale::LastLanguage))
1315
0
        return QLatin1String("Unknown");
1316
0
    return QLatin1String(language_name_list + language_name_index[language]);
1317
0
}
1318
1319
/*!
1320
    Returns a QString containing the name of \a country.
1321
1322
    \sa languageToString(), scriptToString(), country(), bcp47Name()
1323
*/
1324
1325
QString QLocale::countryToString(Country country)
1326
0
{
1327
0
    if (uint(country) > uint(QLocale::LastCountry))
1328
0
        return QLatin1String("Unknown");
1329
0
    return QLatin1String(country_name_list + country_name_index[country]);
1330
0
}
1331
1332
/*!
1333
    \since 4.8
1334
1335
    Returns a QString containing the name of \a script.
1336
1337
    \sa languageToString(), countryToString(), script(), bcp47Name()
1338
*/
1339
QString QLocale::scriptToString(QLocale::Script script)
1340
0
{
1341
0
    if (uint(script) > uint(QLocale::LastScript))
1342
0
        return QLatin1String("Unknown");
1343
0
    return QLatin1String(script_name_list + script_name_index[script]);
1344
0
}
1345
1346
#if QT_STRINGVIEW_LEVEL < 2
1347
/*!
1348
    Returns the short int represented by the localized string \a s.
1349
1350
    If the conversion fails the function returns 0.
1351
1352
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1353
    to \c false, and success by setting *\a{ok} to \c true.
1354
1355
    This function ignores leading and trailing whitespace.
1356
1357
    \sa toUShort(), toString()
1358
*/
1359
1360
short QLocale::toShort(const QString &s, bool *ok) const
1361
0
{
1362
0
    return toIntegral_helper<short>(d, s, ok);
1363
0
}
1364
1365
/*!
1366
    Returns the unsigned short int represented by the localized string \a s.
1367
1368
    If the conversion fails the function returns 0.
1369
1370
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1371
    to \c false, and success by setting *\a{ok} to \c true.
1372
1373
    This function ignores leading and trailing whitespace.
1374
1375
    \sa toShort(), toString()
1376
*/
1377
1378
ushort QLocale::toUShort(const QString &s, bool *ok) const
1379
0
{
1380
0
    return toIntegral_helper<ushort>(d, s, ok);
1381
0
}
1382
1383
/*!
1384
    Returns the int represented by the localized string \a s.
1385
1386
    If the conversion fails the function returns 0.
1387
1388
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1389
    to \c false, and success by setting *\a{ok} to \c true.
1390
1391
    This function ignores leading and trailing whitespace.
1392
1393
    \sa toUInt(), toString()
1394
*/
1395
1396
int QLocale::toInt(const QString &s, bool *ok) const
1397
0
{
1398
0
    return toIntegral_helper<int>(d, s, ok);
1399
0
}
1400
1401
/*!
1402
    Returns the unsigned int represented by the localized string \a s.
1403
1404
    If the conversion fails the function returns 0.
1405
1406
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1407
    to \c false, and success by setting *\a{ok} to \c true.
1408
1409
    This function ignores leading and trailing whitespace.
1410
1411
    \sa toInt(), toString()
1412
*/
1413
1414
uint QLocale::toUInt(const QString &s, bool *ok) const
1415
0
{
1416
0
    return toIntegral_helper<uint>(d, s, ok);
1417
0
}
1418
1419
/*!
1420
 Returns the long int represented by the localized string \a s.
1421
1422
 If the conversion fails the function returns 0.
1423
1424
 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1425
 to \c false, and success by setting *\a{ok} to \c true.
1426
1427
 This function ignores leading and trailing whitespace.
1428
1429
 \sa toInt(), toULong(), toDouble(), toString()
1430
1431
 \since 5.13
1432
 */
1433
1434
1435
long QLocale::toLong(const QString &s, bool *ok) const
1436
0
{
1437
0
    return toIntegral_helper<long>(d, s, ok);
1438
0
}
1439
1440
/*!
1441
 Returns the unsigned long int represented by the localized
1442
 string \a s.
1443
1444
 If the conversion fails the function returns 0.
1445
1446
 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1447
 to \c false, and success by setting *\a{ok} to \c true.
1448
1449
 This function ignores leading and trailing whitespace.
1450
1451
 \sa toLong(), toInt(), toDouble(), toString()
1452
1453
 \since 5.13
1454
*/
1455
1456
ulong QLocale::toULong(const QString &s, bool *ok) const
1457
0
{
1458
0
    return toIntegral_helper<ulong>(d, s, ok);
1459
0
}
1460
1461
/*!
1462
    Returns the long long int represented by the localized string \a s.
1463
1464
    If the conversion fails the function returns 0.
1465
1466
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1467
    to \c false, and success by setting *\a{ok} to \c true.
1468
1469
    This function ignores leading and trailing whitespace.
1470
1471
    \sa toInt(), toULongLong(), toDouble(), toString()
1472
*/
1473
1474
1475
qlonglong QLocale::toLongLong(const QString &s, bool *ok) const
1476
0
{
1477
0
    return toIntegral_helper<qlonglong>(d, s, ok);
1478
0
}
1479
1480
/*!
1481
    Returns the unsigned long long int represented by the localized
1482
    string \a s.
1483
1484
    If the conversion fails the function returns 0.
1485
1486
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1487
    to \c false, and success by setting *\a{ok} to \c true.
1488
1489
    This function ignores leading and trailing whitespace.
1490
1491
    \sa toLongLong(), toInt(), toDouble(), toString()
1492
*/
1493
1494
qulonglong QLocale::toULongLong(const QString &s, bool *ok) const
1495
0
{
1496
0
    return toIntegral_helper<qulonglong>(d, s, ok);
1497
0
}
1498
1499
/*!
1500
    Returns the float represented by the localized string \a s.
1501
1502
    Returns an infinity if the conversion overflows or 0.0 if the
1503
    conversion fails for any other reason (e.g. underflow).
1504
1505
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1506
    to \c false, and success by setting *\a{ok} to \c true.
1507
1508
    This function does not fall back to the 'C' locale if the string
1509
    cannot be interpreted in this locale.
1510
1511
    This function ignores leading and trailing whitespace.
1512
1513
    \sa toDouble(), toInt(), toString()
1514
*/
1515
1516
float QLocale::toFloat(const QString &s, bool *ok) const
1517
0
{
1518
0
    return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok);
1519
0
}
1520
1521
/*!
1522
    Returns the double represented by the localized string \a s.
1523
1524
    Returns an infinity if the conversion overflows or 0.0 if the
1525
    conversion fails for any other reason (e.g. underflow).
1526
1527
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1528
    to \c false, and success by setting *\a{ok} to \c true.
1529
1530
    This function does not fall back to the 'C' locale if the string
1531
    cannot be interpreted in this locale.
1532
1533
    \snippet code/src_corelib_tools_qlocale.cpp 3
1534
1535
    Notice that the last conversion returns 1234.0, because '.' is the
1536
    thousands group separator in the German locale.
1537
1538
    This function ignores leading and trailing whitespace.
1539
1540
    \sa toFloat(), toInt(), toString()
1541
*/
1542
1543
double QLocale::toDouble(const QString &s, bool *ok) const
1544
0
{
1545
0
    return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
1546
0
}
1547
1548
/*!
1549
    Returns the short int represented by the localized string \a s.
1550
1551
    If the conversion fails the function returns 0.
1552
1553
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1554
    to \c false, and success by setting *\a{ok} to \c true.
1555
1556
    This function ignores leading and trailing whitespace.
1557
1558
    \sa toUShort(), toString()
1559
1560
    \since 5.1
1561
*/
1562
1563
short QLocale::toShort(const QStringRef &s, bool *ok) const
1564
0
{
1565
0
    return toIntegral_helper<short>(d, s, ok);
1566
0
}
1567
1568
/*!
1569
    Returns the unsigned short int represented by the localized string \a s.
1570
1571
    If the conversion fails the function returns 0.
1572
1573
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1574
    to \c false, and success by setting *\a{ok} to \c true.
1575
1576
    This function ignores leading and trailing whitespace.
1577
1578
    \sa toShort(), toString()
1579
1580
    \since 5.1
1581
*/
1582
1583
ushort QLocale::toUShort(const QStringRef &s, bool *ok) const
1584
0
{
1585
0
    return toIntegral_helper<ushort>(d, s, ok);
1586
0
}
1587
1588
/*!
1589
    Returns the int represented by the localized string \a s.
1590
1591
    If the conversion fails the function returns 0.
1592
1593
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1594
    to \c false, and success by setting *\a{ok} to \c true.
1595
1596
    This function ignores leading and trailing whitespace.
1597
1598
    \sa toUInt(), toString()
1599
1600
    \since 5.1
1601
*/
1602
1603
int QLocale::toInt(const QStringRef &s, bool *ok) const
1604
0
{
1605
0
    return toIntegral_helper<int>(d, s, ok);
1606
0
}
1607
1608
/*!
1609
    Returns the unsigned int represented by the localized string \a s.
1610
1611
    If the conversion fails the function returns 0.
1612
1613
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1614
    to \c false, and success by setting *\a{ok} to \c true.
1615
1616
    This function ignores leading and trailing whitespace.
1617
1618
    \sa toInt(), toString()
1619
1620
    \since 5.1
1621
*/
1622
1623
uint QLocale::toUInt(const QStringRef &s, bool *ok) const
1624
0
{
1625
0
    return toIntegral_helper<uint>(d, s, ok);
1626
0
}
1627
1628
/*!
1629
 Returns the long int represented by the localized string \a s.
1630
1631
 If the conversion fails the function returns 0.
1632
1633
 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1634
 to \c false, and success by setting *\a{ok} to \c true.
1635
1636
 This function ignores leading and trailing whitespace.
1637
1638
 \sa toInt(), toULong(), toDouble(), toString()
1639
1640
 \since 5.13
1641
 */
1642
1643
1644
long QLocale::toLong(const QStringRef &s, bool *ok) const
1645
0
{
1646
0
    return toIntegral_helper<long>(d, s, ok);
1647
0
}
1648
1649
/*!
1650
 Returns the unsigned long int represented by the localized
1651
 string \a s.
1652
1653
 If the conversion fails the function returns 0.
1654
1655
 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1656
 to \c false, and success by setting *\a{ok} to \c true.
1657
1658
 This function ignores leading and trailing whitespace.
1659
1660
 \sa toLong(), toInt(), toDouble(), toString()
1661
1662
 \since 5.13
1663
 */
1664
1665
ulong QLocale::toULong(const QStringRef &s, bool *ok) const
1666
0
{
1667
0
    return toIntegral_helper<ulong>(d, s, ok);
1668
0
}
1669
1670
/*!
1671
    Returns the long long int represented by the localized string \a s.
1672
1673
    If the conversion fails the function returns 0.
1674
1675
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1676
    to \c false, and success by setting *\a{ok} to \c true.
1677
1678
    This function ignores leading and trailing whitespace.
1679
1680
    \sa toInt(), toULongLong(), toDouble(), toString()
1681
1682
    \since 5.1
1683
*/
1684
1685
1686
qlonglong QLocale::toLongLong(const QStringRef &s, bool *ok) const
1687
0
{
1688
0
    return toIntegral_helper<qlonglong>(d, s, ok);
1689
0
}
1690
1691
/*!
1692
    Returns the unsigned long long int represented by the localized
1693
    string \a s.
1694
1695
    If the conversion fails the function returns 0.
1696
1697
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1698
    to \c false, and success by setting *\a{ok} to \c true.
1699
1700
    This function ignores leading and trailing whitespace.
1701
1702
    \sa toLongLong(), toInt(), toDouble(), toString()
1703
1704
    \since 5.1
1705
*/
1706
1707
qulonglong QLocale::toULongLong(const QStringRef &s, bool *ok) const
1708
0
{
1709
0
    return toIntegral_helper<qulonglong>(d, s, ok);
1710
0
}
1711
1712
/*!
1713
    Returns the float represented by the localized string \a s.
1714
1715
    Returns an infinity if the conversion overflows or 0.0 if the
1716
    conversion fails for any other reason (e.g. underflow).
1717
1718
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1719
    to \c false, and success by setting *\a{ok} to \c true.
1720
1721
    This function does not fall back to the 'C' locale if the string
1722
    cannot be interpreted in this locale.
1723
1724
    This function ignores leading and trailing whitespace.
1725
1726
    \sa toDouble(), toInt(), toString()
1727
1728
    \since 5.1
1729
*/
1730
1731
float QLocale::toFloat(const QStringRef &s, bool *ok) const
1732
0
{
1733
0
    return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok);
1734
0
}
1735
1736
/*!
1737
    Returns the double represented by the localized string \a s.
1738
1739
    Returns an infinity if the conversion overflows or 0.0 if the
1740
    conversion fails for any other reason (e.g. underflow).
1741
1742
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1743
    to \c false, and success by setting *\a{ok} to \c true.
1744
1745
    This function does not fall back to the 'C' locale if the string
1746
    cannot be interpreted in this locale.
1747
1748
    \snippet code/src_corelib_tools_qlocale.cpp 3
1749
1750
    Notice that the last conversion returns 1234.0, because '.' is the
1751
    thousands group separator in the German locale.
1752
1753
    This function ignores leading and trailing whitespace.
1754
1755
    \sa toFloat(), toInt(), toString()
1756
1757
    \since 5.1
1758
*/
1759
1760
double QLocale::toDouble(const QStringRef &s, bool *ok) const
1761
0
{
1762
0
    return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
1763
0
}
1764
#endif // QT_STRINGVIEW_LEVEL < 2
1765
1766
/*!
1767
    Returns the short int represented by the localized string \a s.
1768
1769
    If the conversion fails, the function returns 0.
1770
1771
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1772
    to \c false, and success by setting *\a{ok} to \c true.
1773
1774
    This function ignores leading and trailing whitespace.
1775
1776
    \sa toUShort(), toString()
1777
1778
    \since 5.10
1779
*/
1780
1781
short QLocale::toShort(QStringView s, bool *ok) const
1782
0
{
1783
0
    return toIntegral_helper<short>(d, s, ok);
1784
0
}
1785
1786
/*!
1787
    Returns the unsigned short int represented by the localized string \a s.
1788
1789
    If the conversion fails, the function returns 0.
1790
1791
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1792
    to \c false, and success by setting *\a{ok} to \c true.
1793
1794
    This function ignores leading and trailing whitespace.
1795
1796
    \sa toShort(), toString()
1797
1798
    \since 5.10
1799
*/
1800
1801
ushort QLocale::toUShort(QStringView s, bool *ok) const
1802
0
{
1803
0
    return toIntegral_helper<ushort>(d, s, ok);
1804
0
}
1805
1806
/*!
1807
    Returns the int represented by the localized string \a s.
1808
1809
    If the conversion fails, the function returns 0.
1810
1811
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1812
    to \c false, and success by setting *\a{ok} to \c true.
1813
1814
    This function ignores leading and trailing whitespace.
1815
1816
    \sa toUInt(), toString()
1817
1818
    \since 5.10
1819
*/
1820
1821
int QLocale::toInt(QStringView s, bool *ok) const
1822
0
{
1823
0
    return toIntegral_helper<int>(d, s, ok);
1824
0
}
1825
1826
/*!
1827
    Returns the unsigned int represented by the localized string \a s.
1828
1829
    If the conversion fails, the function returns 0.
1830
1831
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1832
    to \c false, and success by setting *\a{ok} to \c true.
1833
1834
    This function ignores leading and trailing whitespace.
1835
1836
    \sa toInt(), toString()
1837
1838
    \since 5.10
1839
*/
1840
1841
uint QLocale::toUInt(QStringView s, bool *ok) const
1842
0
{
1843
0
    return toIntegral_helper<uint>(d, s, ok);
1844
0
}
1845
1846
/*!
1847
 Returns the long int represented by the localized string \a s.
1848
1849
 If the conversion fails the function returns 0.
1850
1851
 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1852
 to \c false, and success by setting *\a{ok} to \c true.
1853
1854
 This function ignores leading and trailing whitespace.
1855
1856
 \sa toInt(), toULong(), toDouble(), toString()
1857
1858
 \since 5.13
1859
 */
1860
1861
1862
long QLocale::toLong(QStringView s, bool *ok) const
1863
0
{
1864
0
    return toIntegral_helper<long>(d, s, ok);
1865
0
}
1866
1867
/*!
1868
 Returns the unsigned long int represented by the localized
1869
 string \a s.
1870
1871
 If the conversion fails the function returns 0.
1872
1873
 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1874
 to \c false, and success by setting *\a{ok} to \c true.
1875
1876
 This function ignores leading and trailing whitespace.
1877
1878
 \sa toLong(), toInt(), toDouble(), toString()
1879
1880
 \since 5.13
1881
 */
1882
1883
ulong QLocale::toULong(QStringView s, bool *ok) const
1884
0
{
1885
0
    return toIntegral_helper<ulong>(d, s, ok);
1886
0
}
1887
1888
/*!
1889
    Returns the long long int represented by the localized string \a s.
1890
1891
    If the conversion fails, the function returns 0.
1892
1893
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1894
    to \c false, and success by setting *\a{ok} to \c true.
1895
1896
    This function ignores leading and trailing whitespace.
1897
1898
    \sa toInt(), toULongLong(), toDouble(), toString()
1899
1900
    \since 5.10
1901
*/
1902
1903
1904
qlonglong QLocale::toLongLong(QStringView s, bool *ok) const
1905
0
{
1906
0
    return toIntegral_helper<qlonglong>(d, s, ok);
1907
0
}
1908
1909
/*!
1910
    Returns the unsigned long long int represented by the localized
1911
    string \a s.
1912
1913
    If the conversion fails, the function returns 0.
1914
1915
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1916
    to \c false, and success by setting *\a{ok} to \c true.
1917
1918
    This function ignores leading and trailing whitespace.
1919
1920
    \sa toLongLong(), toInt(), toDouble(), toString()
1921
1922
    \since 5.10
1923
*/
1924
1925
qulonglong QLocale::toULongLong(QStringView s, bool *ok) const
1926
0
{
1927
0
    return toIntegral_helper<qulonglong>(d, s, ok);
1928
0
}
1929
1930
/*!
1931
    Returns the float represented by the localized string \a s.
1932
1933
    Returns an infinity if the conversion overflows or 0.0 if the
1934
    conversion fails for any other reason (e.g. underflow).
1935
1936
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1937
    to \c false, and success by setting *\a{ok} to \c true.
1938
1939
    This function ignores leading and trailing whitespace.
1940
1941
    \sa toDouble(), toInt(), toString()
1942
1943
    \since 5.10
1944
*/
1945
1946
float QLocale::toFloat(QStringView s, bool *ok) const
1947
0
{
1948
0
    return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok);
1949
0
}
1950
1951
/*!
1952
    Returns the double represented by the localized string \a s.
1953
1954
    Returns an infinity if the conversion overflows or 0.0 if the
1955
    conversion fails for any other reason (e.g. underflow).
1956
1957
    If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1958
    to \c false, and success by setting *\a{ok} to \c true.
1959
1960
    Unlike QString::toDouble(), this function does not fall back to
1961
    the "C" locale if the string cannot be interpreted in this
1962
    locale.
1963
1964
    \snippet code/src_corelib_tools_qlocale.cpp 3-qstringview
1965
1966
    Notice that the last conversion returns 1234.0, because '.' is the
1967
    thousands group separator in the German locale.
1968
1969
    This function ignores leading and trailing whitespace.
1970
1971
    \sa toFloat(), toInt(), toString()
1972
1973
    \since 5.10
1974
*/
1975
1976
double QLocale::toDouble(QStringView s, bool *ok) const
1977
0
{
1978
0
    return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
1979
0
}
1980
1981
/*!
1982
    Returns a localized string representation of \a i.
1983
1984
    \sa toLongLong(), numberOptions(), zeroDigit(), positiveSign()
1985
*/
1986
1987
QString QLocale::toString(qlonglong i) const
1988
0
{
1989
0
    int flags = d->m_numberOptions & OmitGroupSeparator
1990
0
                    ? 0
1991
0
                    : (d->m_data->m_country_id == Country::India)
1992
0
                      ? QLocaleData::IndianNumberGrouping : QLocaleData::ThousandsGroup;
1993
1994
0
    return d->m_data->longLongToString(i, -1, 10, -1, flags);
1995
0
}
1996
1997
/*!
1998
    \overload
1999
2000
    \sa toULongLong(), numberOptions(), zeroDigit(), positiveSign()
2001
*/
2002
2003
QString QLocale::toString(qulonglong i) const
2004
0
{
2005
0
    int flags = d->m_numberOptions & OmitGroupSeparator
2006
0
                    ? 0
2007
0
                    : (d->m_data->m_country_id == Country::India)
2008
0
                      ? QLocaleData::IndianNumberGrouping : QLocaleData::ThousandsGroup;
2009
2010
0
    return d->m_data->unsLongLongToString(i, -1, 10, -1, flags);
2011
0
}
2012
2013
#if QT_STRINGVIEW_LEVEL < 2
2014
/*!
2015
    Returns a localized string representation of the given \a date in the
2016
    specified \a format.
2017
    If \a format is an empty string, an empty string is returned.
2018
2019
    \sa QDate::toString()
2020
*/
2021
2022
QString QLocale::toString(const QDate &date, const QString &format) const
2023
0
{
2024
0
    return QCalendar().dateTimeToString(format, QDateTime(), date, QTime(), *this);
2025
0
}
2026
#endif
2027
2028
/*!
2029
    \since 5.14
2030
2031
    Returns a localized string representation of the given \a date in the
2032
    specified \a format, optionally for a specified calendar \a cal.
2033
    If \a format is an empty string, an empty string is returned.
2034
2035
    \sa QDate::toString()
2036
*/
2037
QString QLocale::toString(const QDate &date, QStringView format, QCalendar cal) const
2038
0
{
2039
0
    return cal.dateTimeToString(format, QDateTime(), date, QTime(), *this);
2040
0
}
2041
2042
/*!
2043
    \since 5.10
2044
    \overload
2045
*/
2046
QString QLocale::toString(const QDate &date, QStringView format) const
2047
0
{
2048
0
    return QCalendar().dateTimeToString(format, QDateTime(), date, QTime(), *this);
2049
0
}
2050
2051
/*!
2052
    \since 5.14
2053
2054
    Returns a localized string representation of the given \a date according
2055
    to the specified \a format (see dateFormat()), optionally for a specified
2056
    calendar \a cal.
2057
2058
    \note Some locales may use formats that limit the range of years they can
2059
    represent.
2060
*/
2061
QString QLocale::toString(const QDate &date, FormatType format, QCalendar cal) const
2062
0
{
2063
0
    if (!date.isValid())
2064
0
        return QString();
2065
2066
0
#ifndef QT_NO_SYSTEMLOCALE
2067
0
    if (cal.isGregorian() && d->m_data == systemData()) {
2068
0
        QVariant res = systemLocale()->query(format == LongFormat
2069
0
                                             ? QSystemLocale::DateToStringLong
2070
0
                                             : QSystemLocale::DateToStringShort,
2071
0
                                             date);
2072
0
        if (!res.isNull())
2073
0
            return res.toString();
2074
0
    }
2075
0
#endif
2076
2077
0
    QString format_str = dateFormat(format);
2078
0
    return toString(date, format_str, cal);
2079
0
}
2080
2081
/*!
2082
    \since 4.5
2083
    \overload
2084
*/
2085
QString QLocale::toString(const QDate &date, FormatType format) const
2086
0
{
2087
0
    if (!date.isValid())
2088
0
        return QString();
2089
2090
0
#ifndef QT_NO_SYSTEMLOCALE
2091
0
    if (d->m_data == systemData()) {
2092
0
        QVariant res = systemLocale()->query(format == LongFormat
2093
0
                                             ? QSystemLocale::DateToStringLong
2094
0
                                             : QSystemLocale::DateToStringShort,
2095
0
                                             date);
2096
0
        if (!res.isNull())
2097
0
            return res.toString();
2098
0
    }
2099
0
#endif
2100
2101
0
    QString format_str = dateFormat(format);
2102
0
    return toString(date, format_str);
2103
0
}
2104
2105
static bool timeFormatContainsAP(QStringView format)
2106
0
{
2107
0
    int i = 0;
2108
0
    while (i < format.size()) {
2109
0
        if (format.at(i).unicode() == '\'') {
2110
0
            qt_readEscapedFormatString(format, &i);
2111
0
            continue;
2112
0
        }
2113
2114
0
        if (format.at(i).toLower().unicode() == 'a')
2115
0
            return true;
2116
2117
0
        ++i;
2118
0
    }
2119
0
    return false;
2120
0
}
2121
2122
#if QT_STRINGVIEW_LEVEL < 2
2123
/*!
2124
    Returns a localized string representation of the given \a time according
2125
    to the specified \a format.
2126
    If \a format is an empty string, an empty string is returned.
2127
2128
    \sa QTime::toString()
2129
*/
2130
QString QLocale::toString(const QTime &time, const QString &format) const
2131
0
{
2132
0
    return QCalendar().dateTimeToString(format, QDateTime(), QDate(), time, *this);
2133
0
}
2134
#endif
2135
2136
/*!
2137
    \since 4.5
2138
2139
    Returns a localized string representation of the given \a time according
2140
    to the specified \a format.
2141
    If \a format is an empty string, an empty string is returned.
2142
2143
    \sa QTime::toString()
2144
*/
2145
QString QLocale::toString(const QTime &time, QStringView format) const
2146
0
{
2147
0
    return QCalendar().dateTimeToString(format, QDateTime(), QDate(), time, *this);
2148
0
}
2149
2150
#if QT_STRINGVIEW_LEVEL < 2
2151
/*!
2152
    \since 4.4
2153
2154
    Returns a localized string representation of the given \a dateTime according
2155
    to the specified \a format.
2156
    If \a format is an empty string, an empty string is returned.
2157
2158
    \sa QDateTime::toString(), QDate::toString(), QTime::toString()
2159
*/
2160
2161
QString QLocale::toString(const QDateTime &dateTime, const QString &format) const
2162
0
{
2163
0
    return QCalendar().dateTimeToString(format, dateTime, QDate(), QTime(), *this);
2164
0
}
2165
#endif
2166
2167
/*!
2168
    \since 5.14
2169
2170
    Returns a localized string representation of the given \a dateTime according
2171
    to the specified \a format, optionally for a specified calendar \a cal.
2172
    If \a format is an empty string, an empty string is returned.
2173
2174
    \sa QDateTime::toString(), QDate::toString(), QTime::toString()
2175
*/
2176
QString QLocale::toString(const QDateTime &dateTime, QStringView format, QCalendar cal) const
2177
0
{
2178
0
    return cal.dateTimeToString(format, dateTime, QDate(), QTime(), *this);
2179
0
}
2180
2181
/*!
2182
    \since 5.10
2183
    \overload
2184
*/
2185
QString QLocale::toString(const QDateTime &dateTime, QStringView format) const
2186
0
{
2187
0
    return QCalendar().dateTimeToString(format, dateTime, QDate(), QTime(), *this);
2188
0
}
2189
2190
/*!
2191
    \since 5.14
2192
2193
    Returns a localized string representation of the given \a dateTime according
2194
    to the specified \a format (see dateTimeFormat()), optionally for a
2195
    specified calendar \a cal.
2196
2197
    \note Some locales may use formats that limit the range of years they can
2198
    represent.
2199
*/
2200
QString QLocale::toString(const QDateTime &dateTime, FormatType format, QCalendar cal) const
2201
0
{
2202
0
    if (!dateTime.isValid())
2203
0
        return QString();
2204
2205
0
#ifndef QT_NO_SYSTEMLOCALE
2206
0
    if (cal.isGregorian() && d->m_data == systemData()) {
2207
0
        QVariant res = systemLocale()->query(format == LongFormat
2208
0
                                             ? QSystemLocale::DateTimeToStringLong
2209
0
                                             : QSystemLocale::DateTimeToStringShort,
2210
0
                                             dateTime);
2211
0
        if (!res.isNull())
2212
0
            return res.toString();
2213
0
    }
2214
0
#endif
2215
2216
0
    const QString format_str = dateTimeFormat(format);
2217
0
    return toString(dateTime, format_str, cal);
2218
0
}
2219
2220
/*!
2221
    \since 4.4
2222
    \overload
2223
*/
2224
QString QLocale::toString(const QDateTime &dateTime, FormatType format) const
2225
0
{
2226
0
    if (!dateTime.isValid())
2227
0
        return QString();
2228
2229
0
#ifndef QT_NO_SYSTEMLOCALE
2230
0
    if (d->m_data == systemData()) {
2231
0
        QVariant res = systemLocale()->query(format == LongFormat
2232
0
                                             ? QSystemLocale::DateTimeToStringLong
2233
0
                                             : QSystemLocale::DateTimeToStringShort,
2234
0
                                             dateTime);
2235
0
        if (!res.isNull())
2236
0
            return res.toString();
2237
0
    }
2238
0
#endif
2239
2240
0
    const QString format_str = dateTimeFormat(format);
2241
0
    return toString(dateTime, format_str);
2242
0
}
2243
2244
2245
/*!
2246
    Returns a localized string representation of the given \a time in the
2247
    specified \a format (see timeFormat()).
2248
*/
2249
2250
QString QLocale::toString(const QTime &time, FormatType format) const
2251
0
{
2252
0
    if (!time.isValid())
2253
0
        return QString();
2254
2255
0
#ifndef QT_NO_SYSTEMLOCALE
2256
0
    if (d->m_data == systemData()) {
2257
0
        QVariant res = systemLocale()->query(format == LongFormat
2258
0
                                             ? QSystemLocale::TimeToStringLong
2259
0
                                             : QSystemLocale::TimeToStringShort,
2260
0
                                             time);
2261
0
        if (!res.isNull())
2262
0
            return res.toString();
2263
0
    }
2264
0
#endif
2265
2266
0
    QString format_str = timeFormat(format);
2267
0
    return toString(time, format_str);
2268
0
}
2269
2270
/*!
2271
    \since 4.1
2272
2273
    Returns the date format used for the current locale.
2274
2275
    If \a format is LongFormat, the format will be elaborate, otherwise it will be short.
2276
    For example, LongFormat for the \c{en_US} locale is \c{dddd, MMMM d, yyyy},
2277
    ShortFormat is \c{M/d/yy}.
2278
2279
    \sa QDate::toString(), QDate::fromString()
2280
*/
2281
2282
QString QLocale::dateFormat(FormatType format) const
2283
0
{
2284
0
#ifndef QT_NO_SYSTEMLOCALE
2285
0
    if (d->m_data == systemData()) {
2286
0
        QVariant res = systemLocale()->query(format == LongFormat
2287
0
                                             ? QSystemLocale::DateFormatLong
2288
0
                                             : QSystemLocale::DateFormatShort,
2289
0
                                             QVariant());
2290
0
        if (!res.isNull())
2291
0
            return res.toString();
2292
0
    }
2293
0
#endif
2294
2295
0
    quint32 idx, size;
2296
0
    switch (format) {
2297
0
    case LongFormat:
2298
0
        idx = d->m_data->m_long_date_format_idx;
2299
0
        size = d->m_data->m_long_date_format_size;
2300
0
        break;
2301
0
    default:
2302
0
        idx = d->m_data->m_short_date_format_idx;
2303
0
        size = d->m_data->m_short_date_format_size;
2304
0
        break;
2305
0
    }
2306
0
    return getLocaleData(date_format_data + idx, size);
2307
0
}
2308
2309
/*!
2310
    \since 4.1
2311
2312
    Returns the time format used for the current locale.
2313
2314
    If \a format is LongFormat, the format will be elaborate, otherwise it will be short.
2315
    For example, LongFormat for the \c{en_US} locale is \c{h:mm:ss AP t},
2316
    ShortFormat is \c{h:mm AP}.
2317
2318
    \sa QTime::toString(), QTime::fromString()
2319
*/
2320
2321
QString QLocale::timeFormat(FormatType format) const
2322
0
{
2323
0
#ifndef QT_NO_SYSTEMLOCALE
2324
0
    if (d->m_data == systemData()) {
2325
0
        QVariant res = systemLocale()->query(format == LongFormat
2326
0
                                             ? QSystemLocale::TimeFormatLong
2327
0
                                             : QSystemLocale::TimeFormatShort,
2328
0
                                             QVariant());
2329
0
        if (!res.isNull())
2330
0
            return res.toString();
2331
0
    }
2332
0
#endif
2333
2334
0
    quint32 idx, size;
2335
0
    switch (format) {
2336
0
    case LongFormat:
2337
0
        idx = d->m_data->m_long_time_format_idx;
2338
0
        size = d->m_data->m_long_time_format_size;
2339
0
        break;
2340
0
    default:
2341
0
        idx = d->m_data->m_short_time_format_idx;
2342
0
        size = d->m_data->m_short_time_format_size;
2343
0
        break;
2344
0
    }
2345
0
    return getLocaleData(time_format_data + idx, size);
2346
0
}
2347
2348
/*!
2349
    \since 4.4
2350
2351
    Returns the date time format used for the current locale.
2352
2353
    If \a format is LongFormat, the format will be elaborate, otherwise it will be short.
2354
    For example, LongFormat for the \c{en_US} locale is \c{dddd, MMMM d, yyyy h:mm:ss AP t},
2355
    ShortFormat is \c{M/d/yy h:mm AP}.
2356
2357
    \sa QDateTime::toString(), QDateTime::fromString()
2358
*/
2359
2360
QString QLocale::dateTimeFormat(FormatType format) const
2361
0
{
2362
0
#ifndef QT_NO_SYSTEMLOCALE
2363
0
    if (d->m_data == systemData()) {
2364
0
        QVariant res = systemLocale()->query(format == LongFormat
2365
0
                                             ? QSystemLocale::DateTimeFormatLong
2366
0
                                             : QSystemLocale::DateTimeFormatShort,
2367
0
                                             QVariant());
2368
0
        if (!res.isNull()) {
2369
0
            return res.toString();
2370
0
        }
2371
0
    }
2372
0
#endif
2373
0
    return dateFormat(format) + QLatin1Char(' ') + timeFormat(format);
2374
0
}
2375
2376
#if QT_CONFIG(datestring)
2377
/*!
2378
    \since 4.4
2379
2380
    Parses the time string given in \a string and returns the
2381
    time. The format of the time string is chosen according to the
2382
    \a format parameter (see timeFormat()).
2383
2384
    If the time could not be parsed, returns an invalid time.
2385
2386
    \sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
2387
*/
2388
QTime QLocale::toTime(const QString &string, FormatType format) const
2389
0
{
2390
0
    return toTime(string, timeFormat(format));
2391
0
}
2392
2393
#if QT_DEPRECATED_SINCE(5, 15)
2394
/*!
2395
    \since 5.14
2396
    \overload
2397
    \deprecated
2398
*/
2399
QTime QLocale::toTime(const QString &string, FormatType format, QCalendar cal) const
2400
0
{
2401
0
QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
2402
0
    return toTime(string, timeFormat(format), cal);
2403
0
QT_WARNING_POP
2404
0
}
2405
#endif
2406
2407
/*!
2408
    \since 4.4
2409
2410
    Parses the date string given in \a string and returns the
2411
    date. The format of the date string is chosen according to the
2412
    \a format parameter (see dateFormat()).
2413
2414
    If the date could not be parsed, returns an invalid date.
2415
2416
    \sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
2417
*/
2418
QDate QLocale::toDate(const QString &string, FormatType format) const
2419
0
{
2420
0
    return toDate(string, dateFormat(format));
2421
0
}
2422
2423
/*!
2424
    \since 5.14
2425
    \overload
2426
*/
2427
QDate QLocale::toDate(const QString &string, FormatType format, QCalendar cal) const
2428
0
{
2429
0
    return toDate(string, dateFormat(format), cal);
2430
0
}
2431
2432
/*!
2433
    \since 4.4
2434
2435
    Parses the date/time string given in \a string and returns the
2436
    time. The format of the date/time string is chosen according to the
2437
    \a format parameter (see dateTimeFormat()).
2438
2439
    If the string could not be parsed, returns an invalid QDateTime.
2440
2441
    \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
2442
*/
2443
QDateTime QLocale::toDateTime(const QString &string, FormatType format) const
2444
0
{
2445
0
    return toDateTime(string, dateTimeFormat(format));
2446
0
}
2447
2448
/*!
2449
    \since 5.14
2450
    \overload
2451
*/
2452
QDateTime QLocale::toDateTime(const QString &string, FormatType format, QCalendar cal) const
2453
0
{
2454
0
    return toDateTime(string, dateTimeFormat(format), cal);
2455
0
}
2456
2457
/*!
2458
    \since 4.4
2459
2460
    Parses the time string given in \a string and returns the
2461
    time. See QTime::fromString() for information on what is a valid
2462
    format string.
2463
2464
    If the time could not be parsed, returns an invalid time.
2465
2466
    \sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
2467
*/
2468
QTime QLocale::toTime(const QString &string, const QString &format) const
2469
0
{
2470
0
    QTime time;
2471
0
#if QT_CONFIG(datetimeparser)
2472
0
    QDateTimeParser dt(QMetaType::QTime, QDateTimeParser::FromString, QCalendar());
2473
0
    dt.setDefaultLocale(*this);
2474
0
    if (dt.parseFormat(format))
2475
0
        dt.fromString(string, nullptr, &time);
2476
#else
2477
    Q_UNUSED(string);
2478
    Q_UNUSED(format);
2479
#endif
2480
0
    return time;
2481
0
}
2482
2483
#if QT_DEPRECATED_SINCE(5, 15)
2484
/*!
2485
    \since 5.14
2486
    \overload
2487
    \deprecated
2488
*/
2489
QTime QLocale::toTime(const QString &string, const QString &format, QCalendar cal) const
2490
0
{
2491
0
    QTime time;
2492
0
#if QT_CONFIG(datetimeparser)
2493
0
    QDateTimeParser dt(QMetaType::QTime, QDateTimeParser::FromString, cal);
2494
0
    dt.setDefaultLocale(*this);
2495
0
    if (dt.parseFormat(format))
2496
0
        dt.fromString(string, nullptr, &time);
2497
#else
2498
    Q_UNUSED(cal);
2499
    Q_UNUSED(string);
2500
    Q_UNUSED(format);
2501
#endif
2502
0
    return time;
2503
0
}
2504
#endif
2505
2506
/*!
2507
    \since 4.4
2508
2509
    Parses the date string given in \a string and returns the
2510
    date. See QDate::fromString() for information on the expressions
2511
    that can be used with this function.
2512
2513
    This function searches month names and the names of the days of
2514
    the week in the current locale.
2515
2516
    If the date could not be parsed, returns an invalid date.
2517
2518
    \sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
2519
*/
2520
QDate QLocale::toDate(const QString &string, const QString &format) const
2521
0
{
2522
0
    return toDate(string, format, QCalendar());
2523
0
}
2524
2525
/*!
2526
    \since 5.14
2527
    \overload
2528
*/
2529
QDate QLocale::toDate(const QString &string, const QString &format, QCalendar cal) const
2530
0
{
2531
0
    QDate date;
2532
0
#if QT_CONFIG(datetimeparser)
2533
0
    QDateTimeParser dt(QMetaType::QDate, QDateTimeParser::FromString, cal);
2534
0
    dt.setDefaultLocale(*this);
2535
0
    if (dt.parseFormat(format))
2536
0
        dt.fromString(string, &date, nullptr);
2537
#else
2538
    Q_UNUSED(string);
2539
    Q_UNUSED(format);
2540
    Q_UNUSED(cal);
2541
#endif
2542
0
    return date;
2543
0
}
2544
2545
/*!
2546
    \since 4.4
2547
2548
    Parses the date/time string given in \a string and returns the
2549
    time.  See QDateTime::fromString() for information on the expressions
2550
    that can be used with this function.
2551
2552
    \note The month and day names used must be given in the user's local
2553
    language.
2554
2555
    If the string could not be parsed, returns an invalid QDateTime.  If the
2556
    string can be parsed and represents an invalid date-time (e.g. in a gap
2557
    skipped by a time-zone transition), an invalid QDateTime is returned, whose
2558
    toMSecsSinceEpoch() represents a near-by date-time that is valid. Passing
2559
    that to fromMSecsSinceEpoch() will produce a valid date-time that isn't
2560
    faithfully represented by the string parsed.
2561
2562
    \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
2563
*/
2564
QDateTime QLocale::toDateTime(const QString &string, const QString &format) const
2565
0
{
2566
0
    return toDateTime(string, format, QCalendar());
2567
0
}
2568
2569
/*!
2570
    \since 5.14
2571
    \overload
2572
*/
2573
QDateTime QLocale::toDateTime(const QString &string, const QString &format, QCalendar cal) const
2574
0
{
2575
0
#if QT_CONFIG(datetimeparser)
2576
0
    QDateTime datetime;
2577
2578
0
    QDateTimeParser dt(QMetaType::QDateTime, QDateTimeParser::FromString, cal);
2579
0
    dt.setDefaultLocale(*this);
2580
0
    if (dt.parseFormat(format) && (dt.fromString(string, &datetime) || !datetime.isValid()))
2581
0
        return datetime;
2582
#else
2583
    Q_UNUSED(string);
2584
    Q_UNUSED(format);
2585
    Q_UNUSED(cal);
2586
#endif
2587
0
    return QDateTime();
2588
0
}
2589
#endif // datestring
2590
2591
/*!
2592
    \since 4.1
2593
2594
    Returns the decimal point character of this locale.
2595
2596
    \note This function shall change to return a QString instead of QChar in
2597
    Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
2598
    convert early in preparation for this.
2599
2600
    \sa groupSeparator(), toString()
2601
*/
2602
QChar QLocale::decimalPoint() const
2603
1
{
2604
1
    return d->decimal();
2605
1
}
2606
2607
/*!
2608
    \since 4.1
2609
2610
    Returns the group separator character of this locale.
2611
2612
    \note This function shall change to return a QString instead of QChar in
2613
    Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
2614
    convert early in preparation for this.
2615
2616
    \sa decimalPoint(), toString()
2617
*/
2618
QChar QLocale::groupSeparator() const
2619
1
{
2620
1
    return d->group();
2621
1
}
2622
2623
/*!
2624
    \since 4.1
2625
2626
    Returns the percent character of this locale.
2627
2628
    \note This function shall change to return a QString instead of QChar in
2629
    Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
2630
    convert early in preparation for this.
2631
2632
    \sa toString()
2633
*/
2634
QChar QLocale::percent() const
2635
0
{
2636
0
    return d->percent();
2637
0
}
2638
2639
/*!
2640
    \since 4.1
2641
2642
    Returns the zero digit character of this locale.
2643
2644
    \note This function shall change to return a QString instead of QChar in
2645
    Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
2646
    convert early in preparation for this.
2647
2648
    \sa toString()
2649
*/
2650
QChar QLocale::zeroDigit() const
2651
1
{
2652
1
    return d->zero();
2653
1
}
2654
2655
/*!
2656
    \since 4.1
2657
2658
    Returns the negative sign character of this locale.
2659
2660
    \note This function shall change to return a QString instead of QChar in
2661
    Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
2662
    convert early in preparation for this.
2663
2664
    \sa positiveSign(), toString()
2665
*/
2666
QChar QLocale::negativeSign() const
2667
1
{
2668
1
    return d->minus();
2669
1
}
2670
2671
/*!
2672
    \since 4.5
2673
2674
    Returns the positive sign character of this locale.
2675
2676
    \note This function shall change to return a QString instead of QChar in
2677
    Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
2678
    convert early in preparation for this.
2679
2680
    \sa negativeSign(), toString()
2681
*/
2682
QChar QLocale::positiveSign() const
2683
1
{
2684
1
    return d->plus();
2685
1
}
2686
2687
/*!
2688
    \since 4.1
2689
2690
    Returns the exponential character of this locale, used to separate exponent
2691
    from mantissa in some floating-point numeric representations.
2692
2693
    \note This function shall change to return a QString instead of QChar in
2694
    Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
2695
    convert early in preparation for this.
2696
2697
    \sa toString(double, char, int)
2698
*/
2699
QChar QLocale::exponential() const
2700
0
{
2701
0
    return d->exponential();
2702
0
}
2703
2704
static bool qIsUpper(char c)
2705
0
{
2706
0
    return c >= 'A' && c <= 'Z';
2707
0
}
2708
2709
static char qToLower(char c)
2710
0
{
2711
0
    if (c >= 'A' && c <= 'Z')
2712
0
        return c - 'A' + 'a';
2713
0
    else
2714
0
        return c;
2715
0
}
2716
2717
/*!
2718
    \overload
2719
2720
    \a f and \a prec have the same meaning as in QString::number(double, char, int).
2721
2722
    \sa toDouble(), numberOptions(), exponential(), decimalPoint(), zeroDigit(), positiveSign(), percent()
2723
*/
2724
2725
QString QLocale::toString(double i, char f, int prec) const
2726
0
{
2727
0
    QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
2728
0
    uint flags = 0;
2729
2730
0
    if (qIsUpper(f))
2731
0
        flags = QLocaleData::CapitalEorX;
2732
0
    f = qToLower(f);
2733
2734
0
    switch (f) {
2735
0
        case 'f':
2736
0
            form = QLocaleData::DFDecimal;
2737
0
            break;
2738
0
        case 'e':
2739
0
            form = QLocaleData::DFExponent;
2740
0
            break;
2741
0
        case 'g':
2742
0
            form = QLocaleData::DFSignificantDigits;
2743
0
            break;
2744
0
        default:
2745
0
            break;
2746
0
    }
2747
2748
0
    if (!(d->m_numberOptions & OmitGroupSeparator))
2749
0
        flags |= QLocaleData::ThousandsGroup;
2750
0
    if (!(d->m_numberOptions & OmitLeadingZeroInExponent))
2751
0
        flags |= QLocaleData::ZeroPadExponent;
2752
0
    if (d->m_numberOptions & IncludeTrailingZeroesAfterDot)
2753
0
        flags |= QLocaleData::AddTrailingZeroes;
2754
0
    return d->m_data->doubleToString(i, prec, form, -1, flags);
2755
0
}
2756
2757
/*!
2758
    \fn QLocale QLocale::c()
2759
2760
    Returns a QLocale object initialized to the "C" locale.
2761
2762
    This locale is based on en_US but with various quirks of its own, such as
2763
    simplified number formatting and its own date formatting. It implements the
2764
    POSIX standards that describe the behavior of standard library functions of
2765
    the "C" programming language.
2766
2767
    Among other things, this means its collation order is based on the ASCII
2768
    values of letters, so that (for case-sensitive sorting) all upper-case
2769
    letters sort before any lower-case one (rather than each letter's upper- and
2770
    lower-case forms sorting adjacent to one another, before the next letter's
2771
    two forms).
2772
2773
    \sa system()
2774
*/
2775
2776
/*!
2777
    Returns a QLocale object initialized to the system locale.
2778
2779
    On Windows and Mac, this locale will use the decimal/grouping characters and
2780
    date/time formats specified in the system configuration panel.
2781
2782
    \sa c()
2783
*/
2784
2785
QLocale QLocale::system()
2786
0
{
2787
0
    QT_PREPEND_NAMESPACE(systemData)(); // trigger updating of the system data if necessary
2788
0
    if (systemLocalePrivate.isDestroyed())
2789
0
        return QLocale(QLocale::C);
2790
0
    return QLocale(*systemLocalePrivate->data());
2791
0
}
2792
2793
2794
/*!
2795
    \since 4.8
2796
2797
    Returns a list of valid locale objects that match the given \a language, \a
2798
    script and \a country.
2799
2800
    Getting a list of all locales:
2801
    QList<QLocale> allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript,
2802
                                                         QLocale::AnyCountry);
2803
2804
    Getting a list of locales suitable for Russia:
2805
    QList<QLocale> locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript,
2806
                                                      QLocale::Russia);
2807
*/
2808
QList<QLocale> QLocale::matchingLocales(QLocale::Language language,
2809
                                        QLocale::Script script,
2810
                                        QLocale::Country country)
2811
0
{
2812
0
    if (uint(language) > QLocale::LastLanguage || uint(script) > QLocale::LastScript ||
2813
0
            uint(country) > QLocale::LastCountry)
2814
0
        return QList<QLocale>();
2815
2816
0
    if (language == QLocale::C)
2817
0
        return QList<QLocale>() << QLocale(QLocale::C);
2818
2819
0
    QList<QLocale> result;
2820
0
    if (language == QLocale::AnyLanguage && script == QLocale::AnyScript
2821
0
        && country == QLocale::AnyCountry) {
2822
0
        result.reserve(locale_data_size);
2823
0
    }
2824
0
    const QLocaleData *data = locale_data + locale_index[language];
2825
0
    while ( (data != locale_data + locale_data_size)
2826
0
            && (language == QLocale::AnyLanguage || data->m_language_id == uint(language))) {
2827
0
        if ((script == QLocale::AnyScript || data->m_script_id == uint(script))
2828
0
            && (country == QLocale::AnyCountry || data->m_country_id == uint(country))) {
2829
0
            result.append(QLocale(*(data->m_language_id == C ? c_private()
2830
0
                                    : QLocalePrivate::create(data))));
2831
0
        }
2832
0
        ++data;
2833
0
    }
2834
0
    return result;
2835
0
}
2836
2837
/*!
2838
    \obsolete
2839
    \since 4.3
2840
2841
    Returns the list of countries that have entries for \a language in Qt's locale
2842
    database. If the result is an empty list, then \a language is not represented in
2843
    Qt's locale database.
2844
2845
    \sa matchingLocales()
2846
*/
2847
QList<QLocale::Country> QLocale::countriesForLanguage(Language language)
2848
0
{
2849
0
    QList<Country> result;
2850
0
    if (language == C) {
2851
0
        result << AnyCountry;
2852
0
        return result;
2853
0
    }
2854
2855
0
    unsigned language_id = language;
2856
0
    const QLocaleData *data = locale_data + locale_index[language_id];
2857
0
    while (data->m_language_id == language_id) {
2858
0
        const QLocale::Country country = static_cast<Country>(data->m_country_id);
2859
0
        if (!result.contains(country))
2860
0
            result.append(country);
2861
0
        ++data;
2862
0
    }
2863
2864
0
    return result;
2865
0
}
2866
2867
/*!
2868
    \since 4.2
2869
2870
    Returns the localized name of \a month, in the format specified
2871
    by \a type.
2872
2873
    For example, if the locale is \c en_US and \a month is 1,
2874
    \l LongFormat will return \c January. \l ShortFormat \c Jan,
2875
    and \l NarrowFormat \c J.
2876
2877
    \sa dayName(), standaloneMonthName()
2878
*/
2879
QString QLocale::monthName(int month, FormatType type) const
2880
0
{
2881
0
    return QCalendar().monthName(*this, month, QCalendar::Unspecified, type);
2882
0
}
2883
2884
/*!
2885
    \since 4.5
2886
2887
    Returns the localized name of \a month that is used as a
2888
    standalone text, in the format specified by \a type.
2889
2890
    If the locale information doesn't specify the standalone month
2891
    name then return value is the same as in monthName().
2892
2893
    \sa monthName(), standaloneDayName()
2894
*/
2895
QString QLocale::standaloneMonthName(int month, FormatType type) const
2896
0
{
2897
0
    return QCalendar().standaloneMonthName(*this, month, QCalendar::Unspecified, type);
2898
0
}
2899
2900
/*!
2901
    \since 4.2
2902
2903
    Returns the localized name of the \a day (where 1 represents
2904
    Monday, 2 represents Tuesday and so on), in the format specified
2905
    by \a type.
2906
2907
    For example, if the locale is \c en_US and \a day is 1,
2908
    \l LongFormat will return \c Monday, \l ShortFormat \c Mon,
2909
    and \l NarrowFormat \c M.
2910
2911
    \sa monthName(), standaloneDayName()
2912
*/
2913
QString QLocale::dayName(int day, FormatType type) const
2914
0
{
2915
0
    return QCalendar().weekDayName(*this, day, type);
2916
0
}
2917
2918
/*!
2919
    \since 4.5
2920
2921
    Returns the localized name of the \a day (where 1 represents
2922
    Monday, 2 represents Tuesday and so on) that is used as a
2923
    standalone text, in the format specified by \a type.
2924
2925
    If the locale information does not specify the standalone day
2926
    name then return value is the same as in dayName().
2927
2928
    \sa dayName(), standaloneMonthName()
2929
*/
2930
QString QLocale::standaloneDayName(int day, FormatType type) const
2931
0
{
2932
0
    return QCalendar().standaloneWeekDayName(*this, day, type);
2933
0
}
2934
2935
// Calendar look-up of month and day names:
2936
2937
/*!
2938
  \internal
2939
 */
2940
2941
static QString rawMonthName(const QCalendarLocale &localeData,
2942
                            const ushort *monthsData, int month,
2943
                            QLocale::FormatType type)
2944
0
{
2945
0
    quint32 idx, size;
2946
0
    switch (type) {
2947
0
    case QLocale::LongFormat:
2948
0
       idx = localeData.m_long.index;
2949
0
       size = localeData.m_long.size;
2950
0
       break;
2951
0
    case QLocale::ShortFormat:
2952
0
       idx = localeData.m_short.index;
2953
0
       size = localeData.m_short.size;
2954
0
       break;
2955
0
    case QLocale::NarrowFormat:
2956
0
       idx = localeData.m_narrow.index;
2957
0
       size = localeData.m_narrow.size;
2958
0
       break;
2959
0
    default:
2960
0
       return QString();
2961
0
    }
2962
0
    return getLocaleListData(monthsData + idx, size, month - 1);
2963
0
}
2964
2965
/*!
2966
  \internal
2967
 */
2968
2969
static QString rawStandaloneMonthName(const QCalendarLocale &localeData,
2970
                                      const ushort *monthsData, int month,
2971
                                      QLocale::FormatType type)
2972
0
{
2973
0
    quint32 idx, size;
2974
0
    switch (type) {
2975
0
    case QLocale::LongFormat:
2976
0
        idx = localeData.m_standalone_long.index;
2977
0
        size = localeData.m_standalone_long.size;
2978
0
        break;
2979
0
    case QLocale::ShortFormat:
2980
0
        idx = localeData.m_standalone_short.index;
2981
0
        size = localeData.m_standalone_short.size;
2982
0
        break;
2983
0
    case QLocale::NarrowFormat:
2984
0
        idx = localeData.m_standalone_narrow.index;
2985
0
        size = localeData.m_standalone_narrow.size;
2986
0
        break;
2987
0
    default:
2988
0
        return QString();
2989
0
    }
2990
0
    QString name = getLocaleListData(monthsData + idx, size, month - 1);
2991
0
    return name.isEmpty() ? rawMonthName(localeData, monthsData, month, type) : name;
2992
0
}
2993
2994
/*!
2995
  \internal
2996
 */
2997
2998
static QString rawWeekDayName(const QLocaleData *data, const int day,
2999
                              QLocale::FormatType type)
3000
0
{
3001
0
    quint32 idx, size;
3002
0
    switch (type) {
3003
0
    case QLocale::LongFormat:
3004
0
        idx = data->m_long_day_names_idx;
3005
0
        size = data->m_long_day_names_size;
3006
0
        break;
3007
0
    case QLocale::ShortFormat:
3008
0
        idx = data->m_short_day_names_idx;
3009
0
        size = data->m_short_day_names_size;
3010
0
        break;
3011
0
    case QLocale::NarrowFormat:
3012
0
        idx = data->m_narrow_day_names_idx;
3013
0
        size = data->m_narrow_day_names_size;
3014
0
        break;
3015
0
    default:
3016
0
        return QString();
3017
0
    }
3018
0
    return getLocaleListData(days_data + idx, size, day == 7 ? 0 : day);
3019
0
}
3020
3021
/*!
3022
  \internal
3023
 */
3024
3025
static QString rawStandaloneWeekDayName(const QLocaleData *data, const int day,
3026
                                        QLocale::FormatType type)
3027
0
{
3028
0
    quint32 idx, size;
3029
0
    switch (type) {
3030
0
    case QLocale::LongFormat:
3031
0
        idx = data->m_standalone_long_day_names_idx;
3032
0
        size = data->m_standalone_long_day_names_size;
3033
0
        break;
3034
0
    case QLocale::ShortFormat:
3035
0
        idx = data->m_standalone_short_day_names_idx;
3036
0
        size = data->m_standalone_short_day_names_size;
3037
0
        break;
3038
0
    case QLocale::NarrowFormat:
3039
0
        idx = data->m_standalone_narrow_day_names_idx;
3040
0
        size = data->m_standalone_narrow_day_names_size;
3041
0
        break;
3042
0
    default:
3043
0
        return QString();
3044
0
    }
3045
0
    QString name = getLocaleListData(days_data + idx, size, day == 7 ? 0 : day);
3046
0
    if (name.isEmpty())
3047
0
        return rawWeekDayName(data, day, type);
3048
0
    return name;
3049
0
}
3050
3051
// Refugees from qcalendar.cpp that need functions above:
3052
3053
QString QCalendarBackend::monthName(const QLocale &locale, int month, int,
3054
                                    QLocale::FormatType format) const
3055
0
{
3056
0
    Q_ASSERT(month >= 1 && month <= maximumMonthsInYear());
3057
0
    return rawMonthName(localeMonthIndexData()[locale.d->m_data_offset],
3058
0
                        localeMonthData(), month, format);
3059
0
}
3060
3061
QString QGregorianCalendar::monthName(const QLocale &locale, int month, int year,
3062
                                      QLocale::FormatType format) const
3063
0
{
3064
0
#ifndef QT_NO_SYSTEMLOCALE
3065
0
    if (locale.d->m_data == systemData()) {
3066
0
        Q_ASSERT(month >= 1 && month <= 12);
3067
0
        QVariant res = systemLocale()->query(format == QLocale::LongFormat
3068
0
                                             ? QSystemLocale::MonthNameLong
3069
0
                                             : QSystemLocale::MonthNameShort,
3070
0
                                             month);
3071
0
        if (!res.isNull())
3072
0
            return res.toString();
3073
0
    }
3074
0
#endif
3075
3076
0
    return QCalendarBackend::monthName(locale, month, year, format);
3077
0
}
3078
3079
QString QCalendarBackend::standaloneMonthName(const QLocale &locale, int month, int,
3080
                                              QLocale::FormatType format) const
3081
0
{
3082
0
    Q_ASSERT(month >= 1 && month <= maximumMonthsInYear());
3083
0
    return rawStandaloneMonthName(localeMonthIndexData()[locale.d->m_data_offset],
3084
0
                                  localeMonthData(), month, format);
3085
0
}
3086
3087
QString QGregorianCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
3088
                                                QLocale::FormatType format) const
3089
0
{
3090
0
#ifndef QT_NO_SYSTEMLOCALE
3091
0
    if (locale.d->m_data == systemData()) {
3092
0
        Q_ASSERT(month >= 1 && month <= 12);
3093
0
        QVariant res = systemLocale()->query(format == QLocale::LongFormat
3094
0
                                             ? QSystemLocale::StandaloneMonthNameLong
3095
0
                                             : QSystemLocale::StandaloneMonthNameShort,
3096
0
                                             month);
3097
0
        if (!res.isNull())
3098
0
            return res.toString();
3099
0
    }
3100
0
#endif
3101
3102
0
    return QCalendarBackend::standaloneMonthName(locale, month, year, format);
3103
0
}
3104
3105
// Most calendars share the common week-day naming, modulo locale.
3106
// Calendars that don't must override these methods.
3107
QString QCalendarBackend::weekDayName(const QLocale &locale, int day,
3108
                                      QLocale::FormatType format) const
3109
0
{
3110
0
    if (day < 1 || day > 7)
3111
0
        return QString();
3112
3113
0
#ifndef QT_NO_SYSTEMLOCALE
3114
0
    if (locale.d->m_data == systemData()) {
3115
0
        QVariant res = systemLocale()->query(format == QLocale::LongFormat
3116
0
                                             ? QSystemLocale::DayNameLong
3117
0
                                             : QSystemLocale::DayNameShort,
3118
0
                                             day);
3119
0
        if (!res.isNull())
3120
0
            return res.toString();
3121
0
    }
3122
0
#endif
3123
3124
0
    return rawWeekDayName(locale.d->m_data, day, format);
3125
0
}
3126
3127
QString QCalendarBackend::standaloneWeekDayName(const QLocale &locale, int day,
3128
                                                QLocale::FormatType format) const
3129
0
{
3130
0
    if (day < 1 || day > 7)
3131
0
        return QString();
3132
3133
0
#ifndef QT_NO_SYSTEMLOCALE
3134
0
    if (locale.d->m_data == systemData()) {
3135
0
        QVariant res = systemLocale()->query(format == QLocale::LongFormat
3136
0
                                             ? QSystemLocale::DayNameLong
3137
0
                                             : QSystemLocale::DayNameShort,
3138
0
                                             day);
3139
0
        if (!res.isNull())
3140
0
            return res.toString();
3141
0
    }
3142
0
#endif
3143
3144
0
    return rawStandaloneWeekDayName(locale.d->m_data, day, format);
3145
0
}
3146
3147
// End of this block of qcalendar.cpp refugees.  (One more follows.)
3148
3149
/*!
3150
    \since 4.8
3151
3152
    Returns the first day of the week according to the current locale.
3153
*/
3154
Qt::DayOfWeek QLocale::firstDayOfWeek() const
3155
0
{
3156
0
#ifndef QT_NO_SYSTEMLOCALE
3157
0
    if (d->m_data == systemData()) {
3158
0
        QVariant res = systemLocale()->query(QSystemLocale::FirstDayOfWeek, QVariant());
3159
0
        if (!res.isNull())
3160
0
            return static_cast<Qt::DayOfWeek>(res.toUInt());
3161
0
    }
3162
0
#endif
3163
0
    return static_cast<Qt::DayOfWeek>(d->m_data->m_first_day_of_week);
3164
0
}
3165
3166
QLocale::MeasurementSystem QLocalePrivate::measurementSystem() const
3167
0
{
3168
0
    for (int i = 0; i < ImperialMeasurementSystemsCount; ++i) {
3169
0
        if (ImperialMeasurementSystems[i].languageId == m_data->m_language_id
3170
0
            && ImperialMeasurementSystems[i].countryId == m_data->m_country_id) {
3171
0
            return ImperialMeasurementSystems[i].system;
3172
0
        }
3173
0
    }
3174
0
    return QLocale::MetricSystem;
3175
0
}
3176
3177
/*!
3178
    \since 4.8
3179
3180
    Returns a list of days that are considered weekdays according to the current locale.
3181
*/
3182
QList<Qt::DayOfWeek> QLocale::weekdays() const
3183
0
{
3184
0
#ifndef QT_NO_SYSTEMLOCALE
3185
0
    if (d->m_data == systemData()) {
3186
0
        QVariant res = systemLocale()->query(QSystemLocale::Weekdays, QVariant());
3187
0
        if (!res.isNull())
3188
0
            return static_cast<QList<Qt::DayOfWeek> >(qvariant_cast<QList<Qt::DayOfWeek> >(res));
3189
0
    }
3190
0
#endif
3191
0
    QList<Qt::DayOfWeek> weekdays;
3192
0
    quint16 weekendStart = d->m_data->m_weekend_start;
3193
0
    quint16 weekendEnd = d->m_data->m_weekend_end;
3194
0
    for (int day = Qt::Monday; day <= Qt::Sunday; day++) {
3195
0
        if ((weekendEnd >= weekendStart && (day < weekendStart || day > weekendEnd)) ||
3196
0
            (weekendEnd < weekendStart && (day > weekendEnd && day < weekendStart)))
3197
0
                weekdays << static_cast<Qt::DayOfWeek>(day);
3198
0
    }
3199
0
    return weekdays;
3200
0
}
3201
3202
/*!
3203
    \since 4.4
3204
3205
    Returns the measurement system for the locale.
3206
*/
3207
QLocale::MeasurementSystem QLocale::measurementSystem() const
3208
0
{
3209
0
#ifndef QT_NO_SYSTEMLOCALE
3210
0
    if (d->m_data == systemData()) {
3211
0
        QVariant res = systemLocale()->query(QSystemLocale::MeasurementSystem, QVariant());
3212
0
        if (!res.isNull())
3213
0
            return MeasurementSystem(res.toInt());
3214
0
    }
3215
0
#endif
3216
3217
0
    return d->measurementSystem();
3218
0
}
3219
3220
/*!
3221
  \since 4.7
3222
3223
  Returns the text direction of the language.
3224
*/
3225
Qt::LayoutDirection QLocale::textDirection() const
3226
0
{
3227
0
    switch (script()) {
3228
0
    case QLocale::AdlamScript:
3229
0
    case QLocale::ArabicScript:
3230
0
    case QLocale::AvestanScript:
3231
0
    case QLocale::CypriotScript:
3232
0
    case QLocale::HatranScript:
3233
0
    case QLocale::HebrewScript:
3234
0
    case QLocale::ImperialAramaicScript:
3235
0
    case QLocale::InscriptionalPahlaviScript:
3236
0
    case QLocale::InscriptionalParthianScript:
3237
0
    case QLocale::KharoshthiScript:
3238
0
    case QLocale::LydianScript:
3239
0
    case QLocale::MandaeanScript:
3240
0
    case QLocale::ManichaeanScript:
3241
0
    case QLocale::MendeKikakuiScript:
3242
0
    case QLocale::MeroiticCursiveScript:
3243
0
    case QLocale::MeroiticScript:
3244
0
    case QLocale::NabataeanScript:
3245
0
    case QLocale::NkoScript:
3246
0
    case QLocale::OldHungarianScript:
3247
0
    case QLocale::OldNorthArabianScript:
3248
0
    case QLocale::OldSouthArabianScript:
3249
0
    case QLocale::OrkhonScript:
3250
0
    case QLocale::PalmyreneScript:
3251
0
    case QLocale::PhoenicianScript:
3252
0
    case QLocale::PsalterPahlaviScript:
3253
0
    case QLocale::SamaritanScript:
3254
0
    case QLocale::SyriacScript:
3255
0
    case QLocale::ThaanaScript:
3256
0
        return Qt::RightToLeft;
3257
0
    default:
3258
0
        break;
3259
0
    }
3260
0
    return Qt::LeftToRight;
3261
0
}
3262
3263
/*!
3264
  \since 4.8
3265
3266
  Returns an uppercase copy of \a str.
3267
3268
  If Qt Core is using the ICU libraries, they will be used to perform
3269
  the transformation according to the rules of the current locale.
3270
  Otherwise the conversion may be done in a platform-dependent manner,
3271
  with QString::toUpper() as a generic fallback.
3272
3273
  \sa QString::toUpper()
3274
*/
3275
QString QLocale::toUpper(const QString &str) const
3276
0
{
3277
#if QT_CONFIG(icu)
3278
    bool ok = true;
3279
    QString result = QIcu::toUpper(d->bcp47Name('_'), str, &ok);
3280
    if (ok)
3281
        return result;
3282
    // else fall through and use Qt's toUpper
3283
#endif
3284
0
    return str.toUpper();
3285
0
}
3286
3287
/*!
3288
  \since 4.8
3289
3290
  Returns a lowercase copy of \a str.
3291
3292
  If Qt Core is using the ICU libraries, they will be used to perform
3293
  the transformation according to the rules of the current locale.
3294
  Otherwise the conversion may be done in a platform-dependent manner,
3295
  with QString::toLower() as a generic fallback.
3296
3297
  \sa QString::toLower()
3298
*/
3299
QString QLocale::toLower(const QString &str) const
3300
0
{
3301
#if QT_CONFIG(icu)
3302
    bool ok = true;
3303
    const QString result = QIcu::toLower(d->bcp47Name('_'), str, &ok);
3304
    if (ok)
3305
        return result;
3306
    // else fall through and use Qt's toUpper
3307
#endif
3308
0
    return str.toLower();
3309
0
}
3310
3311
3312
/*!
3313
    \since 4.5
3314
3315
    Returns the localized name of the "AM" suffix for times specified using
3316
    the conventions of the 12-hour clock.
3317
3318
    \sa pmText()
3319
*/
3320
QString QLocale::amText() const
3321
0
{
3322
0
#ifndef QT_NO_SYSTEMLOCALE
3323
0
    if (d->m_data == systemData()) {
3324
0
        QVariant res = systemLocale()->query(QSystemLocale::AMText, QVariant());
3325
0
        if (!res.isNull())
3326
0
            return res.toString();
3327
0
    }
3328
0
#endif
3329
0
    return getLocaleData(am_data + d->m_data->m_am_idx, d->m_data->m_am_size);
3330
0
}
3331
3332
/*!
3333
    \since 4.5
3334
3335
    Returns the localized name of the "PM" suffix for times specified using
3336
    the conventions of the 12-hour clock.
3337
3338
    \sa amText()
3339
*/
3340
QString QLocale::pmText() const
3341
0
{
3342
0
#ifndef QT_NO_SYSTEMLOCALE
3343
0
    if (d->m_data == systemData()) {
3344
0
        QVariant res = systemLocale()->query(QSystemLocale::PMText, QVariant());
3345
0
        if (!res.isNull())
3346
0
            return res.toString();
3347
0
    }
3348
0
#endif
3349
0
    return getLocaleData(pm_data + d->m_data->m_pm_idx, d->m_data->m_pm_size);
3350
0
}
3351
3352
// Another intrusion from QCalendar, using some of the tools above:
3353
3354
QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &datetime,
3355
                                           const QDate &dateOnly, const QTime &timeOnly,
3356
                                           const QLocale &locale) const
3357
0
{
3358
0
    QDate date;
3359
0
    QTime time;
3360
0
    bool formatDate = false;
3361
0
    bool formatTime = false;
3362
0
    if (datetime.isValid()) {
3363
0
        date = datetime.date();
3364
0
        time = datetime.time();
3365
0
        formatDate = true;
3366
0
        formatTime = true;
3367
0
    } else if (dateOnly.isValid()) {
3368
0
        date = dateOnly;
3369
0
        formatDate = true;
3370
0
    } else if (timeOnly.isValid()) {
3371
0
        time = timeOnly;
3372
0
        formatTime = true;
3373
0
    } else {
3374
0
        return QString();
3375
0
    }
3376
3377
0
    QString result;
3378
0
    int year = 0, month = 0, day = 0;
3379
0
    if (formatDate) {
3380
0
        const auto parts = julianDayToDate(date.toJulianDay());
3381
0
        if (!parts.isValid())
3382
0
            return QString();
3383
0
        year = parts.year;
3384
0
        month = parts.month;
3385
0
        day = parts.day;
3386
0
    }
3387
3388
0
    int i = 0;
3389
0
    while (i < format.size()) {
3390
0
        if (format.at(i).unicode() == '\'') {
3391
0
            result.append(qt_readEscapedFormatString(format, &i));
3392
0
            continue;
3393
0
        }
3394
3395
0
        const QChar c = format.at(i);
3396
0
        int repeat = qt_repeatCount(format.mid(i));
3397
0
        bool used = false;
3398
0
        if (formatDate) {
3399
0
            switch (c.unicode()) {
3400
0
            case 'y':
3401
0
                used = true;
3402
0
                if (repeat >= 4)
3403
0
                    repeat = 4;
3404
0
                else if (repeat >= 2)
3405
0
                    repeat = 2;
3406
3407
0
                switch (repeat) {
3408
0
                case 4: {
3409
0
                    const int len = (year < 0) ? 5 : 4;
3410
0
                    result.append(locale.d->m_data->longLongToString(year, -1, 10, len,
3411
0
                                                                     QLocaleData::ZeroPadded));
3412
0
                    break;
3413
0
                }
3414
0
                case 2:
3415
0
                    result.append(locale.d->m_data->longLongToString(year % 100, -1, 10, 2,
3416
0
                                                                     QLocaleData::ZeroPadded));
3417
0
                    break;
3418
0
                default:
3419
0
                    repeat = 1;
3420
0
                    result.append(c);
3421
0
                    break;
3422
0
                }
3423
0
                break;
3424
3425
0
            case 'M':
3426
0
                used = true;
3427
0
                repeat = qMin(repeat, 4);
3428
0
                switch (repeat) {
3429
0
                case 1:
3430
0
                    result.append(locale.d->m_data->longLongToString(month));
3431
0
                    break;
3432
0
                case 2:
3433
0
                    result.append(locale.d->m_data->longLongToString(month, -1, 10, 2,
3434
0
                                                                     QLocaleData::ZeroPadded));
3435
0
                    break;
3436
0
                case 3:
3437
0
                    result.append(monthName(locale, month, year, QLocale::ShortFormat));
3438
0
                    break;
3439
0
                case 4:
3440
0
                    result.append(monthName(locale, month, year, QLocale::LongFormat));
3441
0
                    break;
3442
0
                }
3443
0
                break;
3444
3445
0
            case 'd':
3446
0
                used = true;
3447
0
                repeat = qMin(repeat, 4);
3448
0
                switch (repeat) {
3449
0
                case 1:
3450
0
                    result.append(locale.d->m_data->longLongToString(day));
3451
0
                    break;
3452
0
                case 2:
3453
0
                    result.append(locale.d->m_data->longLongToString(day, -1, 10, 2,
3454
0
                                                                     QLocaleData::ZeroPadded));
3455
0
                    break;
3456
0
                case 3:
3457
0
                    result.append(locale.dayName(
3458
0
                                      dayOfWeek(date.toJulianDay()), QLocale::ShortFormat));
3459
0
                    break;
3460
0
                case 4:
3461
0
                    result.append(locale.dayName(
3462
0
                                      dayOfWeek(date.toJulianDay()), QLocale::LongFormat));
3463
0
                    break;
3464
0
                }
3465
0
                break;
3466
3467
0
            default:
3468
0
                break;
3469
0
            }
3470
0
        }
3471
0
        if (!used && formatTime) {
3472
0
            switch (c.unicode()) {
3473
0
            case 'h': {
3474
0
                used = true;
3475
0
                repeat = qMin(repeat, 2);
3476
0
                int hour = time.hour();
3477
0
                if (timeFormatContainsAP(format)) {
3478
0
                    if (hour > 12)
3479
0
                        hour -= 12;
3480
0
                    else if (hour == 0)
3481
0
                        hour = 12;
3482
0
                }
3483
3484
0
                switch (repeat) {
3485
0
                case 1:
3486
0
                    result.append(locale.d->m_data->longLongToString(hour));
3487
0
                    break;
3488
0
                case 2:
3489
0
                    result.append(locale.d->m_data->longLongToString(hour, -1, 10, 2,
3490
0
                                                                     QLocaleData::ZeroPadded));
3491
0
                    break;
3492
0
                }
3493
0
                break;
3494
0
            }
3495
0
            case 'H':
3496
0
                used = true;
3497
0
                repeat = qMin(repeat, 2);
3498
0
                switch (repeat) {
3499
0
                case 1:
3500
0
                    result.append(locale.d->m_data->longLongToString(time.hour()));
3501
0
                    break;
3502
0
                case 2:
3503
0
                    result.append(locale.d->m_data->longLongToString(time.hour(), -1, 10, 2,
3504
0
                                                                     QLocaleData::ZeroPadded));
3505
0
                    break;
3506
0
                }
3507
0
                break;
3508
3509
0
            case 'm':
3510
0
                used = true;
3511
0
                repeat = qMin(repeat, 2);
3512
0
                switch (repeat) {
3513
0
                case 1:
3514
0
                    result.append(locale.d->m_data->longLongToString(time.minute()));
3515
0
                    break;
3516
0
                case 2:
3517
0
                    result.append(locale.d->m_data->longLongToString(time.minute(), -1, 10, 2,
3518
0
                                                                     QLocaleData::ZeroPadded));
3519
0
                    break;
3520
0
                }
3521
0
                break;
3522
3523
0
            case 's':
3524
0
                used = true;
3525
0
                repeat = qMin(repeat, 2);
3526
0
                switch (repeat) {
3527
0
                case 1:
3528
0
                    result.append(locale.d->m_data->longLongToString(time.second()));
3529
0
                    break;
3530
0
                case 2:
3531
0
                    result.append(locale.d->m_data->longLongToString(time.second(), -1, 10, 2,
3532
0
                                                                     QLocaleData::ZeroPadded));
3533
0
                    break;
3534
0
                }
3535
0
                break;
3536
3537
0
            case 'a':
3538
0
                used = true;
3539
0
                repeat = format.mid(i + 1).startsWith(QLatin1Char('p')) ? 2 : 1;
3540
0
                result.append(time.hour() < 12 ? locale.amText().toLower()
3541
0
                                               : locale.pmText().toLower());
3542
0
                break;
3543
3544
0
            case 'A':
3545
0
                used = true;
3546
0
                repeat = format.mid(i + 1).startsWith(QLatin1Char('P')) ? 2 : 1;
3547
0
                result.append(time.hour() < 12 ? locale.amText().toUpper()
3548
0
                                                : locale.pmText().toUpper());
3549
0
                break;
3550
3551
0
            case 'z':
3552
0
                used = true;
3553
0
                repeat = (repeat >= 3) ? 3 : 1;
3554
3555
                // note: the millisecond component is treated like the decimal part of the seconds
3556
                // so ms == 2 is always printed as "002", but ms == 200 can be either "2" or "200"
3557
0
                result.append(locale.d->m_data->longLongToString(time.msec(), -1, 10, 3,
3558
0
                                                                 QLocaleData::ZeroPadded));
3559
0
                if (repeat == 1) {
3560
0
                    if (result.endsWith(locale.d->zero()))
3561
0
                        result.chop(1);
3562
0
                    if (result.endsWith(locale.d->zero()))
3563
0
                        result.chop(1);
3564
0
                }
3565
0
                break;
3566
3567
0
            case 't':
3568
0
                used = true;
3569
0
                repeat = 1;
3570
                // If we have a QDateTime use the time spec otherwise use the current system tzname
3571
0
                result.append(formatDate ? datetime.timeZoneAbbreviation()
3572
0
                                         : QDateTime::currentDateTime().timeZoneAbbreviation());
3573
0
                break;
3574
3575
0
            default:
3576
0
                break;
3577
0
            }
3578
0
        }
3579
0
        if (!used)
3580
0
            result.append(QString(repeat, c));
3581
0
        i += repeat;
3582
0
    }
3583
3584
0
    return result;
3585
0
}
3586
3587
// End of QCalendar intrustions
3588
3589
QString QLocaleData::doubleToString(double d, int precision, DoubleForm form,
3590
                                    int width, unsigned flags) const
3591
0
{
3592
0
    return doubleToString(m_zero, m_plus, m_minus, m_exponential, m_group, m_decimal,
3593
0
                          d, precision, form, width, flags);
3594
0
}
3595
3596
QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const QChar minus,
3597
                                    const QChar exponential, const QChar group, const QChar decimal,
3598
                                    double d, int precision, DoubleForm form, int width,
3599
                                    unsigned flags)
3600
0
{
3601
0
    if (precision != QLocale::FloatingPointShortest && precision < 0)
3602
0
        precision = 6;
3603
0
    if (width < 0)
3604
0
        width = 0;
3605
3606
0
    bool negative = false;
3607
0
    QString num_str;
3608
3609
0
    int decpt;
3610
0
    int bufSize = 1;
3611
0
    if (precision == QLocale::FloatingPointShortest)
3612
0
        bufSize += DoubleMaxSignificant;
3613
0
    else if (form == DFDecimal) // optimize for numbers between -512k and 512k
3614
0
        bufSize += ((d > (1 << 19) || d < -(1 << 19)) ? DoubleMaxDigitsBeforeDecimal : 6) +
3615
0
                precision;
3616
0
    else // Add extra digit due to different interpretations of precision. Also, "nan" has to fit.
3617
0
        bufSize += qMax(2, precision) + 1;
3618
3619
0
    QVarLengthArray<char> buf(bufSize);
3620
0
    int length;
3621
3622
0
    qt_doubleToAscii(d, form, precision, buf.data(), bufSize, negative, length, decpt);
3623
3624
0
    if (qstrncmp(buf.data(), "inf", 3) == 0 || qstrncmp(buf.data(), "nan", 3) == 0) {
3625
0
        num_str = QString::fromLatin1(buf.data(), length);
3626
0
    } else { // Handle normal numbers
3627
0
        QString digits = QString::fromLatin1(buf.data(), length);
3628
3629
0
        if (_zero.unicode() != '0') {
3630
0
            ushort z = _zero.unicode() - '0';
3631
0
            for (int i = 0; i < digits.length(); ++i)
3632
0
                reinterpret_cast<ushort *>(digits.data())[i] += z;
3633
0
        }
3634
3635
0
        bool always_show_decpt = (flags & ForcePoint);
3636
0
        switch (form) {
3637
0
            case DFExponent: {
3638
0
                num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
3639
0
                                       digits, decpt, precision, PMDecimalDigits,
3640
0
                                       always_show_decpt, flags & ZeroPadExponent);
3641
0
                break;
3642
0
            }
3643
0
            case DFDecimal: {
3644
0
                num_str = decimalForm(_zero, decimal, group,
3645
0
                                      digits, decpt, precision, PMDecimalDigits,
3646
0
                                      always_show_decpt, flags & ThousandsGroup);
3647
0
                break;
3648
0
            }
3649
0
            case DFSignificantDigits: {
3650
0
                PrecisionMode mode = (flags & AddTrailingZeroes) ?
3651
0
                            PMSignificantDigits : PMChopTrailingZeros;
3652
3653
0
                int cutoff = precision < 0 ? 6 : precision;
3654
                // Find out which representation is shorter
3655
0
                if (precision == QLocale::FloatingPointShortest && decpt > 0) {
3656
0
                    cutoff = digits.length() + 4; // 'e', '+'/'-', one digit exponent
3657
0
                    if (decpt <= 10) {
3658
0
                        ++cutoff;
3659
0
                    } else {
3660
0
                        cutoff += decpt > 100 ? 2 : 1;
3661
0
                    }
3662
0
                    if (!always_show_decpt && digits.length() > decpt)
3663
0
                        ++cutoff; // decpt shown in exponent form, but not in decimal form
3664
0
                }
3665
3666
0
                if (decpt != digits.length() && (decpt <= -4 || decpt > cutoff))
3667
0
                    num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
3668
0
                                           digits, decpt, precision, mode,
3669
0
                                           always_show_decpt, flags & ZeroPadExponent);
3670
0
                else
3671
0
                    num_str = decimalForm(_zero, decimal, group,
3672
0
                                          digits, decpt, precision, mode,
3673
0
                                          always_show_decpt, flags & ThousandsGroup);
3674
0
                break;
3675
0
            }
3676
0
        }
3677
3678
0
        if (isZero(d))
3679
0
            negative = false;
3680
3681
        // pad with zeros. LeftAdjusted overrides this flag). Also, we don't
3682
        // pad special numbers
3683
0
        if (flags & QLocaleData::ZeroPadded && !(flags & QLocaleData::LeftAdjusted)) {
3684
0
            int num_pad_chars = width - num_str.length();
3685
            // leave space for the sign
3686
0
            if (negative
3687
0
                    || flags & QLocaleData::AlwaysShowSign
3688
0
                    || flags & QLocaleData::BlankBeforePositive)
3689
0
                --num_pad_chars;
3690
3691
0
            for (int i = 0; i < num_pad_chars; ++i)
3692
0
                num_str.prepend(_zero);
3693
0
        }
3694
0
    }
3695
3696
    // add sign
3697
0
    if (negative)
3698
0
        num_str.prepend(minus);
3699
0
    else if (flags & QLocaleData::AlwaysShowSign)
3700
0
        num_str.prepend(plus);
3701
0
    else if (flags & QLocaleData::BlankBeforePositive)
3702
0
        num_str.prepend(QLatin1Char(' '));
3703
3704
0
    if (flags & QLocaleData::CapitalEorX)
3705
0
        num_str = std::move(num_str).toUpper();
3706
3707
0
    return num_str;
3708
0
}
3709
3710
QString QLocaleData::longLongToString(qlonglong l, int precision,
3711
                                            int base, int width,
3712
                                            unsigned flags) const
3713
1
{
3714
1
    return longLongToString(m_zero, m_group, m_plus, m_minus,
3715
1
                                            l, precision, base, width, flags);
3716
1
}
3717
3718
QString QLocaleData::longLongToString(const QChar zero, const QChar group,
3719
                                         const QChar plus, const QChar minus,
3720
                                         qlonglong l, int precision,
3721
                                         int base, int width,
3722
                                         unsigned flags)
3723
1
{
3724
1
    bool precision_not_specified = false;
3725
1
    if (precision == -1) {
3726
1
        precision_not_specified = true;
3727
1
        precision = 1;
3728
1
    }
3729
3730
1
    bool negative = l < 0;
3731
1
    if (base != 10) {
3732
        // these are not supported by sprintf for octal and hex
3733
0
        flags &= ~AlwaysShowSign;
3734
0
        flags &= ~BlankBeforePositive;
3735
0
        negative = false; // neither are negative numbers
3736
0
    }
3737
3738
1
QT_WARNING_PUSH
3739
    /* "unary minus operator applied to unsigned type, result still unsigned" */
3740
1
QT_WARNING_DISABLE_MSVC(4146)
3741
    /*
3742
      Negating std::numeric_limits<qlonglong>::min() hits undefined behavior, so
3743
      taking an absolute value has to cast to unsigned to change sign.
3744
     */
3745
1
    QString num_str = qulltoa(negative ? -qulonglong(l) : qulonglong(l), base, zero);
3746
1
QT_WARNING_POP
3747
3748
1
    uint cnt_thousand_sep = 0;
3749
1
    if (base == 10){
3750
1
        if (flags & ThousandsGroup) {
3751
0
            for (int i = num_str.length() - 3; i > 0; i -= 3) {
3752
0
                num_str.insert(i, group);
3753
0
                ++cnt_thousand_sep;
3754
0
            }
3755
1
        } else if (flags & IndianNumberGrouping) {
3756
0
            if (num_str.length() > 3)
3757
0
                num_str.insert(num_str.length() - 3 , group);
3758
0
            for (int i = num_str.length() - 6; i > 0; i -= 2) {
3759
0
                num_str.insert(i, group);
3760
0
                ++cnt_thousand_sep;
3761
0
            }
3762
0
        }
3763
1
    }
3764
3765
1
    for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
3766
0
        num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
3767
3768
1
    if ((flags & ShowBase)
3769
1
            && base == 8
3770
1
            && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
3771
0
        num_str.prepend(QLatin1Char('0'));
3772
3773
    // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
3774
    // when precision is not specified in the format string
3775
1
    bool zero_padded = flags & ZeroPadded
3776
1
                        && !(flags & LeftAdjusted)
3777
1
                        && precision_not_specified;
3778
3779
1
    if (zero_padded) {
3780
0
        int num_pad_chars = width - num_str.length();
3781
3782
        // leave space for the sign
3783
0
        if (negative
3784
0
                || flags & AlwaysShowSign
3785
0
                || flags & BlankBeforePositive)
3786
0
            --num_pad_chars;
3787
3788
        // leave space for optional '0x' in hex form
3789
0
        if (base == 16 && (flags & ShowBase))
3790
0
            num_pad_chars -= 2;
3791
        // leave space for optional '0b' in binary form
3792
0
        else if (base == 2 && (flags & ShowBase))
3793
0
            num_pad_chars -= 2;
3794
3795
0
        for (int i = 0; i < num_pad_chars; ++i)
3796
0
            num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
3797
0
    }
3798
3799
1
    if (flags & CapitalEorX)
3800
0
        num_str = std::move(num_str).toUpper();
3801
3802
1
    if (base == 16 && (flags & ShowBase))
3803
0
        num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
3804
1
    if (base == 2 && (flags & ShowBase))
3805
0
        num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
3806
3807
    // add sign
3808
1
    if (negative)
3809
0
        num_str.prepend(minus);
3810
1
    else if (flags & AlwaysShowSign)
3811
0
        num_str.prepend(plus);
3812
1
    else if (flags & BlankBeforePositive)
3813
0
        num_str.prepend(QLatin1Char(' '));
3814
3815
1
    return num_str;
3816
1
}
3817
3818
QString QLocaleData::unsLongLongToString(qulonglong l, int precision,
3819
                                            int base, int width,
3820
                                            unsigned flags) const
3821
0
{
3822
0
    return unsLongLongToString(m_zero, m_group, m_plus,
3823
0
                                               l, precision, base, width, flags);
3824
0
}
3825
3826
QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
3827
                                            const QChar plus,
3828
                                            qulonglong l, int precision,
3829
                                            int base, int width,
3830
                                            unsigned flags)
3831
0
{
3832
0
    const QChar resultZero = base == 10 ? zero : QChar(QLatin1Char('0'));
3833
0
    QString num_str = l ? qulltoa(l, base, zero) : QString(resultZero);
3834
3835
0
    bool precision_not_specified = false;
3836
0
    if (precision == -1) {
3837
0
        if (flags == NoFlags)
3838
0
            return num_str; // fast-path: nothing below applies, so we're done.
3839
3840
0
        precision_not_specified = true;
3841
0
        precision = 1;
3842
0
    }
3843
3844
0
    uint cnt_thousand_sep = 0;
3845
0
    if (base == 10) {
3846
0
        if (flags & ThousandsGroup) {
3847
0
            for (int i = num_str.length() - 3; i > 0; i -=3) {
3848
0
                num_str.insert(i, group);
3849
0
                ++cnt_thousand_sep;
3850
0
            }
3851
0
        } else if (flags & IndianNumberGrouping) {
3852
0
            if (num_str.length() > 3)
3853
0
                num_str.insert(num_str.length() - 3 , group);
3854
0
            for (int i = num_str.length() - 6; i > 0; i -= 2) {
3855
0
                num_str.insert(i, group);
3856
0
                ++cnt_thousand_sep;
3857
0
            }
3858
0
        }
3859
0
    }
3860
3861
0
    const int zeroPadding = precision - num_str.length()/* + cnt_thousand_sep*/;
3862
0
    if (zeroPadding > 0)
3863
0
        num_str.prepend(QString(zeroPadding, resultZero));
3864
3865
0
    if ((flags & ShowBase)
3866
0
            && base == 8
3867
0
            && (num_str.isEmpty() || num_str.at(0).unicode() != QLatin1Char('0')))
3868
0
        num_str.prepend(QLatin1Char('0'));
3869
3870
    // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
3871
    // when precision is not specified in the format string
3872
0
    bool zero_padded = flags & ZeroPadded
3873
0
                        && !(flags & LeftAdjusted)
3874
0
                        && precision_not_specified;
3875
3876
0
    if (zero_padded) {
3877
0
        int num_pad_chars = width - num_str.length();
3878
3879
        // leave space for optional '0x' in hex form
3880
0
        if (base == 16 && flags & ShowBase)
3881
0
            num_pad_chars -= 2;
3882
        // leave space for optional '0b' in binary form
3883
0
        else if (base == 2 && flags & ShowBase)
3884
0
            num_pad_chars -= 2;
3885
3886
0
        if (num_pad_chars > 0)
3887
0
            num_str.prepend(QString(num_pad_chars, resultZero));
3888
0
    }
3889
3890
0
    if (flags & CapitalEorX)
3891
0
        num_str = std::move(num_str).toUpper();
3892
3893
0
    if (base == 16 && flags & ShowBase)
3894
0
        num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
3895
0
    else if (base == 2 && flags & ShowBase)
3896
0
        num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
3897
3898
    // add sign
3899
0
    if (flags & AlwaysShowSign)
3900
0
        num_str.prepend(plus);
3901
0
    else if (flags & BlankBeforePositive)
3902
0
        num_str.prepend(QLatin1Char(' '));
3903
3904
0
    return num_str;
3905
0
}
3906
3907
/*
3908
    Converts a number in locale to its representation in the C locale.
3909
    Only has to guarantee that a string that is a correct representation of
3910
    a number will be converted. If junk is passed in, junk will be passed
3911
    out and the error will be detected during the actual conversion to a
3912
    number. We can't detect junk here, since we don't even know the base
3913
    of the number.
3914
*/
3915
bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_options,
3916
                                  CharBuff *result) const
3917
0
{
3918
0
    const QChar *uc = s.data();
3919
0
    auto l = s.size();
3920
0
    decltype(l) idx = 0;
3921
3922
    // Skip whitespace
3923
0
    while (idx < l && uc[idx].isSpace())
3924
0
        ++idx;
3925
0
    if (idx == l)
3926
0
        return false;
3927
3928
    // Check trailing whitespace
3929
0
    for (; idx < l; --l) {
3930
0
        if (!uc[l - 1].isSpace())
3931
0
            break;
3932
0
    }
3933
3934
0
    int group_cnt = 0; // counts number of group chars
3935
0
    int decpt_idx = -1;
3936
0
    int last_separator_idx = -1;
3937
0
    int start_of_digits_idx = -1;
3938
0
    int exponent_idx = -1;
3939
3940
0
    while (idx < l) {
3941
0
        const QChar in = uc[idx];
3942
3943
0
        char out = digitToCLocale(in);
3944
0
        if (out == 0) {
3945
0
            if (in == m_list)
3946
0
                out = ';';
3947
0
            else if (in == m_percent)
3948
0
                out = '%';
3949
            // for handling base-x numbers
3950
0
            else if (in.unicode() >= 'A' && in.unicode() <= 'Z')
3951
0
                out = in.toLower().toLatin1();
3952
0
            else if (in.unicode() >= 'a' && in.unicode() <= 'z')
3953
0
                out = in.toLatin1();
3954
0
            else
3955
0
                break;
3956
0
        } else if (out == '.') {
3957
            // Fail if more than one decimal point or point after e
3958
0
            if (decpt_idx != -1 || exponent_idx != -1)
3959
0
                return false;
3960
0
            decpt_idx = idx;
3961
0
        } else if (out == 'e' || out == 'E') {
3962
0
            exponent_idx = idx;
3963
0
        }
3964
3965
0
        if (number_options & QLocale::RejectLeadingZeroInExponent) {
3966
0
            if (exponent_idx != -1 && out == '0' && idx < l - 1) {
3967
                // After the exponent there can only be '+', '-' or digits.
3968
                // If we find a '0' directly after some non-digit, then that is a leading zero.
3969
0
                if (result->last() < '0' || result->last() > '9')
3970
0
                    return false;
3971
0
            }
3972
0
        }
3973
3974
0
        if (number_options & QLocale::RejectTrailingZeroesAfterDot) {
3975
            // If we've seen a decimal point and the last character after the exponent is 0, then
3976
            // that is a trailing zero.
3977
0
            if (decpt_idx >= 0 && idx == exponent_idx && result->last() == '0')
3978
0
                    return false;
3979
0
        }
3980
3981
0
        if (!(number_options & QLocale::RejectGroupSeparator)) {
3982
0
            if (start_of_digits_idx == -1 && out >= '0' && out <= '9') {
3983
0
                start_of_digits_idx = idx;
3984
0
            } else if (out == ',') {
3985
                // Don't allow group chars after the decimal point or exponent
3986
0
                if (decpt_idx != -1 || exponent_idx != -1)
3987
0
                    return false;
3988
3989
                // check distance from the last separator or from the beginning of the digits
3990
                // ### FIXME: Some locales allow other groupings!
3991
                // See https://en.wikipedia.org/wiki/Thousands_separator
3992
0
                if (m_country_id == QLocale::India) {
3993
0
                    if (last_separator_idx != -1 && idx - last_separator_idx != 3)
3994
0
                        return false;
3995
0
                } else if (last_separator_idx != -1 && idx - last_separator_idx != 4)
3996
0
                    return false;
3997
0
                if (last_separator_idx == -1
3998
0
                    && (start_of_digits_idx == -1 || idx - start_of_digits_idx > 3)) {
3999
0
                    return false;
4000
0
                }
4001
4002
0
                last_separator_idx = idx;
4003
0
                ++group_cnt;
4004
4005
                // don't add the group separator
4006
0
                ++idx;
4007
0
                continue;
4008
0
            } else if (out == '.' || out == 'e' || out == 'E') {
4009
                // check distance from the last separator
4010
                // ### FIXME: Some locales allow other groupings!
4011
                // See https://en.wikipedia.org/wiki/Thousands_separator
4012
0
                if (last_separator_idx != -1 && idx - last_separator_idx != 4)
4013
0
                    return false;
4014
4015
                // stop processing separators
4016
0
                last_separator_idx = -1;
4017
0
            }
4018
0
        }
4019
4020
0
        result->append(out);
4021
4022
0
        ++idx;
4023
0
    }
4024
4025
0
    if (!(number_options & QLocale::RejectGroupSeparator)) {
4026
        // group separator post-processing
4027
        // did we end in a separator?
4028
0
        if (last_separator_idx + 1 == idx)
4029
0
            return false;
4030
        // were there enough digits since the last separator?
4031
0
        if (last_separator_idx != -1 && idx - last_separator_idx != 4)
4032
0
            return false;
4033
0
    }
4034
4035
0
    if (number_options & QLocale::RejectTrailingZeroesAfterDot) {
4036
        // In decimal form, the last character can be a trailing zero if we've seen a decpt.
4037
0
        if (decpt_idx != -1 && exponent_idx == -1 && result->last() == '0')
4038
0
            return false;
4039
0
    }
4040
4041
0
    result->append('\0');
4042
0
    return idx == l;
4043
0
}
4044
4045
bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray *buff,
4046
                                int decDigits, QLocale::NumberOptions number_options) const
4047
0
{
4048
0
    buff->clear();
4049
0
    buff->reserve(str.length());
4050
4051
0
    const bool scientific = numMode == DoubleScientificMode;
4052
0
    bool lastWasE = false;
4053
0
    bool lastWasDigit = false;
4054
0
    int eCnt = 0;
4055
0
    int decPointCnt = 0;
4056
0
    bool dec = false;
4057
0
    int decDigitCnt = 0;
4058
4059
0
    for (qsizetype i = 0; i < str.size(); ++i) {
4060
0
        char c = digitToCLocale(str.at(i));
4061
4062
0
        if (c >= '0' && c <= '9') {
4063
0
            if (numMode != IntegerMode) {
4064
                // If a double has too many digits after decpt, it shall be Invalid.
4065
0
                if (dec && decDigits != -1 && decDigits < ++decDigitCnt)
4066
0
                    return false;
4067
0
            }
4068
4069
            // The only non-digit character after the 'e' can be '+' or '-'.
4070
            // If a zero is directly after that, then the exponent is zero-padded.
4071
0
            if ((number_options & QLocale::RejectLeadingZeroInExponent)
4072
0
                && c == '0' && eCnt > 0 && !lastWasDigit) {
4073
0
                return false;
4074
0
            }
4075
4076
0
            lastWasDigit = true;
4077
0
        } else {
4078
0
            switch (c) {
4079
0
                case '.':
4080
0
                    if (numMode == IntegerMode) {
4081
                        // If an integer has a decimal point, it shall be Invalid.
4082
0
                        return false;
4083
0
                    } else {
4084
                        // If a double has more than one decimal point, it shall be Invalid.
4085
0
                        if (++decPointCnt > 1)
4086
0
                            return false;
4087
#if 0
4088
                        // If a double with no decimal digits has a decimal point, it shall be
4089
                        // Invalid.
4090
                        if (decDigits == 0)
4091
                            return false;
4092
#endif                  // On second thoughts, it shall be Valid.
4093
4094
0
                        dec = true;
4095
0
                    }
4096
0
                    break;
4097
4098
0
                case '+':
4099
0
                case '-':
4100
0
                    if (scientific) {
4101
                        // If a scientific has a sign that's not at the beginning or after
4102
                        // an 'e', it shall be Invalid.
4103
0
                        if (i != 0 && !lastWasE)
4104
0
                            return false;
4105
0
                    } else {
4106
                        // If a non-scientific has a sign that's not at the beginning,
4107
                        // it shall be Invalid.
4108
0
                        if (i != 0)
4109
0
                            return false;
4110
0
                    }
4111
0
                    break;
4112
4113
0
                case ',':
4114
                    //it can only be placed after a digit which is before the decimal point
4115
0
                    if ((number_options & QLocale::RejectGroupSeparator) || !lastWasDigit ||
4116
0
                            decPointCnt > 0)
4117
0
                        return false;
4118
0
                    break;
4119
4120
0
                case 'e':
4121
0
                    if (scientific) {
4122
                        // If a scientific has more than one 'e', it shall be Invalid.
4123
0
                        if (++eCnt > 1)
4124
0
                            return false;
4125
0
                        dec = false;
4126
0
                    } else {
4127
                        // If a non-scientific has an 'e', it shall be Invalid.
4128
0
                        return false;
4129
0
                    }
4130
0
                    break;
4131
4132
0
                default:
4133
                    // If it's not a valid digit, it shall be Invalid.
4134
0
                    return false;
4135
0
            }
4136
0
            lastWasDigit = false;
4137
0
        }
4138
4139
0
        lastWasE = c == 'e';
4140
0
        if (c != ',')
4141
0
            buff->append(c);
4142
0
    }
4143
4144
0
    return true;
4145
0
}
4146
4147
double QLocaleData::stringToDouble(QStringView str, bool *ok,
4148
                                   QLocale::NumberOptions number_options) const
4149
0
{
4150
0
    CharBuff buff;
4151
0
    if (!numberToCLocale(str, number_options, &buff)) {
4152
0
        if (ok != nullptr)
4153
0
            *ok = false;
4154
0
        return 0.0;
4155
0
    }
4156
0
    int processed = 0;
4157
0
    bool nonNullOk = false;
4158
0
    double d = qt_asciiToDouble(buff.constData(), buff.length() - 1, nonNullOk, processed);
4159
0
    if (ok != nullptr)
4160
0
        *ok = nonNullOk;
4161
0
    return d;
4162
0
}
4163
4164
qlonglong QLocaleData::stringToLongLong(QStringView str, int base, bool *ok,
4165
                                        QLocale::NumberOptions number_options) const
4166
0
{
4167
0
    CharBuff buff;
4168
0
    if (!numberToCLocale(str, number_options, &buff)) {
4169
0
        if (ok != nullptr)
4170
0
            *ok = false;
4171
0
        return 0;
4172
0
    }
4173
4174
0
    return bytearrayToLongLong(buff.constData(), base, ok);
4175
0
}
4176
4177
qulonglong QLocaleData::stringToUnsLongLong(QStringView str, int base, bool *ok,
4178
                                            QLocale::NumberOptions number_options) const
4179
0
{
4180
0
    CharBuff buff;
4181
0
    if (!numberToCLocale(str, number_options, &buff)) {
4182
0
        if (ok != nullptr)
4183
0
            *ok = false;
4184
0
        return 0;
4185
0
    }
4186
4187
0
    return bytearrayToUnsLongLong(buff.constData(), base, ok);
4188
0
}
4189
4190
qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok)
4191
0
{
4192
0
    bool _ok;
4193
0
    const char *endptr;
4194
4195
0
    if (*num == '\0') {
4196
0
        if (ok != nullptr)
4197
0
            *ok = false;
4198
0
        return 0;
4199
0
    }
4200
4201
0
    qlonglong l = qstrtoll(num, &endptr, base, &_ok);
4202
4203
0
    if (!_ok) {
4204
0
        if (ok != nullptr)
4205
0
            *ok = false;
4206
0
        return 0;
4207
0
    }
4208
4209
0
    if (*endptr != '\0') {
4210
0
        while (ascii_isspace(*endptr))
4211
0
            ++endptr;
4212
0
    }
4213
4214
0
    if (*endptr != '\0') {
4215
        // we stopped at a non-digit character after converting some digits
4216
0
        if (ok != nullptr)
4217
0
            *ok = false;
4218
0
        return 0;
4219
0
    }
4220
4221
0
    if (ok != nullptr)
4222
0
        *ok = true;
4223
0
    return l;
4224
0
}
4225
4226
qulonglong QLocaleData::bytearrayToUnsLongLong(const char *num, int base, bool *ok)
4227
0
{
4228
0
    bool _ok;
4229
0
    const char *endptr;
4230
0
    qulonglong l = qstrtoull(num, &endptr, base, &_ok);
4231
4232
0
    if (!_ok) {
4233
0
        if (ok != nullptr)
4234
0
            *ok = false;
4235
0
        return 0;
4236
0
    }
4237
4238
0
    if (*endptr != '\0') {
4239
0
        while (ascii_isspace(*endptr))
4240
0
            ++endptr;
4241
0
    }
4242
4243
0
    if (*endptr != '\0') {
4244
0
        if (ok != nullptr)
4245
0
            *ok = false;
4246
0
        return 0;
4247
0
    }
4248
4249
0
    if (ok != nullptr)
4250
0
        *ok = true;
4251
0
    return l;
4252
0
}
4253
4254
/*!
4255
    \since 4.8
4256
4257
    \enum QLocale::CurrencySymbolFormat
4258
4259
    Specifies the format of the currency symbol.
4260
4261
    \value CurrencyIsoCode a ISO-4217 code of the currency.
4262
    \value CurrencySymbol a currency symbol.
4263
    \value CurrencyDisplayName a user readable name of the currency.
4264
*/
4265
4266
/*!
4267
    \since 4.8
4268
    Returns a currency symbol according to the \a format.
4269
*/
4270
QString QLocale::currencySymbol(QLocale::CurrencySymbolFormat format) const
4271
0
{
4272
0
#ifndef QT_NO_SYSTEMLOCALE
4273
0
    if (d->m_data == systemData()) {
4274
0
        QVariant res = systemLocale()->query(QSystemLocale::CurrencySymbol, format);
4275
0
        if (!res.isNull())
4276
0
            return res.toString();
4277
0
    }
4278
0
#endif
4279
0
    quint32 idx, size;
4280
0
    switch (format) {
4281
0
    case CurrencySymbol:
4282
0
        idx = d->m_data->m_currency_symbol_idx;
4283
0
        size = d->m_data->m_currency_symbol_size;
4284
0
        return getLocaleData(currency_symbol_data + idx, size);
4285
0
    case CurrencyDisplayName:
4286
0
        idx = d->m_data->m_currency_display_name_idx;
4287
0
        size = d->m_data->m_currency_display_name_size;
4288
0
        return getLocaleListData(currency_display_name_data + idx, size, 0);
4289
0
    case CurrencyIsoCode: {
4290
0
        int len = 0;
4291
0
        const QLocaleData *data = this->d->m_data;
4292
0
        for (; len < 3; ++len)
4293
0
            if (!data->m_currency_iso_code[len])
4294
0
                break;
4295
0
        return len ? QString::fromLatin1(data->m_currency_iso_code, len) : QString();
4296
0
    }
4297
0
    }
4298
0
    return QString();
4299
0
}
4300
4301
/*!
4302
    \since 4.8
4303
4304
    Returns a localized string representation of \a value as a currency.
4305
    If the \a symbol is provided it is used instead of the default currency symbol.
4306
4307
    \sa currencySymbol()
4308
*/
4309
QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const
4310
0
{
4311
0
#ifndef QT_NO_SYSTEMLOCALE
4312
0
    if (d->m_data == systemData()) {
4313
0
        QSystemLocale::CurrencyToStringArgument arg(value, symbol);
4314
0
        QVariant res =
4315
0
            systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
4316
0
        if (!res.isNull())
4317
0
            return res.toString();
4318
0
    }
4319
0
#endif
4320
0
    const QLocalePrivate *d = this->d;
4321
0
    quint8 idx = d->m_data->m_currency_format_idx;
4322
0
    quint8 size = d->m_data->m_currency_format_size;
4323
0
    if (d->m_data->m_currency_negative_format_size && value < 0) {
4324
0
        idx = d->m_data->m_currency_negative_format_idx;
4325
0
        size = d->m_data->m_currency_negative_format_size;
4326
0
        value = -value;
4327
0
    }
4328
0
    QString str = toString(value);
4329
0
    QString sym = symbol.isNull() ? currencySymbol() : symbol;
4330
0
    if (sym.isEmpty())
4331
0
        sym = currencySymbol(QLocale::CurrencyIsoCode);
4332
0
    QString format = getLocaleData(currency_format_data + idx, size);
4333
0
    return format.arg(str, sym);
4334
0
}
4335
4336
/*!
4337
    \since 4.8
4338
    \overload
4339
*/
4340
QString QLocale::toCurrencyString(qulonglong value, const QString &symbol) const
4341
0
{
4342
0
#ifndef QT_NO_SYSTEMLOCALE
4343
0
    if (d->m_data == systemData()) {
4344
0
        QSystemLocale::CurrencyToStringArgument arg(value, symbol);
4345
0
        QVariant res =
4346
0
            systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
4347
0
        if (!res.isNull())
4348
0
            return res.toString();
4349
0
    }
4350
0
#endif
4351
0
    const QLocaleData *data = this->d->m_data;
4352
0
    quint8 idx = data->m_currency_format_idx;
4353
0
    quint8 size = data->m_currency_format_size;
4354
0
    QString str = toString(value);
4355
0
    QString sym = symbol.isNull() ? currencySymbol() : symbol;
4356
0
    if (sym.isEmpty())
4357
0
        sym = currencySymbol(QLocale::CurrencyIsoCode);
4358
0
    QString format = getLocaleData(currency_format_data + idx, size);
4359
0
    return format.arg(str, sym);
4360
0
}
4361
4362
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
4363
/*!
4364
    \since 4.8
4365
    \overload
4366
*/
4367
QString QLocale::toCurrencyString(double value, const QString &symbol) const
4368
0
{
4369
0
    return toCurrencyString(value, symbol, d->m_data->m_currency_digits);
4370
0
}
4371
#endif
4372
4373
/*!
4374
    \since 5.7
4375
    \overload toCurrencyString()
4376
4377
    Returns a localized string representation of \a value as a currency.
4378
    If the \a symbol is provided it is used instead of the default currency symbol.
4379
    If the \a precision is provided it is used to set the precision of the currency value.
4380
4381
    \sa currencySymbol()
4382
 */
4383
QString QLocale::toCurrencyString(double value, const QString &symbol, int precision) const
4384
0
{
4385
0
#ifndef QT_NO_SYSTEMLOCALE
4386
0
    if (d->m_data == systemData()) {
4387
0
        QSystemLocale::CurrencyToStringArgument arg(value, symbol);
4388
0
        QVariant res =
4389
0
            systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
4390
0
        if (!res.isNull())
4391
0
            return res.toString();
4392
0
    }
4393
0
#endif
4394
0
    const QLocaleData *data = this->d->m_data;
4395
0
    quint8 idx = data->m_currency_format_idx;
4396
0
    quint8 size = data->m_currency_format_size;
4397
0
    if (data->m_currency_negative_format_size && value < 0) {
4398
0
        idx = data->m_currency_negative_format_idx;
4399
0
        size = data->m_currency_negative_format_size;
4400
0
        value = -value;
4401
0
    }
4402
0
    QString str = toString(value, 'f', precision == -1 ? d->m_data->m_currency_digits : precision);
4403
0
    QString sym = symbol.isNull() ? currencySymbol() : symbol;
4404
0
    if (sym.isEmpty())
4405
0
        sym = currencySymbol(QLocale::CurrencyIsoCode);
4406
0
    QString format = getLocaleData(currency_format_data + idx, size);
4407
0
    return format.arg(str, sym);
4408
0
}
4409
4410
/*!
4411
  \fn QString QLocale::toCurrencyString(float i, const QString &symbol) const
4412
  \fn QString QLocale::toCurrencyString(float i, const QString &symbol, int precision) const
4413
  \overload toCurrencyString()
4414
*/
4415
4416
/*!
4417
    \since 5.10
4418
4419
    \enum QLocale::DataSizeFormat
4420
4421
    Specifies the format for representation of data quantities.
4422
4423
    \omitvalue DataSizeBase1000
4424
    \omitvalue DataSizeSIQuantifiers
4425
    \value DataSizeIecFormat            format using base 1024 and IEC prefixes: KiB, MiB, GiB, ...
4426
    \value DataSizeTraditionalFormat    format using base 1024 and SI prefixes: kB, MB, GB, ...
4427
    \value DataSizeSIFormat             format using base 1000 and SI prefixes: kB, MB, GB, ...
4428
4429
    \sa formattedDataSize()
4430
*/
4431
4432
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4433
/*!
4434
    \obsolete
4435
4436
    Use the const version instead.
4437
*/
4438
QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format)
4439
0
{
4440
0
    const auto *that = this;
4441
0
    return that->formattedDataSize(bytes, precision, format);
4442
0
}
4443
#endif
4444
4445
/*!
4446
    \since 5.10
4447
4448
    Converts a size in bytes to a human-readable localized string, comprising a
4449
    number and a quantified unit. The quantifier is chosen such that the number
4450
    is at least one, and as small as possible. For example if \a bytes is
4451
    16384, \a precision is 2, and \a format is \l DataSizeIecFormat (the
4452
    default), this function returns "16.00 KiB"; for 1330409069609 bytes it
4453
    returns "1.21 GiB"; and so on. If \a format is \l DataSizeIecFormat or
4454
    \l DataSizeTraditionalFormat, the given number of bytes is divided by a
4455
    power of 1024, with result less than 1024; for \l DataSizeSIFormat, it is
4456
    divided by a power of 1000, with result less than 1000.
4457
    \c DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so on,
4458
    whereas \c DataSizeSIFormat uses the older SI quantifiers k, M, etc., and
4459
    \c DataSizeTraditionalFormat abuses them.
4460
*/
4461
QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) const
4462
0
{
4463
0
    int power, base = 1000;
4464
0
    if (!bytes) {
4465
0
        power = 0;
4466
0
    } else if (format & DataSizeBase1000) {
4467
0
        power = int(std::log10(qAbs(bytes)) / 3);
4468
0
    } else { // Compute log2(bytes) / 10:
4469
0
        power = int((63 - qCountLeadingZeroBits(quint64(qAbs(bytes)))) / 10);
4470
0
        base = 1024;
4471
0
    }
4472
    // Only go to doubles if we'll be using a quantifier:
4473
0
    const QString number = power
4474
0
        ? toString(bytes / std::pow(double(base), power), 'f', qMin(precision, 3 * power))
4475
0
        : toString(bytes);
4476
4477
    // We don't support sizes in units larger than exbibytes because
4478
    // the number of bytes would not fit into qint64.
4479
0
    Q_ASSERT(power <= 6 && power >= 0);
4480
0
    QString unit;
4481
0
    if (power > 0) {
4482
0
        quint16 index, size;
4483
0
        if (format & DataSizeSIQuantifiers) {
4484
0
            index = d->m_data->m_byte_si_quantified_idx;
4485
0
            size = d->m_data->m_byte_si_quantified_size;
4486
0
        } else {
4487
0
            index = d->m_data->m_byte_iec_quantified_idx;
4488
0
            size = d->m_data->m_byte_iec_quantified_size;
4489
0
        }
4490
0
        unit = getLocaleListData(byte_unit_data + index, size, power - 1);
4491
0
    } else {
4492
0
        unit = getLocaleData(byte_unit_data + d->m_data->m_byte_idx, d->m_data->m_byte_size);
4493
0
    }
4494
4495
0
    return number + QLatin1Char(' ') + unit;
4496
0
}
4497
4498
/*!
4499
    \since 4.8
4500
4501
    Returns an ordered list of locale names for translation purposes in
4502
    preference order (like "en-Latn-US", "en-US", "en").
4503
4504
    The return value represents locale names that the user expects to see the
4505
    UI translation in.
4506
4507
    Most like you do not need to use this function directly, but just pass the
4508
    QLocale object to the QTranslator::load() function.
4509
4510
    The first item in the list is the most preferred one.
4511
4512
    \sa QTranslator, bcp47Name()
4513
*/
4514
QStringList QLocale::uiLanguages() const
4515
0
{
4516
0
    QStringList uiLanguages;
4517
0
    QVector<QLocale> locales;
4518
0
#ifndef QT_NO_SYSTEMLOCALE
4519
0
    if (d->m_data == systemData()) {
4520
0
        QVariant res = systemLocale()->query(QSystemLocale::UILanguages, QVariant());
4521
0
        if (!res.isNull()) {
4522
0
            uiLanguages = res.toStringList();
4523
            // ... but we need to include likely-adjusted forms of each of those, too:
4524
0
            for (const auto &entry : qAsConst(uiLanguages))
4525
0
                locales.append(QLocale(entry));
4526
0
        }
4527
0
        if (locales.isEmpty())
4528
0
            locales.append(systemLocale()->fallbackUiLocale());
4529
        // If the system locale (isn't C and) didn't include itself in the list,
4530
        // or as fallback, presume to know better than it and put its name
4531
        // first. (Known issue, QTBUG-104930, on some macOS versions when in
4532
        // locale en_DE.) Our translation system might have a translation for a
4533
        // locale the platform doesn't believe in.
4534
0
        const QString name = bcp47Name();
4535
0
        if (!name.isEmpty() && language() != C && !uiLanguages.contains(name)) {
4536
            // That uses contains(name) as a cheap pre-test, but there may be an
4537
            // entry that matches this on purging likely subtags.
4538
0
            QLocaleId mine =
4539
0
                { d->m_data->m_language_id, d->m_data->m_script_id, d->m_data->m_country_id };
4540
0
            mine = mine.withLikelySubtagsRemoved();
4541
0
            const auto isMine = [mine](const QString &entry) {
4542
0
                QLocale::Language lang;
4543
0
                QLocale::Script script;
4544
0
                QLocale::Country cntry;
4545
0
                QLocalePrivate::getLangAndCountry(entry, lang, script, cntry);
4546
0
                QLocaleId id = { ushort(lang), ushort(script), ushort(cntry) };
4547
0
                return id.withLikelySubtagsRemoved() == mine;
4548
0
            };
4549
0
            if (std::none_of(uiLanguages.constBegin(), uiLanguages.constEnd(), isMine)) {
4550
0
                locales.prepend(*this);
4551
0
                uiLanguages.prepend(name);
4552
0
            }
4553
0
        }
4554
0
    } else
4555
0
#endif
4556
0
    {
4557
0
        locales.append(*this);
4558
0
    }
4559
0
    for (int i = locales.size(); i-- > 0; ) {
4560
0
        const QLocale &locale = locales.at(i);
4561
0
        int j;
4562
0
        QByteArray prior;
4563
0
        if (i < uiLanguages.size()) {
4564
            // Adding likely-adjusted forms to system locale's list.
4565
            // Name the locale is derived from:
4566
0
            prior = uiLanguages.at(i).toLatin1();
4567
            // Insert just after the entry we're supplementing:
4568
0
            j = i + 1;
4569
0
        } else {
4570
            // Plain locale, not system locale; just append.
4571
0
            j = uiLanguages.size();
4572
0
        }
4573
0
        const auto data = locale.d->m_data;
4574
4575
0
        QLocaleId id
4576
0
            = QLocaleId::fromIds(data->m_language_id, data->m_script_id, data->m_country_id);
4577
0
        const QLocaleId max = id.withLikelySubtagsAdded();
4578
0
        const QLocaleId min = max.withLikelySubtagsRemoved();
4579
0
        id.script_id = 0; // For re-use as script-less variant.
4580
4581
        // Include version with all likely sub-tags (last) if distinct from the rest:
4582
0
        if (max != min && max != id && max.name() != prior)
4583
0
            uiLanguages.insert(j, QString::fromLatin1(max.name()));
4584
4585
        // Include scriptless version if likely-equivalent and distinct:
4586
0
        if (data->m_script_id && id != min && id.name() != prior
4587
0
            && id.withLikelySubtagsAdded() == max) {
4588
0
            uiLanguages.insert(j, QString::fromLatin1(id.name()));
4589
0
        }
4590
4591
        // Include minimal version (first) unless it's what our locale is derived from:
4592
0
        if (min.name() != prior)
4593
0
            uiLanguages.insert(j, QString::fromLatin1(min.name()));
4594
0
    }
4595
0
    return uiLanguages;
4596
0
}
4597
4598
/*!
4599
  \since 5.13
4600
4601
  Returns the locale to use for collation.
4602
4603
  The result is usually this locale; however, the system locale (which is
4604
  commonly the default locale) will return the system collation locale.
4605
  The result is suitable for passing to QCollator's constructor.
4606
4607
  \sa QCollator
4608
*/
4609
QLocale QLocale::collation() const
4610
0
{
4611
0
#ifndef QT_NO_SYSTEMLOCALE
4612
0
    if (d->m_data == systemData()) {
4613
0
        QString res = systemLocale()->query(QSystemLocale::Collation, QVariant()).toString();
4614
0
        if (!res.isEmpty())
4615
0
            return QLocale(res);
4616
0
    }
4617
0
#endif
4618
0
    return *this;
4619
0
}
4620
4621
/*!
4622
    \since 4.8
4623
4624
    Returns a native name of the language for the locale. For example
4625
    "Schwiizertüütsch" for Swiss-German locale.
4626
4627
    \sa nativeCountryName(), languageToString()
4628
*/
4629
QString QLocale::nativeLanguageName() const
4630
0
{
4631
0
#ifndef QT_NO_SYSTEMLOCALE
4632
0
    if (d->m_data == systemData()) {
4633
0
        QVariant res = systemLocale()->query(QSystemLocale::NativeLanguageName, QVariant());
4634
0
        if (!res.isNull())
4635
0
            return res.toString();
4636
0
    }
4637
0
#endif
4638
0
    return getLocaleData(endonyms_data + d->m_data->m_language_endonym_idx,
4639
0
                         d->m_data->m_language_endonym_size);
4640
0
}
4641
4642
/*!
4643
    \since 4.8
4644
4645
    Returns a native name of the country for the locale. For example
4646
    "España" for Spanish/Spain locale.
4647
4648
    \sa nativeLanguageName(), countryToString()
4649
*/
4650
QString QLocale::nativeCountryName() const
4651
0
{
4652
0
#ifndef QT_NO_SYSTEMLOCALE
4653
0
    if (d->m_data == systemData()) {
4654
0
        QVariant res = systemLocale()->query(QSystemLocale::NativeCountryName, QVariant());
4655
0
        if (!res.isNull())
4656
0
            return res.toString();
4657
0
    }
4658
0
#endif
4659
0
    return getLocaleData(endonyms_data + d->m_data->m_country_endonym_idx,
4660
0
                         d->m_data->m_country_endonym_size);
4661
0
}
4662
4663
#ifndef QT_NO_DEBUG_STREAM
4664
QDebug operator<<(QDebug dbg, const QLocale &l)
4665
0
{
4666
0
    QDebugStateSaver saver(dbg);
4667
0
    dbg.nospace().noquote()
4668
0
        << "QLocale(" << QLocale::languageToString(l.language())
4669
0
        << ", " << QLocale::scriptToString(l.script())
4670
0
        << ", " << QLocale::countryToString(l.country()) << ')';
4671
0
    return dbg;
4672
0
}
4673
#endif
4674
QT_END_NAMESPACE
4675
4676
#ifndef QT_NO_QOBJECT
4677
#include "moc_qlocale.cpp"
4678
#endif