1/****************************************************************************
2**
3** Copyright (C) 2019 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
75QT_BEGIN_NAMESPACE
76
77#ifndef QT_NO_SYSTEMLOCALE
78static QSystemLocale *_systemLocale = 0;
79class QSystemLocaleSingleton: public QSystemLocale
80{
81public:
82 QSystemLocaleSingleton() : QSystemLocale(true) {}
83};
84
85Q_GLOBAL_STATIC(QSystemLocaleSingleton, QSystemLocale_globalSystemLocale)
86static QLocaleData globalLocaleData;
87#endif
88
89/******************************************************************************
90** Helpers for accessing Qt locale database
91*/
92
93QT_BEGIN_INCLUDE_NAMESPACE
94#include "qlocale_data_p.h"
95QT_END_INCLUDE_NAMESPACE
96
97QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) noexcept
98{
99 const auto len = code.size();
100 if (len != 2 && len != 3)
101 return QLocale::C;
102 ushort uc1 = code[0].toLower().unicode();
103 ushort uc2 = code[1].toLower().unicode();
104 ushort uc3 = len > 2 ? code[2].toLower().unicode() : 0;
105
106 const unsigned char *c = language_code_list;
107 for (; *c != 0; c += 3) {
108 if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
109 return QLocale::Language((c - language_code_list)/3);
110 }
111
112 if (uc3 == 0) {
113 // legacy codes
114 if (uc1 == 'n' && uc2 == 'o') { // no -> nb
115 Q_STATIC_ASSERT(QLocale::Norwegian == QLocale::NorwegianBokmal);
116 return QLocale::Norwegian;
117 }
118 if (uc1 == 't' && uc2 == 'l') { // tl -> fil
119 Q_STATIC_ASSERT(QLocale::Tagalog == QLocale::Filipino);
120 return QLocale::Tagalog;
121 }
122 if (uc1 == 's' && uc2 == 'h') { // sh -> sr[_Latn]
123 Q_STATIC_ASSERT(QLocale::SerboCroatian == QLocale::Serbian);
124 return QLocale::SerboCroatian;
125 }
126 if (uc1 == 'm' && uc2 == 'o') { // mo -> ro
127 Q_STATIC_ASSERT(QLocale::Moldavian == QLocale::Romanian);
128 return QLocale::Moldavian;
129 }
130 // Android uses the following deprecated codes
131 if (uc1 == 'i' && uc2 == 'w') // iw -> he
132 return QLocale::Hebrew;
133 if (uc1 == 'i' && uc2 == 'n') // in -> id
134 return QLocale::Indonesian;
135 if (uc1 == 'j' && uc2 == 'i') // ji -> yi
136 return QLocale::Yiddish;
137 }
138 return QLocale::C;
139}
140
141QLocale::Script QLocalePrivate::codeToScript(QStringView code) noexcept
142{
143 const auto len = code.size();
144 if (len != 4)
145 return QLocale::AnyScript;
146
147 // script is titlecased in our data
148 unsigned char c0 = code[0].toUpper().toLatin1();
149 unsigned char c1 = code[1].toLower().toLatin1();
150 unsigned char c2 = code[2].toLower().toLatin1();
151 unsigned char c3 = code[3].toLower().toLatin1();
152
153 const unsigned char *c = script_code_list;
154 for (int i = 0; i < QLocale::LastScript; ++i, c += 4) {
155 if (c0 == c[0] && c1 == c[1] && c2 == c[2] && c3 == c[3])
156 return QLocale::Script(i);
157 }
158 return QLocale::AnyScript;
159}
160
161QLocale::Country QLocalePrivate::codeToCountry(QStringView code) noexcept
162{
163 const auto len = code.size();
164 if (len != 2 && len != 3)
165 return QLocale::AnyCountry;
166
167 ushort uc1 = code[0].toUpper().unicode();
168 ushort uc2 = code[1].toUpper().unicode();
169 ushort uc3 = len > 2 ? code[2].toUpper().unicode() : 0;
170
171 const unsigned char *c = country_code_list;
172 for (; *c != 0; c += 3) {
173 if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
174 return QLocale::Country((c - country_code_list)/3);
175 }
176
177 return QLocale::AnyCountry;
178}
179
180QLatin1String QLocalePrivate::languageToCode(QLocale::Language language)
181{
182 if (language == QLocale::AnyLanguage)
183 return QLatin1String();
184 if (language == QLocale::C)
185 return QLatin1String("C");
186
187 const unsigned char *c = language_code_list + 3*(uint(language));
188
189 return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
190
191}
192
193QLatin1String QLocalePrivate::scriptToCode(QLocale::Script script)
194{
195 if (script == QLocale::AnyScript || script > QLocale::LastScript)
196 return QLatin1String();
197 const unsigned char *c = script_code_list + 4*(uint(script));
198 return QLatin1String(reinterpret_cast<const char *>(c), 4);
199}
200
201QLatin1String QLocalePrivate::countryToCode(QLocale::Country country)
202{
203 if (country == QLocale::AnyCountry)
204 return QLatin1String();
205
206 const unsigned char *c = country_code_list + 3*(uint(country));
207
208 return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
209}
210
211// http://www.unicode.org/reports/tr35/#Likely_Subtags
212static bool addLikelySubtags(QLocaleId &localeId)
213{
214 // ### optimize with bsearch
215 const int likely_subtags_count = sizeof(likely_subtags) / sizeof(likely_subtags[0]);
216 const QLocaleId *p = likely_subtags;
217 const QLocaleId *const e = p + likely_subtags_count;
218 for ( ; p < e; p += 2) {
219 if (localeId == p[0]) {
220 localeId = p[1];
221 return true;
222 }
223 }
224 return false;
225}
226
227QLocaleId QLocaleId::withLikelySubtagsAdded() const
228{
229 // language_script_region
230 if (language_id || script_id || country_id) {
231 QLocaleId id = QLocaleId::fromIds(language_id, script_id, country_id);
232 if (addLikelySubtags(id))
233 return id;
234 }
235 // language_region
236 if (script_id) {
237 QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id);
238 if (addLikelySubtags(id)) {
239 id.script_id = script_id;
240 return id;
241 }
242 }
243 // language_script
244 if (country_id) {
245 QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0);
246 if (addLikelySubtags(id)) {
247 id.country_id = country_id;
248 return id;
249 }
250 }
251 // language
252 if (script_id && country_id) {
253 QLocaleId id = QLocaleId::fromIds(language_id, 0, 0);
254 if (addLikelySubtags(id)) {
255 id.script_id = script_id;
256 id.country_id = country_id;
257 return id;
258 }
259 }
260 // und_script
261 if (language_id) {
262 QLocaleId id = QLocaleId::fromIds(0, script_id, 0);
263 if (addLikelySubtags(id)) {
264 id.language_id = language_id;
265 return id;
266 }
267 }
268 return *this;
269}
270
271QLocaleId QLocaleId::withLikelySubtagsRemoved() const
272{
273 QLocaleId max = withLikelySubtagsAdded();
274 // language
275 {
276 QLocaleId id = QLocaleId::fromIds(language_id, 0, 0);
277 if (id.withLikelySubtagsAdded() == max)
278 return id;
279 }
280 // language_region
281 if (country_id) {
282 QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id);
283 if (id.withLikelySubtagsAdded() == max)
284 return id;
285 }
286 // language_script
287 if (script_id) {
288 QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0);
289 if (id.withLikelySubtagsAdded() == max)
290 return id;
291 }
292 return max;
293}
294
295QByteArray QLocaleId::name(char separator) const
296{
297 if (language_id == QLocale::AnyLanguage)
298 return QByteArray();
299 if (language_id == QLocale::C)
300 return QByteArrayLiteral("C");
301
302 const unsigned char *lang = language_code_list + 3 * language_id;
303 const unsigned char *script =
304 (script_id != QLocale::AnyScript ? script_code_list + 4 * script_id : nullptr);
305 const unsigned char *country =
306 (country_id != QLocale::AnyCountry ? country_code_list + 3 * country_id : nullptr);
307 char len = (lang[2] != 0 ? 3 : 2) + (script ? 4 + 1 : 0)
308 + (country ? (country[2] != 0 ? 3 : 2) + 1 : 0);
309 QByteArray name(len, Qt::Uninitialized);
310 char *uc = name.data();
311 *uc++ = lang[0];
312 *uc++ = lang[1];
313 if (lang[2] != 0)
314 *uc++ = lang[2];
315 if (script) {
316 *uc++ = separator;
317 *uc++ = script[0];
318 *uc++ = script[1];
319 *uc++ = script[2];
320 *uc++ = script[3];
321 }
322 if (country) {
323 *uc++ = separator;
324 *uc++ = country[0];
325 *uc++ = country[1];
326 if (country[2] != 0)
327 *uc++ = country[2];
328 }
329 return name;
330}
331
332QByteArray QLocalePrivate::bcp47Name(char separator) const
333{
334 if (m_data->m_language_id == QLocale::AnyLanguage)
335 return QByteArray();
336 if (m_data->m_language_id == QLocale::C)
337 return QByteArrayLiteral("en");
338
339 QLocaleId localeId = QLocaleId::fromIds(m_data->m_language_id, m_data->m_script_id,
340 m_data->m_country_id);
341 return localeId.withLikelySubtagsRemoved().name(separator);
342}
343
344static const QLocaleData *findLocaleDataById(const QLocaleId &localeId)
345{
346 const uint idx = locale_index[localeId.language_id];
347
348 const QLocaleData *data = locale_data + idx;
349
350 if (idx == 0) // default language has no associated script or country
351 return data;
352
353 Q_ASSERT(data->m_language_id == localeId.language_id);
354
355 if (localeId.script_id == QLocale::AnyScript && localeId.country_id == QLocale::AnyCountry)
356 return data;
357
358 if (localeId.script_id == QLocale::AnyScript) {
359 do {
360 if (data->m_country_id == localeId.country_id)
361 return data;
362 ++data;
363 } while (data->m_language_id && data->m_language_id == localeId.language_id);
364 } else if (localeId.country_id == QLocale::AnyCountry) {
365 do {
366 if (data->m_script_id == localeId.script_id)
367 return data;
368 ++data;
369 } while (data->m_language_id && data->m_language_id == localeId.language_id);
370 } else {
371 do {
372 if (data->m_script_id == localeId.script_id
373 && data->m_country_id == localeId.country_id) {
374 return data;
375 }
376 ++data;
377 } while (data->m_language_id && data->m_language_id == localeId.language_id);
378 }
379
380 return nullptr;
381}
382
383const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script,
384 QLocale::Country country)
385{
386 QLocaleId localeId = QLocaleId::fromIds(language, script, country);
387 QLocaleId likelyId = localeId.withLikelySubtagsAdded();
388
389 const uint idx = locale_index[likelyId.language_id];
390
391 // Try a straight match with the likely data:
392 if (const QLocaleData *const data = findLocaleDataById(likelyId))
393 return data;
394 QList<QLocaleId> tried;
395 tried.push_back(likelyId);
396
397 // No match; try again with raw data:
398 if (!tried.contains(localeId)) {
399 if (const QLocaleData *const data = findLocaleDataById(localeId))
400 return data;
401 tried.push_back(localeId);
402 }
403
404 // No match; try again with likely country
405 if (country != QLocale::AnyCountry
406 && (language != QLocale::AnyLanguage || script != QLocale::AnyScript)) {
407 localeId = QLocaleId::fromIds(language, script, QLocale::AnyCountry);
408 likelyId = localeId.withLikelySubtagsAdded();
409 if (!tried.contains(likelyId)) {
410 if (const QLocaleData *const data = findLocaleDataById(likelyId))
411 return data;
412 tried.push_back(likelyId);
413 }
414
415 // No match; try again with any country
416 if (!tried.contains(localeId)) {
417 if (const QLocaleData *const data = findLocaleDataById(localeId))
418 return data;
419 tried.push_back(localeId);
420 }
421 }
422
423 // No match; try again with likely script
424 if (script != QLocale::AnyScript
425 && (language != QLocale::AnyLanguage || country != QLocale::AnyCountry)) {
426 localeId = QLocaleId::fromIds(language, QLocale::AnyScript, country);
427 likelyId = localeId.withLikelySubtagsAdded();
428 if (!tried.contains(likelyId)) {
429 if (const QLocaleData *const data = findLocaleDataById(likelyId))
430 return data;
431 tried.push_back(likelyId);
432 }
433
434 // No match; try again with any script
435 if (!tried.contains(localeId)) {
436 if (const QLocaleData *const data = findLocaleDataById(localeId))
437 return data;
438 tried.push_back(localeId);
439 }
440 }
441
442 // No match; return data at original index
443 return locale_data + idx;
444}
445
446static bool parse_locale_tag(const QString &input, int &i, QString *result,
447 const QString &separators)
448{
449 *result = QString(8, Qt::Uninitialized); // worst case according to BCP47
450 QChar *pch = result->data();
451 const QChar *uc = input.data() + i;
452 const int l = input.length();
453 int size = 0;
454 for (; i < l && size < 8; ++i, ++size) {
455 if (separators.contains(*uc))
456 break;
457 if (! ((uc->unicode() >= 'a' && uc->unicode() <= 'z') ||
458 (uc->unicode() >= 'A' && uc->unicode() <= 'Z') ||
459 (uc->unicode() >= '0' && uc->unicode() <= '9')) ) // latin only
460 return false;
461 *pch++ = *uc++;
462 }
463 result->truncate(size);
464 return true;
465}
466
467bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry)
468{
469 const int length = name.length();
470
471 lang = script = cntry = QString();
472
473 const QString separators = QStringLiteral("_-.@");
474 enum ParserState { NoState, LangState, ScriptState, CountryState };
475 ParserState state = LangState;
476 for (int i = 0; i < length && state != NoState; ) {
477 QString value;
478 if (!parse_locale_tag(name, i, &value, separators) ||value.isEmpty())
479 break;
480 QChar sep = i < length ? name.at(i) : QChar();
481 switch (state) {
482 case LangState:
483 if (!sep.isNull() && !separators.contains(sep)) {
484 state = NoState;
485 break;
486 }
487 lang = value;
488 if (i == length) {
489 // just language was specified
490 state = NoState;
491 break;
492 }
493 state = ScriptState;
494 break;
495 case ScriptState: {
496 QString scripts = QString::fromLatin1((const char *)script_code_list,
497 sizeof(script_code_list) - 1);
498 if (value.length() == 4 && scripts.indexOf(value) % 4 == 0) {
499 // script name is always 4 characters
500 script = value;
501 state = CountryState;
502 } else {
503 // it wasn't a script, maybe it is a country then?
504 cntry = value;
505 state = NoState;
506 }
507 break;
508 }
509 case CountryState:
510 cntry = value;
511 state = NoState;
512 break;
513 case NoState:
514 // shouldn't happen
515 qWarning("QLocale: This should never happen");
516 break;
517 }
518 ++i;
519 }
520 return lang.length() == 2 || lang.length() == 3;
521}
522
523void QLocalePrivate::getLangAndCountry(const QString &name, QLocale::Language &lang,
524 QLocale::Script &script, QLocale::Country &cntry)
525{
526 lang = QLocale::C;
527 script = QLocale::AnyScript;
528 cntry = QLocale::AnyCountry;
529
530 QString lang_code;
531 QString script_code;
532 QString cntry_code;
533 if (!qt_splitLocaleName(name, lang_code, script_code, cntry_code))
534 return;
535
536 lang = QLocalePrivate::codeToLanguage(lang_code);
537 if (lang == QLocale::C)
538 return;
539 script = QLocalePrivate::codeToScript(script_code);
540 cntry = QLocalePrivate::codeToCountry(cntry_code);
541}
542
543static const QLocaleData *findLocaleData(const QString &name)
544{
545 QLocale::Language lang;
546 QLocale::Script script;
547 QLocale::Country cntry;
548 QLocalePrivate::getLangAndCountry(name, lang, script, cntry);
549
550 return QLocaleData::findLocaleData(lang, script, cntry);
551}
552
553QString qt_readEscapedFormatString(QStringView format, int *idx)
554{
555 int &i = *idx;
556
557 Q_ASSERT(format.at(i) == QLatin1Char('\''));
558 ++i;
559 if (i == format.size())
560 return QString();
561 if (format.at(i).unicode() == '\'') { // "''" outside of a quoted stirng
562 ++i;
563 return QLatin1String("'");
564 }
565
566 QString result;
567
568 while (i < format.size()) {
569 if (format.at(i).unicode() == '\'') {
570 if (format.mid(i + 1).startsWith(QLatin1Char('\''))) {
571 // "''" inside a quoted string
572 result.append(QLatin1Char('\''));
573 i += 2;
574 } else {
575 break;
576 }
577 } else {
578 result.append(format.at(i++));
579 }
580 }
581 if (i < format.size())
582 ++i;
583
584 return result;
585}
586
587/*!
588 \internal
589
590 Counts the number of identical leading characters in \a s.
591
592 If \a s is empty, returns 0.
593
594 Otherwise, returns the number of consecutive \c{s.front()}
595 characters at the start of \a s.
596
597 \code
598 qt_repeatCount(u"a"); // == 1
599 qt_repeatCount(u"ab"); // == 1
600 qt_repeatCount(u"aab"); // == 2
601 \endcode
602*/
603int qt_repeatCount(QStringView s)
604{
605 if (s.isEmpty())
606 return 0;
607 const QChar c = s.front();
608 qsizetype j = 1;
609 while (j < s.size() && s.at(j) == c)
610 ++j;
611 return int(j);
612}
613
614static const QLocaleData *default_data = nullptr;
615static QLocale::NumberOptions default_number_options = QLocale::DefaultNumberOptions;
616
617static const QLocaleData *const c_data = locale_data;
618static QLocalePrivate *c_private()
619{
620 static QLocalePrivate c_locale =
621 { c_data, Q_BASIC_ATOMIC_INITIALIZER(1), QLocale::OmitGroupSeparator };
622 return &c_locale;
623}
624
625#ifndef QT_NO_SYSTEMLOCALE
626/******************************************************************************
627** Default system locale behavior
628*/
629
630/*!
631 Constructs a QSystemLocale object.
632
633 The constructor will automatically install this object as the system locale,
634 if there's not one active. It also resets the flag that'll prompt
635 QLocale::system() to re-initialize its data, so that instantiating a
636 QSystemLocale transiently (doesn't install the transient as system locale if
637 there was one already and) triggers an update to the system locale's data.
638*/
639QSystemLocale::QSystemLocale()
640{
641 if (!_systemLocale)
642 _systemLocale = this;
643
644 globalLocaleData.m_language_id = 0;
645}
646
647/*!
648 \internal
649*/
650QSystemLocale::QSystemLocale(bool)
651{ }
652
653/*!
654 Deletes the object.
655*/
656QSystemLocale::~QSystemLocale()
657{
658 if (_systemLocale == this) {
659 _systemLocale = 0;
660
661 globalLocaleData.m_language_id = 0;
662 }
663}
664
665static const QSystemLocale *systemLocale()
666{
667 if (_systemLocale)
668 return _systemLocale;
669 return QSystemLocale_globalSystemLocale();
670}
671
672static void updateSystemPrivate()
673{
674 // This function is NOT thread-safe!
675 // It *should not* be called by anything but systemData()
676 const QSystemLocale *sys_locale = systemLocale();
677
678 // tell the object that the system locale has changed.
679 sys_locale->query(QSystemLocale::LocaleChanged, QVariant());
680
681 // Populate global with fallback as basis:
682 globalLocaleData = *sys_locale->fallbackUiLocaleData();
683
684 QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
685 if (!res.isNull()) {
686 globalLocaleData.m_language_id = res.toInt();
687 globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
688 }
689 res = sys_locale->query(QSystemLocale::CountryId, QVariant());
690 if (!res.isNull()) {
691 globalLocaleData.m_country_id = res.toInt();
692 globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
693 }
694 res = sys_locale->query(QSystemLocale::ScriptId, QVariant());
695 if (!res.isNull())
696 globalLocaleData.m_script_id = res.toInt();
697
698 res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant());
699 if (!res.isNull())
700 globalLocaleData.m_decimal = res.toString().at(0).unicode();
701
702 res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant());
703 if (!res.isNull())
704 globalLocaleData.m_group = res.toString().at(0).unicode();
705
706 res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant());
707 if (!res.isNull())
708 globalLocaleData.m_zero = res.toString().at(0).unicode();
709
710 res = sys_locale->query(QSystemLocale::NegativeSign, QVariant());
711 if (!res.isNull())
712 globalLocaleData.m_minus = res.toString().at(0).unicode();
713
714 res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
715 if (!res.isNull())
716 globalLocaleData.m_plus = res.toString().at(0).unicode();
717}
718#endif // !QT_NO_SYSTEMLOCALE
719
720static const QLocaleData *systemData()
721{
722#ifndef QT_NO_SYSTEMLOCALE
723 /*
724 Copy over the information from the fallback locale and modify.
725
726 This modifies (cross-thread) global state, so take care to only call it in
727 one thread.
728 */
729 {
730 static QBasicMutex systemDataMutex;
731 systemDataMutex.lock();
732 if (globalLocaleData.m_language_id == 0)
733 updateSystemPrivate();
734 systemDataMutex.unlock();
735 }
736
737 return &globalLocaleData;
738#else
739 return locale_data;
740#endif
741}
742
743static const QLocaleData *defaultData()
744{
745 if (!default_data)
746 default_data = systemData();
747 return default_data;
748}
749
750const QLocaleData *QLocaleData::c()
751{
752 Q_ASSERT(locale_index[QLocale::C] == 0);
753 return c_data;
754}
755
756static inline QString getLocaleData(const ushort *data, int size)
757{
758 return size > 0 ? QString::fromRawData(reinterpret_cast<const QChar *>(data), size) : QString();
759}
760
761static QString getLocaleListData(const ushort *data, int size, int index)
762{
763 static const ushort separator = ';';
764 while (index && size > 0) {
765 while (*data != separator)
766 ++data, --size;
767 --index;
768 ++data;
769 --size;
770 }
771 const ushort *end = data;
772 while (size > 0 && *end != separator)
773 ++end, --size;
774 return getLocaleData(data, end - data);
775}
776
777
778#ifndef QT_NO_DATASTREAM
779QDataStream &operator<<(QDataStream &ds, const QLocale &l)
780{
781 ds << l.name();
782 return ds;
783}
784
785QDataStream &operator>>(QDataStream &ds, QLocale &l)
786{
787 QString s;
788 ds >> s;
789 l = QLocale(s);
790 return ds;
791}
792#endif // QT_NO_DATASTREAM
793
794
795static const int locale_data_size = sizeof(locale_data)/sizeof(QLocaleData) - 1;
796
797Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate,
798 (QLocalePrivate::create(defaultData(), default_number_options)))
799Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<QLocalePrivate>, systemLocalePrivate,
800 (QLocalePrivate::create(systemData())))
801
802static QLocalePrivate *localePrivateByName(const QString &name)
803{
804 if (name == QLatin1String("C"))
805 return c_private();
806 const QLocaleData *data = findLocaleData(name);
807 return QLocalePrivate::create(data, data->m_language_id == QLocale::C ?
808 QLocale::OmitGroupSeparator : QLocale::DefaultNumberOptions);
809}
810
811static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Script script,
812 QLocale::Country country)
813{
814 if (language == QLocale::C)
815 return c_private();
816
817 const QLocaleData *data = QLocaleData::findLocaleData(language, script, country);
818
819 QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions;
820
821 // If not found, should default to system
822 if (data->m_language_id == QLocale::C && language != QLocale::C) {
823 numberOptions = default_number_options;
824 data = defaultData();
825 }
826 return QLocalePrivate::create(data, numberOptions);
827}
828
829
830/*!
831 \internal
832*/
833QLocale::QLocale(QLocalePrivate &dd)
834 : d(&dd)
835{}
836
837
838/*!
839 Constructs a QLocale object with the specified \a name,
840 which has the format
841 "language[_script][_country][.codeset][@modifier]" or "C", where:
842
843 \list
844 \li language is a lowercase, two-letter, ISO 639 language code (also some
845 three-letter codes),
846 \li script is a titlecase, four-letter, ISO 15924 script code,
847 \li country is an uppercase, two-letter, ISO 3166 country code
848 (also "419" as defined by United Nations),
849 \li and codeset and modifier are ignored.
850 \endlist
851
852 The separator can be either underscore or a minus sign.
853
854 If the string violates the locale format, or language is not
855 a valid ISO 639 code, the "C" locale is used instead. If country
856 is not present, or is not a valid ISO 3166 code, the most
857 appropriate country is chosen for the specified language.
858
859 The language, script and country codes are converted to their respective
860 \c Language, \c Script and \c Country enums. After this conversion is
861 performed, the constructor behaves exactly like QLocale(Country, Script,
862 Language).
863
864 This constructor is much slower than QLocale(Country, Script, Language).
865
866 \sa bcp47Name()
867*/
868
869QLocale::QLocale(const QString &name)
870 : d(localePrivateByName(name))
871{
872}
873
874/*!
875 Constructs a QLocale object initialized with the default locale. If
876 no default locale was set using setDefault(), this locale will
877 be the same as the one returned by system().
878
879 \sa setDefault()
880*/
881
882QLocale::QLocale()
883 : d(*defaultLocalePrivate)
884{
885 // Make sure system data is up to date
886 systemData();
887}
888
889/*!
890 Constructs a QLocale object with the specified \a language and \a
891 country.
892
893 \list
894 \li If the language/country pair is found in the database, it is used.
895 \li If the language is found but the country is not, or if the country
896 is \c AnyCountry, the language is used with the most
897 appropriate available country (for example, Germany for German),
898 \li If neither the language nor the country are found, QLocale
899 defaults to the default locale (see setDefault()).
900 \endlist
901
902 The language and country that are actually used can be queried
903 using language() and country().
904
905 \sa setDefault(), language(), country()
906*/
907
908QLocale::QLocale(Language language, Country country)
909 : d(findLocalePrivate(language, QLocale::AnyScript, country))
910{
911}
912
913/*!
914 \since 4.8
915
916 Constructs a QLocale object with the specified \a language, \a script and
917 \a country.
918
919 \list
920 \li If the language/script/country is found in the database, it is used.
921 \li If both \a script is AnyScript and \a country is AnyCountry, the
922 language is used with the most appropriate available script and country
923 (for example, Germany for German),
924 \li If either \a script is AnyScript or \a country is AnyCountry, the
925 language is used with the first locale that matches the given \a script
926 and \a country.
927 \li If neither the language nor the country are found, QLocale
928 defaults to the default locale (see setDefault()).
929 \endlist
930
931 The language, script and country that are actually used can be queried
932 using language(), script() and country().
933
934 \sa setDefault(), language(), script(), country()
935*/
936
937QLocale::QLocale(Language language, Script script, Country country)
938 : d(findLocalePrivate(language, script, country))
939{
940}
941
942/*!
943 Constructs a QLocale object as a copy of \a other.
944*/
945
946QLocale::QLocale(const QLocale &other)
947{
948 d = other.d;
949}
950
951/*!
952 Destructor
953*/
954
955QLocale::~QLocale()
956{
957}
958
959/*!
960 Assigns \a other to this QLocale object and returns a reference
961 to this QLocale object.
962*/
963
964QLocale &QLocale::operator=(const QLocale &other)
965{
966 d = other.d;
967 return *this;
968}
969
970bool QLocale::operator==(const QLocale &other) const
971{
972 return d->m_data == other.d->m_data && d->m_numberOptions == other.d->m_numberOptions;
973}
974
975bool QLocale::operator!=(const QLocale &other) const
976{
977 return d->m_data != other.d->m_data || d->m_numberOptions != other.d->m_numberOptions;
978}
979
980/*!
981 \fn void QLocale::swap(QLocale &other)
982 \since 5.6
983
984 Swaps locale \a other with this locale. This operation is very fast and
985 never fails.
986*/
987
988/*!
989 \since 5.6
990 \relates QLocale
991
992 Returns the hash value for \a key, using
993 \a seed to seed the calculation.
994*/
995uint qHash(const QLocale &key, uint seed) noexcept
996{
997 QtPrivate::QHashCombine hash;
998 seed = hash(seed, key.d->m_data);
999 seed = hash(seed, key.d->m_numberOptions);
1000 return seed;
1001}
1002
1003/*!
1004 \since 4.2
1005
1006 Sets the \a options related to number conversions for this
1007 QLocale instance.
1008*/
1009void QLocale::setNumberOptions(NumberOptions options)
1010{
1011 d->m_numberOptions = options;
1012}
1013
1014/*!
1015 \since 4.2
1016
1017 Returns the options related to number conversions for this
1018 QLocale instance.
1019
1020 By default, no options are set for the standard locales.
1021*/
1022QLocale::NumberOptions QLocale::numberOptions() const
1023{
1024 return static_cast<NumberOptions>(d->m_numberOptions);
1025}
1026
1027/*!
1028 \since 4.8
1029
1030 Returns \a str quoted according to the current locale using the given
1031 quotation \a style.
1032*/
1033QString QLocale::quoteString(const QString &str, QuotationStyle style) const
1034{
1035 return quoteString(QStringRef(&str), style);
1036}
1037
1038/*!
1039 \since 4.8
1040
1041 \overload
1042*/
1043QString QLocale::quoteString(const QStringRef &str, QuotationStyle style) const
1044{
1045#ifndef QT_NO_SYSTEMLOCALE
1046 if (d->m_data == systemData()) {
1047 QVariant res;
1048 if (style == QLocale::AlternateQuotation)
1049 res = systemLocale()->query(QSystemLocale::StringToAlternateQuotation,
1050 QVariant::fromValue(str));
1051 if (res.isNull() || style == QLocale::StandardQuotation)
1052 res = systemLocale()->query(QSystemLocale::StringToStandardQuotation,
1053 QVariant::fromValue(str));
1054 if (!res.isNull())
1055 return res.toString();
1056 }
1057#endif
1058
1059 if (style == QLocale::StandardQuotation)
1060 return QChar(d->m_data->m_quotation_start) % str % QChar(d->m_data->m_quotation_end);
1061
1062 return QChar(d->m_data->m_alternate_quotation_start)
1063 % str % QChar(d->m_data->m_alternate_quotation_end);
1064}
1065
1066/*!
1067 \since 4.8
1068
1069 Returns a string that represents a join of a given \a list of strings with
1070 a separator defined by the locale.
1071*/
1072QString QLocale::createSeparatedList(const QStringList &list) const
1073{
1074#ifndef QT_NO_SYSTEMLOCALE
1075 if (d->m_data == systemData()) {
1076 QVariant res =
1077 systemLocale()->query(QSystemLocale::ListToSeparatedString, QVariant::fromValue(list));
1078
1079 if (!res.isNull())
1080 return res.toString();
1081 }
1082#endif
1083
1084 const int size = list.size();
1085 if (size == 1) {
1086 return list.at(0);
1087 } else if (size == 2) {
1088 QString format = getLocaleData(
1089 list_pattern_part_data + d->m_data->m_list_pattern_part_two_idx,
1090 d->m_data->m_list_pattern_part_two_size);
1091 return format.arg(list.at(0), list.at(1));
1092 } else if (size > 2) {
1093 QString formatStart = getLocaleData(
1094 list_pattern_part_data + d->m_data->m_list_pattern_part_start_idx,
1095 d->m_data->m_list_pattern_part_start_size);
1096 QString formatMid = getLocaleData(
1097 list_pattern_part_data + d->m_data->m_list_pattern_part_mid_idx,
1098 d->m_data->m_list_pattern_part_mid_size);
1099 QString formatEnd = getLocaleData(
1100 list_pattern_part_data + d->m_data->m_list_pattern_part_end_idx,
1101 d->m_data->m_list_pattern_part_end_size);
1102 QString result = formatStart.arg(list.at(0), list.at(1));
1103 for (int i = 2; i < size - 1; ++i)
1104 result = formatMid.arg(result, list.at(i));
1105 result = formatEnd.arg(result, list.at(size - 1));
1106 return result;
1107 }
1108
1109 return QString();
1110}
1111
1112/*!
1113 \nonreentrant
1114
1115 Sets the global default locale to \a locale. These
1116 values are used when a QLocale object is constructed with
1117 no arguments. If this function is not called, the system's
1118 locale is used.
1119
1120 \warning In a multithreaded application, the default locale
1121 should be set at application startup, before any non-GUI threads
1122 are created.
1123
1124 \sa system(), c()
1125*/
1126
1127void QLocale::setDefault(const QLocale &locale)
1128{
1129 default_data = locale.d->m_data;
1130 default_number_options = locale.numberOptions();
1131
1132 if (defaultLocalePrivate.exists()) {
1133 // update the cached private
1134 *defaultLocalePrivate = locale.d;
1135 }
1136}
1137
1138/*!
1139 Returns the language of this locale.
1140
1141 \sa script(), country(), languageToString(), bcp47Name()
1142*/
1143QLocale::Language QLocale::language() const
1144{
1145 return Language(d->languageId());
1146}
1147
1148/*!
1149 \since 4.8
1150
1151 Returns the script of this locale.
1152
1153 \sa language(), country(), languageToString(), scriptToString(), bcp47Name()
1154*/
1155QLocale::Script QLocale::script() const
1156{
1157 return Script(d->m_data->m_script_id);
1158}
1159
1160/*!
1161 Returns the country of this locale.
1162
1163 \sa language(), script(), countryToString(), bcp47Name()
1164*/
1165QLocale::Country QLocale::country() const
1166{
1167 return Country(d->countryId());
1168}
1169
1170/*!
1171 Returns the language and country of this locale as a
1172 string of the form "language_country", where
1173 language is a lowercase, two-letter ISO 639 language code,
1174 and country is an uppercase, two- or three-letter ISO 3166 country code.
1175
1176 Note that even if QLocale object was constructed with an explicit script,
1177 name() will not contain it for compatibility reasons. Use bcp47Name() instead
1178 if you need a full locale name.
1179
1180 \sa QLocale(), language(), script(), country(), bcp47Name()
1181*/
1182
1183QString QLocale::name() const
1184{
1185 Language l = language();
1186 if (l == C)
1187 return d->languageCode();
1188
1189 Country c = country();
1190 if (c == AnyCountry)
1191 return d->languageCode();
1192
1193 return d->languageCode() + QLatin1Char('_') + d->countryCode();
1194}
1195
1196static qlonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok,
1197 QLocale::NumberOptions mode, qlonglong)
1198{
1199 return d->stringToLongLong(str, 10, ok, mode);
1200}
1201
1202static qulonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok,
1203 QLocale::NumberOptions mode, qulonglong)
1204{
1205 return d->stringToUnsLongLong(str, 10, ok, mode);
1206}
1207
1208template <typename T> static inline
1209T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok)
1210{
1211 using Int64 =
1212 typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type;
1213
1214 // we select the right overload by the last, unused parameter
1215 Int64 val = toIntegral_helper(d->m_data, str, ok, d->m_numberOptions, Int64());
1216 if (T(val) != val) {
1217 if (ok != nullptr)
1218 *ok = false;
1219 val = 0;
1220 }
1221 return T(val);
1222}
1223
1224
1225/*!
1226 \since 4.8
1227
1228 Returns the dash-separated language, script and country (and possibly other
1229 BCP47 fields) of this locale as a string.
1230
1231 Unlike the uiLanguages() the returned value of the bcp47Name() represents
1232 the locale name of the QLocale data but not the language the user-interface
1233 should be in.
1234
1235 This function tries to conform the locale name to BCP47.
1236
1237 \sa language(), country(), script(), uiLanguages()
1238*/
1239QString QLocale::bcp47Name() const
1240{
1241 return QString::fromLatin1(d->bcp47Name());
1242}
1243
1244/*!
1245 Returns a QString containing the name of \a language.
1246
1247 \sa countryToString(), scriptToString(), bcp47Name()
1248*/
1249
1250QString QLocale::languageToString(Language language)
1251{
1252 if (uint(language) > uint(QLocale::LastLanguage))
1253 return QLatin1String("Unknown");
1254 return QLatin1String(language_name_list + language_name_index[language]);
1255}
1256
1257/*!
1258 Returns a QString containing the name of \a country.
1259
1260 \sa languageToString(), scriptToString(), country(), bcp47Name()
1261*/
1262
1263QString QLocale::countryToString(Country country)
1264{
1265 if (uint(country) > uint(QLocale::LastCountry))
1266 return QLatin1String("Unknown");
1267 return QLatin1String(country_name_list + country_name_index[country]);
1268}
1269
1270/*!
1271 \since 4.8
1272
1273 Returns a QString containing the name of \a script.
1274
1275 \sa languageToString(), countryToString(), script(), bcp47Name()
1276*/
1277QString QLocale::scriptToString(QLocale::Script script)
1278{
1279 if (uint(script) > uint(QLocale::LastScript))
1280 return QLatin1String("Unknown");
1281 return QLatin1String(script_name_list + script_name_index[script]);
1282}
1283
1284#if QT_STRINGVIEW_LEVEL < 2
1285/*!
1286 Returns the short int represented by the localized string \a s.
1287
1288 If the conversion fails the function returns 0.
1289
1290 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1291 to \c false, and success by setting *\a{ok} to \c true.
1292
1293 This function ignores leading and trailing whitespace.
1294
1295 \sa toUShort(), toString()
1296*/
1297
1298short QLocale::toShort(const QString &s, bool *ok) const
1299{
1300 return toIntegral_helper<short>(d, s, ok);
1301}
1302
1303/*!
1304 Returns the unsigned short int represented by the localized string \a s.
1305
1306 If the conversion fails the function returns 0.
1307
1308 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1309 to \c false, and success by setting *\a{ok} to \c true.
1310
1311 This function ignores leading and trailing whitespace.
1312
1313 \sa toShort(), toString()
1314*/
1315
1316ushort QLocale::toUShort(const QString &s, bool *ok) const
1317{
1318 return toIntegral_helper<ushort>(d, s, ok);
1319}
1320
1321/*!
1322 Returns the int represented by the localized string \a s.
1323
1324 If the conversion fails the function returns 0.
1325
1326 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1327 to \c false, and success by setting *\a{ok} to \c true.
1328
1329 This function ignores leading and trailing whitespace.
1330
1331 \sa toUInt(), toString()
1332*/
1333
1334int QLocale::toInt(const QString &s, bool *ok) const
1335{
1336 return toIntegral_helper<int>(d, s, ok);
1337}
1338
1339/*!
1340 Returns the unsigned int represented by the localized string \a s.
1341
1342 If the conversion fails the function returns 0.
1343
1344 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1345 to \c false, and success by setting *\a{ok} to \c true.
1346
1347 This function ignores leading and trailing whitespace.
1348
1349 \sa toInt(), toString()
1350*/
1351
1352uint QLocale::toUInt(const QString &s, bool *ok) const
1353{
1354 return toIntegral_helper<uint>(d, s, ok);
1355}
1356
1357/*!
1358 Returns the long int represented by the localized string \a s.
1359
1360 If the conversion fails the function returns 0.
1361
1362 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1363 to \c false, and success by setting *\a{ok} to \c true.
1364
1365 This function ignores leading and trailing whitespace.
1366
1367 \sa toInt(), toULong(), toDouble(), toString()
1368
1369 \since 5.13
1370 */
1371
1372
1373long QLocale::toLong(const QString &s, bool *ok) const
1374{
1375 return toIntegral_helper<long>(d, s, ok);
1376}
1377
1378/*!
1379 Returns the unsigned long int represented by the localized
1380 string \a s.
1381
1382 If the conversion fails the function returns 0.
1383
1384 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1385 to \c false, and success by setting *\a{ok} to \c true.
1386
1387 This function ignores leading and trailing whitespace.
1388
1389 \sa toLong(), toInt(), toDouble(), toString()
1390
1391 \since 5.13
1392*/
1393
1394ulong QLocale::toULong(const QString &s, bool *ok) const
1395{
1396 return toIntegral_helper<ulong>(d, s, ok);
1397}
1398
1399/*!
1400 Returns the long long int represented by the localized string \a s.
1401
1402 If the conversion fails the function returns 0.
1403
1404 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1405 to \c false, and success by setting *\a{ok} to \c true.
1406
1407 This function ignores leading and trailing whitespace.
1408
1409 \sa toInt(), toULongLong(), toDouble(), toString()
1410*/
1411
1412
1413qlonglong QLocale::toLongLong(const QString &s, bool *ok) const
1414{
1415 return toIntegral_helper<qlonglong>(d, s, ok);
1416}
1417
1418/*!
1419 Returns the unsigned long long int represented by the localized
1420 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 toLongLong(), toInt(), toDouble(), toString()
1430*/
1431
1432qulonglong QLocale::toULongLong(const QString &s, bool *ok) const
1433{
1434 return toIntegral_helper<qulonglong>(d, s, ok);
1435}
1436
1437/*!
1438 Returns the float represented by the localized string \a s.
1439
1440 Returns an infinity if the conversion overflows or 0.0 if the
1441 conversion fails for any other reason (e.g. underflow).
1442
1443 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1444 to \c false, and success by setting *\a{ok} to \c true.
1445
1446 This function does not fall back to the 'C' locale if the string
1447 cannot be interpreted in this locale.
1448
1449 This function ignores leading and trailing whitespace.
1450
1451 \sa toDouble(), toInt(), toString()
1452*/
1453
1454float QLocale::toFloat(const QString &s, bool *ok) const
1455{
1456 return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok);
1457}
1458
1459/*!
1460 Returns the double represented by the localized string \a s.
1461
1462 Returns an infinity if the conversion overflows or 0.0 if the
1463 conversion fails for any other reason (e.g. underflow).
1464
1465 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1466 to \c false, and success by setting *\a{ok} to \c true.
1467
1468 This function does not fall back to the 'C' locale if the string
1469 cannot be interpreted in this locale.
1470
1471 \snippet code/src_corelib_tools_qlocale.cpp 3
1472
1473 Notice that the last conversion returns 1234.0, because '.' is the
1474 thousands group separator in the German locale.
1475
1476 This function ignores leading and trailing whitespace.
1477
1478 \sa toFloat(), toInt(), toString()
1479*/
1480
1481double QLocale::toDouble(const QString &s, bool *ok) const
1482{
1483 return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
1484}
1485
1486/*!
1487 Returns the short int represented by the localized string \a s.
1488
1489 If the conversion fails the function returns 0.
1490
1491 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1492 to \c false, and success by setting *\a{ok} to \c true.
1493
1494 This function ignores leading and trailing whitespace.
1495
1496 \sa toUShort(), toString()
1497
1498 \since 5.1
1499*/
1500
1501short QLocale::toShort(const QStringRef &s, bool *ok) const
1502{
1503 return toIntegral_helper<short>(d, s, ok);
1504}
1505
1506/*!
1507 Returns the unsigned short int represented by the localized string \a s.
1508
1509 If the conversion fails the function returns 0.
1510
1511 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1512 to \c false, and success by setting *\a{ok} to \c true.
1513
1514 This function ignores leading and trailing whitespace.
1515
1516 \sa toShort(), toString()
1517
1518 \since 5.1
1519*/
1520
1521ushort QLocale::toUShort(const QStringRef &s, bool *ok) const
1522{
1523 return toIntegral_helper<ushort>(d, s, ok);
1524}
1525
1526/*!
1527 Returns the int represented by the localized string \a s.
1528
1529 If the conversion fails the function returns 0.
1530
1531 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1532 to \c false, and success by setting *\a{ok} to \c true.
1533
1534 This function ignores leading and trailing whitespace.
1535
1536 \sa toUInt(), toString()
1537
1538 \since 5.1
1539*/
1540
1541int QLocale::toInt(const QStringRef &s, bool *ok) const
1542{
1543 return toIntegral_helper<int>(d, s, ok);
1544}
1545
1546/*!
1547 Returns the unsigned int represented by the localized string \a s.
1548
1549 If the conversion fails the function returns 0.
1550
1551 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1552 to \c false, and success by setting *\a{ok} to \c true.
1553
1554 This function ignores leading and trailing whitespace.
1555
1556 \sa toInt(), toString()
1557
1558 \since 5.1
1559*/
1560
1561uint QLocale::toUInt(const QStringRef &s, bool *ok) const
1562{
1563 return toIntegral_helper<uint>(d, s, ok);
1564}
1565
1566/*!
1567 Returns the long int represented by the localized string \a s.
1568
1569 If the conversion fails the function returns 0.
1570
1571 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1572 to \c false, and success by setting *\a{ok} to \c true.
1573
1574 This function ignores leading and trailing whitespace.
1575
1576 \sa toInt(), toULong(), toDouble(), toString()
1577
1578 \since 5.13
1579 */
1580
1581
1582long QLocale::toLong(const QStringRef &s, bool *ok) const
1583{
1584 return toIntegral_helper<long>(d, s, ok);
1585}
1586
1587/*!
1588 Returns the unsigned long int represented by the localized
1589 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 toLong(), toInt(), toDouble(), toString()
1599
1600 \since 5.13
1601 */
1602
1603ulong QLocale::toULong(const QStringRef &s, bool *ok) const
1604{
1605 return toIntegral_helper<ulong>(d, s, ok);
1606}
1607
1608/*!
1609 Returns the long long 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(), toULongLong(), toDouble(), toString()
1619
1620 \since 5.1
1621*/
1622
1623
1624qlonglong QLocale::toLongLong(const QStringRef &s, bool *ok) const
1625{
1626 return toIntegral_helper<qlonglong>(d, s, ok);
1627}
1628
1629/*!
1630 Returns the unsigned long long int represented by the localized
1631 string \a s.
1632
1633 If the conversion fails the function returns 0.
1634
1635 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1636 to \c false, and success by setting *\a{ok} to \c true.
1637
1638 This function ignores leading and trailing whitespace.
1639
1640 \sa toLongLong(), toInt(), toDouble(), toString()
1641
1642 \since 5.1
1643*/
1644
1645qulonglong QLocale::toULongLong(const QStringRef &s, bool *ok) const
1646{
1647 return toIntegral_helper<qulonglong>(d, s, ok);
1648}
1649
1650/*!
1651 Returns the float represented by the localized string \a s.
1652
1653 Returns an infinity if the conversion overflows or 0.0 if the
1654 conversion fails for any other reason (e.g. underflow).
1655
1656 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1657 to \c false, and success by setting *\a{ok} to \c true.
1658
1659 This function does not fall back to the 'C' locale if the string
1660 cannot be interpreted in this locale.
1661
1662 This function ignores leading and trailing whitespace.
1663
1664 \sa toDouble(), toInt(), toString()
1665
1666 \since 5.1
1667*/
1668
1669float QLocale::toFloat(const QStringRef &s, bool *ok) const
1670{
1671 return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok);
1672}
1673
1674/*!
1675 Returns the double represented by the localized string \a s.
1676
1677 Returns an infinity if the conversion overflows or 0.0 if the
1678 conversion fails for any other reason (e.g. underflow).
1679
1680 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1681 to \c false, and success by setting *\a{ok} to \c true.
1682
1683 This function does not fall back to the 'C' locale if the string
1684 cannot be interpreted in this locale.
1685
1686 \snippet code/src_corelib_tools_qlocale.cpp 3
1687
1688 Notice that the last conversion returns 1234.0, because '.' is the
1689 thousands group separator in the German locale.
1690
1691 This function ignores leading and trailing whitespace.
1692
1693 \sa toFloat(), toInt(), toString()
1694
1695 \since 5.1
1696*/
1697
1698double QLocale::toDouble(const QStringRef &s, bool *ok) const
1699{
1700 return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
1701}
1702#endif // QT_STRINGVIEW_LEVEL < 2
1703
1704/*!
1705 Returns the short int represented by the localized string \a s.
1706
1707 If the conversion fails, the function returns 0.
1708
1709 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1710 to \c false, and success by setting *\a{ok} to \c true.
1711
1712 This function ignores leading and trailing whitespace.
1713
1714 \sa toUShort(), toString()
1715
1716 \since 5.10
1717*/
1718
1719short QLocale::toShort(QStringView s, bool *ok) const
1720{
1721 return toIntegral_helper<short>(d, s, ok);
1722}
1723
1724/*!
1725 Returns the unsigned short int represented by the localized string \a s.
1726
1727 If the conversion fails, the function returns 0.
1728
1729 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1730 to \c false, and success by setting *\a{ok} to \c true.
1731
1732 This function ignores leading and trailing whitespace.
1733
1734 \sa toShort(), toString()
1735
1736 \since 5.10
1737*/
1738
1739ushort QLocale::toUShort(QStringView s, bool *ok) const
1740{
1741 return toIntegral_helper<ushort>(d, s, ok);
1742}
1743
1744/*!
1745 Returns the int represented by the localized string \a s.
1746
1747 If the conversion fails, the function returns 0.
1748
1749 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1750 to \c false, and success by setting *\a{ok} to \c true.
1751
1752 This function ignores leading and trailing whitespace.
1753
1754 \sa toUInt(), toString()
1755
1756 \since 5.10
1757*/
1758
1759int QLocale::toInt(QStringView s, bool *ok) const
1760{
1761 return toIntegral_helper<int>(d, s, ok);
1762}
1763
1764/*!
1765 Returns the unsigned int represented by the localized string \a s.
1766
1767 If the conversion fails, the function returns 0.
1768
1769 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1770 to \c false, and success by setting *\a{ok} to \c true.
1771
1772 This function ignores leading and trailing whitespace.
1773
1774 \sa toInt(), toString()
1775
1776 \since 5.10
1777*/
1778
1779uint QLocale::toUInt(QStringView s, bool *ok) const
1780{
1781 return toIntegral_helper<uint>(d, s, ok);
1782}
1783
1784/*!
1785 Returns the long int represented by the localized string \a s.
1786
1787 If the conversion fails the function returns 0.
1788
1789 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1790 to \c false, and success by setting *\a{ok} to \c true.
1791
1792 This function ignores leading and trailing whitespace.
1793
1794 \sa toInt(), toULong(), toDouble(), toString()
1795
1796 \since 5.13
1797 */
1798
1799
1800long QLocale::toLong(QStringView s, bool *ok) const
1801{
1802 return toIntegral_helper<long>(d, s, ok);
1803}
1804
1805/*!
1806 Returns the unsigned long int represented by the localized
1807 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 toLong(), toInt(), toDouble(), toString()
1817
1818 \since 5.13
1819 */
1820
1821ulong QLocale::toULong(QStringView s, bool *ok) const
1822{
1823 return toIntegral_helper<ulong>(d, s, ok);
1824}
1825
1826/*!
1827 Returns the long long 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(), toULongLong(), toDouble(), toString()
1837
1838 \since 5.10
1839*/
1840
1841
1842qlonglong QLocale::toLongLong(QStringView s, bool *ok) const
1843{
1844 return toIntegral_helper<qlonglong>(d, s, ok);
1845}
1846
1847/*!
1848 Returns the unsigned long long int represented by the localized
1849 string \a s.
1850
1851 If the conversion fails, the function returns 0.
1852
1853 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1854 to \c false, and success by setting *\a{ok} to \c true.
1855
1856 This function ignores leading and trailing whitespace.
1857
1858 \sa toLongLong(), toInt(), toDouble(), toString()
1859
1860 \since 5.10
1861*/
1862
1863qulonglong QLocale::toULongLong(QStringView s, bool *ok) const
1864{
1865 return toIntegral_helper<qulonglong>(d, s, ok);
1866}
1867
1868/*!
1869 Returns the float represented by the localized string \a s.
1870
1871 Returns an infinity if the conversion overflows or 0.0 if the
1872 conversion fails for any other reason (e.g. underflow).
1873
1874 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1875 to \c false, and success by setting *\a{ok} to \c true.
1876
1877 This function ignores leading and trailing whitespace.
1878
1879 \sa toDouble(), toInt(), toString()
1880
1881 \since 5.10
1882*/
1883
1884float QLocale::toFloat(QStringView s, bool *ok) const
1885{
1886 return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok);
1887}
1888
1889/*!
1890 Returns the double represented by the localized string \a s.
1891
1892 Returns an infinity if the conversion overflows or 0.0 if the
1893 conversion fails for any other reason (e.g. underflow).
1894
1895 If \a ok is not \nullptr, failure is reported by setting *\a{ok}
1896 to \c false, and success by setting *\a{ok} to \c true.
1897
1898 Unlike QString::toDouble(), this function does not fall back to
1899 the "C" locale if the string cannot be interpreted in this
1900 locale.
1901
1902 \snippet code/src_corelib_tools_qlocale.cpp 3-qstringview
1903
1904 Notice that the last conversion returns 1234.0, because '.' is the
1905 thousands group separator in the German locale.
1906
1907 This function ignores leading and trailing whitespace.
1908
1909 \sa toFloat(), toInt(), toString()
1910
1911 \since 5.10
1912*/
1913
1914double QLocale::toDouble(QStringView s, bool *ok) const
1915{
1916 return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
1917}
1918
1919/*!
1920 Returns a localized string representation of \a i.
1921
1922 \sa toLongLong()
1923*/
1924
1925QString QLocale::toString(qlonglong i) const
1926{
1927 int flags = d->m_numberOptions & OmitGroupSeparator
1928 ? 0
1929 : QLocaleData::ThousandsGroup;
1930
1931 return d->m_data->longLongToString(i, -1, 10, -1, flags);
1932}
1933
1934/*!
1935 \overload
1936
1937 \sa toULongLong()
1938*/
1939
1940QString QLocale::toString(qulonglong i) const
1941{
1942 int flags = d->m_numberOptions & OmitGroupSeparator
1943 ? 0
1944 : QLocaleData::ThousandsGroup;
1945
1946 return d->m_data->unsLongLongToString(i, -1, 10, -1, flags);
1947}
1948
1949#if QT_STRINGVIEW_LEVEL < 2
1950/*!
1951 Returns a localized string representation of the given \a date in the
1952 specified \a format.
1953 If \a format is an empty string, an empty string is returned.
1954
1955 \sa QDate::toString()
1956*/
1957
1958QString QLocale::toString(const QDate &date, const QString &format) const
1959{
1960 return d->dateTimeToString(format, QDateTime(), date, QTime(), this);
1961}
1962#endif
1963
1964/*!
1965 \since 5.10
1966
1967 Returns a localized string representation of the given \a date in the
1968 specified \a format.
1969 If \a format is an empty string, an empty string is returned.
1970
1971 \sa QDate::toString()
1972*/
1973QString QLocale::toString(const QDate &date, QStringView format) const
1974{
1975 return d->dateTimeToString(format, QDateTime(), date, QTime(), this);
1976}
1977
1978/*!
1979 Returns a localized string representation of the given \a date according
1980 to the specified \a format.
1981*/
1982
1983QString QLocale::toString(const QDate &date, FormatType format) const
1984{
1985 if (!date.isValid())
1986 return QString();
1987
1988#ifndef QT_NO_SYSTEMLOCALE
1989 if (d->m_data == systemData()) {
1990 QVariant res = systemLocale()->query(format == LongFormat
1991 ? QSystemLocale::DateToStringLong
1992 : QSystemLocale::DateToStringShort,
1993 date);
1994 if (!res.isNull())
1995 return res.toString();
1996 }
1997#endif
1998
1999 QString format_str = dateFormat(format);
2000 return toString(date, format_str);
2001}
2002
2003static bool timeFormatContainsAP(QStringView format)
2004{
2005 int i = 0;
2006 while (i < format.size()) {
2007 if (format.at(i).unicode() == '\'') {
2008 qt_readEscapedFormatString(format, &i);
2009 continue;
2010 }
2011
2012 if (format.at(i).toLower().unicode() == 'a')
2013 return true;
2014
2015 ++i;
2016 }
2017 return false;
2018}
2019
2020#if QT_STRINGVIEW_LEVEL < 2
2021/*!
2022 Returns a localized string representation of the given \a time according
2023 to the specified \a format.
2024 If \a format is an empty string, an empty string is returned.
2025
2026 \sa QTime::toString()
2027*/
2028QString QLocale::toString(const QTime &time, const QString &format) const
2029{
2030 return d->dateTimeToString(format, QDateTime(), QDate(), time, this);
2031}
2032#endif
2033
2034/*!
2035 \since 5.10
2036
2037 Returns a localized string representation of the given \a time according
2038 to the specified \a format.
2039 If \a format is an empty string, an empty string is returned.
2040
2041 \sa QTime::toString()
2042*/
2043QString QLocale::toString(const QTime &time, QStringView format) const
2044{
2045 return d->dateTimeToString(format, QDateTime(), QDate(), time, this);
2046}
2047
2048#if QT_STRINGVIEW_LEVEL < 2
2049/*!
2050 \since 4.4
2051
2052 Returns a localized string representation of the given \a dateTime according
2053 to the specified \a format.
2054 If \a format is an empty string, an empty string is returned.
2055
2056 \sa QDateTime::toString(), QDate::toString(), QTime::toString()
2057*/
2058
2059QString QLocale::toString(const QDateTime &dateTime, const QString &format) const
2060{
2061 return d->dateTimeToString(format, dateTime, QDate(), QTime(), this);
2062}
2063#endif
2064
2065/*!
2066 \since 5.10
2067
2068 Returns a localized string representation of the given \a dateTime according
2069 to the specified \a format.
2070 If \a format is an empty string, an empty string is returned.
2071
2072 \sa QDateTime::toString(), QDate::toString(), QTime::toString()
2073*/
2074QString QLocale::toString(const QDateTime &dateTime, QStringView format) const
2075{
2076 return d->dateTimeToString(format, dateTime, QDate(), QTime(), this);
2077}
2078
2079/*!
2080 \since 4.4
2081
2082 Returns a localized string representation of the given \a dateTime according
2083 to the specified \a format.
2084*/
2085
2086QString QLocale::toString(const QDateTime &dateTime, FormatType format) const
2087{
2088 if (!dateTime.isValid())
2089 return QString();
2090
2091#ifndef QT_NO_SYSTEMLOCALE
2092 if (d->m_data == systemData()) {
2093 QVariant res = systemLocale()->query(format == LongFormat
2094 ? QSystemLocale::DateTimeToStringLong
2095 : QSystemLocale::DateTimeToStringShort,
2096 dateTime);
2097 if (!res.isNull())
2098 return res.toString();
2099 }
2100#endif
2101
2102 const QString format_str = dateTimeFormat(format);
2103 return toString(dateTime, format_str);
2104}
2105
2106
2107/*!
2108 Returns a localized string representation of the given \a time in the
2109 specified \a format.
2110*/
2111
2112QString QLocale::toString(const QTime &time, FormatType format) const
2113{
2114 if (!time.isValid())
2115 return QString();
2116
2117#ifndef QT_NO_SYSTEMLOCALE
2118 if (d->m_data == systemData()) {
2119 QVariant res = systemLocale()->query(format == LongFormat
2120 ? QSystemLocale::TimeToStringLong
2121 : QSystemLocale::TimeToStringShort,
2122 time);
2123 if (!res.isNull())
2124 return res.toString();
2125 }
2126#endif
2127
2128 QString format_str = timeFormat(format);
2129 return toString(time, format_str);
2130}
2131
2132/*!
2133 \since 4.1
2134
2135 Returns the date format used for the current locale.
2136
2137 If \a format is LongFormat the format will be a long version.
2138 Otherwise it uses a shorter version.
2139
2140 \sa QDate::toString(), QDate::fromString()
2141*/
2142
2143QString QLocale::dateFormat(FormatType format) const
2144{
2145#ifndef QT_NO_SYSTEMLOCALE
2146 if (d->m_data == systemData()) {
2147 QVariant res = systemLocale()->query(format == LongFormat
2148 ? QSystemLocale::DateFormatLong
2149 : QSystemLocale::DateFormatShort,
2150 QVariant());
2151 if (!res.isNull())
2152 return res.toString();
2153 }
2154#endif
2155
2156 quint32 idx, size;
2157 switch (format) {
2158 case LongFormat:
2159 idx = d->m_data->m_long_date_format_idx;
2160 size = d->m_data->m_long_date_format_size;
2161 break;
2162 default:
2163 idx = d->m_data->m_short_date_format_idx;
2164 size = d->m_data->m_short_date_format_size;
2165 break;
2166 }
2167 return getLocaleData(date_format_data + idx, size);
2168}
2169
2170/*!
2171 \since 4.1
2172
2173 Returns the time format used for the current locale.
2174
2175 If \a format is LongFormat the format will be a long version.
2176 Otherwise it uses a shorter version.
2177
2178 \sa QTime::toString(), QTime::fromString()
2179*/
2180
2181QString QLocale::timeFormat(FormatType format) const
2182{
2183#ifndef QT_NO_SYSTEMLOCALE
2184 if (d->m_data == systemData()) {
2185 QVariant res = systemLocale()->query(format == LongFormat
2186 ? QSystemLocale::TimeFormatLong
2187 : QSystemLocale::TimeFormatShort,
2188 QVariant());
2189 if (!res.isNull())
2190 return res.toString();
2191 }
2192#endif
2193
2194 quint32 idx, size;
2195 switch (format) {
2196 case LongFormat:
2197 idx = d->m_data->m_long_time_format_idx;
2198 size = d->m_data->m_long_time_format_size;
2199 break;
2200 default:
2201 idx = d->m_data->m_short_time_format_idx;
2202 size = d->m_data->m_short_time_format_size;
2203 break;
2204 }
2205 return getLocaleData(time_format_data + idx, size);
2206}
2207
2208/*!
2209 \since 4.4
2210
2211 Returns the date time format used for the current locale.
2212
2213 If \a format is ShortFormat the format will be a short version.
2214 Otherwise it uses a longer version.
2215
2216 \sa QDateTime::toString(), QDateTime::fromString()
2217*/
2218
2219QString QLocale::dateTimeFormat(FormatType format) const
2220{
2221#ifndef QT_NO_SYSTEMLOCALE
2222 if (d->m_data == systemData()) {
2223 QVariant res = systemLocale()->query(format == LongFormat
2224 ? QSystemLocale::DateTimeFormatLong
2225 : QSystemLocale::DateTimeFormatShort,
2226 QVariant());
2227 if (!res.isNull()) {
2228 return res.toString();
2229 }
2230 }
2231#endif
2232 return dateFormat(format) + QLatin1Char(' ') + timeFormat(format);
2233}
2234
2235/*!
2236 \since 4.4
2237
2238 Parses the time string given in \a string and returns the
2239 time. The format of the time string is chosen according to the
2240 \a format parameter (see timeFormat()).
2241
2242 If the time could not be parsed, returns an invalid time.
2243
2244 \sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
2245*/
2246#if QT_CONFIG(datestring)
2247QTime QLocale::toTime(const QString &string, FormatType format) const
2248{
2249 return toTime(string, timeFormat(format));
2250}
2251#endif
2252
2253/*!
2254 \since 4.4
2255
2256 Parses the date string given in \a string and returns the
2257 date. The format of the date string is chosen according to the
2258 \a format parameter (see dateFormat()).
2259
2260 If the date could not be parsed, returns an invalid date.
2261
2262 \sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
2263*/
2264#if QT_CONFIG(datestring)
2265QDate QLocale::toDate(const QString &string, FormatType format) const
2266{
2267 return toDate(string, dateFormat(format));
2268}
2269#endif
2270
2271/*!
2272 \since 4.4
2273
2274 Parses the date/time string given in \a string and returns the
2275 time. The format of the date/time string is chosen according to the
2276 \a format parameter (see dateTimeFormat()).
2277
2278 If the string could not be parsed, returns an invalid QDateTime.
2279
2280 \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
2281*/
2282
2283#if QT_CONFIG(datestring)
2284QDateTime QLocale::toDateTime(const QString &string, FormatType format) const
2285{
2286 return toDateTime(string, dateTimeFormat(format));
2287}
2288#endif
2289
2290/*!
2291 \since 4.4
2292
2293 Parses the time string given in \a string and returns the
2294 time. See QTime::fromString() for information on what is a valid
2295 format string.
2296
2297 If the time could not be parsed, returns an invalid time.
2298
2299 \sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
2300*/
2301#if QT_CONFIG(datestring)
2302QTime QLocale::toTime(const QString &string, const QString &format) const
2303{
2304 QTime time;
2305#if QT_CONFIG(datetimeparser)
2306 QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
2307 dt.setDefaultLocale(*this);
2308 if (dt.parseFormat(format))
2309 dt.fromString(string, 0, &time);
2310#else
2311 Q_UNUSED(string);
2312 Q_UNUSED(format);
2313#endif
2314 return time;
2315}
2316#endif
2317
2318/*!
2319 \since 4.4
2320
2321 Parses the date string given in \a string and returns the
2322 date. See QDate::fromString() for information on the expressions
2323 that can be used with this function.
2324
2325 This function searches month names and the names of the days of
2326 the week in the current locale.
2327
2328 If the date could not be parsed, returns an invalid date.
2329
2330 \sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
2331*/
2332#if QT_CONFIG(datestring)
2333QDate QLocale::toDate(const QString &string, const QString &format) const
2334{
2335 QDate date;
2336#if QT_CONFIG(datetimeparser)
2337 QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
2338 dt.setDefaultLocale(*this);
2339 if (dt.parseFormat(format))
2340 dt.fromString(string, &date, 0);
2341#else
2342 Q_UNUSED(string);
2343 Q_UNUSED(format);
2344#endif
2345 return date;
2346}
2347#endif
2348
2349/*!
2350 \since 4.4
2351
2352 Parses the date/time string given in \a string and returns the
2353 time. See QDateTime::fromString() for information on the expressions
2354 that can be used with this function.
2355
2356 \note The month and day names used must be given in the user's local
2357 language.
2358
2359 If the string could not be parsed, returns an invalid QDateTime.
2360
2361 \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
2362*/
2363#if QT_CONFIG(datestring)
2364QDateTime QLocale::toDateTime(const QString &string, const QString &format) const
2365{
2366#if QT_CONFIG(datetimeparser)
2367 QTime time;
2368 QDate date;
2369
2370 QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
2371 dt.setDefaultLocale(*this);
2372 if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
2373 return QDateTime(date, time);
2374#else
2375 Q_UNUSED(string);
2376 Q_UNUSED(format);
2377#endif
2378 return QDateTime(QDate(), QTime(-1, -1, -1));
2379}
2380#endif
2381
2382
2383/*!
2384 \since 4.1
2385
2386 Returns the decimal point character of this locale.
2387*/
2388QChar QLocale::decimalPoint() const
2389{
2390 return d->decimal();
2391}
2392
2393/*!
2394 \since 4.1
2395
2396 Returns the group separator character of this locale.
2397*/
2398QChar QLocale::groupSeparator() const
2399{
2400 return d->group();
2401}
2402
2403/*!
2404 \since 4.1
2405
2406 Returns the percent character of this locale.
2407*/
2408QChar QLocale::percent() const
2409{
2410 return d->percent();
2411}
2412
2413/*!
2414 \since 4.1
2415
2416 Returns the zero digit character of this locale.
2417*/
2418QChar QLocale::zeroDigit() const
2419{
2420 return d->zero();
2421}
2422
2423/*!
2424 \since 4.1
2425
2426 Returns the negative sign character of this locale.
2427*/
2428QChar QLocale::negativeSign() const
2429{
2430 return d->minus();
2431}
2432
2433/*!
2434 \since 4.5
2435
2436 Returns the positive sign character of this locale.
2437*/
2438QChar QLocale::positiveSign() const
2439{
2440 return d->plus();
2441}
2442
2443/*!
2444 \since 4.1
2445
2446 Returns the exponential character of this locale.
2447*/
2448QChar QLocale::exponential() const
2449{
2450 return d->exponential();
2451}
2452
2453static bool qIsUpper(char c)
2454{
2455 return c >= 'A' && c <= 'Z';
2456}
2457
2458static char qToLower(char c)
2459{
2460 if (c >= 'A' && c <= 'Z')
2461 return c - 'A' + 'a';
2462 else
2463 return c;
2464}
2465
2466/*!
2467 \overload
2468
2469 \a f and \a prec have the same meaning as in QString::number(double, char, int).
2470
2471 \sa toDouble()
2472*/
2473
2474QString QLocale::toString(double i, char f, int prec) const
2475{
2476 QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
2477 uint flags = 0;
2478
2479 if (qIsUpper(f))
2480 flags = QLocaleData::CapitalEorX;
2481 f = qToLower(f);
2482
2483 switch (f) {
2484 case 'f':
2485 form = QLocaleData::DFDecimal;
2486 break;
2487 case 'e':
2488 form = QLocaleData::DFExponent;
2489 break;
2490 case 'g':
2491 form = QLocaleData::DFSignificantDigits;
2492 break;
2493 default:
2494 break;
2495 }
2496
2497 if (!(d->m_numberOptions & OmitGroupSeparator))
2498 flags |= QLocaleData::ThousandsGroup;
2499 if (!(d->m_numberOptions & OmitLeadingZeroInExponent))
2500 flags |= QLocaleData::ZeroPadExponent;
2501 if (d->m_numberOptions & IncludeTrailingZeroesAfterDot)
2502 flags |= QLocaleData::AddTrailingZeroes;
2503 return d->m_data->doubleToString(i, prec, form, -1, flags);
2504}
2505
2506/*!
2507 \fn QLocale QLocale::c()
2508
2509 Returns a QLocale object initialized to the "C" locale.
2510
2511 This locale is based on en_US but with various quirks of its own, such as
2512 simplified number formatting and its own date formatting. It implements the
2513 POSIX standards that describe the behavior of standard library functions of
2514 the "C" programming language.
2515
2516 Among other things, this means its collation order is based on the ASCII
2517 values of letters, so that (for case-sensitive sorting) all upper-case
2518 letters sort before any lower-case one (rather than each letter's upper- and
2519 lower-case forms sorting adjacent to one another, before the next letter's
2520 two forms).
2521
2522 \sa system()
2523*/
2524
2525/*!
2526 Returns a QLocale object initialized to the system locale.
2527
2528 On Windows and Mac, this locale will use the decimal/grouping characters and
2529 date/time formats specified in the system configuration panel.
2530
2531 \sa c()
2532*/
2533
2534QLocale QLocale::system()
2535{
2536 QT_PREPEND_NAMESPACE(systemData)(); // trigger updating of the system data if necessary
2537 if (systemLocalePrivate.isDestroyed())
2538 return QLocale(QLocale::C);
2539 return QLocale(*systemLocalePrivate->data());
2540}
2541
2542
2543/*!
2544 \since 4.8
2545
2546 Returns a list of valid locale objects that match the given \a language, \a
2547 script and \a country.
2548
2549 Getting a list of all locales:
2550 QList<QLocale> allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript,
2551 QLocale::AnyCountry);
2552
2553 Getting a list of locales suitable for Russia:
2554 QList<QLocale> locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript,
2555 QLocale::Russia);
2556*/
2557QList<QLocale> QLocale::matchingLocales(QLocale::Language language,
2558 QLocale::Script script,
2559 QLocale::Country country)
2560{
2561 if (uint(language) > QLocale::LastLanguage || uint(script) > QLocale::LastScript ||
2562 uint(country) > QLocale::LastCountry)
2563 return QList<QLocale>();
2564
2565 if (language == QLocale::C)
2566 return QList<QLocale>() << QLocale(QLocale::C);
2567
2568 QList<QLocale> result;
2569 if (language == QLocale::AnyLanguage && script == QLocale::AnyScript
2570 && country == QLocale::AnyCountry) {
2571 result.reserve(locale_data_size);
2572 }
2573 const QLocaleData *data = locale_data + locale_index[language];
2574 while ( (data != locale_data + locale_data_size)
2575 && (language == QLocale::AnyLanguage || data->m_language_id == uint(language))) {
2576 if ((script == QLocale::AnyScript || data->m_script_id == uint(script))
2577 && (country == QLocale::AnyCountry || data->m_country_id == uint(country))) {
2578 result.append(QLocale(*(data->m_language_id == C ? c_private()
2579 : QLocalePrivate::create(data))));
2580 }
2581 ++data;
2582 }
2583 return result;
2584}
2585
2586/*!
2587 \obsolete
2588 \since 4.3
2589
2590 Returns the list of countries that have entries for \a language in Qt's locale
2591 database. If the result is an empty list, then \a language is not represented in
2592 Qt's locale database.
2593
2594 \sa matchingLocales()
2595*/
2596QList<QLocale::Country> QLocale::countriesForLanguage(Language language)
2597{
2598 QList<Country> result;
2599 if (language == C) {
2600 result << AnyCountry;
2601 return result;
2602 }
2603
2604 unsigned language_id = language;
2605 const QLocaleData *data = locale_data + locale_index[language_id];
2606 while (data->m_language_id == language_id) {
2607 const QLocale::Country country = static_cast<Country>(data->m_country_id);
2608 if (!result.contains(country))
2609 result.append(country);
2610 ++data;
2611 }
2612
2613 return result;
2614}
2615
2616/*!
2617 \since 4.2
2618
2619 Returns the localized name of \a month, in the format specified
2620 by \a type.
2621
2622 \sa dayName(), standaloneMonthName()
2623*/
2624QString QLocale::monthName(int month, FormatType type) const
2625{
2626 if (month < 1 || month > 12)
2627 return QString();
2628
2629#ifndef QT_NO_SYSTEMLOCALE
2630 if (d->m_data == systemData()) {
2631 QVariant res = systemLocale()->query(type == LongFormat
2632 ? QSystemLocale::MonthNameLong
2633 : QSystemLocale::MonthNameShort,
2634 month);
2635 if (!res.isNull())
2636 return res.toString();
2637 }
2638#endif
2639
2640 quint32 idx, size;
2641 switch (type) {
2642 case QLocale::LongFormat:
2643 idx = d->m_data->m_long_month_names_idx;
2644 size = d->m_data->m_long_month_names_size;
2645 break;
2646 case QLocale::ShortFormat:
2647 idx = d->m_data->m_short_month_names_idx;
2648 size = d->m_data->m_short_month_names_size;
2649 break;
2650 case QLocale::NarrowFormat:
2651 idx = d->m_data->m_narrow_month_names_idx;
2652 size = d->m_data->m_narrow_month_names_size;
2653 break;
2654 default:
2655 return QString();
2656 }
2657 return getLocaleListData(months_data + idx, size, month - 1);
2658}
2659
2660/*!
2661 \since 4.5
2662
2663 Returns the localized name of \a month that is used as a
2664 standalone text, in the format specified by \a type.
2665
2666 If the locale information doesn't specify the standalone month
2667 name then return value is the same as in monthName().
2668
2669 \sa monthName(), standaloneDayName()
2670*/
2671QString QLocale::standaloneMonthName(int month, FormatType type) const
2672{
2673 if (month < 1 || month > 12)
2674 return QString();
2675
2676#ifndef QT_NO_SYSTEMLOCALE
2677 if (d->m_data == systemData()) {
2678 QVariant res = systemLocale()->query(type == LongFormat
2679 ? QSystemLocale::StandaloneMonthNameLong
2680 : QSystemLocale::StandaloneMonthNameShort,
2681 month);
2682 if (!res.isNull())
2683 return res.toString();
2684 }
2685#endif
2686
2687 quint32 idx, size;
2688 switch (type) {
2689 case QLocale::LongFormat:
2690 idx = d->m_data->m_standalone_long_month_names_idx;
2691 size = d->m_data->m_standalone_long_month_names_size;
2692 break;
2693 case QLocale::ShortFormat:
2694 idx = d->m_data->m_standalone_short_month_names_idx;
2695 size = d->m_data->m_standalone_short_month_names_size;
2696 break;
2697 case QLocale::NarrowFormat:
2698 idx = d->m_data->m_standalone_narrow_month_names_idx;
2699 size = d->m_data->m_standalone_narrow_month_names_size;
2700 break;
2701 default:
2702 return QString();
2703 }
2704 QString name = getLocaleListData(months_data + idx, size, month - 1);
2705 if (name.isEmpty())
2706 return monthName(month, type);
2707 return name;
2708}
2709
2710/*!
2711 \since 4.2
2712
2713 Returns the localized name of the \a day (where 1 represents
2714 Monday, 2 represents Tuesday and so on), in the format specified
2715 by \a type.
2716
2717 \sa monthName(), standaloneDayName()
2718*/
2719QString QLocale::dayName(int day, FormatType type) const
2720{
2721 if (day < 1 || day > 7)
2722 return QString();
2723
2724#ifndef QT_NO_SYSTEMLOCALE
2725 if (d->m_data == systemData()) {
2726 QVariant res = systemLocale()->query(type == LongFormat
2727 ? QSystemLocale::DayNameLong
2728 : QSystemLocale::DayNameShort,
2729 day);
2730 if (!res.isNull())
2731 return res.toString();
2732 }
2733#endif
2734 if (day == 7)
2735 day = 0;
2736
2737 quint32 idx, size;
2738 switch (type) {
2739 case QLocale::LongFormat:
2740 idx = d->m_data->m_long_day_names_idx;
2741 size = d->m_data->m_long_day_names_size;
2742 break;
2743 case QLocale::ShortFormat:
2744 idx = d->m_data->m_short_day_names_idx;
2745 size = d->m_data->m_short_day_names_size;
2746 break;
2747 case QLocale::NarrowFormat:
2748 idx = d->m_data->m_narrow_day_names_idx;
2749 size = d->m_data->m_narrow_day_names_size;
2750 break;
2751 default:
2752 return QString();
2753 }
2754 return getLocaleListData(days_data + idx, size, day);
2755}
2756
2757/*!
2758 \since 4.5
2759
2760 Returns the localized name of the \a day (where 1 represents
2761 Monday, 2 represents Tuesday and so on) that is used as a
2762 standalone text, in the format specified by \a type.
2763
2764 If the locale information does not specify the standalone day
2765 name then return value is the same as in dayName().
2766
2767 \sa dayName(), standaloneMonthName()
2768*/
2769QString QLocale::standaloneDayName(int day, FormatType type) const
2770{
2771 if (day < 1 || day > 7)
2772 return QString();
2773
2774#ifndef QT_NO_SYSTEMLOCALE
2775 if (d->m_data == systemData()) {
2776 QVariant res = systemLocale()->query(type == LongFormat
2777 ? QSystemLocale::DayNameLong
2778 : QSystemLocale::DayNameShort,
2779 day);
2780 if (!res.isNull())
2781 return res.toString();
2782 }
2783#endif
2784 if (day == 7)
2785 day = 0;
2786
2787 quint32 idx, size;
2788 switch (type) {
2789 case QLocale::LongFormat:
2790 idx = d->m_data->m_standalone_long_day_names_idx;
2791 size = d->m_data->m_standalone_long_day_names_size;
2792 break;
2793 case QLocale::ShortFormat:
2794 idx = d->m_data->m_standalone_short_day_names_idx;
2795 size = d->m_data->m_standalone_short_day_names_size;
2796 break;
2797 case QLocale::NarrowFormat:
2798 idx = d->m_data->m_standalone_narrow_day_names_idx;
2799 size = d->m_data->m_standalone_narrow_day_names_size;
2800 break;
2801 default:
2802 return QString();
2803 }
2804 QString name = getLocaleListData(days_data + idx, size, day);
2805 if (name.isEmpty())
2806 return dayName(day == 0 ? 7 : day, type);
2807 return name;
2808}
2809
2810/*!
2811 \since 4.8
2812
2813 Returns the first day of the week according to the current locale.
2814*/
2815Qt::DayOfWeek QLocale::firstDayOfWeek() const
2816{
2817#ifndef QT_NO_SYSTEMLOCALE
2818 if (d->m_data == systemData()) {
2819 QVariant res = systemLocale()->query(QSystemLocale::FirstDayOfWeek, QVariant());
2820 if (!res.isNull())
2821 return static_cast<Qt::DayOfWeek>(res.toUInt());
2822 }
2823#endif
2824 return static_cast<Qt::DayOfWeek>(d->m_data->m_first_day_of_week);
2825}
2826
2827QLocale::MeasurementSystem QLocalePrivate::measurementSystem() const
2828{
2829 for (int i = 0; i < ImperialMeasurementSystemsCount; ++i) {
2830 if (ImperialMeasurementSystems[i].languageId == m_data->m_language_id
2831 && ImperialMeasurementSystems[i].countryId == m_data->m_country_id) {
2832 return ImperialMeasurementSystems[i].system;
2833 }
2834 }
2835 return QLocale::MetricSystem;
2836}
2837
2838/*!
2839 \since 4.8
2840
2841 Returns a list of days that are considered weekdays according to the current locale.
2842*/
2843QList<Qt::DayOfWeek> QLocale::weekdays() const
2844{
2845#ifndef QT_NO_SYSTEMLOCALE
2846 if (d->m_data == systemData()) {
2847 QVariant res = systemLocale()->query(QSystemLocale::Weekdays, QVariant());
2848 if (!res.isNull())
2849 return static_cast<QList<Qt::DayOfWeek> >(res.value<QList<Qt::DayOfWeek> >());
2850 }
2851#endif
2852 QList<Qt::DayOfWeek> weekdays;
2853 quint16 weekendStart = d->m_data->m_weekend_start;
2854 quint16 weekendEnd = d->m_data->m_weekend_end;
2855 for (int day = Qt::Monday; day <= Qt::Sunday; day++) {
2856 if ((weekendEnd >= weekendStart && (day < weekendStart || day > weekendEnd)) ||
2857 (weekendEnd < weekendStart && (day > weekendEnd && day < weekendStart)))
2858 weekdays << static_cast<Qt::DayOfWeek>(day);
2859 }
2860 return weekdays;
2861}
2862
2863/*!
2864 \since 4.4
2865
2866 Returns the measurement system for the locale.
2867*/
2868QLocale::MeasurementSystem QLocale::measurementSystem() const
2869{
2870#ifndef QT_NO_SYSTEMLOCALE
2871 if (d->m_data == systemData()) {
2872 QVariant res = systemLocale()->query(QSystemLocale::MeasurementSystem, QVariant());
2873 if (!res.isNull())
2874 return MeasurementSystem(res.toInt());
2875 }
2876#endif
2877
2878 return d->measurementSystem();
2879}
2880
2881/*!
2882 \since 4.7
2883
2884 Returns the text direction of the language.
2885*/
2886Qt::LayoutDirection QLocale::textDirection() const
2887{
2888 switch (script()) {
2889 case QLocale::AdlamScript:
2890 case QLocale::ArabicScript:
2891 case QLocale::AvestanScript:
2892 case QLocale::CypriotScript:
2893 case QLocale::HatranScript:
2894 case QLocale::HebrewScript:
2895 case QLocale::ImperialAramaicScript:
2896 case QLocale::InscriptionalPahlaviScript:
2897 case QLocale::InscriptionalParthianScript:
2898 case QLocale::KharoshthiScript:
2899 case QLocale::LydianScript:
2900 case QLocale::MandaeanScript:
2901 case QLocale::ManichaeanScript:
2902 case QLocale::MendeKikakuiScript:
2903 case QLocale::MeroiticCursiveScript:
2904 case QLocale::MeroiticScript:
2905 case QLocale::NabataeanScript:
2906 case QLocale::NkoScript:
2907 case QLocale::OldHungarianScript:
2908 case QLocale::OldNorthArabianScript:
2909 case QLocale::OldSouthArabianScript:
2910 case QLocale::OrkhonScript:
2911 case QLocale::PalmyreneScript:
2912 case QLocale::PhoenicianScript:
2913 case QLocale::PsalterPahlaviScript:
2914 case QLocale::SamaritanScript:
2915 case QLocale::SyriacScript:
2916 case QLocale::ThaanaScript:
2917 return Qt::RightToLeft;
2918 default:
2919 break;
2920 }
2921 return Qt::LeftToRight;
2922}
2923
2924/*!
2925 \since 4.8
2926
2927 Returns an uppercase copy of \a str.
2928
2929 If Qt Core is using the ICU libraries, they will be used to perform
2930 the transformation according to the rules of the current locale.
2931 Otherwise the conversion may be done in a platform-dependent manner,
2932 with QString::toUpper() as a generic fallback.
2933
2934 \sa QString::toUpper()
2935*/
2936QString QLocale::toUpper(const QString &str) const
2937{
2938#if QT_CONFIG(icu)
2939 bool ok = true;
2940 QString result = QIcu::toUpper(d->bcp47Name('_'), str, &ok);
2941 if (ok)
2942 return result;
2943 // else fall through and use Qt's toUpper
2944#endif
2945 return str.toUpper();
2946}
2947
2948/*!
2949 \since 4.8
2950
2951 Returns a lowercase copy of \a str.
2952
2953 If Qt Core is using the ICU libraries, they will be used to perform
2954 the transformation according to the rules of the current locale.
2955 Otherwise the conversion may be done in a platform-dependent manner,
2956 with QString::toLower() as a generic fallback.
2957
2958 \sa QString::toLower()
2959*/
2960QString QLocale::toLower(const QString &str) const
2961{
2962#if QT_CONFIG(icu)
2963 bool ok = true;
2964 const QString result = QIcu::toLower(d->bcp47Name('_'), str, &ok);
2965 if (ok)
2966 return result;
2967 // else fall through and use Qt's toUpper
2968#endif
2969 return str.toLower();
2970}
2971
2972
2973/*!
2974 \since 4.5
2975
2976 Returns the localized name of the "AM" suffix for times specified using
2977 the conventions of the 12-hour clock.
2978
2979 \sa pmText()
2980*/
2981QString QLocale::amText() const
2982{
2983#ifndef QT_NO_SYSTEMLOCALE
2984 if (d->m_data == systemData()) {
2985 QVariant res = systemLocale()->query(QSystemLocale::AMText, QVariant());
2986 if (!res.isNull())
2987 return res.toString();
2988 }
2989#endif
2990 return getLocaleData(am_data + d->m_data->m_am_idx, d->m_data->m_am_size);
2991}
2992
2993/*!
2994 \since 4.5
2995
2996 Returns the localized name of the "PM" suffix for times specified using
2997 the conventions of the 12-hour clock.
2998
2999 \sa amText()
3000*/
3001QString QLocale::pmText() const
3002{
3003#ifndef QT_NO_SYSTEMLOCALE
3004 if (d->m_data == systemData()) {
3005 QVariant res = systemLocale()->query(QSystemLocale::PMText, QVariant());
3006 if (!res.isNull())
3007 return res.toString();
3008 }
3009#endif
3010 return getLocaleData(pm_data + d->m_data->m_pm_idx, d->m_data->m_pm_size);
3011}
3012
3013
3014QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &datetime,
3015 const QDate &dateOnly, const QTime &timeOnly,
3016 const QLocale *q) const
3017{
3018 QDate date;
3019 QTime time;
3020 bool formatDate = false;
3021 bool formatTime = false;
3022 if (datetime.isValid()) {
3023 date = datetime.date();
3024 time = datetime.time();
3025 formatDate = true;
3026 formatTime = true;
3027 } else if (dateOnly.isValid()) {
3028 date = dateOnly;
3029 formatDate = true;
3030 } else if (timeOnly.isValid()) {
3031 time = timeOnly;
3032 formatTime = true;
3033 } else {
3034 return QString();
3035 }
3036
3037 QString result;
3038
3039 int i = 0;
3040 while (i < format.size()) {
3041 if (format.at(i).unicode() == '\'') {
3042 result.append(qt_readEscapedFormatString(format, &i));
3043 continue;
3044 }
3045
3046 const QChar c = format.at(i);
3047 int repeat = qt_repeatCount(format.mid(i));
3048 bool used = false;
3049 if (formatDate) {
3050 switch (c.unicode()) {
3051 case 'y':
3052 used = true;
3053 if (repeat >= 4)
3054 repeat = 4;
3055 else if (repeat >= 2)
3056 repeat = 2;
3057
3058 switch (repeat) {
3059 case 4: {
3060 const int yr = date.year();
3061 const int len = (yr < 0) ? 5 : 4;
3062 result.append(m_data->longLongToString(yr, -1, 10, len,
3063 QLocaleData::ZeroPadded));
3064 break;
3065 }
3066 case 2:
3067 result.append(m_data->longLongToString(date.year() % 100, -1, 10, 2,
3068 QLocaleData::ZeroPadded));
3069 break;
3070 default:
3071 repeat = 1;
3072 result.append(c);
3073 break;
3074 }
3075 break;
3076
3077 case 'M':
3078 used = true;
3079 repeat = qMin(repeat, 4);
3080 switch (repeat) {
3081 case 1:
3082 result.append(m_data->longLongToString(date.month()));
3083 break;
3084 case 2:
3085 result.append(m_data->longLongToString(date.month(), -1, 10, 2,
3086 QLocaleData::ZeroPadded));
3087 break;
3088 case 3:
3089 result.append(q->monthName(date.month(), QLocale::ShortFormat));
3090 break;
3091 case 4:
3092 result.append(q->monthName(date.month(), QLocale::LongFormat));
3093 break;
3094 }
3095 break;
3096
3097 case 'd':
3098 used = true;
3099 repeat = qMin(repeat, 4);
3100 switch (repeat) {
3101 case 1:
3102 result.append(m_data->longLongToString(date.day()));
3103 break;
3104 case 2:
3105 result.append(m_data->longLongToString(date.day(), -1, 10, 2,
3106 QLocaleData::ZeroPadded));
3107 break;
3108 case 3:
3109 result.append(q->dayName(date.dayOfWeek(), QLocale::ShortFormat));
3110 break;
3111 case 4:
3112 result.append(q->dayName(date.dayOfWeek(), QLocale::LongFormat));
3113 break;
3114 }
3115 break;
3116
3117 default:
3118 break;
3119 }
3120 }
3121 if (!used && formatTime) {
3122 switch (c.unicode()) {
3123 case 'h': {
3124 used = true;
3125 repeat = qMin(repeat, 2);
3126 int hour = time.hour();
3127 if (timeFormatContainsAP(format)) {
3128 if (hour > 12)
3129 hour -= 12;
3130 else if (hour == 0)
3131 hour = 12;
3132 }
3133
3134 switch (repeat) {
3135 case 1:
3136 result.append(m_data->longLongToString(hour));
3137 break;
3138 case 2:
3139 result.append(m_data->longLongToString(hour, -1, 10, 2,
3140 QLocaleData::ZeroPadded));
3141 break;
3142 }
3143 break;
3144 }
3145 case 'H':
3146 used = true;
3147 repeat = qMin(repeat, 2);
3148 switch (repeat) {
3149 case 1:
3150 result.append(m_data->longLongToString(time.hour()));
3151 break;
3152 case 2:
3153 result.append(m_data->longLongToString(time.hour(), -1, 10, 2,
3154 QLocaleData::ZeroPadded));
3155 break;
3156 }
3157 break;
3158
3159 case 'm':
3160 used = true;
3161 repeat = qMin(repeat, 2);
3162 switch (repeat) {
3163 case 1:
3164 result.append(m_data->longLongToString(time.minute()));
3165 break;
3166 case 2:
3167 result.append(m_data->longLongToString(time.minute(), -1, 10, 2,
3168 QLocaleData::ZeroPadded));
3169 break;
3170 }
3171 break;
3172
3173 case 's':
3174 used = true;
3175 repeat = qMin(repeat, 2);
3176 switch (repeat) {
3177 case 1:
3178 result.append(m_data->longLongToString(time.second()));
3179 break;
3180 case 2:
3181 result.append(m_data->longLongToString(time.second(), -1, 10, 2,
3182 QLocaleData::ZeroPadded));
3183 break;
3184 }
3185 break;
3186
3187 case 'a':
3188 used = true;
3189 repeat = format.mid(i + 1).startsWith(QLatin1Char('p')) ? 2 : 1;
3190 result.append(time.hour() < 12 ? q->amText().toLower() : q->pmText().toLower());
3191 break;
3192
3193 case 'A':
3194 used = true;
3195 repeat = format.mid(i + 1).startsWith(QLatin1Char('P')) ? 2 : 1;
3196 result.append(time.hour() < 12 ? q->amText().toUpper() : q->pmText().toUpper());
3197 break;
3198
3199 case 'z':
3200 used = true;
3201 repeat = (repeat >= 3) ? 3 : 1;
3202
3203 // note: the millisecond component is treated like the decimal part of the seconds
3204 // so ms == 2 is always printed as "002", but ms == 200 can be either "2" or "200"
3205 result.append(m_data->longLongToString(time.msec(), -1, 10, 3,
3206 QLocaleData::ZeroPadded));
3207 if (repeat == 1) {
3208 if (result.endsWith(zero()))
3209 result.chop(1);
3210 if (result.endsWith(zero()))
3211 result.chop(1);
3212 }
3213
3214 break;
3215
3216 case 't':
3217 used = true;
3218 repeat = 1;
3219 // If we have a QDateTime use the time spec otherwise use the current system tzname
3220 result.append(formatDate ? datetime.timeZoneAbbreviation()
3221 : QDateTime::currentDateTime().timeZoneAbbreviation());
3222 break;
3223
3224 default:
3225 break;
3226 }
3227 }
3228 if (!used)
3229 result.append(QString(repeat, c));
3230 i += repeat;
3231 }
3232
3233 return result;
3234}
3235
3236QString QLocaleData::doubleToString(double d, int precision, DoubleForm form,
3237 int width, unsigned flags) const
3238{
3239 return doubleToString(m_zero, m_plus, m_minus, m_exponential, m_group, m_decimal,
3240 d, precision, form, width, flags);
3241}
3242
3243QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const QChar minus,
3244 const QChar exponential, const QChar group, const QChar decimal,
3245 double d, int precision, DoubleForm form, int width,
3246 unsigned flags)
3247{
3248 if (precision != QLocale::FloatingPointShortest && precision < 0)
3249 precision = 6;
3250 if (width < 0)
3251 width = 0;
3252
3253 bool negative = false;
3254 QString num_str;
3255
3256 int decpt;
3257 int bufSize = 1;
3258 if (precision == QLocale::FloatingPointShortest)
3259 bufSize += DoubleMaxSignificant;
3260 else if (form == DFDecimal) // optimize for numbers between -512k and 512k
3261 bufSize += ((d > (1 << 19) || d < -(1 << 19)) ? DoubleMaxDigitsBeforeDecimal : 6) +
3262 precision;
3263 else // Add extra digit due to different interpretations of precision. Also, "nan" has to fit.
3264 bufSize += qMax(2, precision) + 1;
3265
3266 QVarLengthArray<char> buf(bufSize);
3267 int length;
3268
3269 qt_doubleToAscii(d, form, precision, buf.data(), bufSize, negative, length, decpt);
3270
3271 if (qstrncmp(buf.data(), "inf", 3) == 0 || qstrncmp(buf.data(), "nan", 3) == 0) {
3272 num_str = QString::fromLatin1(buf.data(), length);
3273 } else { // Handle normal numbers
3274 QString digits = QString::fromLatin1(buf.data(), length);
3275
3276 if (_zero.unicode() != '0') {
3277 ushort z = _zero.unicode() - '0';
3278 for (int i = 0; i < digits.length(); ++i)
3279 reinterpret_cast<ushort *>(digits.data())[i] += z;
3280 }
3281
3282 bool always_show_decpt = (flags & ForcePoint);
3283 switch (form) {
3284 case DFExponent: {
3285 num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
3286 digits, decpt, precision, PMDecimalDigits,
3287 always_show_decpt, flags & ZeroPadExponent);
3288 break;
3289 }
3290 case DFDecimal: {
3291 num_str = decimalForm(_zero, decimal, group,
3292 digits, decpt, precision, PMDecimalDigits,
3293 always_show_decpt, flags & ThousandsGroup);
3294 break;
3295 }
3296 case DFSignificantDigits: {
3297 PrecisionMode mode = (flags & AddTrailingZeroes) ?
3298 PMSignificantDigits : PMChopTrailingZeros;
3299
3300 int cutoff = precision < 0 ? 6 : precision;
3301 // Find out which representation is shorter
3302 if (precision == QLocale::FloatingPointShortest && decpt > 0) {
3303 cutoff = digits.length() + 4; // 'e', '+'/'-', one digit exponent
3304 if (decpt <= 10) {
3305 ++cutoff;
3306 } else {
3307 cutoff += decpt > 100 ? 2 : 1;
3308 }
3309 if (!always_show_decpt && digits.length() > decpt)
3310 ++cutoff; // decpt shown in exponent form, but not in decimal form
3311 }
3312
3313 if (decpt != digits.length() && (decpt <= -4 || decpt > cutoff))
3314 num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
3315 digits, decpt, precision, mode,
3316 always_show_decpt, flags & ZeroPadExponent);
3317 else
3318 num_str = decimalForm(_zero, decimal, group,
3319 digits, decpt, precision, mode,
3320 always_show_decpt, flags & ThousandsGroup);
3321 break;
3322 }
3323 }
3324
3325 if (isZero(d))
3326 negative = false;
3327
3328 // pad with zeros. LeftAdjusted overrides this flag). Also, we don't
3329 // pad special numbers
3330 if (flags & QLocaleData::ZeroPadded && !(flags & QLocaleData::LeftAdjusted)) {
3331 int num_pad_chars = width - num_str.length();
3332 // leave space for the sign
3333 if (negative
3334 || flags & QLocaleData::AlwaysShowSign
3335 || flags & QLocaleData::BlankBeforePositive)
3336 --num_pad_chars;
3337
3338 for (int i = 0; i < num_pad_chars; ++i)
3339 num_str.prepend(_zero);
3340 }
3341 }
3342
3343 // add sign
3344 if (negative)
3345 num_str.prepend(minus);
3346 else if (flags & QLocaleData::AlwaysShowSign)
3347 num_str.prepend(plus);
3348 else if (flags & QLocaleData::BlankBeforePositive)
3349 num_str.prepend(QLatin1Char(' '));
3350
3351 if (flags & QLocaleData::CapitalEorX)
3352 num_str = std::move(num_str).toUpper();
3353
3354 return num_str;
3355}
3356
3357QString QLocaleData::longLongToString(qlonglong l, int precision,
3358 int base, int width,
3359 unsigned flags) const
3360{
3361 return longLongToString(m_zero, m_group, m_plus, m_minus,
3362 l, precision, base, width, flags);
3363}
3364
3365QString QLocaleData::longLongToString(const QChar zero, const QChar group,
3366 const QChar plus, const QChar minus,
3367 qlonglong l, int precision,
3368 int base, int width,
3369 unsigned flags)
3370{
3371 bool precision_not_specified = false;
3372 if (precision == -1) {
3373 precision_not_specified = true;
3374 precision = 1;
3375 }
3376
3377 bool negative = l < 0;
3378 if (base != 10) {
3379 // these are not supported by sprintf for octal and hex
3380 flags &= ~AlwaysShowSign;
3381 flags &= ~BlankBeforePositive;
3382 negative = false; // neither are negative numbers
3383 }
3384
3385QT_WARNING_PUSH
3386 /* "unary minus operator applied to unsigned type, result still unsigned" */
3387QT_WARNING_DISABLE_MSVC(4146)
3388 /*
3389 Negating std::numeric_limits<qlonglong>::min() hits undefined behavior, so
3390 taking an absolute value has to cast to unsigned to change sign.
3391 */
3392 QString num_str = qulltoa(negative ? -qulonglong(l) : qulonglong(l), base, zero);
3393QT_WARNING_POP
3394
3395 uint cnt_thousand_sep = 0;
3396 if (flags & ThousandsGroup && base == 10) {
3397 for (int i = num_str.length() - 3; i > 0; i -= 3) {
3398 num_str.insert(i, group);
3399 ++cnt_thousand_sep;
3400 }
3401 }
3402
3403 for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
3404 num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
3405
3406 if ((flags & ShowBase)
3407 && base == 8
3408 && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
3409 num_str.prepend(QLatin1Char('0'));
3410
3411 // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
3412 // when precision is not specified in the format string
3413 bool zero_padded = flags & ZeroPadded
3414 && !(flags & LeftAdjusted)
3415 && precision_not_specified;
3416
3417 if (zero_padded) {
3418 int num_pad_chars = width - num_str.length();
3419
3420 // leave space for the sign
3421 if (negative
3422 || flags & AlwaysShowSign
3423 || flags & BlankBeforePositive)
3424 --num_pad_chars;
3425
3426 // leave space for optional '0x' in hex form
3427 if (base == 16 && (flags & ShowBase))
3428 num_pad_chars -= 2;
3429 // leave space for optional '0b' in binary form
3430 else if (base == 2 && (flags & ShowBase))
3431 num_pad_chars -= 2;
3432
3433 for (int i = 0; i < num_pad_chars; ++i)
3434 num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
3435 }
3436
3437 if (flags & CapitalEorX)
3438 num_str = std::move(num_str).toUpper();
3439
3440 if (base == 16 && (flags & ShowBase))
3441 num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
3442 if (base == 2 && (flags & ShowBase))
3443 num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
3444
3445 // add sign
3446 if (negative)
3447 num_str.prepend(minus);
3448 else if (flags & AlwaysShowSign)
3449 num_str.prepend(plus);
3450 else if (flags & BlankBeforePositive)
3451 num_str.prepend(QLatin1Char(' '));
3452
3453 return num_str;
3454}
3455
3456QString QLocaleData::unsLongLongToString(qulonglong l, int precision,
3457 int base, int width,
3458 unsigned flags) const
3459{
3460 return unsLongLongToString(m_zero, m_group, m_plus,
3461 l, precision, base, width, flags);
3462}
3463
3464QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
3465 const QChar plus,
3466 qulonglong l, int precision,
3467 int base, int width,
3468 unsigned flags)
3469{
3470 const QChar resultZero = base == 10 ? zero : QChar(QLatin1Char('0'));
3471 QString num_str = l ? qulltoa(l, base, zero) : QString(resultZero);
3472
3473 bool precision_not_specified = false;
3474 if (precision == -1) {
3475 if (flags == NoFlags)
3476 return num_str; // fast-path: nothing below applies, so we're done.
3477
3478 precision_not_specified = true;
3479 precision = 1;
3480 }
3481
3482 uint cnt_thousand_sep = 0;
3483 if (flags & ThousandsGroup && base == 10) {
3484 for (int i = num_str.length() - 3; i > 0; i -=3) {
3485 num_str.insert(i, group);
3486 ++cnt_thousand_sep;
3487 }
3488 }
3489
3490 const int zeroPadding = precision - num_str.length()/* + cnt_thousand_sep*/;
3491 if (zeroPadding > 0)
3492 num_str.prepend(QString(zeroPadding, resultZero));
3493
3494 if ((flags & ShowBase)
3495 && base == 8
3496 && (num_str.isEmpty() || num_str.at(0).unicode() != QLatin1Char('0')))
3497 num_str.prepend(QLatin1Char('0'));
3498
3499 // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
3500 // when precision is not specified in the format string
3501 bool zero_padded = flags & ZeroPadded
3502 && !(flags & LeftAdjusted)
3503 && precision_not_specified;
3504
3505 if (zero_padded) {
3506 int num_pad_chars = width - num_str.length();
3507
3508 // leave space for optional '0x' in hex form
3509 if (base == 16 && flags & ShowBase)
3510 num_pad_chars -= 2;
3511 // leave space for optional '0b' in binary form
3512 else if (base == 2 && flags & ShowBase)
3513 num_pad_chars -= 2;
3514
3515 if (num_pad_chars > 0)
3516 num_str.prepend(QString(num_pad_chars, resultZero));
3517 }
3518
3519 if (flags & CapitalEorX)
3520 num_str = std::move(num_str).toUpper();
3521
3522 if (base == 16 && flags & ShowBase)
3523 num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
3524 else if (base == 2 && flags & ShowBase)
3525 num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
3526
3527 // add sign
3528 if (flags & AlwaysShowSign)
3529 num_str.prepend(plus);
3530 else if (flags & BlankBeforePositive)
3531 num_str.prepend(QLatin1Char(' '));
3532
3533 return num_str;
3534}
3535
3536/*
3537 Converts a number in locale to its representation in the C locale.
3538 Only has to guarantee that a string that is a correct representation of
3539 a number will be converted. If junk is passed in, junk will be passed
3540 out and the error will be detected during the actual conversion to a
3541 number. We can't detect junk here, since we don't even know the base
3542 of the number.
3543*/
3544bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_options,
3545 CharBuff *result) const
3546{
3547 const QChar *uc = s.data();
3548 auto l = s.size();
3549 decltype(l) idx = 0;
3550
3551 // Skip whitespace
3552 while (idx < l && uc[idx].isSpace())
3553 ++idx;
3554 if (idx == l)
3555 return false;
3556
3557 // Check trailing whitespace
3558 for (; idx < l; --l) {
3559 if (!uc[l - 1].isSpace())
3560 break;
3561 }
3562
3563 int group_cnt = 0; // counts number of group chars
3564 int decpt_idx = -1;
3565 int last_separator_idx = -1;
3566 int start_of_digits_idx = -1;
3567 int exponent_idx = -1;
3568
3569 while (idx < l) {
3570 const QChar in = uc[idx];
3571
3572 char out =