Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qlocale.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2021 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qglobal.h"
6
7#if (defined(QT_STATIC) || defined(QT_BOOTSTRAPPED)) && defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1000
8QT_WARNING_DISABLE_GCC("-Wfree-nonheap-object") // false positive tracking
9#endif
10
11#if defined(Q_OS_MACOS)
12# include "private/qcore_mac_p.h"
13# include <CoreFoundation/CoreFoundation.h>
14#endif
15
16#include "qplatformdefs.h"
17
18#include "qdatastream.h"
19#include "qdebug.h"
20#include "qhashfunctions.h"
21#include "qstring.h"
22#include "qlocale.h"
23#include "qlocale_p.h"
24#include "qlocale_tools_p.h"
25#include <private/qtools_p.h>
26#if QT_CONFIG(datetimeparser)
27#include "private/qdatetimeparser_p.h"
28#endif
29#include "qnamespace.h"
30#include "qdatetime.h"
31#include "qstringlist.h"
32#include "qvariant.h"
33#include "qvarlengtharray.h"
34#include "qstringbuilder.h"
35#if QT_CONFIG(timezone)
36# include "qtimezone.h"
37#endif
38#include "private/qnumeric_p.h"
39#include "private/qtools_p.h"
40#include <cmath>
41#ifndef QT_NO_SYSTEMLOCALE
42# include "qmutex.h"
43#endif
44#ifdef Q_OS_WIN
45# include <qt_windows.h>
46# include <time.h>
47#endif
48
49#include "private/qcalendarbackend_p.h"
50#include "private/qgregoriancalendar_p.h"
51#include "qcalendar.h"
52
53#include <q20iterator.h>
54
56
58
59QT_IMPL_METATYPE_EXTERN_TAGGED(QList<Qt::DayOfWeek>, QList_Qt__DayOfWeek)
60#ifndef QT_NO_SYSTEMLOCALE
62 QSystemLocale__CurrencyToStringArgument)
63#endif
64
65using namespace Qt::StringLiterals;
66using namespace QtMiscUtils;
67
68#ifndef QT_NO_SYSTEMLOCALE
69Q_CONSTINIT static QSystemLocale *_systemLocale = nullptr;
70Q_CONSTINIT static QLocaleData systemLocaleData = {};
71#endif
72
73static_assert(ascii_isspace(' '));
74static_assert(ascii_isspace('\t'));
75static_assert(ascii_isspace('\n'));
76static_assert(ascii_isspace('\v'));
77static_assert(ascii_isspace('\f'));
78static_assert(ascii_isspace('\r'));
79static_assert(!ascii_isspace('\0'));
80static_assert(!ascii_isspace('\a'));
81static_assert(!ascii_isspace('a'));
82static_assert(!ascii_isspace('\177'));
83static_assert(!ascii_isspace(uchar('\200')));
84static_assert(!ascii_isspace(uchar('\xA0'))); // NBSP (is a space but Latin 1, not ASCII)
85static_assert(!ascii_isspace(uchar('\377')));
86
87/******************************************************************************
88** Helpers for accessing Qt locale database
89*/
90
92#include "qlocale_data_p.h"
94
96 QLocale::LanguageCodeTypes codeTypes) noexcept
97{
98 const auto len = code.size();
99 if (len != 2 && len != 3)
101
102 const char16_t uc1 = code[0].toLower().unicode();
103 const char16_t uc2 = code[1].toLower().unicode();
104 const char16_t uc3 = len > 2 ? code[2].toLower().unicode() : 0;
105
106 // All language codes are ASCII.
107 if (uc1 > 0x7F || uc2 > 0x7F || uc3 > 0x7F)
109
110 const AlphaCode codeBuf = { char(uc1), char(uc2), char(uc3) };
111
112 auto searchCode = [codeBuf](auto f) {
113 return std::find_if(languageCodeList.begin(), languageCodeList.end(),
114 [=](LanguageCodeEntry i) { return f(i) == codeBuf; });
115 };
116
117 if (codeTypes.testFlag(QLocale::ISO639Part1) && uc3 == 0) {
118 auto i = searchCode([](LanguageCodeEntry i) { return i.part1; });
119 if (i != languageCodeList.end())
120 return QLocale::Language(std::distance(languageCodeList.begin(), i));
121 }
122
123 if (uc3 != 0) {
124 if (codeTypes.testFlag(QLocale::ISO639Part2B)) {
125 auto i = searchCode([](LanguageCodeEntry i) { return i.part2B; });
126 if (i != languageCodeList.end())
127 return QLocale::Language(std::distance(languageCodeList.begin(), i));
128 }
129
130 // Optimization: Part 2T code if present is always the same as Part 3 code.
131 // This is asserted in iso639_3.LanguageCodeData.
132 if (codeTypes.testFlag(QLocale::ISO639Part2T)
133 && !codeTypes.testFlag(QLocale::ISO639Part3)) {
134 auto i = searchCode([](LanguageCodeEntry i) { return i.part2T; });
135 if (i != languageCodeList.end())
136 return QLocale::Language(std::distance(languageCodeList.begin(), i));
137 }
138
139 if (codeTypes.testFlag(QLocale::ISO639Part3)) {
140 auto i = searchCode([](LanguageCodeEntry i) { return i.part3; });
141 if (i != languageCodeList.end())
142 return QLocale::Language(std::distance(languageCodeList.begin(), i));
143 }
144 }
145
146 if (codeTypes.testFlag(QLocale::LegacyLanguageCode) && uc3 == 0) {
147 // legacy codes
148 if (uc1 == 'n' && uc2 == 'o') // no -> nb
150 if (uc1 == 't' && uc2 == 'l') // tl -> fil
151 return QLocale::Filipino;
152 if (uc1 == 's' && uc2 == 'h') // sh -> sr[_Latn]
153 return QLocale::Serbian;
154 if (uc1 == 'm' && uc2 == 'o') // mo -> ro
155 return QLocale::Romanian;
156 // Android uses the following deprecated codes
157 if (uc1 == 'i' && uc2 == 'w') // iw -> he
158 return QLocale::Hebrew;
159 if (uc1 == 'i' && uc2 == 'n') // in -> id
160 return QLocale::Indonesian;
161 if (uc1 == 'j' && uc2 == 'i') // ji -> yi
162 return QLocale::Yiddish;
163 }
165}
166
168{
169 const auto len = code.size();
170 if (len != 4)
171 return QLocale::AnyScript;
172
173 // script is titlecased in our data
174 unsigned char c0 = code[0].toUpper().toLatin1();
175 unsigned char c1 = code[1].toLower().toLatin1();
176 unsigned char c2 = code[2].toLower().toLatin1();
177 unsigned char c3 = code[3].toLower().toLatin1();
178
179 const unsigned char *c = script_code_list;
180 for (qsizetype i = 0; i < QLocale::LastScript; ++i, c += 4) {
181 if (c0 == c[0] && c1 == c[1] && c2 == c[2] && c3 == c[3])
182 return QLocale::Script(i);
183 }
184 return QLocale::AnyScript;
185}
186
188{
189 const auto len = code.size();
190 if (len != 2 && len != 3)
192
193 char16_t uc1 = code[0].toUpper().unicode();
194 char16_t uc2 = code[1].toUpper().unicode();
195 char16_t uc3 = len > 2 ? code[2].toUpper().unicode() : 0;
196
197 const unsigned char *c = territory_code_list;
198 for (; *c != 0; c += 3) {
199 if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
201 }
202
204}
205
207 QLocale::LanguageCodeTypes codeTypes)
208{
210 return {};
211 if (language == QLocale::C)
212 return {'C'};
213
215
216 if (codeTypes.testFlag(QLocale::ISO639Part1) && i.part1.isValid())
217 return i.part1.decode();
218
219 if (codeTypes.testFlag(QLocale::ISO639Part2B) && i.part2B.isValid())
220 return i.part2B.decode();
221
222 if (codeTypes.testFlag(QLocale::ISO639Part2T) && i.part2T.isValid())
223 return i.part2T.decode();
224
225 if (codeTypes.testFlag(QLocale::ISO639Part3))
226 return i.part3.decode();
227
228 return {};
229}
230
232{
233 if (script == QLocale::AnyScript || script > QLocale::LastScript)
234 return {};
235 const unsigned char *c = script_code_list + 4 * script;
236 return {reinterpret_cast<const char *>(c), 4};
237}
238
240{
241 if (territory == QLocale::AnyTerritory || territory > QLocale::LastTerritory)
242 return {};
243
244 const unsigned char *c = territory_code_list + 3 * territory;
245 return {reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3};
246}
247
248namespace {
249struct LikelyPair
250{
251 QLocaleId key; // Search key.
252 QLocaleId value = QLocaleId { 0, 0, 0 };
253};
254
255bool operator<(LikelyPair lhs, LikelyPair rhs)
256{
257 // Must match the comparison LocaleDataWriter.likelySubtags() uses when
258 // sorting, see qtbase/util/locale_database.qlocalexml2cpp.py
259 const auto compare = [](int lhs, int rhs) {
260 // 0 sorts after all other values; lhs and rhs are passed ushort values.
261 const int huge = 0x10000;
262 return (lhs ? lhs : huge) - (rhs ? rhs : huge);
263 };
264 const auto &left = lhs.key;
265 const auto &right = rhs.key;
266 // Comparison order: language, region, script:
267 if (int cmp = compare(left.language_id, right.language_id))
268 return cmp < 0;
269 if (int cmp = compare(left.territory_id, right.territory_id))
270 return cmp < 0;
271 return compare(left.script_id, right.script_id) < 0;
272}
273} // anonymous namespace
274
299{
300 /* Each pattern that appears in a comments below, language_script_region and
301 similar, indicates which of this's fields (even if blank) are being
302 attended to in a given search; for fields left out of the pattern, the
303 search uses 0 regardless of whether this has specified the field.
304
305 If a key matches what we're searching for (possibly with a wildcard in
306 the key matching a non-wildcard in our search), the tags from this that
307 are specified in the key are replaced by the match (even if different);
308 but the other tags of this replace what's in the match (even when the
309 match does specify a value).
310 */
311 static_assert(std::size(likely_subtags) % 2 == 0);
312 auto *pairs = reinterpret_cast<const LikelyPair *>(likely_subtags);
313 auto *const afterPairs = pairs + std::size(likely_subtags) / 2;
314 LikelyPair sought { *this };
315 // Our array is sorted in the order that puts all candidate matches in the
316 // order we would want them; ones we should prefer appear before the others.
317 if (language_id) {
318 // language_script_region, language_region, language_script, language:
319 pairs = std::lower_bound(pairs, afterPairs, sought);
320 // Single language's block isn't long enough to warrant more binary
321 // chopping within it - just traverse it all:
322 for (; pairs < afterPairs && pairs->key.language_id == language_id; ++pairs) {
323 const QLocaleId &key = pairs->key;
324 if (key.territory_id && key.territory_id != territory_id)
325 continue;
326 if (key.script_id && key.script_id != script_id)
327 continue;
328 QLocaleId value = pairs->value;
329 if (territory_id && !key.territory_id)
331 if (script_id && !key.script_id)
332 value.script_id = script_id;
333 return value;
334 }
335 }
336 // und_script_region or und_region (in that order):
337 if (territory_id) {
338 sought.key = QLocaleId { 0, script_id, territory_id };
339 pairs = std::lower_bound(pairs, afterPairs, sought);
340 // Again, individual und_?_region block isn't long enough to make binary
341 // chop a win:
342 for (; pairs < afterPairs && pairs->key.territory_id == territory_id; ++pairs) {
343 const QLocaleId &key = pairs->key;
344 Q_ASSERT(!key.language_id);
345 if (key.script_id && key.script_id != script_id)
346 continue;
347 QLocaleId value = pairs->value;
348 if (language_id)
350 if (script_id && !key.script_id)
351 value.script_id = script_id;
352 return value;
353 }
354 }
355 // und_script:
356 if (script_id) {
357 sought.key = QLocaleId { 0, script_id, 0 };
358 pairs = std::lower_bound(pairs, afterPairs, sought);
359 if (pairs < afterPairs && pairs->key.script_id == script_id) {
360 Q_ASSERT(!pairs->key.language_id && !pairs->key.territory_id);
361 QLocaleId value = pairs->value;
362 if (language_id)
364 if (territory_id)
365 value.territory_id = territory_id;
366 return value;
367 }
368 }
369 if (matchesAll()) { // Skipped all of the above.
370 // CLDR has no match-all at v37, but might get one some day ...
371 pairs = std::lower_bound(pairs, afterPairs, sought);
372 if (pairs < afterPairs) {
373 // All other keys are < match-all.
374 Q_ASSERT(pairs + 1 == afterPairs);
375 Q_ASSERT(pairs->key.matchesAll());
376 return pairs->value;
377 }
378 }
379 return *this;
380}
381
383{
385 // language
386 {
387 QLocaleId id { language_id, 0, 0 };
388 if (id.withLikelySubtagsAdded() == max)
389 return id;
390 }
391 // language_region
392 if (territory_id) {
394 if (id.withLikelySubtagsAdded() == max)
395 return id;
396 }
397 // language_script
398 if (script_id) {
400 if (id.withLikelySubtagsAdded() == max)
401 return id;
402 }
403 return max;
404}
405
406QByteArray QLocaleId::name(char separator) const
407{
409 return QByteArray();
410 if (language_id == QLocale::C)
411 return QByteArrayLiteral("C");
412
414 AlphaCode lang;
415 qsizetype langLen;
416
417 if (language.part1.isValid()) {
418 lang = language.part1;
419 langLen = 2;
420 } else {
421 lang = language.part2B.isValid() ? language.part2B : language.part3;
422 langLen = 3;
423 }
424
425 const unsigned char *script =
427 const unsigned char *country =
429 ? territory_code_list + 3 * territory_id : nullptr);
430 qsizetype len = langLen + (script ? 4 + 1 : 0) + (country ? (country[2] != 0 ? 3 : 2) + 1 : 0);
432 char *uc = name.data();
433
434 auto langArray = lang.decode();
435
436 *uc++ = langArray[0];
437 *uc++ = langArray[1];
438 if (langLen > 2)
439 *uc++ = langArray[2];
440
441 if (script) {
442 *uc++ = separator;
443 *uc++ = script[0];
444 *uc++ = script[1];
445 *uc++ = script[2];
446 *uc++ = script[3];
447 }
448 if (country) {
449 *uc++ = separator;
450 *uc++ = country[0];
451 *uc++ = country[1];
452 if (country[2] != 0)
453 *uc++ = country[2];
454 }
455 return name;
456}
457
459{
460 if (m_data->m_language_id == QLocale::AnyLanguage)
461 return QByteArray();
462 if (m_data->m_language_id == QLocale::C)
463 return QByteArrayLiteral("en");
464
465 return m_data->id().withLikelySubtagsRemoved().name(separator);
466}
467
469{
470 qsizetype idx = locale_index[localeId.language_id];
471 // If there are no locales for specified language (so we we've got the
472 // default language, which has no associated script or country), give up:
473 if (localeId.language_id && idx == 0)
474 return idx;
475
476 Q_ASSERT(localeId.acceptLanguage(locale_data[idx].m_language_id));
477
478 do {
479 if (localeId.acceptScriptTerritory(locale_data[idx].id()))
480 return idx;
481 ++idx;
482 } while (localeId.acceptLanguage(locale_data[idx].m_language_id));
483
484 return -1;
485}
486
488{
489 QLocaleId localeId = lid;
490 QLocaleId likelyId = localeId.withLikelySubtagsAdded();
491 const ushort fallback = likelyId.language_id;
492
493 // Try a straight match with the likely data:
495 if (index >= 0)
496 return index;
497 QVarLengthArray<QLocaleId, 6> tried;
498 tried.push_back(likelyId);
499
500#define CheckCandidate(id) do { \
501 if (!tried.contains(id)) { \
502 index = findLocaleIndexById(id); \
503 if (index >= 0) \
504 return index; \
505 tried.push_back(id); \
506 } \
507 } while (false) // end CheckCandidate
508
509 // No match; try again with raw data:
510 CheckCandidate(localeId);
511
512 // No match; try again with likely country for language_script
513 if (lid.territory_id && (lid.language_id || lid.script_id)) {
514 localeId.territory_id = 0;
515 likelyId = localeId.withLikelySubtagsAdded();
516 CheckCandidate(likelyId);
517
518 // No match; try again with any country
519 CheckCandidate(localeId);
520 }
521
522 // No match; try again with likely script for language_region
523 if (lid.script_id && (lid.language_id || lid.territory_id)) {
524 localeId = QLocaleId { lid.language_id, 0, lid.territory_id };
525 likelyId = localeId.withLikelySubtagsAdded();
526 CheckCandidate(likelyId);
527
528 // No match; try again with any script
529 CheckCandidate(localeId);
530 }
531#undef CheckCandidate
532
533 // No match; return base index for initial likely language:
534 return locale_index[fallback];
535}
536
538{
539 const std::u16string_view v(name.utf16(), size_t(name.size()));
540 const auto i = v.find_first_of(u"_-.@");
541 if (i == std::string_view::npos)
542 return name;
543 return name.first(qsizetype(i));
544}
545
547{
548 // Is tag is a non-empty sequence of ASCII letters and/or digits ?
549 for (QChar uc : tag) {
550 const char16_t ch = uc.unicode();
552 return false;
553 }
554 return tag.size() > 0;
555}
556
558{
559 // Every script name is 4 characters, a capital followed by three lower-case;
560 // so a search for tag in allScripts *can* only match if it's aligned.
561 static const QString allScripts =
562 QString::fromLatin1(reinterpret_cast<const char *>(script_code_list),
563 sizeof(script_code_list) - 1);
564 return tag.size() == 4 && allScripts.indexOf(tag) % 4 == 0;
565}
566
568{
569 // Assume each of lang, script and land is nullptr or points to an empty QStringView.
570 enum ParserState { NoState, LangState, ScriptState, CountryState };
571 ParserState state = LangState;
572 while (name.size() && state != NoState) {
573 const QStringView tag = findTag(name);
574 if (!validTag(tag))
575 break;
576 name = name.sliced(tag.size());
577 const bool sep = name.size() > 0;
578 if (sep) // tag wasn't all that remained; there was a separator
579 name = name.sliced(1);
580
581 switch (state) {
582 case LangState:
583 if (tag.size() != 2 && tag.size() != 3)
584 return false;
585 if (lang)
586 *lang = tag;
587 state = sep ? ScriptState : NoState;
588 break;
589 case ScriptState:
590 if (isScript(tag)) {
591 if (script)
592 *script = tag;
593 state = sep ? CountryState : NoState;
594 break;
595 }
596 // It wasn't a script, assume it's a country.
598 case CountryState:
599 if (land)
600 *land = tag;
601 state = NoState;
602 break;
603 case NoState: // Precluded by loop condition !
604 Q_UNREACHABLE();
605 break;
606 }
607 }
608 return state != LangState;
609}
610
612{
613 QStringView lang;
614 QStringView script;
615 QStringView land;
616 if (!qt_splitLocaleName(name, &lang, &script, &land))
617 return { QLocale::C, 0, 0 };
618
620 if (langId == QLocale::AnyLanguage)
621 return { QLocale::C, 0, 0 };
622 return { langId, QLocalePrivate::codeToScript(script), QLocalePrivate::codeToTerritory(land) };
623}
624
626{
627 qsizetype &i = *idx;
628
629 Q_ASSERT(format.at(i) == u'\'');
630 ++i;
631 if (i == format.size())
632 return QString();
633 if (format.at(i).unicode() == '\'') { // "''" outside of a quoted string
634 ++i;
635 return "'"_L1;
636 }
637
639
640 while (i < format.size()) {
641 if (format.at(i).unicode() == '\'') {
642 if (format.mid(i + 1).startsWith(u'\'')) {
643 // "''" inside a quoted string
644 result.append(u'\'');
645 i += 2;
646 } else {
647 break;
648 }
649 } else {
650 result.append(format.at(i++));
651 }
652 }
653 if (i < format.size())
654 ++i;
655
656 return result;
657}
658
676{
677 if (s.isEmpty())
678 return 0;
679 const QChar c = s.front();
680 qsizetype j = 1;
681 while (j < s.size() && s.at(j) == c)
682 ++j;
683 return j;
684}
685
686Q_CONSTINIT static const QLocaleData *default_data = nullptr;
688
690{
692 return &c_locale;
693}
694
695#ifndef QT_NO_SYSTEMLOCALE
696/******************************************************************************
697** Default system locale behavior
698*/
699
721{
722 _systemLocale = this;
723
724 systemLocaleData.m_language_id = 0;
725}
726
732{
733 if (_systemLocale == this) {
734 _systemLocale = next;
735
736 // Change to system locale => force refresh.
737 systemLocaleData.m_language_id = 0;
738 } else {
739 for (QSystemLocale *p = _systemLocale; p; p = p->next) {
740 if (p->next == this)
741 p->next = next;
742 }
743 }
744}
745
747{
748 if (_systemLocale)
749 return _systemLocale;
750
751 // As this is only ever instantiated with _systemLocale null, it is
752 // necessarily the ->next-most in any chain that may subsequently develop;
753 // and it won't be destructed until exit()-time.
754 static QSystemLocale globalInstance;
755 return &globalInstance;
756}
757
759{
760 // This function is NOT thread-safe!
761 // It *should not* be called by anything but systemData()
762 // It *is* called before {system,default}LocalePrivate exist.
763 const QSystemLocale *sys_locale = systemLocale();
764
765 // tell the object that the system locale has changed.
766 sys_locale->query(QSystemLocale::LocaleChanged);
767
768 // Populate system locale with fallback as basis
769 systemLocaleData = locale_data[sys_locale->fallbackLocaleIndex()];
770
771 QVariant res = sys_locale->query(QSystemLocale::LanguageId);
772 if (!res.isNull()) {
773 systemLocaleData.m_language_id = res.toInt();
774 systemLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
775 }
776 res = sys_locale->query(QSystemLocale::TerritoryId);
777 if (!res.isNull()) {
778 systemLocaleData.m_territory_id = res.toInt();
779 systemLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
780 }
781 res = sys_locale->query(QSystemLocale::ScriptId);
782 if (!res.isNull())
783 systemLocaleData.m_script_id = res.toInt();
784
785 // Should we replace Any values based on likely sub-tags ?
786
787 // If system locale is default locale, update the default collator's generation:
789 QLocalePrivate::s_generation.fetchAndAddRelaxed(1);
790}
791#endif // !QT_NO_SYSTEMLOCALE
792
793static const QLocaleData *systemData(qsizetype *sysIndex = nullptr)
794{
795#ifndef QT_NO_SYSTEMLOCALE
796 /*
797 Copy over the information from the fallback locale and modify.
798
799 If sysIndex is passed, it should be the m_index of the system locale's
800 QLocalePrivate, which we'll update if it needs it.
801
802 This modifies (cross-thread) global state, so is mutex-protected.
803 */
804 {
805 Q_CONSTINIT static QLocaleId sysId;
806 bool updated = false;
807
808 Q_CONSTINIT static QBasicMutex systemDataMutex;
809 systemDataMutex.lock();
810 if (systemLocaleData.m_language_id == 0) {
812 updated = true;
813 }
814 // Initialization of system private has *sysIndex == -1 to hit this.
815 if (sysIndex && (updated || *sysIndex < 0)) {
816 const QLocaleId nowId = systemLocaleData.id();
817 if (sysId != nowId || *sysIndex < 0) {
818 // This look-up may be expensive:
819 *sysIndex = QLocaleData::findLocaleIndex(nowId);
820 sysId = nowId;
821 }
822 }
823 systemDataMutex.unlock();
824 }
825
826 return &systemLocaleData;
827#else
828 Q_UNUSED(sysIndex);
829 return locale_data;
830#endif
831}
832
834{
835 if (!default_data)
837 return default_data;
838}
839
841{
842 const QLocaleData *const data = defaultData();
843#ifndef QT_NO_SYSTEMLOCALE
844 if (data == &systemLocaleData) {
845 // Work out a suitable index matching the system data, for use when
846 // accessing calendar data, when not fetched from system.
848 }
849#endif
850
852 Q_ASSERT(q_points_into_range(data, locale_data));
853 return data - locale_data;
854}
855
857{
859 return locale_data;
860}
861
862#ifndef QT_NO_DATASTREAM
864{
865 ds << l.name();
866 return ds;
867}
868
870{
871 QString s;
872 ds >> s;
873 l = QLocale(s);
874 return ds;
875}
876#endif // QT_NO_DATASTREAM
877
878static constexpr qsizetype locale_data_size = q20::ssize(locale_data) - 1; // trailing guard
879
880Q_GLOBAL_STATIC(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate,
882
883static QLocalePrivate *localePrivateByName(QStringView name)
884{
885 if (name == u"C")
886 return c_private();
890 locale_data[index].m_language_id == QLocale::C
892}
893
895 QLocale::Territory territory)
896{
897 if (language == QLocale::C)
898 return c_private();
899
903
904 QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions;
905
906 // If not found, should use default locale:
907 if (data->m_language_id == QLocale::C) {
908 if (defaultLocalePrivate.exists())
909 numberOptions = defaultLocalePrivate->data()->m_numberOptions;
910 data = defaultData();
912 }
913 return new QLocalePrivate(data, index, numberOptions);
914}
915
916static std::optional<QString>
918{
919#ifndef QT_NO_SYSTEMLOCALE
920 if (that != &systemLocaleData)
921 return std::nullopt;
922
923 QVariant v = systemLocale()->query(type);
924 if (v.metaType() != QMetaType::fromType<QString>())
925 return std::nullopt;
926
927 return v.toString();
928#else
929 Q_UNUSED(that)
931 return std::nullopt;
932#endif
933}
934
937{
938 if (auto opt = systemLocaleString(that, type))
939 return *opt;
940 return range.getData(single_character_data);
941}
942
944{
945 return localeString(this, QSystemLocale::DecimalPoint, decimalSeparator());
946}
947
949{
950 return localeString(this, QSystemLocale::GroupSeparator, groupDelim());
951}
952
954{
955 return percent().getData(single_character_data);
956}
957
959{
960 return listDelimit().getData(single_character_data);
961}
962
967
968char32_t QLocaleData::zeroUcs() const
969{
970#ifndef QT_NO_SYSTEMLOCALE
971 if (this == &systemLocaleData) {
972 const auto text = systemLocale()->query(QSystemLocale::ZeroDigit).toString();
973 if (!text.isEmpty()) {
974 if (text.size() == 1 && !text.at(0).isSurrogate())
975 return text.at(0).unicode();
976 if (text.size() == 2 && text.at(0).isHighSurrogate())
977 return QChar::surrogateToUcs4(text.at(0), text.at(1));
978 }
979 }
980#endif
981 return zero().ucsFirst(single_character_data);
982}
983
985{
986 return localeString(this, QSystemLocale::NegativeSign, minus());
987}
988
993
995{
996 return exponential().getData(single_character_data);
997}
998
1003 : d(&dd)
1004{}
1005
1052 : d(localePrivateByName(name))
1053{
1054}
1055
1071 : d(*defaultLocalePrivate)
1072{
1073 // Make sure system data is up to date:
1074 systemData();
1075}
1076
1090 : d(findLocalePrivate(language, AnyScript, territory))
1091{
1092}
1093
1114 : d(findLocalePrivate(language, script, territory))
1115{
1116}
1117
1122QLocale::QLocale(const QLocale &other) noexcept = default;
1123
1129{
1130}
1131
1137QLocale &QLocale::operator=(const QLocale &other) noexcept = default;
1138
1144bool QLocale::equals(const QLocale &other) const
1145{
1146 return d->m_data == other.d->m_data && d->m_numberOptions == other.d->m_numberOptions;
1147}
1148
1164size_t qHash(const QLocale &key, size_t seed) noexcept
1165{
1166 return qHashMulti(seed, key.d->m_data, key.d->m_numberOptions);
1167}
1168
1177void QLocale::setNumberOptions(NumberOptions options)
1178{
1179 d->m_numberOptions = options;
1180}
1181
1193QLocale::NumberOptions QLocale::numberOptions() const
1194{
1195 return static_cast<NumberOptions>(d->m_numberOptions);
1196}
1197
1213{
1214#ifndef QT_NO_SYSTEMLOCALE
1215 if (d->m_data == &systemLocaleData) {
1216 QVariant res;
1217 if (style == AlternateQuotation)
1220 if (res.isNull() || style == StandardQuotation)
1223 if (!res.isNull())
1224 return res.toString();
1225 }
1226#endif
1227
1229 if (style == StandardQuotation) {
1230 start = d->m_data->quoteStart();
1231 end = d->m_data->quoteEnd();
1232 } else {
1233 start = d->m_data->quoteStartAlternate();
1234 end = d->m_data->quoteEndAlternate();
1235 }
1236
1237 return start.viewData(single_character_data) % str % end.viewData(single_character_data);
1238}
1239
1247{
1248 // May be empty if list is empty or sole entry is empty.
1249#ifndef QT_NO_SYSTEMLOCALE
1250 if (d->m_data == &systemLocaleData) {
1251 QVariant res =
1253
1254 if (!res.isNull())
1255 return res.toString();
1256 }
1257#endif
1258
1259 const qsizetype size = list.size();
1260 if (size < 1)
1261 return QString();
1262
1263 if (size == 1)
1264 return list.at(0);
1265
1266 if (size == 2)
1267 return d->m_data->pairListPattern().getData(
1268 list_pattern_part_data).arg(list.at(0), list.at(1));
1269
1270 QStringView formatStart = d->m_data->startListPattern().viewData(list_pattern_part_data);
1271 QStringView formatMid = d->m_data->midListPattern().viewData(list_pattern_part_data);
1272 QStringView formatEnd = d->m_data->endListPattern().viewData(list_pattern_part_data);
1273 QString result = formatStart.arg(list.at(0), list.at(1));
1274 for (qsizetype i = 2; i < size - 1; ++i)
1275 result = formatMid.arg(result, list.at(i));
1276 result = formatEnd.arg(result, list.at(size - 1));
1277 return result;
1278}
1279
1295void QLocale::setDefault(const QLocale &locale)
1296{
1297 default_data = locale.d->m_data;
1298
1299 if (defaultLocalePrivate.isDestroyed())
1300 return; // avoid crash on exit
1301 if (!defaultLocalePrivate.exists()) {
1302 // Force it to exist; see QTBUG-83016
1303 QLocale ignoreme;
1304 Q_ASSERT(defaultLocalePrivate.exists());
1305 }
1306
1307 // update the cached private
1308 *defaultLocalePrivate = locale.d;
1309 QLocalePrivate::s_generation.fetchAndAddRelaxed(1);
1310}
1311
1318{
1319 return Language(d->languageId());
1320}
1321
1330{
1331 return Script(d->m_data->m_script_id);
1332}
1333
1342{
1343 return Territory(d->territoryId());
1344}
1345
1346#if QT_DEPRECATED_SINCE(6, 6)
1354QLocale::Country QLocale::country() const
1355{
1356 return territory();
1357}
1358#endif
1359
1387{
1388 qWarning("QLocale::%s(): Using non-ASCII separator '%c' (%02x) is unsupported",
1389 method, sep, uint(uchar(sep)));
1390}
1391
1413{
1414 const char sep = char(separator);
1415 if (uchar(sep) > 0x7f) {
1416 badSeparatorWarning("name", sep);
1417 return {};
1418 }
1419 const auto code = d->languageCode();
1420 QLatin1StringView view{code.data()};
1421
1422 Language l = language();
1423 if (l == C)
1424 return view;
1425
1426 Territory c = territory();
1427 if (c == AnyTerritory)
1428 return view;
1429
1430 return view + QLatin1Char(sep) + d->territoryCode();
1431}
1432
1433template <typename T> static inline
1435{
1436 constexpr bool isUnsigned = std::is_unsigned_v<T>;
1437 using Int64 = typename std::conditional_t<isUnsigned, quint64, qint64>;
1438
1439 QSimpleParsedNumber<Int64> r{};
1440 if constexpr (isUnsigned)
1441 r = d->m_data->stringToUnsLongLong(str, 10, d->m_numberOptions);
1442 else
1443 r = d->m_data->stringToLongLong(str, 10, d->m_numberOptions);
1444
1445 if (ok)
1446 *ok = r.ok();
1447
1448 Int64 val = r.result;
1449 if (T(val) != val) {
1450 if (ok != nullptr)
1451 *ok = false;
1452 val = 0;
1453 }
1454 return T(val);
1455}
1456
1457
1483{
1484 const char sep = char(separator);
1485 if (uchar(sep) > 0x7f) {
1486 badSeparatorWarning("bcp47Name", sep);
1487 return {};
1488 }
1489 return QString::fromLatin1(d->bcp47Name(sep));
1490}
1491
1511{
1512 const auto code = QLocalePrivate::languageToCode(language, codeTypes);
1513 return QLatin1StringView{code.data()};
1514}
1515
1531 LanguageCodeTypes codeTypes) noexcept
1532{
1533 return QLocalePrivate::codeToLanguage(languageCode, codeTypes);
1534}
1535
1550
1562{
1563 return QLocalePrivate::codeToTerritory(territoryCode);
1564}
1565
1566#if QT_DEPRECATED_SINCE(6, 6)
1577QString QLocale::countryToCode(Country country)
1578{
1579 return territoryToCode(country);
1580}
1581
1592QLocale::Country QLocale::codeToCountry(QStringView countryCode) noexcept
1593{
1594 return QLocalePrivate::codeToTerritory(countryCode);
1595}
1596#endif
1597
1611
1622{
1623 return QLocalePrivate::codeToScript(scriptCode);
1624}
1625
1638
1652
1653#if QT_DEPRECATED_SINCE(6, 6)
1661QString QLocale::countryToString(Country country)
1662{
1663 return territoryToString(country);
1664}
1665#endif
1666
1675{
1676 if (script > LastScript)
1677 return "Unknown"_L1;
1679}
1680
1854{
1855 return toIntegral_helper<short>(d, s, ok);
1856}
1857
1874{
1875 return toIntegral_helper<ushort>(d, s, ok);
1876}
1877
1894{
1895 return toIntegral_helper<int>(d, s, ok);
1896}
1897
1914{
1915 return toIntegral_helper<uint>(d, s, ok);
1916}
1917
1933{
1934 return toIntegral_helper<long>(d, s, ok);
1935}
1936
1953{
1954 return toIntegral_helper<ulong>(d, s, ok);
1955}
1956
1974{
1975 return toIntegral_helper<qlonglong>(d, s, ok);
1976}
1977
1995{
1996 return toIntegral_helper<qulonglong>(d, s, ok);
1997}
1998
2016{
2018}
2019
2041double QLocale::toDouble(QStringView s, bool *ok) const
2042{
2043 return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
2044}
2045
2053{
2056
2057 return d->m_data->longLongToString(i, -1, 10, -1, flags);
2058}
2059
2067{
2070
2071 return d->m_data->unsLongLongToString(i, -1, 10, -1, flags);
2072}
2073
2086
2099
2121{
2122 return cal.dateTimeToString(format, QDateTime(), date, QTime(), *this);
2123}
2124
2133
2145{
2146 if (!date.isValid())
2147 return QString();
2148
2149#ifndef QT_NO_SYSTEMLOCALE
2150 if (cal.isGregorian() && d->m_data == &systemLocaleData) {
2154 date);
2155 if (!res.isNull())
2156 return res.toString();
2157 }
2158#endif
2159
2160 QString format_str = dateFormat(format);
2161 return toString(date, format_str, cal);
2162}
2163
2169{
2170 if (!date.isValid())
2171 return QString();
2172
2173#ifndef QT_NO_SYSTEMLOCALE
2174 if (d->m_data == &systemLocaleData) {
2178 date);
2179 if (!res.isNull())
2180 return res.toString();
2181 }
2182#endif
2183
2184 QString format_str = dateFormat(format);
2185 return toString(date, format_str);
2186}
2187
2189{
2190 qsizetype i = 0;
2191 while (i < format.size()) {
2192 if (format.at(i).unicode() == '\'') {
2194 continue;
2195 }
2196
2197 if (format.at(i).toLower().unicode() == 'a')
2198 return true;
2199
2200 ++i;
2201 }
2202 return false;
2203}
2204
2218
2229{
2230 return cal.dateTimeToString(format, dateTime, QDate(), QTime(), *this);
2231}
2232
2241
2253{
2254 if (!dateTime.isValid())
2255 return QString();
2256
2257#ifndef QT_NO_SYSTEMLOCALE
2258 if (cal.isGregorian() && d->m_data == &systemLocaleData) {
2262 dateTime);
2263 if (!res.isNull())
2264 return res.toString();
2265 }
2266#endif
2267
2268 const QString format_str = dateTimeFormat(format);
2269 return toString(dateTime, format_str, cal);
2270}
2271
2277{
2278 if (!dateTime.isValid())
2279 return QString();
2280
2281#ifndef QT_NO_SYSTEMLOCALE
2282 if (d->m_data == &systemLocaleData) {
2286 dateTime);
2287 if (!res.isNull())
2288 return res.toString();
2289 }
2290#endif
2291
2292 const QString format_str = dateTimeFormat(format);
2293 return toString(dateTime, format_str);
2294}
2295
2296
2303{
2304 if (!time.isValid())
2305 return QString();
2306
2307#ifndef QT_NO_SYSTEMLOCALE
2308 if (d->m_data == &systemLocaleData) {
2312 time);
2313 if (!res.isNull())
2314 return res.toString();
2315 }
2316#endif
2317
2318 QString format_str = timeFormat(format);
2319 return toString(time, format_str);
2320}
2321
2335{
2336#ifndef QT_NO_SYSTEMLOCALE
2337 if (d->m_data == &systemLocaleData) {
2341 QVariant());
2342 if (!res.isNull())
2343 return res.toString();
2344 }
2345#endif
2346
2347 return (format == LongFormat
2348 ? d->m_data->longDateFormat()
2349 : d->m_data->shortDateFormat()
2351}
2352
2366{
2367#ifndef QT_NO_SYSTEMLOCALE
2368 if (d->m_data == &systemLocaleData) {
2372 QVariant());
2373 if (!res.isNull())
2374 return res.toString();
2375 }
2376#endif
2377
2378 return (format == LongFormat
2379 ? d->m_data->longTimeFormat()
2380 : d->m_data->shortTimeFormat()
2382}
2383
2397{
2398#ifndef QT_NO_SYSTEMLOCALE
2399 if (d->m_data == &systemLocaleData) {
2403 QVariant());
2404 if (!res.isNull()) {
2405 return res.toString();
2406 }
2407 }
2408#endif
2409 return dateFormat(format) + u' ' + timeFormat(format);
2410}
2411
2412#if QT_CONFIG(datestring)
2428QTime QLocale::toTime(const QString &string, FormatType format) const
2429{
2430 return toTime(string, timeFormat(format));
2431}
2432
2442
2450
2458QDate QLocale::toDate(const QString &string, FormatType format, int baseYear) const
2459{
2460 return toDate(string, dateFormat(format), baseYear);
2461}
2462
2467QDate QLocale::toDate(const QString &string, FormatType format, QCalendar cal, int baseYear) const
2468{
2469 return toDate(string, dateFormat(format), cal, baseYear);
2470}
2471
2491QDateTime QLocale::toDateTime(const QString &string, FormatType format, int baseYear) const
2492{
2493 return toDateTime(string, dateTimeFormat(format), baseYear);
2494}
2495
2500QDateTime QLocale::toDateTime(const QString &string, FormatType format, QCalendar cal,
2501 int baseYear) const
2502{
2503 return toDateTime(string, dateTimeFormat(format), cal, baseYear);
2504}
2505
2521QTime QLocale::toTime(const QString &string, const QString &format) const
2522{
2523 QTime time;
2524#if QT_CONFIG(datetimeparser)
2525 QDateTimeParser dt(QMetaType::QTime, QDateTimeParser::FromString, QCalendar());
2526 dt.setDefaultLocale(*this);
2527 if (dt.parseFormat(format))
2528 dt.fromString(string, nullptr, &time);
2529#else
2530 Q_UNUSED(string);
2532#endif
2533 return time;
2534}
2535
2545
2553
2561QDate QLocale::toDate(const QString &string, const QString &format, int baseYear) const
2562{
2563 return toDate(string, format, QCalendar(), baseYear);
2564}
2565
2570QDate QLocale::toDate(const QString &string, const QString &format, QCalendar cal, int baseYear) const
2571{
2572 QDate date;
2573#if QT_CONFIG(datetimeparser)
2574 QDateTimeParser dt(QMetaType::QDate, QDateTimeParser::FromString, cal);
2575 dt.setDefaultLocale(*this);
2576 if (dt.parseFormat(format))
2577 dt.fromString(string, &date, nullptr, baseYear);
2578#else
2579 Q_UNUSED(string);
2581 Q_UNUSED(baseYear);
2582 Q_UNUSED(cal);
2583#endif
2584 return date;
2585}
2586
2610QDateTime QLocale::toDateTime(const QString &string, const QString &format, int baseYear) const
2611{
2612 return toDateTime(string, format, QCalendar(), baseYear);
2613}
2614
2619QDateTime QLocale::toDateTime(const QString &string, const QString &format, QCalendar cal,
2620 int baseYear) const
2621{
2622#if QT_CONFIG(datetimeparser)
2623 QDateTime datetime;
2624
2625 QDateTimeParser dt(QMetaType::QDateTime, QDateTimeParser::FromString, cal);
2626 dt.setDefaultLocale(*this);
2627 if (dt.parseFormat(format) && (dt.fromString(string, &datetime, baseYear)
2628 || !datetime.isValid())) {
2629 return datetime;
2630 }
2631#else
2632 Q_UNUSED(string);
2634 Q_UNUSED(baseYear);
2635 Q_UNUSED(cal);
2636#endif
2637 return QDateTime();
2638}
2639#endif // datestring
2640
2656{
2657 return d->m_data->decimalPoint();
2658}
2659
2675{
2676 return d->m_data->groupSeparator();
2677}
2678
2692{
2693 return d->m_data->percentSign();
2694}
2695
2711{
2712 return d->m_data->zeroDigit();
2713}
2714
2728{
2729 return d->m_data->negativeSign();
2730}
2731
2745{
2746 return d->m_data->positiveSign();
2747}
2748
2763{
2764 return d->m_data->exponentSeparator();
2765}
2766
2802{
2805
2807 case 'f':
2809 break;
2810 case 'e':
2812 break;
2813 case 'g':
2815 break;
2816 default:
2817 break;
2818 }
2819
2826 return d->m_data->doubleToString(f, precision, form, -1, flags);
2827}
2828
2863{
2864 constexpr auto sysData = []() {
2865 // Same return as systemData(), but leave the setup to the actual call to it.
2866#ifdef QT_NO_SYSTEMLOCALE
2867 return locale_data;
2868#else
2869 return &systemLocaleData;
2870#endif
2871 };
2872 Q_CONSTINIT static QLocalePrivate locale(sysData(), -1, DefaultNumberOptions, 1);
2873 // Calling systemData() ensures system data is up to date; we also need it
2874 // to ensure that locale's index stays up to date:
2875 systemData(&locale.m_index);
2876 Q_ASSERT(locale.m_index >= 0 && locale.m_index < locale_data_size);
2877
2878 return QLocale(locale);
2879}
2880
2894{
2896 if (!filter.isValid())
2897 return QList<QLocale>();
2898
2899 if (language == C)
2900 return QList<QLocale>{QLocale(C)};
2901
2902 QList<QLocale> result;
2903 if (filter.matchesAll())
2904 result.reserve(locale_data_size);
2905
2907 // There may be no matches, for some languages (e.g. Abkhazian at CLDR v39).
2908 while (filter.acceptLanguage(locale_data[index].m_language_id)) {
2909 const QLocaleId id = locale_data[index].id();
2910 if (filter.acceptScriptTerritory(id)) {
2911 result.append(QLocale(*(id.language_id == C ? c_private()
2913 }
2914 ++index;
2915 }
2916
2917 // Add current system locale, if it matches
2918 const auto syslocaledata = systemData();
2919
2920 if (filter.acceptLanguage(syslocaledata->m_language_id)) {
2921 const QLocaleId id = syslocaledata->id();
2922 if (filter.acceptScriptTerritory(id))
2923 result.append(system());
2924 }
2925
2926 return result;
2927}
2928
2929#if QT_DEPRECATED_SINCE(6, 6)
2940QList<QLocale::Country> QLocale::countriesForLanguage(Language language)
2941{
2942 const auto locales = matchingLocales(language, AnyScript, AnyCountry);
2943 QList<Country> result;
2944 result.reserve(locales.size());
2945 for (const auto &locale : locales)
2946 result.append(locale.territory());
2947 return result;
2948}
2949#endif
2950
2964{
2965 return QCalendar().monthName(*this, month, QCalendar::Unspecified, type);
2966}
2967
2983
2998{
2999 return QCalendar().weekDayName(*this, day, type);
3000}
3001
3015{
3016 return QCalendar().standaloneWeekDayName(*this, day, type);
3017}
3018
3019// Calendar look-up of month and day names:
3020
3021// Only used in assertions
3022[[maybe_unused]] static bool sameLocale(const QLocaleData *locale, const QCalendarLocale &calendar)
3023{
3024 return locale->m_language_id == calendar.m_language_id
3025 && locale->m_script_id == calendar.m_script_id
3026 && locale->m_territory_id == calendar.m_territory_id;
3027}
3028
3033static QString rawMonthName(const QCalendarLocale &localeData,
3034 const char16_t *monthsData, int month,
3036{
3038 switch (type) {
3040 range = localeData.longMonth();
3041 break;
3043 range = localeData.shortMonth();
3044 break;
3046 range = localeData.narrowMonth();
3047 break;
3048 default:
3049 return QString();
3050 }
3051 return range.getListEntry(monthsData, month - 1);
3052}
3053
3059 const char16_t *monthsData, int month,
3061{
3063 switch (type) {
3065 range = localeData.longMonthStandalone();
3066 break;
3068 range = localeData.shortMonthStandalone();
3069 break;
3071 range = localeData.narrowMonthStandalone();
3072 break;
3073 default:
3074 return QString();
3075 }
3076 QString name = range.getListEntry(monthsData, month - 1);
3077 return name.isEmpty() ? rawMonthName(localeData, monthsData, month, type) : name;
3078}
3079
3084static QString rawWeekDayName(const QLocaleData *data, const int day,
3086{
3088 switch (type) {
3090 range = data->longDayNames();
3091 break;
3093 range = data->shortDayNames();
3094 break;
3096 range = data->narrowDayNames();
3097 break;
3098 default:
3099 return QString();
3100 }
3101 return range.getListEntry(days_data, day == 7 ? 0 : day);
3102}
3103
3110{
3112 switch (type) {
3114 range =data->longDayNamesStandalone();
3115 break;
3117 range = data->shortDayNamesStandalone();
3118 break;
3120 range = data->narrowDayNamesStandalone();
3121 break;
3122 default:
3123 return QString();
3124 }
3125 QString name = range.getListEntry(days_data, day == 7 ? 0 : day);
3126 if (name.isEmpty())
3127 return rawWeekDayName(data, day, type);
3128 return name;
3129}
3130
3131// Refugees from qcalendar.cpp that need functions above:
3132
3133QString QCalendarBackend::monthName(const QLocale &locale, int month, int,
3135{
3136 Q_ASSERT(month >= 1 && month <= maximumMonthsInYear());
3137 const QCalendarLocale &monthly = localeMonthIndexData()[locale.d->m_index];
3138 Q_ASSERT(sameLocale(locale.d->m_data, monthly));
3139 return rawMonthName(monthly, localeMonthData(), month, format);
3140}
3141
3142QString QRomanCalendar::monthName(const QLocale &locale, int month, int year,
3144{
3145#ifndef QT_NO_SYSTEMLOCALE
3146 if (locale.d->m_data == &systemLocaleData) {
3147 Q_ASSERT(month >= 1 && month <= 12);
3149 switch (format) {
3151 queryType = QSystemLocale::MonthNameLong;
3152 break;
3155 break;
3158 break;
3159 }
3160 QVariant res = systemLocale()->query(queryType, month);
3161 if (!res.isNull())
3162 return res.toString();
3163 }
3164#endif
3165
3166 return QCalendarBackend::monthName(locale, month, year, format);
3167}
3168
3171{
3172 Q_ASSERT(month >= 1 && month <= maximumMonthsInYear());
3173 const QCalendarLocale &monthly = localeMonthIndexData()[locale.d->m_index];
3174 Q_ASSERT(sameLocale(locale.d->m_data, monthly));
3175 return rawStandaloneMonthName(monthly, localeMonthData(), month, format);
3176}
3177
3178QString QRomanCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
3180{
3181#ifndef QT_NO_SYSTEMLOCALE
3182 if (locale.d->m_data == &systemLocaleData) {
3183 Q_ASSERT(month >= 1 && month <= 12);
3185 switch (format) {
3188 break;
3191 break;
3194 break;
3195 }
3196 QVariant res = systemLocale()->query(queryType, month);
3197 if (!res.isNull())
3198 return res.toString();
3199 }
3200#endif
3201
3202 return QCalendarBackend::standaloneMonthName(locale, month, year, format);
3203}
3204
3205// Most calendars share the common week-day naming, modulo locale.
3206// Calendars that don't must override these methods.
3209{
3210 if (day < 1 || day > 7)
3211 return QString();
3212
3213#ifndef QT_NO_SYSTEMLOCALE
3214 if (locale.d->m_data == &systemLocaleData) {
3216 switch (format) {
3218 queryType = QSystemLocale::DayNameLong;
3219 break;
3221 queryType = QSystemLocale::DayNameShort;
3222 break;
3224 queryType = QSystemLocale::DayNameNarrow;
3225 break;
3226 }
3227 QVariant res = systemLocale()->query(queryType, day);
3228 if (!res.isNull())
3229 return res.toString();
3230 }
3231#endif
3232
3233 return rawWeekDayName(locale.d->m_data, day, format);
3234}
3235
3238{
3239 if (day < 1 || day > 7)
3240 return QString();
3241
3242#ifndef QT_NO_SYSTEMLOCALE
3243 if (locale.d->m_data == &systemLocaleData) {
3245 switch (format) {
3248 break;
3251 break;
3254 break;
3255 }
3256 QVariant res = systemLocale()->query(queryType, day);
3257 if (!res.isNull())
3258 return res.toString();
3259 }
3260#endif
3261
3262 return rawStandaloneWeekDayName(locale.d->m_data, day, format);
3263}
3264
3265// End of this block of qcalendar.cpp refugees. (One more follows.)
3266
3273{
3274#ifndef QT_NO_SYSTEMLOCALE
3275 if (d->m_data == &systemLocaleData) {
3276 const auto res = systemLocale()->query(QSystemLocale::FirstDayOfWeek);
3277 if (!res.isNull())
3278 return static_cast<Qt::DayOfWeek>(res.toUInt());
3279 }
3280#endif
3281 return static_cast<Qt::DayOfWeek>(d->m_data->m_first_day_of_week);
3282}
3283
3285{
3286 for (const auto &system : ImperialMeasurementSystems) {
3287 if (system.languageId == m_data->m_language_id
3288 && system.territoryId == m_data->m_territory_id) {
3289 return system.system;
3290 }
3291 }
3292 return QLocale::MetricSystem;
3293}
3294
3300QList<Qt::DayOfWeek> QLocale::weekdays() const
3301{
3302#ifndef QT_NO_SYSTEMLOCALE
3303 if (d->m_data == &systemLocaleData) {
3304 auto res
3305 = qvariant_cast<QList<Qt::DayOfWeek> >(systemLocale()->query(QSystemLocale::Weekdays));
3306 if (!res.isEmpty())
3307 return res;
3308 }
3309#endif
3310 QList<Qt::DayOfWeek> weekdays;
3311 quint16 weekendStart = d->m_data->m_weekend_start;
3312 quint16 weekendEnd = d->m_data->m_weekend_end;
3313 for (int day = Qt::Monday; day <= Qt::Sunday; day++) {
3314 if ((weekendEnd >= weekendStart && (day < weekendStart || day > weekendEnd)) ||
3315 (weekendEnd < weekendStart && (day > weekendEnd && day < weekendStart)))
3316 weekdays << static_cast<Qt::DayOfWeek>(day);
3317 }
3318 return weekdays;
3319}
3320
3327{
3328#ifndef QT_NO_SYSTEMLOCALE
3329 if (d->m_data == &systemLocaleData) {
3330 const auto res = systemLocale()->query(QSystemLocale::MeasurementSystem);
3331 if (!res.isNull())
3332 return MeasurementSystem(res.toInt());
3333 }
3334#endif
3335
3336 return d->measurementSystem();
3337}
3338
3345{
3346 switch (script()) {
3347 case AdlamScript:
3348 case ArabicScript:
3349 case AvestanScript:
3350 case CypriotScript:
3351 case HatranScript:
3352 case HebrewScript:
3356 case KharoshthiScript:
3357 case LydianScript:
3358 case MandaeanScript:
3359 case ManichaeanScript:
3360 case MendeKikakuiScript:
3362 case MeroiticScript:
3363 case NabataeanScript:
3364 case NkoScript:
3365 case OldHungarianScript:
3368 case OrkhonScript:
3369 case PalmyreneScript:
3370 case PhoenicianScript:
3372 case SamaritanScript:
3373 case SyriacScript:
3374 case ThaanaScript:
3375 return Qt::RightToLeft;
3376 default:
3377 break;
3378 }
3379 return Qt::LeftToRight;
3380}
3381
3395{
3396#if QT_CONFIG(icu)
3397 bool ok = true;
3398 QString result = QIcu::toUpper(d->bcp47Name('_'), str, &ok);
3399 if (ok)
3400 return result;
3401 // else fall through and use Qt's toUpper
3402#endif
3403 return str.toUpper();
3404}
3405
3419{
3420#if QT_CONFIG(icu)
3421 bool ok = true;
3422 const QString result = QIcu::toLower(d->bcp47Name('_'), str, &ok);
3423 if (ok)
3424 return result;
3425 // else fall through and use Qt's toUpper
3426#endif
3427 return str.toLower();
3428}
3429
3430
3440{
3441#ifndef QT_NO_SYSTEMLOCALE
3442 if (d->m_data == &systemLocaleData) {
3443 auto res = systemLocale()->query(QSystemLocale::AMText).toString();
3444 if (!res.isEmpty())
3445 return res;
3446 }
3447#endif
3448 return d->m_data->anteMeridiem().getData(am_data);
3449}
3450
3460{
3461#ifndef QT_NO_SYSTEMLOCALE
3462 if (d->m_data == &systemLocaleData) {
3463 auto res = systemLocale()->query(QSystemLocale::PMText).toString();
3464 if (!res.isEmpty())
3465 return res;
3466 }
3467#endif
3468 return d->m_data->postMeridiem().getData(pm_data);
3469}
3470
3471// Another intrusion from QCalendar, using some of the tools above:
3472
3474 QDate dateOnly, QTime timeOnly,
3475 const QLocale &locale) const
3476{
3477 QDate date;
3478 QTime time;
3479 bool formatDate = false;
3480 bool formatTime = false;
3481 if (datetime.isValid()) {
3482 date = datetime.date();
3483 time = datetime.time();
3484 formatDate = true;
3485 formatTime = true;
3486 } else if (dateOnly.isValid()) {
3487 date = dateOnly;
3488 formatDate = true;
3489 } else if (timeOnly.isValid()) {
3490 time = timeOnly;
3491 formatTime = true;
3492 } else {
3493 return QString();
3494 }
3495
3497 int year = 0, month = 0, day = 0;
3498 if (formatDate) {
3499 const auto parts = julianDayToDate(date.toJulianDay());
3500 if (!parts.isValid())
3501 return QString();
3502 year = parts.year;
3503 month = parts.month;
3504 day = parts.day;
3505 }
3506
3507 auto appendToResult = [&](int t, int repeat) {
3508 auto data = locale.d->m_data;
3509 if (repeat > 1)
3510 result.append(data->longLongToString(t, -1, 10, repeat, QLocaleData::ZeroPadded));
3511 else
3512 result.append(data->longLongToString(t));
3513 };
3514
3515 auto formatType = [](int repeat) {
3516 return repeat == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
3517 };
3518
3519 qsizetype i = 0;
3520 while (i < format.size()) {
3521 if (format.at(i).unicode() == '\'') {
3523 continue;
3524 }
3525
3526 const QChar c = format.at(i);
3527 qsizetype rep = qt_repeatCount(format.mid(i));
3528 Q_ASSERT(rep < std::numeric_limits<int>::max());
3529 int repeat = int(rep);
3530 bool used = false;
3531 if (formatDate) {
3532 switch (c.unicode()) {
3533 case 'y':
3534 used = true;
3535 if (repeat >= 4)
3536 repeat = 4;
3537 else if (repeat >= 2)
3538 repeat = 2;
3539
3540 switch (repeat) {
3541 case 4:
3542 appendToResult(year, (year < 0) ? 5 : 4);
3543 break;
3544 case 2:
3545 appendToResult(year % 100, 2);
3546 break;
3547 default:
3548 repeat = 1;
3549 result.append(c);
3550 break;
3551 }
3552 break;
3553
3554 case 'M':
3555 used = true;
3556 repeat = qMin(repeat, 4);
3557 if (repeat <= 2)
3558 appendToResult(month, repeat);
3559 else
3560 result.append(monthName(locale, month, year, formatType(repeat)));
3561 break;
3562
3563 case 'd':
3564 used = true;
3565 repeat = qMin(repeat, 4);
3566 if (repeat <= 2)
3567 appendToResult(day, repeat);
3568 else
3569 result.append(
3570 locale.dayName(dayOfWeek(date.toJulianDay()), formatType(repeat)));
3571 break;
3572
3573 default:
3574 break;
3575 }
3576 }
3577 if (!used && formatTime) {
3578 switch (c.unicode()) {
3579 case 'h': {
3580 used = true;
3581 repeat = qMin(repeat, 2);
3582 int hour = time.hour();
3584 if (hour > 12)
3585 hour -= 12;
3586 else if (hour == 0)
3587 hour = 12;
3588 }
3589 appendToResult(hour, repeat);
3590 break;
3591 }
3592 case 'H':
3593 used = true;
3594 repeat = qMin(repeat, 2);
3595 appendToResult(time.hour(), repeat);
3596 break;
3597
3598 case 'm':
3599 used = true;
3600 repeat = qMin(repeat, 2);
3601 appendToResult(time.minute(), repeat);
3602 break;
3603
3604 case 's':
3605 used = true;
3606 repeat = qMin(repeat, 2);
3607 appendToResult(time.second(), repeat);
3608 break;
3609
3610 case 'A':
3611 case 'a': {
3612 QString text = time.hour() < 12 ? locale.amText() : locale.pmText();
3613 used = true;
3614 repeat = 1;
3615 if (format.mid(i + 1).startsWith(u'p', Qt::CaseInsensitive))
3616 ++repeat;
3617 if (c.unicode() == 'A' && (repeat == 1 || format.at(i + 1).unicode() == 'P'))
3618 text = std::move(text).toUpper();
3619 else if (c.unicode() == 'a' && (repeat == 1 || format.at(i + 1).unicode() == 'p'))
3620 text = std::move(text).toLower();
3621 // else 'Ap' or 'aP' => use CLDR text verbatim, preserving case
3623 break;
3624 }
3625
3626 case 'z':
3627 used = true;
3628 repeat = qMin(repeat, 3);
3629
3630 // note: the millisecond component is treated like the decimal part of the seconds
3631 // so ms == 2 is always printed as "002", but ms == 200 can be either "2" or "200"
3632 appendToResult(time.msec(), 3);
3633 if (repeat != 3) {
3634 if (result.endsWith(locale.zeroDigit()))
3635 result.chop(1);
3636 if (result.endsWith(locale.zeroDigit()))
3637 result.chop(1);
3638 }
3639 break;
3640
3641 case 't': {
3642 enum AbbrType { Long, Offset, Short };
3643 const auto tzAbbr = [locale](const QDateTime &when, AbbrType type) {
3644#if QT_CONFIG(timezone)
3645 if (type != Short || locale != QLocale::system()) {
3646 QTimeZone::NameType mode =
3647 type == Short ? QTimeZone::ShortName
3648 : type == Long ? QTimeZone::LongName : QTimeZone::OffsetName;
3649 return when.timeRepresentation().displayName(when, mode, locale);
3650 } // else: prefer QDateTime's abbreviation, for backwards-compatibility.
3651#endif // else, make do with non-localized abbreviation:
3652 if (type != Offset)
3653 return when.timeZoneAbbreviation();
3654 // For Offset, we can coerce to a UTC-based zone's abbreviation:
3655 return when.toOffsetFromUtc(when.offsetFromUtc()).timeZoneAbbreviation();
3656 };
3657 used = true;
3658 repeat = qMin(repeat, 4);
3659 // If we don't have a date-time, use the current system time:
3660 const QDateTime when = formatDate ? datetime : QDateTime::currentDateTime();
3661 QString text;
3662 switch (repeat) {
3663 case 4:
3664 text = tzAbbr(when, Long);
3665 break;
3666 case 3: // ±hh:mm
3667 case 2: // ±hhmm (we'll remove the ':' at the end)
3668 text = tzAbbr(when, Offset);
3669 Q_ASSERT(text.startsWith("UTC"_L1)); // Need to strip this.
3670 // The Qt::UTC case omits the zero offset:
3671 text = (text.size() == 3
3672 ? u"+00:00"_s
3673 : (text.size() <= 6
3674 // Whole-hour offsets may lack the zero minutes:
3675 ? QStringView{text}.sliced(3) + ":00"_L1
3676 : std::move(text).sliced(3)));
3677 if (repeat == 2)
3678 text = text.remove(u':');
3679 break;
3680 default:
3681 text = tzAbbr(when, Short);
3682 // UTC-offset zones only include minutes if non-zero.
3683 if (text.startsWith("UTC"_L1) && text.size() == 6)
3684 text += ":00"_L1;
3685 break;
3686 }
3687 if (!text.isEmpty())
3689 break;
3690 }
3691
3692 default:
3693 break;
3694 }
3695 }
3696 if (!used)
3697 result.resize(result.size() + repeat, c);
3698 i += repeat;
3699 }
3700
3701 return result;
3702}
3703
3704// End of QCalendar intrustions
3705
3707 int width, unsigned flags) const
3708{
3709 // Although the special handling of F.P.Shortest below is limited to
3710 // DFSignificantDigits, the double-conversion library does treat it
3711 // specially for the other forms, shedding trailing zeros for DFDecimal and
3712 // using the shortest mantissa that faithfully represents the value for
3713 // DFExponent.
3715 precision = 6;
3716 if (width < 0)
3717 width = 0;
3718
3719 int decpt;
3720 qsizetype bufSize = 1;
3722 bufSize += std::numeric_limits<double>::max_digits10;
3723 else if (form == DFDecimal && qt_is_finite(d))
3725 else // Add extra digit due to different interpretations of precision.
3726 bufSize += qMax(2, precision) + 1; // Must also be big enough for "nan" or "inf"
3727
3728 QVarLengthArray<char> buf(bufSize);
3729 int length;
3730 bool negative = false;
3731 qt_doubleToAscii(d, form, precision, buf.data(), bufSize, negative, length, decpt);
3732
3733 const QString prefix = signPrefix(negative && !isZero(d), flags);
3734 QString numStr;
3735
3736 if (length == 3
3737 && (qstrncmp(buf.data(), "inf", 3) == 0 || qstrncmp(buf.data(), "nan", 3) == 0)) {
3738 numStr = QString::fromLatin1(buf.data(), length);
3739 } else { // Handle finite values
3740 const QString zero = zeroDigit();
3742
3743 if (zero == u"0") {
3744 // No need to convert digits.
3745 Q_ASSERT(std::all_of(buf.cbegin(), buf.cbegin() + length, isAsciiDigit));
3746 // That check is taken care of in unicodeForDigits, below.
3747 } else if (zero.size() == 2 && zero.at(0).isHighSurrogate()) {
3748 const char32_t zeroUcs4 = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
3749 QString converted;
3750 converted.reserve(2 * digits.size());
3751 for (QChar ch : std::as_const(digits)) {
3752 const char32_t digit = unicodeForDigit(ch.unicode() - '0', zeroUcs4);
3753 Q_ASSERT(QChar::requiresSurrogates(digit));
3754 converted.append(QChar::highSurrogate(digit));
3755 converted.append(QChar::lowSurrogate(digit));
3756 }
3757 digits = converted;
3758 } else {
3759 Q_ASSERT(zero.size() == 1);
3760 Q_ASSERT(!zero.at(0).isSurrogate());
3761 char16_t z = zero.at(0).unicode();
3762 char16_t *const value = reinterpret_cast<char16_t *>(digits.data());
3763 for (qsizetype i = 0; i < digits.size(); ++i)
3764 value[i] = unicodeForDigit(value[i] - '0', z);
3765 }
3766
3767 const bool mustMarkDecimal = flags & ForcePoint;
3768 const bool groupDigits = flags & GroupDigits;
3769 const int minExponentDigits = flags & ZeroPadExponent ? 2 : 1;
3770 switch (form) {
3771 case DFExponent:
3772 numStr = exponentForm(std::move(digits), decpt, precision, PMDecimalDigits,
3773 mustMarkDecimal, minExponentDigits);
3774 break;
3775 case DFDecimal:
3776 numStr = decimalForm(std::move(digits), decpt, precision, PMDecimalDigits,
3777 mustMarkDecimal, groupDigits);
3778 break;
3779 case DFSignificantDigits: {
3780 PrecisionMode mode
3781 = (flags & AddTrailingZeroes) ? PMSignificantDigits : PMChopTrailingZeros;
3782
3783 /* POSIX specifies sprintf() to follow fprintf(), whose 'g/G' format
3784 says; with P = 6 if precision unspecified else 1 if precision is
3785 0 else precision; when 'e/E' would have exponent X, use:
3786 * 'f/F' if P > X >= -4, with precision P-1-X
3787 * 'e/E' otherwise, with precision P-1
3788 Helpfully, we already have mapped precision < 0 to 6 - except for
3789 F.P.Shortest mode, which is its own story - and those of our
3790 callers with unspecified precision either used 6 or -1 for it.
3791 */
3792 bool useDecimal;
3794 // Find out which representation is shorter.
3795 // Set bias to everything added to exponent form but not
3796 // decimal, minus the converse.
3797
3798 // Exponent adds separator, sign and digits:
3799 int bias = 2 + minExponentDigits;
3800 // Decimal form may get grouping separators inserted:
3801 if (groupDigits && decpt >= m_grouping_top + m_grouping_least)
3802 bias -= (decpt - m_grouping_least) / m_grouping_higher + 1;
3803 // X = decpt - 1 needs two digits if decpt > 10:
3804 if (decpt > 10 && minExponentDigits == 1)
3805 ++bias;
3806 // Assume digitCount < 95, so we can ignore the 3-digit
3807 // exponent case (we'll set useDecimal false anyway).
3808
3809 const qsizetype digitCount = digits.size() / zero.size();
3810 if (!mustMarkDecimal) {
3811 // Decimal separator is skipped if at end; adjust if
3812 // that happens for only one form:
3813 if (digitCount <= decpt && digitCount > 1)
3814 ++bias; // decimal but not exponent
3815 else if (digitCount == 1 && decpt <= 0)
3816 --bias; // exponent but not decimal
3817 }
3818 // When 0 < decpt <= digitCount, the forms have equal digit
3819 // counts, plus things bias has taken into account; otherwise
3820 // decimal form's digit count is right-padded with zeros to
3821 // decpt, when decpt is positive, otherwise it's left-padded
3822 // with 1 - decpt zeros.
3823 useDecimal = (decpt <= 0 ? 1 - decpt <= bias
3824 : decpt <= digitCount ? 0 <= bias : decpt <= digitCount + bias);
3825 } else {
3826 // X == decpt - 1, POSIX's P; -4 <= X < P iff -4 < decpt <= P
3827 Q_ASSERT(precision >= 0);
3828 useDecimal = decpt > -4 && decpt <= (precision ? precision : 1);
3829 }
3830
3831 numStr = useDecimal
3832 ? decimalForm(std::move(digits), decpt, precision, mode,
3833 mustMarkDecimal, groupDigits)
3834 : exponentForm(std::move(digits), decpt, precision, mode,
3835 mustMarkDecimal, minExponentDigits);
3836 break;
3837 }
3838 }
3839
3840 // Pad with zeros. LeftAdjusted overrides ZeroPadded.
3841 if (flags & ZeroPadded && !(flags & LeftAdjusted)) {
3842 for (qsizetype i = numStr.size() / zero.size() + prefix.size(); i < width; ++i)
3843 numStr.prepend(zero);
3844 }
3845 }
3846
3847 return prefix + (flags & CapitalEorX ? std::move(numStr).toUpper() : numStr);
3848}
3849
3850QString QLocaleData::decimalForm(QString &&digits, int decpt, int precision,
3851 PrecisionMode pm, bool mustMarkDecimal,
3852 bool groupDigits) const
3853{
3854 const QString zero = zeroDigit();
3855 const auto digitWidth = zero.size();
3856 Q_ASSERT(digitWidth == 1 || digitWidth == 2);
3857 Q_ASSERT(digits.size() % digitWidth == 0);
3858
3859 // Separator needs to go at index decpt: so add zeros before or after the
3860 // given digits, if they don't reach that position already:
3861 if (decpt < 0) {
3862 for (; decpt < 0; ++decpt)
3863 digits.prepend(zero);
3864 } else {
3865 for (qsizetype i = digits.size() / digitWidth; i < decpt; ++i)
3866 digits.append(zero);
3867 }
3868
3869 switch (pm) {
3870 case PMDecimalDigits:
3871 for (qsizetype i = digits.size() / digitWidth - decpt; i < precision; ++i)
3872 digits.append(zero);
3873 break;
3874 case PMSignificantDigits:
3875 for (qsizetype i = digits.size() / digitWidth; i < precision; ++i)
3876 digits.append(zero);
3877 break;
3878 case PMChopTrailingZeros:
3879 Q_ASSERT(digits.size() / digitWidth <= qMax(decpt, 1) || !digits.endsWith(zero));
3880 break;
3881 }
3882
3883 if (mustMarkDecimal || decpt < digits.size() / digitWidth)
3884 digits.insert(decpt * digitWidth, decimalPoint());
3885
3886 if (groupDigits) {
3887 const QString group = groupSeparator();
3888 qsizetype i = decpt - m_grouping_least;
3889 if (i >= m_grouping_top) {
3890 digits.insert(i * digitWidth, group);
3891 while ((i -= m_grouping_higher) > 0)
3892 digits.insert(i * digitWidth, group);
3893 }
3894 }
3895
3896 if (decpt == 0)
3897 digits.prepend(zero);
3898
3899 return std::move(digits);
3900}
3901
3902QString QLocaleData::exponentForm(QString &&digits, int decpt, int precision,
3903 PrecisionMode pm, bool mustMarkDecimal,
3904 int minExponentDigits) const
3905{
3906 const QString zero = zeroDigit();
3907 const auto digitWidth = zero.size();
3908 Q_ASSERT(digitWidth == 1 || digitWidth == 2);
3909 Q_ASSERT(digits.size() % digitWidth == 0);
3910
3911 switch (pm) {
3912 case PMDecimalDigits:
3913 for (qsizetype i = digits.size() / digitWidth; i < precision + 1; ++i)
3914 digits.append(zero);
3915 break;
3916 case PMSignificantDigits:
3917 for (qsizetype i = digits.size() / digitWidth; i < precision; ++i)
3918 digits.append(zero);
3919 break;
3920 case PMChopTrailingZeros:
3921 Q_ASSERT(digits.size() / digitWidth <= 1 || !digits.endsWith(zero));
3922 break;
3923 }
3924
3925 if (mustMarkDecimal || digits.size() > digitWidth)
3926 digits.insert(digitWidth, decimalPoint());
3927
3928 digits.append(exponentSeparator());
3929 digits.append(longLongToString(decpt - 1, minExponentDigits, 10, -1, AlwaysShowSign));
3930
3931 return std::move(digits);
3932}
3933
3934QString QLocaleData::signPrefix(bool negative, unsigned flags) const
3935{
3936 if (negative)
3937 return negativeSign();
3938 if (flags & AlwaysShowSign)
3939 return positiveSign();
3941 return QStringView(u" ").toString();
3942 return {};
3943}
3944
3946 int base, int width, unsigned flags) const
3947{
3948 bool negative = n < 0;
3949
3950 /*
3951 Negating std::numeric_limits<qlonglong>::min() hits undefined behavior, so
3952 taking an absolute value has to take a slight detour.
3953 */
3954 QString numStr = qulltoa(negative ? 1u + qulonglong(-(n + 1)) : qulonglong(n),
3955 base, zeroDigit());
3956
3957 return applyIntegerFormatting(std::move(numStr), negative, precision, base, width, flags);
3958}
3959
3961 int base, int width, unsigned flags) const
3962{
3963 const QString zero = zeroDigit();
3964 QString resultZero = base == 10 ? zero : QStringLiteral("0");
3965 return applyIntegerFormatting(l ? qulltoa(l, base, zero) : resultZero,
3966 false, precision, base, width, flags);
3967}
3968
3969QString QLocaleData::applyIntegerFormatting(QString &&numStr, bool negative, int precision,
3970 int base, int width, unsigned flags) const
3971{
3972 const QString zero = base == 10 ? zeroDigit() : QStringLiteral("0");
3973 const auto digitWidth = zero.size();
3974 const auto digitCount = numStr.size() / digitWidth;
3975
3976 const auto basePrefix = [&] () -> QStringView {
3977 if (flags & ShowBase) {
3978 const bool upper = flags & UppercaseBase;
3979 if (base == 16)
3980 return upper ? u"0X" : u"0x";
3981 if (base == 2)
3982 return upper ? u"0B" : u"0b";
3983 if (base == 8 && !numStr.startsWith(zero))
3984 return zero;
3985 }
3986 return {};
3987 }();
3988
3989 const QString prefix = signPrefix(negative, flags) + basePrefix;
3990 // Count how much of width we've used up. Each digit counts as one
3991 qsizetype usedWidth = digitCount + prefix.size();
3992
3993 if (base == 10 && flags & GroupDigits) {
3994 const QString group = groupSeparator();
3996 if (i >= m_grouping_top) {
3997 numStr.insert(i * digitWidth, group);
3998 ++usedWidth;
3999 while ((i -= m_grouping_higher) > 0) {
4000 numStr.insert(i * digitWidth, group);
4001 ++usedWidth;
4002 }
4003 }
4004 // TODO: should we group any zero-padding we add later ?
4005 }
4006
4007 const bool noPrecision = precision == -1;
4008 if (noPrecision)
4009 precision = 1;
4010
4011 for (qsizetype i = numStr.size(); i < precision; ++i) {
4012 numStr.prepend(zero);
4013 usedWidth++;
4014 }
4015
4016 // LeftAdjusted overrides ZeroPadded; and sprintf() only pads when
4017 // precision is not specified in the format string.
4018 if (noPrecision && flags & ZeroPadded && !(flags & LeftAdjusted)) {
4019 for (qsizetype i = usedWidth; i < width; ++i)
4020 numStr.prepend(zero);
4021 }
4022
4023 QString result(flags & CapitalEorX ? std::move(numStr).toUpper() : std::move(numStr));
4024 if (prefix.size())
4025 result.prepend(prefix);
4026 return result;
4027}
4028
4030{
4032 if (this == c()) {
4033 result.isC = true;
4034 return result;
4035 }
4036 result.setZero(zero().viewData(single_character_data));
4037 result.group = groupDelim().viewData(single_character_data);
4038 // Note: minus, plus and exponent might not actually be single characters.
4039 result.minus = minus().viewData(single_character_data);
4040 result.plus = plus().viewData(single_character_data);
4041 if (mode != IntegerMode)
4042 result.decimal = decimalSeparator().viewData(single_character_data);
4043 if (mode == DoubleScientificMode) {
4044 result.exponent = exponential().viewData(single_character_data);
4045 // exponentCyrillic means "apply the Cyrrilic-specific exponent hack"
4046 result.exponentCyrillic = m_script_id == QLocale::CyrillicScript;
4047 }
4048#ifndef QT_NO_SYSTEMLOCALE
4049 if (this == &systemLocaleData) {
4050 const auto getString = [sys = systemLocale()](QSystemLocale::QueryType query) {
4051 return sys->query(query).toString();
4052 };
4053 if (mode != IntegerMode) {
4055 if (result.sysDecimal.size())
4056 result.decimal = QStringView{result.sysDecimal};
4057 }
4059 if (result.sysGroup.size())
4060 result.group = QStringView{result.sysGroup};
4062 if (result.sysMinus.size())
4063 result.minus = QStringView{result.sysMinus};
4065 if (result.sysPlus.size())
4066 result.plus = QStringView{result.sysPlus};
4068 }
4069#endif
4070
4071 return result;
4072}
4073
4074namespace {
4075// A bit like QStringIterator but rather specialized ... and some of the tokens
4076// it recognizes aren't single Unicode code-points (but it does map each to a
4077// single character).
4078class NumericTokenizer
4079{
4080 // TODO: use deterministic finite-state-automata.
4081 // TODO QTBUG-95460: CLDR has Inf/NaN representations per locale.
4082 static constexpr char lettersInfNaN[] = "afin"; // Letters of Inf, NaN
4083 static constexpr auto matchInfNaN = QtPrivate::makeCharacterSetMatch<lettersInfNaN>();
4084 const QStringView m_text;
4085 const QLocaleData::NumericData m_guide;
4086 qsizetype m_index = 0;
4087 const QLocaleData::NumberMode m_mode;
4088 static_assert('+' + 1 == ',' && ',' + 1 == '-' && '-' + 1 == '.');
4089 char lastMark; // C locale accepts '+' through lastMark.
4090public:
4091 NumericTokenizer(QStringView text, QLocaleData::NumericData &&guide,
4093 : m_text(text), m_guide(guide), m_mode(mode),
4094 lastMark(mode == QLocaleData::IntegerMode ? '-' : '.')
4095 {
4096 Q_ASSERT(m_guide.isValid(mode));
4097 }
4098 bool done() const { return !(m_index < m_text.size()); }
4099 qsizetype index() const { return m_index; }
4100 inline int asBmpDigit(char16_t digit) const;
4101 char nextToken();
4102};
4103
4104int NumericTokenizer::asBmpDigit(char16_t digit) const
4105{
4106 // If digit *is* a digit, result will be in range 0 through 9; otherwise not.
4107 // Must match qlocale_tools.h's unicodeForDigit()
4108 if (m_guide.zeroUcs != u'\u3007' || digit == m_guide.zeroUcs)
4109 return digit - m_guide.zeroUcs;
4110
4111 // QTBUG-85409: Suzhou's digits aren't contiguous !
4112 if (digit == u'\u3020') // U+3020 POSTAL MARK FACE is not a digit.
4113 return -1;
4114 // ... but is followed by digits 1 through 9.
4115 return digit - u'\u3020';
4116}
4117
4118char NumericTokenizer::nextToken()
4119{
4120 // As long as caller stops iterating on a zero return, those don't need to
4121 // keep m_index correctly updated.
4122 Q_ASSERT(!done());
4123 // Mauls non-letters above 'Z' but we don't care:
4124 const auto asciiLower = [](unsigned char c) { return c >= 'A' ? c | 0x20 : c; };
4125 const QStringView tail = m_text.sliced(m_index);
4126 const QChar ch = tail.front();
4127 if (ch == u'\u2212') {
4128 // Special case: match the "proper" minus sign, for all locales.
4129 ++m_index;
4130 return '-';
4131 }
4132 if (m_guide.isC) {
4133 // "Conversion" to C locale is just a filter:
4134 ++m_index;
4135 if (Q_LIKELY(ch.unicode() < 256)) {
4136 unsigned char ascii = asciiLower(ch.toLatin1());
4137 if (Q_LIKELY(isAsciiDigit(ascii) || ('+' <= ascii && ascii <= lastMark)
4138 // No caller presently (6.5) passes DoubleStandardMode,
4139 // so !IntegerMode implies scientific, for now.
4140 || (m_mode != QLocaleData::IntegerMode
4141 && matchInfNaN.matches(ascii))
4143 && ascii == 'e'))) {
4144 return ascii;
4145 }
4146 }
4147 return 0;
4148 }
4149 if (ch.unicode() < 256) {
4150 // Accept the C locale's digits and signs in all locales:
4151 char ascii = asciiLower(ch.toLatin1());
4152 if (isAsciiDigit(ascii) || ascii == '-' || ascii == '+'
4153 // Also its Inf and NaN letters:
4154 || (m_mode != QLocaleData::IntegerMode && matchInfNaN.matches(ascii))) {
4155 ++m_index;
4156 return ascii;
4157 }
4158 }
4159
4160 // Other locales may be trickier:
4161 if (tail.startsWith(m_guide.minus)) {
4162 m_index += m_guide.minus.size();
4163 return '-';
4164 }
4165 if (tail.startsWith(m_guide.plus)) {
4166 m_index += m_guide.plus.size();
4167 return '+';
4168 }
4169 if (!m_guide.group.isEmpty() && tail.startsWith(m_guide.group)) {
4170 m_index += m_guide.group.size();
4171 return ',';
4172 }
4173 if (m_mode != QLocaleData::IntegerMode && tail.startsWith(m_guide.decimal)) {
4174 m_index += m_guide.decimal.size();
4175 return '.';
4176 }
4178 && tail.startsWith(m_guide.exponent, Qt::CaseInsensitive)) {
4179 m_index += m_guide.exponent.size();
4180 return 'e';
4181 }
4182
4183 // Must match qlocale_tools.h's unicodeForDigit()
4184 if (m_guide.zeroLen == 1) {
4185 if (!ch.isSurrogate()) {
4186 const uint gap = asBmpDigit(ch.unicode());
4187 if (gap < 10u) {
4188 ++m_index;
4189 return '0' + gap;
4190 }
4191 } else if (ch.isHighSurrogate() && tail.size() > 1 && tail.at(1).isLowSurrogate()) {
4192 return 0;
4193 }
4194 } else if (ch.isHighSurrogate()) {
4195 // None of the corner cases below matches a surrogate, so (update
4196 // already and) return early if we don't have a digit.
4197 if (tail.size() > 1) {
4198 QChar low = tail.at(1);
4199 if (low.isLowSurrogate()) {
4200 m_index += 2;
4201 const uint gap = QChar::surrogateToUcs4(ch, low) - m_guide.zeroUcs;
4202 return gap < 10u ? '0' + gap : 0;
4203 }
4204 }
4205 return 0;
4206 }
4207
4208 // All cases where tail starts with properly-matched surrogate pair
4209 // have been handled by this point.
4210 Q_ASSERT(!(ch.isHighSurrogate() && tail.size() > 1 && tail.at(1).isLowSurrogate()));
4211
4212 // Weird corner cases follow (code above assumes these match no surrogates).
4213
4214 // Some locales use a non-breaking space (U+00A0) or its thin version
4215 // (U+202f) for grouping. These look like spaces, so people (and thus some
4216 // of our tests) use a regular space instead and complain if it doesn't
4217 // work.
4218 // Should this be extended generally to any case where group is a space ?
4219 if ((m_guide.group == u"\u00a0" || m_guide.group == u"\u202f") && tail.startsWith(u' ')) {
4220 ++m_index;
4221 return ',';
4222 }
4223
4224 // Cyrillic has its own E, used by Ukrainian as exponent; but others
4225 // writing Cyrillic may well use that; and Ukrainians might well use E.
4226 // All other Cyrillic locales (officially) use plain ASCII E.
4227 if (m_guide.exponentCyrillic // Only true in scientific float mode.
4228 && (tail.startsWith(u"\u0415", Qt::CaseInsensitive)
4229 || tail.startsWith(u"E", Qt::CaseInsensitive))) {
4230 ++m_index;
4231 return 'e';
4232 }
4233
4234 return 0;
4235}
4236} // namespace with no name
4237
4238/*
4239 Converts a number in locale representation to the C locale equivalent.
4240
4241 Only has to guarantee that a string that is a correct representation of a
4242 number will be converted. Checks signs, separators and digits appear in all
4243 the places they should, and nowhere else.
4244
4245 Returns true precisely if the number appears to be well-formed, modulo
4246 things a parser for C Locale strings (without digit-grouping separators;
4247 they're stripped) will catch. When it returns true, it records (and
4248 '\0'-terminates) the C locale representation in *result.
4249
4250 Note: only QString integer-parsing methods have a base parameter (hence need
4251 to cope with letters as possible digits); but these are now all routed via
4252 byteArrayToU?LongLong(), so no longer come via here. The QLocale
4253 number-parsers only work in decimal, so don't have to cope with any digits
4254 other than 0 through 9.
4255*/
4256bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_options,
4258{
4259 s = s.trimmed();
4260 if (s.size() < 1)
4261 return false;
4262 NumericTokenizer tokens(s, numericData(mode), mode);
4263
4264 // Digit-grouping details (all modes):
4265 qsizetype digitsInGroup = 0;
4266 qsizetype last_separator_idx = -1;
4267 qsizetype start_of_digits_idx = -1;
4268
4269 // Floating-point details (non-integer modes):
4270 qsizetype decpt_idx = -1;
4271 qsizetype exponent_idx = -1;
4272
4273 char last = '\0';
4274 while (!tokens.done()) {
4275 qsizetype idx = tokens.index(); // before nextToken() advances
4276 char out = tokens.nextToken();
4277 if (out == 0)
4278 return false;
4279 Q_ASSERT(tokens.index() > idx); // it always *should* advance (except on zero return)
4280
4281 if (out == '.') {
4282 // Fail if more than one decimal point or point after e
4283 if (decpt_idx != -1 || exponent_idx != -1)
4284 return false;
4285 decpt_idx = idx;
4286 } else if (out == 'e') {
4287 exponent_idx = idx;
4288 }
4289
4290 if (number_options.testFlag(QLocale::RejectLeadingZeroInExponent)
4291 && exponent_idx != -1 && out == '0') {
4292 // After the exponent there can only be '+', '-' or digits.
4293 // If we find a '0' directly after some non-digit, then that is a
4294 // leading zero, acceptable only if it is the whole exponent.
4295 if (!tokens.done() && !isAsciiDigit(last))
4296 return false;
4297 }
4298
4299 if (number_options.testFlag(QLocale::RejectTrailingZeroesAfterDot) && decpt_idx >= 0) {
4300 // In a fractional part, a 0 just before the exponent is trailing:
4301 if (idx == exponent_idx && last == '0')
4302 return false;
4303 }
4304
4305 if (!number_options.testFlag(QLocale::RejectGroupSeparator)) {
4306 if (isAsciiDigit(out)) {
4307 if (start_of_digits_idx == -1)
4308 start_of_digits_idx = idx;
4309 ++digitsInGroup;
4310 } else if (out == ',') {
4311 // Don't allow group chars after the decimal point or exponent
4312 if (decpt_idx != -1 || exponent_idx != -1)
4313 return false;
4314
4315 if (last_separator_idx == -1) {
4316 // Check distance from the beginning of the digits:
4317 if (start_of_digits_idx == -1 || m_grouping_top > digitsInGroup
4318 || digitsInGroup >= m_grouping_least + m_grouping_top) {
4319 return false;
4320 }
4321 } else {
4322 // Check distance from the last separator:
4323 if (digitsInGroup != m_grouping_higher)
4324 return false;
4325 }
4326
4327 last_separator_idx = idx;
4328 digitsInGroup = 0;
4329 } else if (mode != IntegerMode && (out == '.' || idx == exponent_idx)
4330 && last_separator_idx != -1) {
4331 // Were there enough digits since the last group separator?
4332 if (digitsInGroup != m_grouping_least)
4333 return false;
4334
4335 // stop processing separators
4336 last_separator_idx = -1;
4337 }
4338 } else if (out == ',') {
4339 return false;
4340 }
4341
4342 last = out;
4343 if (out != ',') // Leave group separators out of the result.
4344 result->append(out);
4345 }
4346
4347 if (!number_options.testFlag(QLocale::RejectGroupSeparator) && last_separator_idx != -1) {
4348 // Were there enough digits since the last group separator?
4349 if (digitsInGroup != m_grouping_least)
4350 return false;
4351 }
4352
4353 if (number_options.testFlag(QLocale::RejectTrailingZeroesAfterDot)
4354 && decpt_idx != -1 && exponent_idx == -1) {
4355 // In the fractional part, a final zero is trailing:
4356 if (last == '0')
4357 return false;
4358 }
4359
4360 result->append('\0');
4361 return true;
4362}
4363
4366 QLocale::NumberOptions number_options) const
4367{
4369 result.buff.reserve(str.size());
4370
4371 enum { Whole, Fractional, Exponent } state = Whole;
4372 const bool scientific = numMode == DoubleScientificMode;
4373 NumericTokenizer tokens(str, numericData(numMode), numMode);
4374 char last = '\0';
4375
4376 while (!tokens.done()) {
4377 char c = tokens.nextToken();
4378
4379 if (isAsciiDigit(c)) {
4380 switch (state) {
4381 case Whole:
4382 // Nothing special to do (unless we want to check grouping sizes).
4383 break;
4384 case Fractional:
4385 // If a double has too many digits in its fractional part it is Invalid.
4386 if (decDigits-- == 0)
4387 return {};
4388 break;
4389 case Exponent:
4390 if (!isAsciiDigit(last)) {
4391 // This is the first digit in the exponent (there may have beena '+'
4392 // or '-' in before). If it's a zero, the exponent is zero-padded.
4393 if (c == '0' && (number_options & QLocale::RejectLeadingZeroInExponent))
4394 return {};
4395 }
4396 break;
4397 }
4398
4399 } else {
4400 switch (c) {
4401 case '.':
4402 // If an integer has a decimal point, it is Invalid.
4403 // A double can only have one, at the end of its whole-number part.
4404 if (numMode == IntegerMode || state != Whole)
4405 return {};
4406 // Even when decDigits is 0, we do allow the decimal point to be
4407 // present - just as long as no digits follow it.
4408
4409 state = Fractional;
4410 break;
4411
4412 case '+':
4413 case '-':
4414 // A sign can only appear at the start or after the e of scientific:
4415 if (last != '\0' && !(scientific && last == 'e'))
4416 return {};
4417 break;
4418
4419 case ',':
4420 // Grouping is only allowed after a digit in the whole-number portion:
4421 if ((number_options & QLocale::RejectGroupSeparator) || state != Whole
4422 || !isAsciiDigit(last)) {
4423 return {};
4424 }
4425 // We could check grouping sizes are correct, but fixup()s are
4426 // probably better off correcting any misplacement instead.
4427 break;
4428
4429 case 'e':
4430 // Only one e is allowed and only in scientific:
4431 if (!scientific || state == Exponent)
4432 return {};
4433 state = Exponent;
4434 break;
4435
4436 default:
4437 // Nothing else can validly appear in a number.
4438 // NumericTokenizer allows letters of "inf" and "nan", but
4439 // validators don't accept those values.
4440 // For anything else, tokens.nextToken() must have returned 0.
4441 Q_ASSERT(!c || c == 'a' || c == 'f' || c == 'i' || c == 'n');
4442 return {};
4443 }
4444 }
4445
4446 last = c;
4447 if (c != ',') // Skip grouping
4448 result.buff.append(c);
4449 }
4450
4452
4453 // Intermediate if it ends with any character that requires a digit after
4454 // it to be valid e.g. group separator, sign, or exponent
4455 if (last == ',' || last == '-' || last == '+' || last == 'e')
4457
4458 return result;
4459}
4460
4462 QLocale::NumberOptions number_options) const
4463{
4464 CharBuff buff;
4465 if (!numberToCLocale(str, number_options, DoubleScientificMode, &buff)) {
4466 if (ok != nullptr)
4467 *ok = false;
4468 return 0.0;
4469 }
4470 auto r = qt_asciiToDouble(buff.constData(), buff.size() - 1);
4471 if (ok != nullptr)
4472 *ok = r.ok();
4473 return r.result;
4474}
4475
4476QSimpleParsedNumber<qint64>
4478 QLocale::NumberOptions number_options) const
4479{
4480 CharBuff buff;
4481 if (!numberToCLocale(str, number_options, IntegerMode, &buff))
4482 return {};
4483
4484 return bytearrayToLongLong(QByteArrayView(buff), base);
4485}
4486
4487QSimpleParsedNumber<quint64>
4489 QLocale::NumberOptions number_options) const
4490{
4491 CharBuff buff;
4492 if (!numberToCLocale(str, number_options, IntegerMode, &buff))
4493 return {};
4494
4495 return bytearrayToUnsLongLong(QByteArrayView(buff), base);
4496}
4497
4499{
4500 if (used <= 0)
4501 return false;
4502
4503 const qsizetype len = num.size();
4504 if (used < len && num[used] != '\0') {
4505 while (used < len && ascii_isspace(num[used]))
4506 ++used;
4507 }
4508
4509 if (used < len && num[used] != '\0')
4510 // we stopped at a non-digit character after converting some digits
4511 return false;
4512
4513 return true;
4514}
4515
4517{
4518 auto r = qstrntoll(num.data(), num.size(), base);
4519 if (!checkParsed(num, r.used))
4520 return {};
4521 return r;
4522}
4523
4525{
4526 auto r = qstrntoull(num.data(), num.size(), base);
4527 if (!checkParsed(num, r.used))
4528 return {};
4529 return r;
4530}
4531
4549{
4550#ifndef QT_NO_SYSTEMLOCALE
4551 if (d->m_data == &systemLocaleData) {
4552 auto res = systemLocale()->query(QSystemLocale::CurrencySymbol, format).toString();
4553 if (!res.isEmpty())
4554 return res;
4555 }
4556#endif
4557 switch (format) {
4558 case CurrencySymbol:
4559 return d->m_data->currencySymbol().getData(currency_symbol_data);
4560 case CurrencyDisplayName:
4561 return d->m_data->currencyDisplayName().getData(currency_display_name_data);
4562 case CurrencyIsoCode: {
4563 const char *code = d->m_data->m_currency_iso_code;
4564 if (auto len = qstrnlen(code, 3))
4565 return QString::fromLatin1(code, qsizetype(len));
4566 break;
4567 }
4568 }
4569 return QString();
4570}
4571
4581{
4582#ifndef QT_NO_SYSTEMLOCALE
4583 if (d->m_data == &systemLocaleData) {
4586 QVariant::fromValue(arg)).toString();
4587 if (!res.isEmpty())
4588 return res;
4589 }
4590#endif
4591 QLocaleData::DataRange range = d->m_data->currencyFormatNegative();
4592 if (!range.size || value >= 0)
4593 range = d->m_data->currencyFormat();
4594 else
4595 value = -value;
4597 QString sym = symbol.isNull() ? currencySymbol() : symbol;
4598 if (sym.isEmpty())
4599 sym = currencySymbol(CurrencyIsoCode);
4600 return range.viewData(currency_format_data).arg(str, sym);
4601}
4602
4608{
4609#ifndef QT_NO_SYSTEMLOCALE
4610 if (d->m_data == &systemLocaleData) {
4613 QVariant::fromValue(arg)).toString();
4614 if (!res.isEmpty())
4615 return res;
4616 }
4617#endif
4619 QString sym = symbol.isNull() ? currencySymbol() : symbol;
4620 if (sym.isEmpty())
4621 sym = currencySymbol(CurrencyIsoCode);
4622 return d->m_data->currencyFormat().getData(currency_format_data).arg(str, sym);
4623}
4624
4636{
4637#ifndef QT_NO_SYSTEMLOCALE
4638 if (d->m_data == &systemLocaleData) {
4641 QVariant::fromValue(arg)).toString();
4642 if (!res.isEmpty())
4643 return res;
4644 }
4645#endif
4646 QLocaleData::DataRange range = d->m_data->currencyFormatNegative();
4647 if (!range.size || value >= 0)
4648 range = d->m_data->currencyFormat();
4649 else
4650 value = -value;
4651 QString str = toString(value, 'f', precision == -1 ? d->m_data->m_currency_digits : precision);
4652 QString sym = symbol.isNull() ? currencySymbol() : symbol;
4653 if (sym.isEmpty())
4654 sym = currencySymbol(CurrencyIsoCode);
4655 return range.viewData(currency_format_data).arg(str, sym);
4656}
4657
4696{
4697 int power, base = 1000;
4698 if (!bytes) {
4699 power = 0;
4700 } else if (format & DataSizeBase1000) {
4701 power = int(std::log10(qAbs(bytes)) / 3);
4702 } else { // Compute log2(bytes) / 10:
4703 power = int((63 - qCountLeadingZeroBits(quint64(qAbs(bytes)))) / 10);
4704 base = 1024;
4705 }
4706 // Only go to doubles if we'll be using a quantifier:
4707 const QString number = power
4708 ? toString(bytes / std::pow(double(base), power), 'f', qMin(precision, 3 * power))
4709 : toString(bytes);
4710
4711 // We don't support sizes in units larger than exbibytes because
4712 // the number of bytes would not fit into qint64.
4713 Q_ASSERT(power <= 6 && power >= 0);
4714 QStringView unit;
4715 if (power > 0) {
4716 QLocaleData::DataRange range = (format & DataSizeSIQuantifiers)
4717 ? d->m_data->byteAmountSI() : d->m_data->byteAmountIEC();
4718 unit = range.viewListEntry(byte_unit_data, power - 1);
4719 } else {
4720 unit = d->m_data->byteCount().viewData(byte_unit_data);
4721 }
4722
4723 return number + u' ' + unit;
4724}
4725
4749{
4750 const char sep = char(separator);
4751 QStringList uiLanguages;
4752 if (uchar(sep) > 0x7f) {
4753 badSeparatorWarning("uiLanguages", sep);
4754 return uiLanguages;
4755 }
4756 QList<QLocaleId> localeIds;
4757#ifdef QT_NO_SYSTEMLOCALE
4758 constexpr bool isSystem = false;
4759#else
4760 const bool isSystem = d->m_data == &systemLocaleData;
4761 if (isSystem) {
4762 uiLanguages = systemLocale()->query(QSystemLocale::UILanguages).toStringList();
4763 if (separator != TagSeparator::Dash) {
4764 // Map from default separator, Dash, used by backends:
4765 const QChar join = QLatin1Char(sep);
4766 uiLanguages = uiLanguages.replaceInStrings(u"-", QStringView(&join, 1));
4767 }
4768 // ... but we need to include likely-adjusted forms of each of those, too.
4769 // For now, collect up locale Ids representing the entries, for later processing:
4770 for (const auto &entry : std::as_const(uiLanguages))
4771 localeIds.append(QLocaleId::fromName(entry));
4772 if (localeIds.isEmpty())
4773 localeIds.append(systemLocale()->fallbackLocale().d->m_data->id());
4774 // If the system locale (isn't C and) didn't include itself in the list,
4775 // or as fallback, presume to know better than it and put its name
4776 // first. (Known issue, QTBUG-104930, on some macOS versions when in
4777 // locale en_DE.) Our translation system might have a translation for a
4778 // locale the platform doesn't believe in.
4779 const QString name = bcp47Name(separator);
4780 if (!name.isEmpty() && language() != C && !uiLanguages.contains(name)) {
4781 // That uses contains(name) as a cheap pre-test, but there may be an
4782 // entry that matches this on purging likely subtags.
4783 const QLocaleId mine = d->m_data->id().withLikelySubtagsRemoved();
4784 const auto isMine = [mine](const QString &entry) {
4785 return QLocaleId::fromName(entry).withLikelySubtagsRemoved() == mine;
4786 };
4787 if (std::none_of(uiLanguages.constBegin(), uiLanguages.constEnd(), isMine)) {
4788 localeIds.prepend(d->m_data->id());
4789 uiLanguages.prepend(name);
4790 }
4791 }
4792 } else
4793#endif
4794 {
4795 localeIds.append(d->m_data->id());
4796 }
4797 for (qsizetype i = localeIds.size(); i-- > 0; ) {
4798 QLocaleId id = localeIds.at(i);
4799 qsizetype j;
4800 QByteArray prior;
4801 if (isSystem && i < uiLanguages.size()) {
4802 // Adding likely-adjusted forms to system locale's list.
4803 // Name the locale is derived from:
4804 prior = uiLanguages.at(i).toLatin1();
4805 // Insert just after the entry we're supplementing:
4806 j = i + 1;
4807 } else if (id.language_id == C) {
4808 // Attempt no likely sub-tag amendments to C:
4809 uiLanguages.append(QString::fromLatin1(id.name(sep)));
4810 continue;
4811 } else {
4812 // Plain locale or empty system uiLanguages; just append.
4813 prior = id.name(sep);
4814 uiLanguages.append(QString::fromLatin1(prior));
4815 j = uiLanguages.size();
4816 }
4817
4818 const QLocaleId max = id.withLikelySubtagsAdded();
4819 const QLocaleId min = max.withLikelySubtagsRemoved();
4820
4821 // Include minimal version (last) unless it's what our locale is derived from:
4822 if (auto name = min.name(sep); name != prior)
4823 uiLanguages.insert(j, QString::fromLatin1(name));
4824 else if (!isSystem)
4825 --j; // bcp47Name() matches min(): put more specific forms *before* it.
4826
4827 if (id.script_id) {
4828 // Include scriptless version if likely-equivalent and distinct:
4829 id.script_id = 0;
4830 if (id != min && id.withLikelySubtagsAdded() == max) {
4831 if (auto name = id.name(sep); name != prior)
4832 uiLanguages.insert(j, QString::fromLatin1(name));
4833 }
4834 }
4835
4836 if (!id.territory_id) {
4837 Q_ASSERT(!min.territory_id);
4838 Q_ASSERT(!id.script_id); // because we just cleared it.
4839 // Include version with territory if it likely-equivalent and distinct:
4840 id.territory_id = max.territory_id;
4841 if (id != max && id.withLikelySubtagsAdded() == max) {
4842 if (auto name = id.name(sep); name != prior)
4843 uiLanguages.insert(j, QString::fromLatin1(name));
4844 }
4845 }
4846
4847 // Include version with all likely sub-tags (first) if distinct from the rest:
4848 if (max != min && max != id) {
4849 if (auto name = max.name(sep); name != prior)
4850 uiLanguages.insert(j, QString::fromLatin1(name));
4851 }
4852 }
4853 return uiLanguages;
4854}
4855
4868{
4869#ifndef QT_NO_SYSTEMLOCALE
4870 if (d->m_data == &systemLocaleData) {
4871 const auto res = systemLocale()->query(QSystemLocale::Collation).toString();
4872 if (!res.isEmpty())
4873 return QLocale(res);
4874 }
4875#endif
4876 return *this;
4877}
4878
4888{
4889#ifndef QT_NO_SYSTEMLOCALE
4890 if (d->m_data == &systemLocaleData) {
4891 auto res = systemLocale()->query(QSystemLocale::NativeLanguageName).toString();
4892 if (!res.isEmpty())
4893 return res;
4894 }
4895#endif
4896 return d->m_data->endonymLanguage().getData(endonyms_data);
4897}
4898
4908{
4909#ifndef QT_NO_SYSTEMLOCALE
4910 if (d->m_data == &systemLocaleData) {
4911 auto res = systemLocale()->query(QSystemLocale::NativeTerritoryName).toString();
4912 if (!res.isEmpty())
4913 return res;
4914 }
4915#endif
4916 return d->m_data->endonymTerritory().getData(endonyms_data);
4917}
4918
4919#if QT_DEPRECATED_SINCE(6, 6)
4929QString QLocale::nativeCountryName() const
4930{
4931 return nativeTerritoryName();
4932}
4933#endif
4934
4935#ifndef QT_NO_DEBUG_STREAM
4937{
4938 QDebugStateSaver saver(dbg);
4939 dbg.nospace().noquote()
4940 << "QLocale(" << QLocale::languageToString(l.language())
4941 << ", " << QLocale::scriptToString(l.script())
4942 << ", " << QLocale::territoryToString(l.territory()) << ')';
4943 return dbg;
4944}
4945#endif
4947
4948#ifndef QT_NO_QOBJECT
4949#include "moc_qlocale.cpp"
4950#endif
\inmodule QtCore
Definition qbytearray.h:57
virtual QString standaloneWeekDayName(const QLocale &locale, int day, QLocale::FormatType format) const
Returns the standalone name of the specified day of the week in the chosen locale,...
Definition qlocale.cpp:3236
virtual const char16_t * localeMonthData() const =0
virtual QString standaloneMonthName(const QLocale &locale, int month, int year, QLocale::FormatType format) const
Returns the standalone name of the specified month in the chosen locale, using the specified format t...
Definition qlocale.cpp:3169
virtual QString dateTimeToString(QStringView format, const QDateTime &datetime, QDate dateOnly, QTime timeOnly, const QLocale &locale) const
Returns a string representing a given date, time or date-time.
Definition qlocale.cpp:3473
virtual const QCalendarLocale * localeMonthIndexData() const =0
virtual int dayOfWeek(qint64 jd) const
Returns the day of the week for the given Julian Day Number jd.
virtual QString weekDayName(const QLocale &locale, int day, QLocale::FormatType format) const
Returns the name of the specified day of the week in the chosen locale, using the specified format to...
Definition qlocale.cpp:3207
virtual QCalendar::YearMonthDay julianDayToDate(qint64 jd) const =0
Computes the year, month, and day in this calendar for the given Julian day number jd.
virtual QString monthName(const QLocale &locale, int month, int year, QLocale::FormatType format) const
Returns the name of the specified month in the given year for the chosen locale, using the given form...
Definition qlocale.cpp:3133
virtual int maximumMonthsInYear() const
Returns the maximum number of months possible in any year.
The QCalendar class describes calendar systems.
Definition qcalendar.h:53
@ Unspecified
Definition qcalendar.h:57
QString standaloneMonthName(const QLocale &locale, int month, int year=Unspecified, QLocale::FormatType format=QLocale::LongFormat) const
Returns a suitably localised standalone name for a month.
QString dateTimeToString(QStringView format, const QDateTime &datetime, QDate dateOnly, QTime timeOnly, const QLocale &locale) const
Returns a string representing a given date, time or date-time.
QString monthName(const QLocale &locale, int month, int year=Unspecified, QLocale::FormatType format=QLocale::LongFormat) const
Returns a suitably localised name for a month.
QString standaloneWeekDayName(const QLocale &locale, int day, QLocale::FormatType format=QLocale::LongFormat) const
Returns a suitably localised standalone name for a day of the week.
QString weekDayName(const QLocale &locale, int day, QLocale::FormatType format=QLocale::LongFormat) const
Returns a suitably localised name for a day of the week.
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qdatastream.h:46
\inmodule QtCore\reentrant
Definition qdatetime.h:283
int offsetFromUtc() const
static QDateTime currentDateTime()
This is an overloaded member function, provided for convenience. It differs from the above function o...
QTime time() const
Returns the time part of the datetime.
QString timeZoneAbbreviation() const
bool isValid() const
Returns true if this datetime represents a definite moment, otherwise false.
QDateTime toOffsetFromUtc(int offsetSeconds) const
QTimeZone timeRepresentation() const
QDate date() const
Returns the date part of the datetime.
\inmodule QtCore \reentrant
Definition qdatetime.h:29
constexpr bool isValid() const
Returns true if this date is valid; otherwise returns false.
Definition qdatetime.h:71
constexpr qint64 toJulianDay() const
Converts the date to a Julian day.
Definition qdatetime.h:170
\inmodule QtCore
\inmodule QtCore
QVariant data(int key) const
Returns this item's custom data for the key key as a QVariant.
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
static QLatin1StringView scriptToCode(QLocale::Script script)
Definition qlocale.cpp:231
quint16 languageId() const
Definition qlocale_p.h:499
static QLocale::Language codeToLanguage(QStringView code, QLocale::LanguageCodeTypes codeTypes=QLocale::AnyLanguageCode) noexcept
Definition qlocale.cpp:95
const QLocaleData *const m_data
Definition qlocale_p.h:529
QLocale::MeasurementSystem measurementSystem() const
Definition qlocale.cpp:3284
quint16 territoryId() const
Definition qlocale_p.h:500
static QLatin1StringView territoryToCode(QLocale::Territory territory)
Definition qlocale.cpp:239
static QLocale::Territory codeToTerritory(QStringView code) noexcept
Definition qlocale.cpp:187
static std::array< char, 4 > languageToCode(QLocale::Language language, QLocale::LanguageCodeTypes codeTypes=QLocale::AnyLanguageCode)
Definition qlocale.cpp:206
static QLocale::Script codeToScript(QStringView code) noexcept
Definition qlocale.cpp:167
QLocale::NumberOptions m_numberOptions
Definition qlocale_p.h:532
QLatin1StringView territoryCode() const
Definition qlocale_p.h:511
std::array< char, 4 > languageCode(QLocale::LanguageCodeTypes codeTypes=QLocale::AnyLanguageCode) const
Definition qlocale_p.h:505
static QBasicAtomicInt s_generation
Definition qlocale_p.h:534
QByteArray bcp47Name(char separator='-') const
Definition qlocale.cpp:458
QString decimalPoint() const
Definition qlocale.cpp:2655
static QString languageToCode(Language language, LanguageCodeTypes codeTypes=AnyLanguageCode)
Returns the two- or three-letter language code for language, as defined in the ISO 639 standards.
Definition qlocale.cpp:1510
QString quoteString(const QString &str, QuotationStyle style=StandardQuotation) const
Definition qlocale.h:1161
QString dateTimeFormat(FormatType format=LongFormat) const
Definition qlocale.cpp:2396
Language language() const
Returns the language of this locale.
Definition qlocale.cpp:1317
QString zeroDigit() const
Definition qlocale.cpp:2710
QLocale & operator=(const QLocale &other) noexcept
Assigns other to this QLocale object and returns a reference to this QLocale object.
double toDouble(const QString &s, bool *ok=nullptr) const
Returns the double represented by the localized string s.
Definition qlocale.h:969
QString dateFormat(FormatType format=LongFormat) const
Definition qlocale.cpp:2334
static constexpr int DefaultTwoDigitBaseYear
Definition qlocale.h:39
float toFloat(const QString &s, bool *ok=nullptr) const
Returns the float represented by the localized string s.
Definition qlocale.h:967
static QString scriptToString(Script script)
Definition qlocale.cpp:1674
void setNumberOptions(NumberOptions options)
Definition qlocale.cpp:1177
QString negativeSign() const
Definition qlocale.cpp:2727
Qt::DayOfWeek firstDayOfWeek() const
Definition qlocale.cpp:3272
uint toUInt(const QString &s, bool *ok=nullptr) const
Returns the unsigned int represented by the localized string s.
Definition qlocale.h:957
QString toUpper(const QString &str) const
Definition qlocale.cpp:3394
long toLong(const QString &s, bool *ok=nullptr) const
Definition qlocale.h:959
Qt::LayoutDirection textDirection() const
Definition qlocale.cpp:3344
QuotationStyle
Definition qlocale.h:1159
@ AlternateQuotation
Definition qlocale.h:1159
@ StandardQuotation
Definition qlocale.h:1159
static Territory codeToTerritory(QStringView territoryCode) noexcept
Definition qlocale.cpp:1561
@ FloatingPointShortest
Definition qlocale.h:890
QString dayName(int, FormatType format=LongFormat) const
Definition qlocale.cpp:2997
@ OldHungarianScript
Definition qlocale.h:507
@ ImperialAramaicScript
Definition qlocale.h:462
@ InscriptionalParthianScript
Definition qlocale.h:464
@ HatranScript
Definition qlocale.h:459
@ AdlamScript
Definition qlocale.h:414
@ MeroiticCursiveScript
Definition qlocale.h:493
@ NabataeanScript
Definition qlocale.h:500
@ OldSouthArabianScript
Definition qlocale.h:512
@ AvestanScript
Definition qlocale.h:419
@ NkoScript
Definition qlocale.h:503
@ ManichaeanScript
Definition qlocale.h:489
@ LastScript
Definition qlocale.h:563
@ MandaeanScript
Definition qlocale.h:488
@ ThaanaScript
Definition qlocale.h:545
@ CyrillicScript
Definition qlocale.h:440
@ MeroiticScript
Definition qlocale.h:494
@ KharoshthiScript
Definition qlocale.h:472
@ CypriotScript
Definition qlocale.h:439
@ OrkhonScript
Definition qlocale.h:513
@ LydianScript
Definition qlocale.h:485
@ HebrewScript
Definition qlocale.h:460
@ PalmyreneScript
Definition qlocale.h:517
@ SyriacScript
Definition qlocale.h:536
@ PhoenicianScript
Definition qlocale.h:520
@ MendeKikakuiScript
Definition qlocale.h:558
@ AnyScript
Definition qlocale.h:413
@ OldNorthArabianScript
Definition qlocale.h:509
@ InscriptionalPahlaviScript
Definition qlocale.h:463
@ SamaritanScript
Definition qlocale.h:525
@ PsalterPahlaviScript
Definition qlocale.h:522
@ ArabicScript
Definition qlocale.h:417
static QString territoryToCode(Territory territory)
Definition qlocale.cpp:1546
MeasurementSystem
Definition qlocale.h:867
@ MetricSystem
Definition qlocale.h:868
CurrencySymbolFormat
Definition qlocale.h:896
@ LongFormat
Definition qlocale.h:875
@ NarrowFormat
Definition qlocale.h:875
@ ShortFormat
Definition qlocale.h:875
QString toCurrencyString(qlonglong, const QString &symbol=QString()) const
Definition qlocale.cpp:4580
QString timeFormat(FormatType format=LongFormat) const
Definition qlocale.cpp:2365
@ ISO639Part1
Definition qlocale.h:1103
@ ISO639Part2T
Definition qlocale.h:1105
@ ISO639Part2B
Definition qlocale.h:1104
@ ISO639Part3
Definition qlocale.h:1106
@ LegacyLanguageCode
Definition qlocale.h:1107
Country Territory
Definition qlocale.h:861
QString groupSeparator() const
Definition qlocale.cpp:2674
QString createSeparatedList(const QStringList &strl) const
Definition qlocale.cpp:1246
static void setDefault(const QLocale &locale)
\nonreentrant
Definition qlocale.cpp:1295
QString monthName(int, FormatType format=LongFormat) const
Definition qlocale.cpp:2963
static QString territoryToString(Territory territory)
Definition qlocale.cpp:1646
MeasurementSystem measurementSystem() const
Definition qlocale.cpp:3326
QString percent() const
Definition qlocale.cpp:2691
QString amText() const
Definition qlocale.cpp:3439
QLocale collation() const
Definition qlocale.cpp:4867
@ AnyCountry
Definition qlocale.h:831
@ AnyTerritory
Definition qlocale.h:568
@ LastTerritory
Definition qlocale.h:856
QString bcp47Name(TagSeparator separator=TagSeparator::Dash) const
Returns the BCP47 field names joined with dashes.
Definition qlocale.cpp:1482
QString nativeTerritoryName() const
Definition qlocale.cpp:4907
static Script codeToScript(QStringView scriptCode) noexcept
Returns the QLocale::Script enum corresponding to the four-letter script scriptCode,...
Definition qlocale.cpp:1621
static QString languageToString(Language language)
Returns a QString containing the name of language.
Definition qlocale.cpp:1632
friend class QString
Definition qlocale.h:31
int toInt(const QString &s, bool *ok=nullptr) const
Returns the int represented by the localized string s.
Definition qlocale.h:955
static QString scriptToCode(Script script)
Returns the four-letter script code for script, as defined in the ISO 15924 standard.
Definition qlocale.cpp:1607
QString exponential() const
Definition qlocale.cpp:2762
QString pmText() const
Definition qlocale.cpp:3459
QString formattedDataSize(qint64 bytes, int precision=2, DataSizeFormats format=DataSizeIecFormat) const
Definition qlocale.cpp:4695
qulonglong toULongLong(const QString &s, bool *ok=nullptr) const
Returns the unsigned long long int represented by the localized string s.
Definition qlocale.h:965
QList< Qt::DayOfWeek > weekdays() const
Definition qlocale.cpp:3300
QString positiveSign() const
Definition qlocale.cpp:2744
QStringList uiLanguages(TagSeparator separator=TagSeparator::Dash) const
List of locale names for use in selecting translations.
Definition qlocale.cpp:4748
QString toString(qlonglong i) const
Returns a localized string representation of i.
Definition qlocale.cpp:2052
ulong toULong(const QString &s, bool *ok=nullptr) const
Definition qlocale.h:961
QString standaloneMonthName(int, FormatType format=LongFormat) const
Definition qlocale.cpp:2979
NumberOptions numberOptions() const
Definition qlocale.cpp:1193
short toShort(const QString &s, bool *ok=nullptr) const
Returns the short int represented by the localized string s.
Definition qlocale.h:951
Territory territory() const
Definition qlocale.cpp:1341
qlonglong toLongLong(const QString &s, bool *ok=nullptr) const
Returns the long long int represented by the localized string s.
Definition qlocale.h:963
QLocale()
Constructs a QLocale object initialized with the default locale.
Definition qlocale.cpp:1070
QString name(TagSeparator separator=TagSeparator::Underscore) const
The short name of this locale.
Definition qlocale.cpp:1412
ushort toUShort(const QString &s, bool *ok=nullptr) const
Returns the unsigned short int represented by the localized string s.
Definition qlocale.h:953
QString nativeLanguageName() const
Definition qlocale.cpp:4887
Script script() const
Definition qlocale.cpp:1329
static Language codeToLanguage(QStringView languageCode, LanguageCodeTypes codeTypes=AnyLanguageCode) noexcept
Returns the QLocale::Language enum corresponding to the two- or three-letter languageCode,...
Definition qlocale.cpp:1530
QString toLower(const QString &str) const
Definition qlocale.cpp:3418
QString standaloneDayName(int, FormatType format=LongFormat) const
Definition qlocale.cpp:3014
QString currencySymbol(CurrencySymbolFormat=CurrencySymbol) const
Definition qlocale.cpp:4548
~QLocale()
Destructor.
Definition qlocale.cpp:1128
friend class QLocalePrivate
Definition qlocale.h:1170
@ OmitGroupSeparator
Definition qlocale.h:879
@ RejectTrailingZeroesAfterDot
Definition qlocale.h:884
@ RejectLeadingZeroInExponent
Definition qlocale.h:882
@ IncludeTrailingZeroesAfterDot
Definition qlocale.h:883
@ OmitLeadingZeroInExponent
Definition qlocale.h:881
@ RejectGroupSeparator
Definition qlocale.h:880
@ DefaultNumberOptions
Definition qlocale.h:878
static QList< QLocale > matchingLocales(QLocale::Language language, QLocale::Script script, QLocale::Territory territory)
Returns a list of valid locale objects that match the given language, script and territory.
Definition qlocale.cpp:2893
TagSeparator
Definition qlocale.h:893
static QLocale system()
Returns a QLocale object initialized to the system locale.
Definition qlocale.cpp:2862
@ LastLanguage
Definition qlocale.h:409
@ NorwegianBokmal
Definition qlocale.h:253
@ Filipino
Definition qlocale.h:127
@ Indonesian
Definition qlocale.h:156
@ Hebrew
Definition qlocale.h:147
@ AnyLanguage
Definition qlocale.h:44
@ Serbian
Definition qlocale.h:296
@ Yiddish
Definition qlocale.h:367
@ Romanian
Definition qlocale.h:279
\inmodule QtCore
Definition qmutex.h:281
void lock() noexcept
Locks the mutex.
Definition qmutex.h:286
QString standaloneMonthName(const QLocale &locale, int month, int year, QLocale::FormatType format) const override
Returns the standalone name of the specified month in the chosen locale, using the specified format t...
Definition qlocale.cpp:3178
QString monthName(const QLocale &locale, int month, int year, QLocale::FormatType format) const override
Returns the name of the specified month in the given year for the chosen locale, using the given form...
Definition qlocale.cpp:3142
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
bool startsWith(QStringView s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
QString arg(Args &&...args) const
constexpr qsizetype size() const noexcept
Returns the size of this string view, in UTF-16 code units (that is, surrogate pairs count as two for...
QString toString() const
Returns a deep copy of this string view's data as a QString.
Definition qstring.h:1121
constexpr QChar at(qsizetype n) const noexcept
Returns the character at position n in this string view.
constexpr QChar front() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QByteArray toLatin1() const &
Definition qstring.h:630
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5455
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
Definition qstring.h:1325
QString sliced(qsizetype pos) const &
Definition qstring.h:394
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:994
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8870
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
QString toLower() const &
Definition qstring.h:435
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1240
QString & append(QChar c)
Definition qstring.cpp:3252
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition qstring.cpp:3466
QString toUpper() const &
Definition qstring.h:439
const QChar * unicode() const
Returns a Unicode representation of the string.
Definition qstring.h:1230
void resize(qsizetype size)
Sets the size of the string to size characters.
Definition qstring.cpp:2668
@ StringToAlternateQuotation
Definition qlocale_p.h:160
@ DateTimeToStringShort
Definition qlocale_p.h:148
@ StandaloneMonthNameLong
Definition qlocale_p.h:166
@ ListToSeparatedString
Definition qlocale_p.h:162
@ StandaloneDayNameNarrow
Definition qlocale_p.h:171
@ StandaloneMonthNameNarrow
Definition qlocale_p.h:168
@ StringToStandardQuotation
Definition qlocale_p.h:159
@ StandaloneDayNameShort
Definition qlocale_p.h:170
@ StandaloneDayNameLong
Definition qlocale_p.h:169
@ StandaloneMonthNameShort
Definition qlocale_p.h:167
virtual ~QSystemLocale()
Definition qlocale.cpp:731
\inmodule QtCore \reentrant
Definition qdatetime.h:215
int hour() const
Returns the hour part (0 to 23) of the time.
int minute() const
Returns the minute part (0 to 59) of the time.
bool isValid() const
Returns true if the time is valid; otherwise returns false.
int msec() const
Returns the millisecond part (0 to 999) of the time.
int second() const
Returns the second part (0 to 59) of the time.
constexpr size_type size() const noexcept
const T * constData() const
\inmodule QtCore
Definition qvariant.h:65
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:536
QString str
[2]
QString text
QDate date
[1]
list append(new Employee("Blackpool", "Stephen"))
QStyleOptionButton opt
else opt state
[0]
short next
Definition keywords.cpp:445
Language
Definition language.h:13
Combined button and popup list for selecting options.
constexpr bool isAsciiDigit(char32_t c) noexcept
Definition qtools_p.h:67
constexpr bool isAsciiLetterOrNumber(char32_t c) noexcept
Definition qtools_p.h:82
constexpr bool isAsciiUpper(char32_t c) noexcept
Definition qtools_p.h:72
constexpr char toAsciiLower(char ch) noexcept
Definition qtools_p.h:87
static constexpr bool q_points_into_range(const T *p, const T *b, const T *e, Cmp less={}) noexcept
LayoutDirection
@ LeftToRight
@ RightToLeft
@ CaseInsensitive
constexpr Initialization Uninitialized
DayOfWeek
@ Sunday
@ Monday
constexpr auto ssize(const C &c) -> std::common_type_t< std::ptrdiff_t, std::make_signed_t< decltype(c.size())> >
Definition q20iterator.h:33
QT_POPCOUNT_RELAXED_CONSTEXPR uint qCountLeadingZeroBits(quint32 v) noexcept
#define Q_BASIC_ATOMIC_INITIALIZER(a)
static constexpr uchar asciiLower(uchar c)
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
int qstrncmp(const char *str1, const char *str2, size_t len)
size_t qstrnlen(const char *str, size_t maxlen)
#define Q_FALLTHROUGH()
#define Q_LIKELY(x)
#define Q_DECL_COLD_FUNCTION
#define QT_WARNING_DISABLE_GCC(text)
AudioChannelLayoutTag tag
static qsizetype digitCount(QStringView str)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
size_t qHash(const QFileSystemWatcherPathKey &key, size_t seed=0)
quint16 Offset
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
constexpr QtPrivate::QHashMultiReturnType< T... > qHashMulti(size_t seed, const T &... args) noexcept(std::conjunction_v< QtPrivate::QNothrowHashable< T >... >)
static Q_CONSTINIT QSystemLocale * _systemLocale
Definition qlocale.cpp:69
QDataStream & operator<<(QDataStream &ds, const QLocale &l)
Definition qlocale.cpp:863
static constexpr qsizetype locale_data_size
Definition qlocale.cpp:878
static QLocalePrivate * findLocalePrivate(QLocale::Language language, QLocale::Script script, QLocale::Territory territory)
Definition qlocale.cpp:894
static qsizetype findLocaleIndexById(QLocaleId localeId)
Definition qlocale.cpp:468
static std::optional< QString > systemLocaleString(const QLocaleData *that, QSystemLocale::QueryType type)
Definition qlocale.cpp:917
static const QSystemLocale * systemLocale()
Definition qlocale.cpp:746
static bool checkParsed(QByteArrayView num, qsizetype used)
Definition qlocale.cpp:4498
static QString rawWeekDayName(const QLocaleData *data, const int day, QLocale::FormatType type)
Definition qlocale.cpp:3084
QDataStream & operator>>(QDataStream &ds, QLocale &l)
Definition qlocale.cpp:869
static Q_CONSTINIT const QLocaleData * default_data
Definition qlocale.cpp:686
static Q_CONSTINIT QLocaleData systemLocaleData
Definition qlocale.cpp:70
#define CheckCandidate(id)
static Q_DECL_COLD_FUNCTION void badSeparatorWarning(const char *method, char sep)
Definition qlocale.cpp:1386
static QString rawStandaloneWeekDayName(const QLocaleData *data, const int day, QLocale::FormatType type)
Definition qlocale.cpp:3108
static QStringView findTag(QStringView name) noexcept
Definition qlocale.cpp:537
static bool validTag(QStringView tag)
Definition qlocale.cpp:546
static QLocalePrivate * c_private()
Definition qlocale.cpp:689
static bool isScript(QStringView tag)
Definition qlocale.cpp:557
static T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok)
Definition qlocale.cpp:1434
static bool timeFormatContainsAP(QStringView format)
Definition qlocale.cpp:2188
static bool sameLocale(const QLocaleData *locale, const QCalendarLocale &calendar)
Definition qlocale.cpp:3022
qsizetype qt_repeatCount(QStringView s)
Definition qlocale.cpp:675
bool qt_splitLocaleName(QStringView name, QStringView *lang, QStringView *script, QStringView *land)
Definition qlocale.cpp:567
static void updateSystemPrivate()
Definition qlocale.cpp:758
static QString rawMonthName(const QCalendarLocale &localeData, const char16_t *monthsData, int month, QLocale::FormatType type)
Definition qlocale.cpp:3033
QString qt_readEscapedFormatString(QStringView format, qsizetype *idx)
Definition qlocale.cpp:625
static const QLocaleData * defaultData()
Definition qlocale.cpp:833
static QString rawStandaloneMonthName(const QCalendarLocale &localeData, const char16_t *monthsData, int month, QLocale::FormatType type)
Definition qlocale.cpp:3058
static QString localeString(const QLocaleData *that, QSystemLocale::QueryType type, QLocaleData::DataRange range)
Definition qlocale.cpp:935
static const QLocaleData * systemData(qsizetype *sysIndex=nullptr)
Definition qlocale.cpp:793
static qsizetype defaultIndex()
Definition qlocale.cpp:840
static constexpr char16_t single_character_data[]
static constexpr char16_t days_data[]
constexpr std::array< LanguageCodeEntry, 344 > languageCodeList
static constexpr quint16 locale_index[]
static constexpr char16_t pm_data[]
static constexpr TerritoryLanguage ImperialMeasurementSystems[]
static constexpr QLocaleData locale_data[]
static constexpr char16_t endonyms_data[]
static constexpr QLocaleId likely_subtags[]
static constexpr char territory_name_list[]
static constexpr char16_t am_data[]
static constexpr char16_t currency_format_data[]
static constexpr unsigned char territory_code_list[]
static constexpr quint16 territory_name_index[]
static constexpr char language_name_list[]
static constexpr quint16 script_name_index[]
static constexpr char16_t byte_unit_data[]
static constexpr quint16 language_name_index[]
static constexpr char16_t list_pattern_part_data[]
static constexpr char16_t date_format_data[]
static constexpr char16_t currency_display_name_data[]
static constexpr char16_t time_format_data[]
static constexpr char script_name_list[]
static constexpr char16_t currency_symbol_data[]
static constexpr unsigned char script_code_list[]
bool qt_splitLocaleName(QStringView name, QStringView *lang=nullptr, QStringView *script=nullptr, QStringView *cntry=nullptr)
Definition qlocale.cpp:567
constexpr bool ascii_isspace(uchar c)
Definition qlocale_p.h:556
QT_CLOCALE_HOLDER void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, qsizetype bufSize, bool &sign, int &length, int &decpt)
static constexpr int digits(int number)
QSimpleParsedNumber< qlonglong > qstrntoll(const char *begin, qsizetype size, int base)
QSimpleParsedNumber< qulonglong > qstrntoull(const char *begin, qsizetype size, int base)
QString qulltoa(qulonglong number, int base, const QStringView zero)
QSimpleParsedNumber< double > qt_asciiToDouble(const char *num, qsizetype numLen, StrayCharacterMode strayCharMode)
constexpr bool isZero(double d)
int wholePartSpace(double d)
UcsInt unicodeForDigit(uint digit, UcsInt zero)
#define qWarning
Definition qlogging.h:166
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1384
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
static Q_DECL_CONST_FUNCTION bool qt_is_finite(double d)
Definition qnumeric_p.h:117
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLenum mode
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLenum GLuint GLenum GLsizei length
GLenum GLuint id
[7]
GLdouble GLdouble right
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLsizei range
GLint GLsizei width
GLint left
GLenum type
GLboolean GLuint group
GLenum GLuint GLenum GLsizei const GLchar * buf
GLbitfield flags
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint start
GLuint name
GLsizei bufSize
GLfloat n
GLint GLsizei GLsizei GLenum format
GLdouble s
[6]
Definition qopenglext.h:235
GLenum query
GLuint res
const GLubyte * c
GLuint GLfloat * val
GLuint entry
GLfloat bias
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLsizei len
GLuint num
GLenum GLint GLint * precision
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
static constexpr QChar sep
static ISC_DATE toDate(QDate t)
static ISC_TIME toTime(QTime t)
SSL_CTX int void * arg
#define QStringLiteral(str)
QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
#define zero
#define QT_BEGIN_INCLUDE_NAMESPACE
#define QT_END_INCLUDE_NAMESPACE
#define Q_UNUSED(x)
static int compare(quint64 a, quint64 b)
unsigned char uchar
Definition qtypes.h:32
unsigned short quint16
Definition qtypes.h:48
unsigned long ulong
Definition qtypes.h:35
quint64 qulonglong
Definition qtypes.h:64
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
unsigned short ushort
Definition qtypes.h:33
qint64 qlonglong
Definition qtypes.h:63
static const uint base
Definition qurlidna.cpp:20
static QByteArray getData(int cf, IDataObject *pDataObj, int lindex=-1)
static QString getString(IMFActivate *device, const IID &id)
QList< int > list
[14]
QTextStream out(stdout)
[7]
QDataStream & operator<<(QDataStream &out, const MyClass &myObj)
[4]
MyCustomStruct c2
QDateTime dateTime
[12]
QSharedPointer< T > other(t)
[5]
QCalendarWidget * calendar
[0]
QQuickView * view
[0]
char * toString(const MyType &t)
[31]
std::array< char, 4 > decode() const
\inmodule QtCore \reentrant
Definition qchar.h:18
bool isValid(NumberMode mode) const
Definition qlocale_p.h:365
QString positiveSign() const
Definition qlocale.cpp:989
static float convertDoubleToFloat(double d, bool *ok)
Definition qlocale_p.h:309
QString groupSeparator() const
Definition qlocale.cpp:948
QSimpleParsedNumber< qint64 > stringToLongLong(QStringView str, int base, QLocale::NumberOptions options) const
Definition qlocale.cpp:4477
char32_t zeroUcs() const
Definition qlocale.cpp:968
quint8 m_grouping_least
Definition qlocale_p.h:487
QString zeroDigit() const
Definition qlocale.cpp:963
Q_CORE_EXPORT ParsingResult validateChars(QStringView str, NumberMode numMode, int decDigits=-1, QLocale::NumberOptions number_options=QLocale::DefaultNumberOptions) const
Definition qlocale.cpp:4365
bool numberToCLocale(QStringView s, QLocale::NumberOptions number_options, NumberMode mode, CharBuff *result) const
Definition qlocale.cpp:4256
quint8 m_grouping_top
Definition qlocale_p.h:485
quint8 m_grouping_higher
Definition qlocale_p.h:486
QString decimalPoint() const
Definition qlocale.cpp:943
QString doubleToString(double d, int precision=-1, DoubleForm form=DFSignificantDigits, int width=-1, unsigned flags=NoFlags) const
Definition qlocale.cpp:3706
quint8 m_weekend_start
Definition qlocale_p.h:483
static const QLocaleData * c()
Definition qlocale.cpp:856
QLocaleId id() const
Definition qlocale_p.h:386
QString listSeparator() const
Definition qlocale.cpp:958
static qsizetype findLocaleIndex(QLocaleId localeId)
Definition qlocale.cpp:487
static QSimpleParsedNumber< quint64 > bytearrayToUnsLongLong(QByteArrayView num, int base)
Definition qlocale.cpp:4524
QString percentSign() const
Definition qlocale.cpp:953
@ BlankBeforePositive
Definition qlocale_p.h:262
@ AddTrailingZeroes
Definition qlocale_p.h:259
double stringToDouble(QStringView str, bool *ok, QLocale::NumberOptions options) const
Definition qlocale.cpp:4461
QString longLongToString(qint64 l, int precision=-1, int base=10, int width=-1, unsigned flags=NoFlags) const
Definition qlocale.cpp:3945
@ DoubleScientificMode
Definition qlocale_p.h:273
@ DFSignificantDigits
Definition qlocale_p.h:253
quint8 m_first_day_of_week
Definition qlocale_p.h:482
quint8 m_weekend_end
Definition qlocale_p.h:484
NumericData numericData(NumberMode mode) const
Definition qlocale.cpp:4029
QString exponentSeparator() const
Definition qlocale.cpp:994
QString negativeSign() const
Definition qlocale.cpp:984
static Q_CORE_EXPORT QSimpleParsedNumber< qint64 > bytearrayToLongLong(QByteArrayView num, int base)
Definition qlocale.cpp:4516
QSimpleParsedNumber< quint64 > stringToUnsLongLong(QStringView str, int base, QLocale::NumberOptions options) const
Definition qlocale.cpp:4488
QString unsLongLongToString(quint64 l, int precision=-1, int base=10, int width=-1, unsigned flags=NoFlags) const
Definition qlocale.cpp:3960
QLocaleId withLikelySubtagsRemoved() const
Definition qlocale.cpp:382
bool matchesAll() const
Definition qlocale_p.h:201
ushort script_id
Definition qlocale_p.h:223
QLocaleId withLikelySubtagsAdded() const
Fill in blank fields of a locale ID.
Definition qlocale.cpp:298
ushort territory_id
Definition qlocale_p.h:223
QByteArray name(char separator='-') const
Definition qlocale.cpp:406
ushort language_id
Definition qlocale_p.h:223
static Q_AUTOTEST_EXPORT QLocaleId fromName(QStringView name)
Definition qlocale.cpp:611