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