1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qglobal.h"
43
44 #ifndef QT_NO_SYSTEMLOCALE
45 QT_BEGIN_NAMESPACE
46 class QSystemLocale;
47 static QSystemLocale *QSystemLocale_globalSystemLocale();
48 QT_END_NAMESPACE
49 #endif
50
51 #if !defined(QWS) && defined(Q_OS_MAC)
52 # include "private/qcore_mac_p.h"
53 # include <CoreFoundation/CoreFoundation.h>
54 #endif
55
56 #include "qplatformdefs.h"
57
58 #include "qdatastream.h"
59 #include "qstring.h"
60 #include "qlocale.h"
61 #include "qlocale_p.h"
62 #include "qlocale_tools_p.h"
63 #include "qdatetime_p.h"
64 #include "qnamespace.h"
65 #include "qdatetime.h"
66 #include "qstringlist.h"
67 #include "qvariant.h"
68 #include "qstringbuilder.h"
69 #if defined(Q_WS_WIN)
70 # include "qt_windows.h"
71 # include <time.h>
72 #endif
73 #include "private/qnumeric_p.h"
74 #include "private/qsystemlibrary_p.h"
75
76 QT_BEGIN_NAMESPACE
77
78 #if defined(Q_OS_SYMBIAN)
79 void qt_symbianUpdateSystemPrivate();
80 #endif
81
82 #ifndef QT_NO_SYSTEMLOCALE
83 static QSystemLocale *_systemLocale = 0;
84 Q_GLOBAL_STATIC_WITH_ARGS(QSystemLocale, QSystemLocale_globalSystemLocale, (true))
85 static QLocalePrivate *system_lp = 0;
86 Q_GLOBAL_STATIC(QLocalePrivate, globalLocalePrivate)
87 #endif
88
89 #ifdef QT_USE_ICU
90 extern bool qt_initIcu(const QString &localeName);
91 extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale);
92 extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale);
93 #endif
94
95 /******************************************************************************
96 ** Helpers for accessing Qt locale database
97 */
98
99 QT_BEGIN_INCLUDE_NAMESPACE
100 #include "qlocale_data_p.h"
101 QT_END_INCLUDE_NAMESPACE
102
codeToLanguage(const QString & code)103 QLocale::Language QLocalePrivate::codeToLanguage(const QString &code)
104 {
105 int len = code.length();
106 if (len != 2 && len != 3)
107 return QLocale::C;
108 ushort uc1 = len-- > 0 ? code[0].toLower().unicode() : 0;
109 ushort uc2 = len-- > 0 ? code[1].toLower().unicode() : 0;
110 ushort uc3 = len-- > 0 ? code[2].toLower().unicode() : 0;
111
112 if (uc1 == 'n' && uc2 == 'o' && uc3 == 0)
113 uc2 = 'b';
114
115 const unsigned char *c = language_code_list;
116 for (; *c != 0; c += 3) {
117 if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
118 return QLocale::Language((c - language_code_list)/3);
119 }
120
121 return QLocale::C;
122 }
123
codeToScript(const QString & code)124 QLocale::Script QLocalePrivate::codeToScript(const QString &code)
125 {
126 int len = code.length();
127 if (len != 4)
128 return QLocale::AnyScript;
129
130 // script is titlecased in our data
131 unsigned char c0 = code.at(0).toUpper().toLatin1();
132 unsigned char c1 = code.at(1).toLower().toLatin1();
133 unsigned char c2 = code.at(2).toLower().toLatin1();
134 unsigned char c3 = code.at(3).toLower().toLatin1();
135
136 const unsigned char *c = script_code_list;
137 for (int i = 0; i < QLocale::LastScript; ++i, c += 4) {
138 if (c0 == c[0] && c1 == c[1] && c2 == c[2] && c3 == c[3])
139 return QLocale::Script(i);
140 }
141 return QLocale::AnyScript;
142 }
143
codeToCountry(const QString & code)144 QLocale::Country QLocalePrivate::codeToCountry(const QString &code)
145 {
146 int len = code.length();
147 if (len != 2 && len != 3)
148 return QLocale::AnyCountry;
149 ushort uc1 = len-- > 0 ? code[0].toUpper().unicode() : 0;
150 ushort uc2 = len-- > 0 ? code[1].toUpper().unicode() : 0;
151 ushort uc3 = len-- > 0 ? code[2].toUpper().unicode() : 0;
152
153 const unsigned char *c = country_code_list;
154 for (; *c != 0; c += 3) {
155 if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
156 return QLocale::Country((c - country_code_list)/3);
157 }
158
159 return QLocale::AnyCountry;
160 }
161
languageCode() const162 QString QLocalePrivate::languageCode() const
163 {
164 if (m_language_id == QLocale::AnyLanguage)
165 return QString();
166 if (m_language_id == QLocale::C)
167 return QLatin1String("C");
168
169 const unsigned char *c = language_code_list + 3*(uint(m_language_id));
170
171 QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
172
173 code[0] = ushort(c[0]);
174 code[1] = ushort(c[1]);
175 if (c[2] != 0)
176 code[2] = ushort(c[2]);
177
178 return code;
179 }
180
scriptCode() const181 QString QLocalePrivate::scriptCode() const
182 {
183 if (m_script_id == QLocale::AnyScript || m_script_id > QLocale::LastScript)
184 return QString();
185 const unsigned char *c = script_code_list + 4*(uint(m_script_id));
186 return QString::fromLatin1((const char *)c, 4);
187 }
188
countryCode() const189 QString QLocalePrivate::countryCode() const
190 {
191 if (m_country_id == QLocale::AnyCountry)
192 return QString();
193
194 const unsigned char *c = country_code_list + 3*(uint(m_country_id));
195
196 QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
197
198 code[0] = ushort(c[0]);
199 code[1] = ushort(c[1]);
200 if (c[2] != 0)
201 code[2] = ushort(c[2]);
202
203 return code;
204 }
205
bcp47Name() const206 QString QLocalePrivate::bcp47Name() const
207 {
208 if (m_language_id == QLocale::AnyLanguage)
209 return QString();
210 if (m_language_id == QLocale::C)
211 return QLatin1String("C");
212 const unsigned char *lang = language_code_list + 3*(uint(m_language_id));
213 const unsigned char *script =
214 (m_script_id != QLocale::AnyScript ? script_code_list + 4*(uint(m_script_id)) : 0);
215 const unsigned char *country =
216 (m_country_id != QLocale::AnyCountry ? country_code_list + 3*(uint(m_country_id)) : 0);
217 char len = (lang[2] != 0 ? 3 : 2) + (script ? 4+1 : 0) + (country ? (country[2] != 0 ? 3 : 2)+1 : 0);
218 QString name(len, Qt::Uninitialized);
219 QChar *uc = name.data();
220 *uc++ = ushort(lang[0]);
221 *uc++ = ushort(lang[1]);
222 if (lang[2] != 0)
223 *uc++ = ushort(lang[2]);
224 if (script) {
225 *uc++ = QLatin1Char('-');
226 *uc++ = ushort(script[0]);
227 *uc++ = ushort(script[1]);
228 *uc++ = ushort(script[2]);
229 *uc++ = ushort(script[3]);
230 }
231 if (country) {
232 *uc++ = QLatin1Char('-');
233 *uc++ = ushort(country[0]);
234 *uc++ = ushort(country[1]);
235 if (country[2] != 0)
236 *uc++ = ushort(country[2]);
237 }
238 return name;
239 }
240
findLocale(QLocale::Language language,QLocale::Script script,QLocale::Country country)241 const QLocalePrivate *QLocalePrivate::findLocale(QLocale::Language language, QLocale::Script script, QLocale::Country country)
242 {
243 const unsigned language_id = language;
244 const unsigned script_id = script;
245 const unsigned country_id = country;
246
247 uint idx = locale_index[language_id];
248
249 const QLocalePrivate *d = locale_data + idx;
250
251 if (idx == 0) // default language has no associated country
252 return d;
253
254 if (script == QLocale::AnyScript && country == QLocale::AnyCountry)
255 return d;
256
257 Q_ASSERT(d->languageId() == language_id);
258
259 if (country == QLocale::AnyCountry) {
260 while (d->m_language_id == language_id && d->m_script_id != script_id)
261 ++d;
262 if (d->m_language_id == language_id && d->m_script_id == script_id)
263 return d;
264 } else if (script == QLocale::AnyScript) {
265 while (d->m_language_id == language_id) {
266 if (d->m_script_id == script_id && d->m_country_id == country_id)
267 return d;
268 ++d;
269 }
270 } else {
271 // both script and country are explicitly specified
272 while (d->m_language_id == language_id) {
273 if (d->m_script_id == script_id && d->m_country_id == country_id)
274 return d;
275 ++d;
276 }
277 }
278
279 return locale_data + idx;
280 }
281
parse_locale_tag(const QString & input,int & i,QString * result,const QString & separators)282 static bool parse_locale_tag(const QString &input, int &i, QString *result, const QString &separators)
283 {
284 *result = QString(8, Qt::Uninitialized); // worst case according to BCP47
285 QChar *pch = result->data();
286 const QChar *uc = input.data() + i;
287 const int l = input.length();
288 int size = 0;
289 for (; i < l && size < 8; ++i, ++size) {
290 if (separators.contains(*uc))
291 break;
292 if (! ((uc->unicode() >= 'a' && uc->unicode() <= 'z') ||
293 (uc->unicode() >= 'A' && uc->unicode() <= 'Z') ||
294 (uc->unicode() >= '0' && uc->unicode() <= '9')) ) // latin only
295 return false;
296 *pch++ = *uc++;
297 }
298 result->truncate(size);
299 return true;
300 }
301
qt_splitLocaleName(const QString & name,QString & lang,QString & script,QString & cntry)302 bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry)
303 {
304 const int length = name.length();
305
306 lang = script = cntry = QString();
307
308 const QString separators = QLatin1String("_-.@");
309 enum ParserState { NoState, LangState, ScriptState, CountryState };
310 ParserState state = LangState;
311 for (int i = 0; i < length && state != NoState; ) {
312 QString value;
313 if (!parse_locale_tag(name, i, &value, separators) ||value.isEmpty())
314 break;
315 QChar sep = i < length ? name.at(i) : QChar();
316 switch (state) {
317 case LangState:
318 if (!sep.isNull() && !separators.contains(sep)) {
319 state = NoState;
320 break;
321 }
322 lang = value;
323 if (i == length) {
324 // just language was specified
325 state = NoState;
326 break;
327 }
328 state = ScriptState;
329 break;
330 case ScriptState: {
331 QString scripts = QString::fromLatin1((const char *)script_code_list, sizeof(script_code_list));
332 if (value.length() == 4 && scripts.indexOf(value) % 4 == 0) {
333 // script name is always 4 characters
334 script = value;
335 state = CountryState;
336 } else {
337 // it wasn't a script, maybe it is a country then?
338 cntry = value;
339 state = NoState;
340 }
341 break;
342 }
343 case CountryState:
344 cntry = value;
345 state = NoState;
346 break;
347 case NoState:
348 // shouldn't happen
349 qWarning("QLocale: This should never happen");
350 break;
351 }
352 ++i;
353 }
354 return lang.length() == 2 || lang.length() == 3;
355 }
356
getLangAndCountry(const QString & name,QLocale::Language & lang,QLocale::Script & script,QLocale::Country & cntry)357 void QLocalePrivate::getLangAndCountry(const QString &name, QLocale::Language &lang,
358 QLocale::Script &script, QLocale::Country &cntry)
359 {
360 lang = QLocale::C;
361 script = QLocale::AnyScript;
362 cntry = QLocale::AnyCountry;
363
364 QString lang_code;
365 QString script_code;
366 QString cntry_code;
367 if (!qt_splitLocaleName(name, lang_code, script_code, cntry_code))
368 return;
369
370 lang = QLocalePrivate::codeToLanguage(lang_code);
371 if (lang == QLocale::C)
372 return;
373 script = QLocalePrivate::codeToScript(script_code);
374 cntry = QLocalePrivate::codeToCountry(cntry_code);
375 }
376
findLocale(const QString & name)377 static const QLocalePrivate *findLocale(const QString &name)
378 {
379 QLocale::Language lang;
380 QLocale::Script script;
381 QLocale::Country cntry;
382 QLocalePrivate::getLangAndCountry(name, lang, script, cntry);
383
384 return QLocalePrivate::findLocale(lang, script, cntry);
385 }
386
qt_readEscapedFormatString(const QString & format,int * idx)387 QString qt_readEscapedFormatString(const QString &format, int *idx)
388 {
389 int &i = *idx;
390
391 Q_ASSERT(format.at(i) == QLatin1Char('\''));
392 ++i;
393 if (i == format.size())
394 return QString();
395 if (format.at(i).unicode() == '\'') { // "''" outside of a quoted stirng
396 ++i;
397 return QLatin1String("'");
398 }
399
400 QString result;
401
402 while (i < format.size()) {
403 if (format.at(i).unicode() == '\'') {
404 if (i + 1 < format.size() && format.at(i + 1).unicode() == '\'') {
405 // "''" inside of a quoted string
406 result.append(QLatin1Char('\''));
407 i += 2;
408 } else {
409 break;
410 }
411 } else {
412 result.append(format.at(i++));
413 }
414 }
415 if (i < format.size())
416 ++i;
417
418 return result;
419 }
420
qt_repeatCount(const QString & s,int i)421 int qt_repeatCount(const QString &s, int i)
422 {
423 QChar c = s.at(i);
424 int j = i + 1;
425 while (j < s.size() && s.at(j) == c)
426 ++j;
427 return j - i;
428 }
429
430 static const QLocalePrivate *default_lp = 0;
431 static uint default_number_options = 0;
432
433 #ifndef QT_NO_SYSTEMLOCALE
434
435
436 /******************************************************************************
437 ** Default system locale behavior
438 */
439
440 /*!
441 Constructs a QSystemLocale object. The constructor will automatically
442 install this object as the system locale and remove any earlier installed
443 system locales.
444 */
QSystemLocale()445 QSystemLocale::QSystemLocale()
446 {
447 delete _systemLocale;
448 _systemLocale = this;
449
450 if (system_lp)
451 system_lp->m_language_id = 0;
452 }
453
454 /*! \internal */
QSystemLocale(bool)455 QSystemLocale::QSystemLocale(bool)
456 { }
457
458 /*!
459 Deletes the object.
460 */
~QSystemLocale()461 QSystemLocale::~QSystemLocale()
462 {
463 if (_systemLocale == this) {
464 _systemLocale = 0;
465
466 if (system_lp)
467 system_lp->m_language_id = 0;
468 }
469 }
470
systemLocale()471 static const QSystemLocale *systemLocale()
472 {
473 if (_systemLocale)
474 return _systemLocale;
475 return QSystemLocale_globalSystemLocale();
476 }
477
updateSystemPrivate()478 void QLocalePrivate::updateSystemPrivate()
479 {
480 const QSystemLocale *sys_locale = systemLocale();
481 if (!system_lp)
482 system_lp = globalLocalePrivate();
483
484 // tell the object that the system locale has changed.
485 sys_locale->query(QSystemLocale::LocaleChanged, QVariant());
486
487 *system_lp = *sys_locale->fallbackLocale().d();
488
489 #if defined(Q_OS_SYMBIAN)
490 qt_symbianUpdateSystemPrivate();
491 #endif
492
493 QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
494 if (!res.isNull()) {
495 system_lp->m_language_id = res.toInt();
496 system_lp->m_script_id = QLocale::AnyScript; // default for compatibility
497 }
498 res = sys_locale->query(QSystemLocale::CountryId, QVariant());
499 if (!res.isNull()) {
500 system_lp->m_country_id = res.toInt();
501 system_lp->m_script_id = QLocale::AnyScript; // default for compatibility
502 }
503 res = sys_locale->query(QSystemLocale::ScriptId, QVariant());
504 if (!res.isNull())
505 system_lp->m_script_id = res.toInt();
506
507 res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant());
508 if (!res.isNull())
509 system_lp->m_decimal = res.toString().at(0).unicode();
510
511 res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant());
512 if (!res.isNull())
513 system_lp->m_group = res.toString().at(0).unicode();
514
515 res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant());
516 if (!res.isNull())
517 system_lp->m_zero = res.toString().at(0).unicode();
518
519 res = sys_locale->query(QSystemLocale::NegativeSign, QVariant());
520 if (!res.isNull())
521 system_lp->m_minus = res.toString().at(0).unicode();
522
523 res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
524 if (!res.isNull())
525 system_lp->m_plus = res.toString().at(0).unicode();
526
527 #ifdef QT_USE_ICU
528 if (!default_lp)
529 qt_initIcu(system_lp->bcp47Name());
530 #endif
531
532 }
533 #endif
534
systemPrivate()535 static const QLocalePrivate *systemPrivate()
536 {
537 #ifndef QT_NO_SYSTEMLOCALE
538 // copy over the information from the fallback locale and modify
539 if (!system_lp || system_lp->m_language_id == 0)
540 QLocalePrivate::updateSystemPrivate();
541
542 return system_lp;
543 #else
544 return locale_data;
545 #endif
546 }
547
defaultPrivate()548 static const QLocalePrivate *defaultPrivate()
549 {
550 if (!default_lp)
551 default_lp = systemPrivate();
552 return default_lp;
553 }
554
getLocaleListData(const ushort * data,int size,int index)555 static QString getLocaleListData(const ushort *data, int size, int index)
556 {
557 static const ushort separator = ';';
558 while (index && size > 0) {
559 while (*data != separator)
560 ++data, --size;
561 --index;
562 ++data;
563 --size;
564 }
565 const ushort *end = data;
566 while (size > 0 && *end != separator)
567 ++end, --size;
568 if (end-data == 0)
569 return QString();
570 return QString::fromRawData(reinterpret_cast<const QChar*>(data), end-data);
571 }
572
getLocaleData(const ushort * data,int size)573 static inline QString getLocaleData(const ushort *data, int size)
574 {
575 return size ? QString::fromRawData(reinterpret_cast<const QChar*>(data), size) : QString();
576 }
577
578
579 #ifndef QT_NO_DATASTREAM
operator <<(QDataStream & ds,const QLocale & l)580 QDataStream &operator<<(QDataStream &ds, const QLocale &l)
581 {
582 ds << l.name();
583 return ds;
584 }
585
operator >>(QDataStream & ds,QLocale & l)586 QDataStream &operator>>(QDataStream &ds, QLocale &l)
587 {
588 QString s;
589 ds >> s;
590 l = QLocale(s);
591 return ds;
592 }
593 #endif // QT_NO_DATASTREAM
594
595
596 static const int locale_data_size = sizeof(locale_data)/sizeof(QLocalePrivate) - 1;
597
dataPointerHelper(quint16 index)598 static const QLocalePrivate *dataPointerHelper(quint16 index)
599 {
600 #ifndef QT_NO_SYSTEMLOCALE
601 Q_ASSERT(index <= locale_data_size);
602 if (index == locale_data_size)
603 return system_lp;
604 #else
605 Q_ASSERT(index < locale_data_size);
606 #endif
607
608 return &locale_data[index];
609 }
610
localePrivateIndex(const QLocalePrivate * p)611 static quint16 localePrivateIndex(const QLocalePrivate *p)
612 {
613 #ifndef QT_NO_SYSTEMLOCALE
614 Q_ASSERT((p >= locale_data && p - locale_data < locale_data_size)
615 || (p != 0 && p == system_lp));
616 quint16 index = p == system_lp ? locale_data_size : p - locale_data;
617 #else
618 Q_ASSERT(p >= locale_data && p - locale_data < locale_data_size);
619 quint16 index = p - locale_data;
620 #endif
621
622 return index;
623 }
624
625 /*!
626 Constructs a QLocale object with the specified \a name,
627 which has the format
628 "language[_script][_country][.codeset][@modifier]" or "C", where:
629
630 \list
631 \i language is a lowercase, two-letter, ISO 639 language code,
632 \i script is a titlecase, four-letter, ISO 15924 script code,
633 \i country is an uppercase, two- or three-letter, ISO 3166 country code (also "419" as defined by United Nations),
634 \i and codeset and modifier are ignored.
635 \endlist
636
637 The separator can be either underscore or a minus sign.
638
639 If the string violates the locale format, or language is not
640 a valid ISO 369 code, the "C" locale is used instead. If country
641 is not present, or is not a valid ISO 3166 code, the most
642 appropriate country is chosen for the specified language.
643
644 The language, script and country codes are converted to their respective
645 \c Language, \c Script and \c Country enums. After this conversion is
646 performed the constructor behaves exactly like QLocale(Country, Script,
647 Language).
648
649 This constructor is much slower than QLocale(Country, Script, Language).
650
651 \sa bcp47Name()
652 */
653
QLocale(const QString & name)654 QLocale::QLocale(const QString &name)
655 : v(0)
656 {
657 p.numberOptions = 0;
658 p.index = localePrivateIndex(findLocale(name));
659 }
660
661 /*!
662 Constructs a QLocale object initialized with the default locale. If
663 no default locale was set using setDefaultLocale(), this locale will
664 be the same as the one returned by system().
665
666 \sa setDefault()
667 */
668
QLocale()669 QLocale::QLocale()
670 : v(0)
671 {
672 p.numberOptions = default_number_options;
673 p.index = localePrivateIndex(defaultPrivate());
674 }
675
676 /*!
677 Constructs a QLocale object with the specified \a language and \a
678 country.
679
680 \list
681 \i If the language/country pair is found in the database, it is used.
682 \i If the language is found but the country is not, or if the country
683 is \c AnyCountry, the language is used with the most
684 appropriate available country (for example, Germany for German),
685 \i If neither the language nor the country are found, QLocale
686 defaults to the default locale (see setDefault()).
687 \endlist
688
689 The language and country that are actually used can be queried
690 using language() and country().
691
692 \sa setDefault() language() country()
693 */
694
QLocale(Language language,Country country)695 QLocale::QLocale(Language language, Country country)
696 : v(0)
697 {
698 const QLocalePrivate *d = QLocalePrivate::findLocale(language, QLocale::AnyScript, country);
699
700 // If not found, should default to system
701 if (d->languageId() == QLocale::C && language != QLocale::C) {
702 p.numberOptions = default_number_options;
703 p.index = localePrivateIndex(defaultPrivate());
704 } else {
705 p.numberOptions = 0;
706 p.index = localePrivateIndex(d);
707 }
708 }
709 \
710 /*!
711 \since 4.8
712
713 Constructs a QLocale object with the specified \a language, \a script and
714 \a country.
715
716 \list
717 \i If the language/script/country is found in the database, it is used.
718 \i If both \a script is AnyScript and \a country is AnyCountry, the
719 language is used with the most appropriate available script and country
720 (for example, Germany for German),
721 \i If either \a script is AnyScript or \a country is AnyCountry, the
722 language is used with the first locale that matches the given \a script
723 and \a country.
724 \i If neither the language nor the country are found, QLocale
725 defaults to the default locale (see setDefault()).
726 \endlist
727
728 The language, script and country that are actually used can be queried
729 using language(), script() and country().
730
731 \sa setDefault() language() script() country()
732 */
733
QLocale(Language language,Script script,Country country)734 QLocale::QLocale(Language language, Script script, Country country)
735 : v(0)
736 {
737 const QLocalePrivate *d = QLocalePrivate::findLocale(language, script, country);
738
739 // If not found, should default to system
740 if (d->languageId() == QLocale::C && language != QLocale::C) {
741 p.numberOptions = default_number_options;
742 p.index = localePrivateIndex(defaultPrivate());
743 } else {
744 p.numberOptions = 0;
745 p.index = localePrivateIndex(d);
746 }
747 }
748
749 /*!
750 Constructs a QLocale object as a copy of \a other.
751 */
752
QLocale(const QLocale & other)753 QLocale::QLocale(const QLocale &other)
754 {
755 v = other.v;
756 }
757
d() const758 const QLocalePrivate *QLocale::d() const
759 {
760 return dataPointerHelper(p.index);
761 }
762
763 /*!
764 Assigns \a other to this QLocale object and returns a reference
765 to this QLocale object.
766 */
767
operator =(const QLocale & other)768 QLocale &QLocale::operator=(const QLocale &other)
769 {
770 v = other.v;
771 return *this;
772 }
773
774 /*!
775 \since 4.2
776
777 Sets the \a options related to number conversions for this
778 QLocale instance.
779 */
setNumberOptions(NumberOptions options)780 void QLocale::setNumberOptions(NumberOptions options)
781 {
782 p.numberOptions = options;
783 }
784
785 /*!
786 \since 4.2
787
788 Returns the options related to number conversions for this
789 QLocale instance.
790
791 By default, no options are set for the standard locales.
792 */
numberOptions() const793 QLocale::NumberOptions QLocale::numberOptions() const
794 {
795 return static_cast<NumberOption>(p.numberOptions);
796 }
797
798 /*!
799 \since 4.8
800
801 Returns \a str quoted according to the current locale using the given
802 quotation \a style.
803 */
quoteString(const QString & str,QuotationStyle style) const804 QString QLocale::quoteString(const QString &str, QuotationStyle style) const
805 {
806 return quoteString(&str, style);
807 }
808
809 /*!
810 \since 4.8
811
812 \overload
813 */
quoteString(const QStringRef & str,QuotationStyle style) const814 QString QLocale::quoteString(const QStringRef &str, QuotationStyle style) const
815 {
816 #ifndef QT_NO_SYSTEMLOCALE
817 if (d() == systemPrivate()) {
818 QVariant res;
819 if (style == QLocale::AlternateQuotation)
820 res = systemLocale()->query(QSystemLocale::StringToAlternateQuotation, QVariant::fromValue(str));
821 if (res.isNull() || style == QLocale::StandardQuotation)
822 res = systemLocale()->query(QSystemLocale::StringToStandardQuotation, QVariant::fromValue(str));
823 if (!res.isNull())
824 return res.toString();
825 }
826 #endif
827
828 if (style == QLocale::StandardQuotation)
829 return QChar(d()->m_quotation_start) % str % QChar(d()->m_quotation_end);
830 else
831 return QChar(d()->m_alternate_quotation_start) % str % QChar(d()->m_alternate_quotation_end);
832 }
833
834 /*!
835 \since 4.8
836
837 Returns a string that represents a join of a given \a list of strings with
838 a separator defined by the locale.
839 */
createSeparatedList(const QStringList & list) const840 QString QLocale::createSeparatedList(const QStringList &list) const
841 {
842 #ifndef QT_NO_SYSTEMLOCALE
843 if (d() == systemPrivate()) {
844 QVariant res;
845 res = systemLocale()->query(QSystemLocale::ListToSeparatedString, QVariant::fromValue(list));
846
847 if (!res.isNull())
848 return res.toString();
849 }
850 #endif
851
852 const int size = list.size();
853 if (size == 1) {
854 return list.at(0);
855 } else if (size == 2) {
856 QString format = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_two_idx, d()->m_list_pattern_part_two_size);
857 return format.arg(list.at(0), list.at(1));
858 } else if (size > 2) {
859 QString formatStart = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_start_idx, d()->m_list_pattern_part_start_size);
860 QString formatMid = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_mid_idx, d()->m_list_pattern_part_mid_size);
861 QString formatEnd = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_end_idx, d()->m_list_pattern_part_end_size);
862 QString result = formatStart.arg(list.at(0), list.at(1));
863 for (int i = 2; i < size - 1; ++i)
864 result = formatMid.arg(result, list.at(i));
865 result = formatEnd.arg(result, list.at(size - 1));
866 return result;
867 }
868
869 return QString();
870 }
871
872 /*!
873 \nonreentrant
874
875 Sets the global default locale to \a locale. These
876 values are used when a QLocale object is constructed with
877 no arguments. If this function is not called, the system's
878 locale is used.
879
880 \warning In a multithreaded application, the default locale
881 should be set at application startup, before any non-GUI threads
882 are created.
883
884 \sa system() c()
885 */
886
setDefault(const QLocale & locale)887 void QLocale::setDefault(const QLocale &locale)
888 {
889 default_lp = locale.d();
890 default_number_options = locale.numberOptions();
891
892 #ifdef QT_USE_ICU
893 qt_initIcu(locale.bcp47Name());
894 #endif
895 }
896
897 /*!
898 Returns the language of this locale.
899
900 \sa script(), country(), languageToString(), bcp47Name()
901 */
language() const902 QLocale::Language QLocale::language() const
903 {
904 return Language(d()->languageId());
905 }
906
907 /*!
908 \since 4.8
909
910 Returns the script of this locale.
911
912 \sa language(), country(), languageToString(), scriptToString(), bcp47Name()
913 */
script() const914 QLocale::Script QLocale::script() const
915 {
916 return Script(d()->m_script_id);
917 }
918
919 /*!
920 Returns the country of this locale.
921
922 \sa language(), script(), countryToString(), bcp47Name()
923 */
country() const924 QLocale::Country QLocale::country() const
925 {
926 return Country(d()->countryId());
927 }
928
929 /*!
930 Returns the language and country of this locale as a
931 string of the form "language_country", where
932 language is a lowercase, two-letter ISO 639 language code,
933 and country is an uppercase, two- or three-letter ISO 3166 country code.
934
935 Note that even if QLocale object was constructed with an explicit script,
936 name() will not contain it for compatibility reasons. Use bcp47Name() instead
937 if you need a full locale name.
938
939 \sa QLocale(), language(), script(), country(), bcp47Name()
940 */
941
name() const942 QString QLocale::name() const
943 {
944 const QLocalePrivate *dd = d();
945
946 if (dd->m_language_id == QLocale::AnyLanguage)
947 return QString();
948 if (dd->m_language_id == QLocale::C)
949 return QLatin1String("C");
950
951 const unsigned char *c = language_code_list + 3*(uint(dd->m_language_id));
952
953 QString result(7, Qt::Uninitialized);
954 ushort *data = (ushort *)result.unicode();
955 const ushort *begin = data;
956
957 *data++ = ushort(c[0]);
958 *data++ = ushort(c[1]);
959 if (c[2] != 0)
960 *data++ = ushort(c[2]);
961 if (dd->m_country_id != AnyCountry) {
962 *data++ = '_';
963 const unsigned char *c = country_code_list + 3*(uint(dd->m_country_id));
964 *data++ = ushort(c[0]);
965 *data++ = ushort(c[1]);
966 if (c[2] != 0)
967 *data++ = ushort(c[2]);
968 }
969 result.resize(data - begin);
970
971 return result;
972 }
973
974 /*!
975 \since 4.8
976
977 Returns the dash-separated language, script and country (and possibly other BCP47 fields)
978 of this locale as a string.
979
980 Unlike the uiLanguages() the returned value of the bcp47Name() represents
981 the locale name of the QLocale data but not the language the user-interface
982 should be in.
983
984 This function tries to conform the locale name to BCP47.
985
986 \sa language(), country(), script(), uiLanguages()
987 */
bcp47Name() const988 QString QLocale::bcp47Name() const
989 {
990 return d()->bcp47Name();
991 }
992
993 /*!
994 Returns a QString containing the name of \a language.
995
996 \sa countryToString(), scriptToString(), bcp47Name()
997 */
998
languageToString(Language language)999 QString QLocale::languageToString(Language language)
1000 {
1001 if (uint(language) > uint(QLocale::LastLanguage))
1002 return QLatin1String("Unknown");
1003 return QLatin1String(language_name_list + language_name_index[language]);
1004 }
1005
1006 /*!
1007 Returns a QString containing the name of \a country.
1008
1009 \sa languageToString(), scriptToString(), country(), bcp47Name()
1010 */
1011
countryToString(Country country)1012 QString QLocale::countryToString(Country country)
1013 {
1014 if (uint(country) > uint(QLocale::LastCountry))
1015 return QLatin1String("Unknown");
1016 return QLatin1String(country_name_list + country_name_index[country]);
1017 }
1018
1019 /*!
1020 \since 4.8
1021
1022 Returns a QString containing the name of \a script.
1023
1024 \sa languageToString(), countryToString(), script(), bcp47Name()
1025 */
scriptToString(QLocale::Script script)1026 QString QLocale::scriptToString(QLocale::Script script)
1027 {
1028 if (uint(script) > uint(QLocale::LastScript))
1029 return QLatin1String("Unknown");
1030 return QLatin1String(script_name_list + script_name_index[script]);
1031 }
1032
1033 /*!
1034 Returns the short int represented by the localized string \a s,
1035 using base \a base. If \a base is 0 the base is determined
1036 automatically using the following rules: If the string begins with
1037 "0x", it is assumed to be hexadecimal; if it begins with "0", it
1038 is assumed to be octal; otherwise it is assumed to be decimal.
1039
1040 If the conversion fails the function returns 0.
1041
1042 If \a ok is not 0, failure is reported by setting *ok to false, and
1043 success by setting *ok to true.
1044
1045 This function ignores leading and trailing whitespace.
1046
1047 \sa toUShort(), toString()
1048 */
1049
toShort(const QString & s,bool * ok,int base) const1050 short QLocale::toShort(const QString &s, bool *ok, int base) const
1051 {
1052 qlonglong i = toLongLong(s, ok, base);
1053 if (i < SHRT_MIN || i > SHRT_MAX) {
1054 if (ok != 0)
1055 *ok = false;
1056 return 0;
1057 }
1058 return short(i);
1059 }
1060
1061 /*!
1062 Returns the unsigned short int represented by the localized string
1063 \a s, using base \a base. If \a base is 0 the base is determined
1064 automatically using the following rules: If the string begins with
1065 "0x", it is assumed to be hexadecimal; if it begins with "0", it
1066 is assumed to be octal; otherwise it is assumed to be decimal.
1067
1068 If the conversion fails the function returns 0.
1069
1070 If \a ok is not 0, failure is reported by setting *ok to false, and
1071 success by setting *ok to true.
1072
1073 This function ignores leading and trailing whitespace.
1074
1075 \sa toShort(), toString()
1076 */
1077
toUShort(const QString & s,bool * ok,int base) const1078 ushort QLocale::toUShort(const QString &s, bool *ok, int base) const
1079 {
1080 qulonglong i = toULongLong(s, ok, base);
1081 if (i > USHRT_MAX) {
1082 if (ok != 0)
1083 *ok = false;
1084 return 0;
1085 }
1086 return ushort(i);
1087 }
1088
1089 /*!
1090 Returns the int represented by the localized string \a s, using
1091 base \a base. If \a base is 0 the base is determined automatically
1092 using the following rules: If the string begins with "0x", it is
1093 assumed to be hexadecimal; if it begins with "0", it is assumed to
1094 be octal; otherwise it is assumed to be decimal.
1095
1096 If the conversion fails the function returns 0.
1097
1098 If \a ok is not 0, failure is reported by setting *ok to false, and
1099 success by setting *ok to true.
1100
1101 This function ignores leading and trailing whitespace.
1102
1103 \sa toUInt(), toString()
1104 */
1105
toInt(const QString & s,bool * ok,int base) const1106 int QLocale::toInt(const QString &s, bool *ok, int base) const
1107 {
1108 qlonglong i = toLongLong(s, ok, base);
1109 if (i < INT_MIN || i > INT_MAX) {
1110 if (ok != 0)
1111 *ok = false;
1112 return 0;
1113 }
1114 return int(i);
1115 }
1116
1117 /*!
1118 Returns the unsigned int represented by the localized string \a s,
1119 using base \a base. If \a base is 0 the base is determined
1120 automatically using the following rules: If the string begins with
1121 "0x", it is assumed to be hexadecimal; if it begins with "0", it
1122 is assumed to be octal; otherwise it is assumed to be decimal.
1123
1124 If the conversion fails the function returns 0.
1125
1126 If \a ok is not 0, failure is reported by setting *ok to false, and
1127 success by setting *ok to true.
1128
1129 This function ignores leading and trailing whitespace.
1130
1131 \sa toInt(), toString()
1132 */
1133
toUInt(const QString & s,bool * ok,int base) const1134 uint QLocale::toUInt(const QString &s, bool *ok, int base) const
1135 {
1136 qulonglong i = toULongLong(s, ok, base);
1137 if (i > UINT_MAX) {
1138 if (ok != 0)
1139 *ok = false;
1140 return 0;
1141 }
1142 return uint(i);
1143 }
1144
1145 /*!
1146 Returns the long long int represented by the localized string \a
1147 s, using base \a base. If \a base is 0 the base is determined
1148 automatically using the following rules: If the string begins with
1149 "0x", it is assumed to be hexadecimal; if it begins with "0", it
1150 is assumed to be octal; otherwise it is assumed to be decimal.
1151
1152 If the conversion fails the function returns 0.
1153
1154 If \a ok is not 0, failure is reported by setting *ok to false, and
1155 success by setting *ok to true.
1156
1157 This function ignores leading and trailing whitespace.
1158
1159 \sa toInt(), toULongLong(), toDouble(), toString()
1160 */
1161
1162
toLongLong(const QString & s,bool * ok,int base) const1163 qlonglong QLocale::toLongLong(const QString &s, bool *ok, int base) const
1164 {
1165 QLocalePrivate::GroupSeparatorMode mode
1166 = p.numberOptions & RejectGroupSeparator
1167 ? QLocalePrivate::FailOnGroupSeparators
1168 : QLocalePrivate::ParseGroupSeparators;
1169
1170 return d()->stringToLongLong(s, base, ok, mode);
1171 }
1172
1173 // ### Qt5: make the return type for toULongLong() qulonglong.
1174
1175 /*!
1176 Returns the unsigned long long int represented by the localized
1177 string \a s, using base \a base. If \a base is 0 the base is
1178 determined automatically using the following rules: If the string
1179 begins with "0x", it is assumed to be hexadecimal; if it begins
1180 with "0", it is assumed to be octal; otherwise it is assumed to be
1181 decimal.
1182
1183 If the conversion fails the function returns 0.
1184
1185 If \a ok is not 0, failure is reported by setting *ok to false, and
1186 success by setting *ok to true.
1187
1188 This function ignores leading and trailing whitespace.
1189
1190 \sa toLongLong(), toInt(), toDouble(), toString()
1191 */
1192
toULongLong(const QString & s,bool * ok,int base) const1193 qlonglong QLocale::toULongLong(const QString &s, bool *ok, int base) const
1194 {
1195 QLocalePrivate::GroupSeparatorMode mode
1196 = p.numberOptions & RejectGroupSeparator
1197 ? QLocalePrivate::FailOnGroupSeparators
1198 : QLocalePrivate::ParseGroupSeparators;
1199
1200 return d()->stringToUnsLongLong(s, base, ok, mode);
1201 }
1202
1203 /*!
1204 Returns the float represented by the localized string \a s, or 0.0
1205 if the conversion failed.
1206
1207 If \a ok is not 0, reports failure by setting
1208 *ok to false and success by setting *ok to true.
1209
1210 This function ignores leading and trailing whitespace.
1211
1212 \sa toDouble(), toInt(), toString()
1213 */
1214
1215 #define QT_MAX_FLOAT 3.4028234663852886e+38
1216
toFloat(const QString & s,bool * ok) const1217 float QLocale::toFloat(const QString &s, bool *ok) const
1218 {
1219 bool myOk;
1220 double d = toDouble(s, &myOk);
1221 if (!myOk || d > QT_MAX_FLOAT || d < -QT_MAX_FLOAT) {
1222 if (ok != 0)
1223 *ok = false;
1224 return 0.0;
1225 }
1226 if (ok != 0)
1227 *ok = true;
1228 return float(d);
1229 }
1230
1231 /*!
1232 Returns the double represented by the localized string \a s, or
1233 0.0 if the conversion failed.
1234
1235 If \a ok is not 0, reports failure by setting
1236 *ok to false and success by setting *ok to true.
1237
1238 Unlike QString::toDouble(), this function does not fall back to
1239 the "C" locale if the string cannot be interpreted in this
1240 locale.
1241
1242 \snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 3
1243
1244 Notice that the last conversion returns 1234.0, because '.' is the
1245 thousands group separator in the German locale.
1246
1247 This function ignores leading and trailing whitespace.
1248
1249 \sa toFloat(), toInt(), toString()
1250 */
1251
toDouble(const QString & s,bool * ok) const1252 double QLocale::toDouble(const QString &s, bool *ok) const
1253 {
1254 QLocalePrivate::GroupSeparatorMode mode
1255 = p.numberOptions & RejectGroupSeparator
1256 ? QLocalePrivate::FailOnGroupSeparators
1257 : QLocalePrivate::ParseGroupSeparators;
1258
1259 return d()->stringToDouble(s, ok, mode);
1260 }
1261
1262 /*!
1263 Returns a localized string representation of \a i.
1264
1265 \sa toLongLong()
1266 */
1267
toString(qlonglong i) const1268 QString QLocale::toString(qlonglong i) const
1269 {
1270 int flags = p.numberOptions & OmitGroupSeparator
1271 ? 0
1272 : QLocalePrivate::ThousandsGroup;
1273
1274 return d()->longLongToString(i, -1, 10, -1, flags);
1275 }
1276
1277 /*!
1278 \overload
1279
1280 \sa toULongLong()
1281 */
1282
toString(qulonglong i) const1283 QString QLocale::toString(qulonglong i) const
1284 {
1285 int flags = p.numberOptions & OmitGroupSeparator
1286 ? 0
1287 : QLocalePrivate::ThousandsGroup;
1288
1289 return d()->unsLongLongToString(i, -1, 10, -1, flags);
1290 }
1291
1292 /*!
1293 Returns a localized string representation of the given \a date in the
1294 specified \a format.
1295 If \a format is an empty string, an empty string is returned.
1296 */
1297
toString(const QDate & date,const QString & format) const1298 QString QLocale::toString(const QDate &date, const QString &format) const
1299 {
1300 return d()->dateTimeToString(format, &date, 0, this);
1301 }
1302
1303 /*!
1304 Returns a localized string representation of the given \a date according
1305 to the specified \a format.
1306 */
1307
toString(const QDate & date,FormatType format) const1308 QString QLocale::toString(const QDate &date, FormatType format) const
1309 {
1310 if (!date.isValid())
1311 return QString();
1312
1313 #ifndef QT_NO_SYSTEMLOCALE
1314 if (d() == systemPrivate()) {
1315 QVariant res = systemLocale()->query(format == LongFormat
1316 ? QSystemLocale::DateToStringLong : QSystemLocale::DateToStringShort,
1317 date);
1318 if (!res.isNull())
1319 return res.toString();
1320 }
1321 #endif
1322
1323 QString format_str = dateFormat(format);
1324 return toString(date, format_str);
1325 }
1326
timeFormatContainsAP(const QString & format)1327 static bool timeFormatContainsAP(const QString &format)
1328 {
1329 int i = 0;
1330 while (i < format.size()) {
1331 if (format.at(i).unicode() == '\'') {
1332 qt_readEscapedFormatString(format, &i);
1333 continue;
1334 }
1335
1336 if (format.at(i).toLower().unicode() == 'a')
1337 return true;
1338
1339 ++i;
1340 }
1341 return false;
1342 }
1343
timeZone()1344 static QString timeZone()
1345 {
1346 #if defined(Q_OS_WINCE)
1347 TIME_ZONE_INFORMATION info;
1348 DWORD res = GetTimeZoneInformation(&info);
1349 if (res == TIME_ZONE_ID_UNKNOWN)
1350 return QString();
1351 return QString::fromWCharArray(info.StandardName);
1352 #elif defined(Q_OS_WIN)
1353 _tzset();
1354 # if defined(_MSC_VER) && _MSC_VER >= 1400
1355 size_t returnSize = 0;
1356 char timeZoneName[512];
1357 if (_get_tzname(&returnSize, timeZoneName, 512, 1))
1358 return QString();
1359 return QString::fromLocal8Bit(timeZoneName);
1360 # else
1361 return QString::fromLocal8Bit(_tzname[1]);
1362 # endif
1363 #elif defined(Q_OS_VXWORKS)
1364 return QString();
1365 #else
1366 tzset();
1367 return QString::fromLocal8Bit(tzname[1]);
1368 #endif
1369 }
1370
1371 /*!
1372 Returns a localized string representation of the given \a time according
1373 to the specified \a format.
1374 If \a format is an empty string, an empty string is returned.
1375 */
toString(const QTime & time,const QString & format) const1376 QString QLocale::toString(const QTime &time, const QString &format) const
1377 {
1378 return d()->dateTimeToString(format, 0, &time, this);
1379 }
1380
1381 /*!
1382 \since 4.4
1383
1384 Returns a localized string representation of the given \a dateTime according
1385 to the specified \a format.
1386 If \a format is an empty string, an empty string is returned.
1387 */
1388
toString(const QDateTime & dateTime,const QString & format) const1389 QString QLocale::toString(const QDateTime &dateTime, const QString &format) const
1390 {
1391 const QDate dt = dateTime.date();
1392 const QTime tm = dateTime.time();
1393 return d()->dateTimeToString(format, &dt, &tm, this);
1394 }
1395
1396 /*!
1397 \since 4.4
1398
1399 Returns a localized string representation of the given \a dateTime according
1400 to the specified \a format.
1401 */
1402
toString(const QDateTime & dateTime,FormatType format) const1403 QString QLocale::toString(const QDateTime &dateTime, FormatType format) const
1404 {
1405 if (!dateTime.isValid())
1406 return QString();
1407
1408 #ifndef QT_NO_SYSTEMLOCALE
1409 if (d() == systemPrivate()) {
1410 QVariant res = systemLocale()->query(format == LongFormat
1411 ? QSystemLocale::DateTimeToStringLong
1412 : QSystemLocale::DateTimeToStringShort,
1413 dateTime);
1414 if (!res.isNull())
1415 return res.toString();
1416 }
1417 #endif
1418
1419 const QString format_str = dateTimeFormat(format);
1420 return toString(dateTime, format_str);
1421 }
1422
1423
1424 /*!
1425 Returns a localized string representation of the given \a time in the
1426 specified \a format.
1427 */
1428
toString(const QTime & time,FormatType format) const1429 QString QLocale::toString(const QTime &time, FormatType format) const
1430 {
1431 if (!time.isValid())
1432 return QString();
1433
1434 #ifndef QT_NO_SYSTEMLOCALE
1435 if (d() == systemPrivate()) {
1436 QVariant res = systemLocale()->query(format == LongFormat
1437 ? QSystemLocale::TimeToStringLong : QSystemLocale::TimeToStringShort,
1438 time);
1439 if (!res.isNull())
1440 return res.toString();
1441 }
1442 #endif
1443
1444 QString format_str = timeFormat(format);
1445 return toString(time, format_str);
1446 }
1447
1448 /*!
1449 \since 4.1
1450
1451 Returns the date format used for the current locale.
1452
1453 If \a format is LongFormat the format will be a long version.
1454 Otherwise it uses a shorter version.
1455
1456 \sa QDate::toString(), QDate::fromString()
1457 */
1458
dateFormat(FormatType format) const1459 QString QLocale::dateFormat(FormatType format) const
1460 {
1461 #ifndef QT_NO_SYSTEMLOCALE
1462 if (d() == systemPrivate()) {
1463 QVariant res = systemLocale()->query(format == LongFormat
1464 ? QSystemLocale::DateFormatLong : QSystemLocale::DateFormatShort,
1465 QVariant());
1466 if (!res.isNull())
1467 return res.toString();
1468 }
1469 #endif
1470
1471 quint32 idx, size;
1472 switch (format) {
1473 case LongFormat:
1474 idx = d()->m_long_date_format_idx;
1475 size = d()->m_long_date_format_size;
1476 break;
1477 default:
1478 idx = d()->m_short_date_format_idx;
1479 size = d()->m_short_date_format_size;
1480 break;
1481 }
1482 return getLocaleData(date_format_data + idx, size);
1483 }
1484
1485 /*!
1486 \since 4.1
1487
1488 Returns the time format used for the current locale.
1489
1490 If \a format is LongFormat the format will be a long version.
1491 Otherwise it uses a shorter version.
1492
1493 \sa QTime::toString(), QTime::fromString()
1494 */
1495
timeFormat(FormatType format) const1496 QString QLocale::timeFormat(FormatType format) const
1497 {
1498 #ifndef QT_NO_SYSTEMLOCALE
1499 if (d() == systemPrivate()) {
1500 QVariant res = systemLocale()->query(format == LongFormat
1501 ? QSystemLocale::TimeFormatLong : QSystemLocale::TimeFormatShort,
1502 QVariant());
1503 if (!res.isNull())
1504 return res.toString();
1505 }
1506 #endif
1507
1508 quint32 idx, size;
1509 switch (format) {
1510 case LongFormat:
1511 idx = d()->m_long_time_format_idx;
1512 size = d()->m_long_time_format_size;
1513 break;
1514 default:
1515 idx = d()->m_short_time_format_idx;
1516 size = d()->m_short_time_format_size;
1517 break;
1518 }
1519 return getLocaleData(time_format_data + idx, size);
1520 }
1521
1522 /*!
1523 \since 4.4
1524
1525 Returns the date time format used for the current locale.
1526
1527 If \a format is ShortFormat the format will be a short version.
1528 Otherwise it uses a longer version.
1529
1530 \sa QDateTime::toString(), QDateTime::fromString()
1531 */
1532
dateTimeFormat(FormatType format) const1533 QString QLocale::dateTimeFormat(FormatType format) const
1534 {
1535 #ifndef QT_NO_SYSTEMLOCALE
1536 if (d() == systemPrivate()) {
1537 QVariant res = systemLocale()->query(format == LongFormat
1538 ? QSystemLocale::DateTimeFormatLong
1539 : QSystemLocale::DateTimeFormatShort,
1540 QVariant());
1541 if (!res.isNull()) {
1542 return res.toString();
1543 }
1544 }
1545 #endif
1546 return dateFormat(format) + QLatin1Char(' ') + timeFormat(format);
1547 }
1548
1549 /*!
1550 \since 4.4
1551
1552 Parses the time string given in \a string and returns the
1553 time. The format of the time string is chosen according to the
1554 \a format parameter (see timeFormat()).
1555
1556 If the time could not be parsed, returns an invalid time.
1557
1558 \sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
1559 */
1560 #ifndef QT_NO_DATESTRING
toTime(const QString & string,FormatType format) const1561 QTime QLocale::toTime(const QString &string, FormatType format) const
1562 {
1563 return toTime(string, timeFormat(format));
1564 }
1565 #endif
1566
1567 /*!
1568 \since 4.4
1569
1570 Parses the date string given in \a string and returns the
1571 date. The format of the date string is chosen according to the
1572 \a format parameter (see dateFormat()).
1573
1574 If the date could not be parsed, returns an invalid date.
1575
1576 \sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
1577 */
1578 #ifndef QT_NO_DATESTRING
toDate(const QString & string,FormatType format) const1579 QDate QLocale::toDate(const QString &string, FormatType format) const
1580 {
1581 return toDate(string, dateFormat(format));
1582 }
1583 #endif
1584
1585 /*!
1586 \since 4.4
1587
1588 Parses the date/time string given in \a string and returns the
1589 time. The format of the date/time string is chosen according to the
1590 \a format parameter (see dateTimeFormat()).
1591
1592 If the string could not be parsed, returns an invalid QDateTime.
1593
1594 \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
1595 */
1596
1597 #ifndef QT_NO_DATESTRING
toDateTime(const QString & string,FormatType format) const1598 QDateTime QLocale::toDateTime(const QString &string, FormatType format) const
1599 {
1600 return toDateTime(string, dateTimeFormat(format));
1601 }
1602 #endif
1603
1604 /*!
1605 \since 4.4
1606
1607 Parses the time string given in \a string and returns the
1608 time. See QTime::fromString() for information on what is a valid
1609 format string.
1610
1611 If the time could not be parsed, returns an invalid time.
1612
1613 \sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
1614 */
1615 #ifndef QT_NO_DATESTRING
toTime(const QString & string,const QString & format) const1616 QTime QLocale::toTime(const QString &string, const QString &format) const
1617 {
1618 QTime time;
1619 #ifndef QT_BOOTSTRAPPED
1620 QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
1621 dt.defaultLocale = *this;
1622 if (dt.parseFormat(format))
1623 dt.fromString(string, 0, &time);
1624 #else
1625 Q_UNUSED(string);
1626 Q_UNUSED(format);
1627 #endif
1628 return time;
1629 }
1630 #endif
1631
1632 /*!
1633 \since 4.4
1634
1635 Parses the date string given in \a string and returns the
1636 date. See QDate::fromString() for information on the expressions
1637 that can be used with this function.
1638
1639 This function searches month names and the names of the days of
1640 the week in the current locale.
1641
1642 If the date could not be parsed, returns an invalid date.
1643
1644 \sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
1645 */
1646 #ifndef QT_NO_DATESTRING
toDate(const QString & string,const QString & format) const1647 QDate QLocale::toDate(const QString &string, const QString &format) const
1648 {
1649 QDate date;
1650 #ifndef QT_BOOTSTRAPPED
1651 QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
1652 dt.defaultLocale = *this;
1653 if (dt.parseFormat(format))
1654 dt.fromString(string, &date, 0);
1655 #else
1656 Q_UNUSED(string);
1657 Q_UNUSED(format);
1658 #endif
1659 return date;
1660 }
1661 #endif
1662
1663 /*!
1664 \since 4.4
1665
1666 Parses the date/time string given in \a string and returns the
1667 time. See QDateTime::fromString() for information on the expressions
1668 that can be used with this function.
1669
1670 \note The month and day names used must be given in the user's local
1671 language.
1672
1673 If the string could not be parsed, returns an invalid QDateTime.
1674
1675 \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
1676 */
1677 #ifndef QT_NO_DATESTRING
toDateTime(const QString & string,const QString & format) const1678 QDateTime QLocale::toDateTime(const QString &string, const QString &format) const
1679 {
1680 #ifndef QT_BOOTSTRAPPED
1681 QTime time;
1682 QDate date;
1683
1684 QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
1685 dt.defaultLocale = *this;
1686 if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
1687 return QDateTime(date, time);
1688 #else
1689 Q_UNUSED(string);
1690 Q_UNUSED(format);
1691 #endif
1692 return QDateTime(QDate(), QTime(-1, -1, -1));
1693 }
1694 #endif
1695
1696
1697 /*!
1698 \since 4.1
1699
1700 Returns the decimal point character of this locale.
1701 */
decimalPoint() const1702 QChar QLocale::decimalPoint() const
1703 {
1704 return d()->decimal();
1705 }
1706
1707 /*!
1708 \since 4.1
1709
1710 Returns the group separator character of this locale.
1711 */
groupSeparator() const1712 QChar QLocale::groupSeparator() const
1713 {
1714 return d()->group();
1715 }
1716
1717 /*!
1718 \since 4.1
1719
1720 Returns the percent character of this locale.
1721 */
percent() const1722 QChar QLocale::percent() const
1723 {
1724 return d()->percent();
1725 }
1726
1727 /*!
1728 \since 4.1
1729
1730 Returns the zero digit character of this locale.
1731 */
zeroDigit() const1732 QChar QLocale::zeroDigit() const
1733 {
1734 return d()->zero();
1735 }
1736
1737 /*!
1738 \since 4.1
1739
1740 Returns the negative sign character of this locale.
1741 */
negativeSign() const1742 QChar QLocale::negativeSign() const
1743 {
1744 return d()->minus();
1745 }
1746
1747 /*!
1748 \since 4.5
1749
1750 Returns the positive sign character of this locale.
1751 */
positiveSign() const1752 QChar QLocale::positiveSign() const
1753 {
1754 return d()->plus();
1755 }
1756
1757 /*!
1758 \since 4.1
1759
1760 Returns the exponential character of this locale.
1761 */
exponential() const1762 QChar QLocale::exponential() const
1763 {
1764 return d()->exponential();
1765 }
1766
qIsUpper(char c)1767 static bool qIsUpper(char c)
1768 {
1769 return c >= 'A' && c <= 'Z';
1770 }
1771
qToLower(char c)1772 static char qToLower(char c)
1773 {
1774 if (c >= 'A' && c <= 'Z')
1775 return c - 'A' + 'a';
1776 else
1777 return c;
1778 }
1779
1780 /*!
1781 \overload
1782
1783 \a f and \a prec have the same meaning as in QString::number(double, char, int).
1784
1785 \sa toDouble()
1786 */
1787
toString(double i,char f,int prec) const1788 QString QLocale::toString(double i, char f, int prec) const
1789 {
1790 QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
1791 uint flags = 0;
1792
1793 if (qIsUpper(f))
1794 flags = QLocalePrivate::CapitalEorX;
1795 f = qToLower(f);
1796
1797 switch (f) {
1798 case 'f':
1799 form = QLocalePrivate::DFDecimal;
1800 break;
1801 case 'e':
1802 form = QLocalePrivate::DFExponent;
1803 break;
1804 case 'g':
1805 form = QLocalePrivate::DFSignificantDigits;
1806 break;
1807 default:
1808 break;
1809 }
1810
1811 if (!(p.numberOptions & OmitGroupSeparator))
1812 flags |= QLocalePrivate::ThousandsGroup;
1813 return d()->doubleToString(i, prec, form, -1, flags);
1814 }
1815
1816 /*!
1817 \fn QLocale QLocale::c()
1818
1819 Returns a QLocale object initialized to the "C" locale.
1820
1821 \sa system()
1822 */
1823
1824 /*!
1825 Returns a QLocale object initialized to the system locale.
1826
1827 On Windows and Mac, this locale will use the decimal/grouping characters and date/time
1828 formats specified in the system configuration panel.
1829
1830 \sa c()
1831 */
1832
system()1833 QLocale QLocale::system()
1834 {
1835 QLocale result(C);
1836 result.p.index = localePrivateIndex(systemPrivate());
1837 return result;
1838 }
1839
1840
1841 /*!
1842 \since 4.8
1843
1844 Returns a list of valid locale objects that match the given \a language, \a
1845 script and \a country.
1846
1847 Getting a list of all locales:
1848 QList<QLocale> allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
1849 */
matchingLocales(QLocale::Language language,QLocale::Script script,QLocale::Country country)1850 QList<QLocale> QLocale::matchingLocales(QLocale::Language language,
1851 QLocale::Script script,
1852 QLocale::Country country)
1853 {
1854 if (uint(language) > QLocale::LastLanguage || uint(script) > QLocale::LastScript ||
1855 uint(country) > QLocale::LastCountry)
1856 return QList<QLocale>();
1857
1858 QList<QLocale> result;
1859 const QLocalePrivate *d = locale_data;
1860 if (language == QLocale::AnyLanguage && script == QLocale::AnyScript && country == QLocale::AnyCountry)
1861 result.reserve(locale_data_size);
1862 if (language != QLocale::C)
1863 d += locale_index[language];
1864 while ( (d != locale_data + locale_data_size)
1865 && (language == QLocale::AnyLanguage || d->m_language_id == uint(language))) {
1866 QLocale locale(QLocale::C);
1867 locale.p.index = localePrivateIndex(d);
1868 result.append(locale);
1869 ++d;
1870 }
1871 return result;
1872 }
1873
1874 /*!
1875 \obsolete
1876 \since 4.3
1877
1878 Returns the list of countries that have entires for \a language in Qt's locale
1879 database. If the result is an empty list, then \a language is not represented in
1880 Qt's locale database.
1881
1882 \sa matchingLocales()
1883 */
countriesForLanguage(Language language)1884 QList<QLocale::Country> QLocale::countriesForLanguage(Language language)
1885 {
1886 QList<Country> result;
1887
1888 unsigned language_id = language;
1889 uint idx = locale_index[language_id];
1890
1891 if (language == C) {
1892 result << AnyCountry;
1893 return result;
1894 }
1895
1896 const QLocalePrivate *d = locale_data + idx;
1897
1898 while (d->languageId() == language_id) {
1899 result << static_cast<Country>(d->countryId());
1900 ++d;
1901 }
1902
1903 return result;
1904 }
1905
1906 /*!
1907 \since 4.2
1908
1909 Returns the localized name of \a month, in the format specified
1910 by \a type.
1911
1912 \sa dayName(), standaloneMonthName()
1913 */
monthName(int month,FormatType type) const1914 QString QLocale::monthName(int month, FormatType type) const
1915 {
1916 if (month < 1 || month > 12)
1917 return QString();
1918
1919 #ifndef QT_NO_SYSTEMLOCALE
1920 if (d() == systemPrivate()) {
1921 QVariant res = systemLocale()->query(type == LongFormat
1922 ? QSystemLocale::MonthNameLong : QSystemLocale::MonthNameShort,
1923 month);
1924 if (!res.isNull())
1925 return res.toString();
1926 }
1927 #endif
1928
1929 quint32 idx, size;
1930 switch (type) {
1931 case QLocale::LongFormat:
1932 idx = d()->m_long_month_names_idx;
1933 size = d()->m_long_month_names_size;
1934 break;
1935 case QLocale::ShortFormat:
1936 idx = d()->m_short_month_names_idx;
1937 size = d()->m_short_month_names_size;
1938 break;
1939 case QLocale::NarrowFormat:
1940 idx = d()->m_narrow_month_names_idx;
1941 size = d()->m_narrow_month_names_size;
1942 break;
1943 default:
1944 return QString();
1945 }
1946 return getLocaleListData(months_data + idx, size, month - 1);
1947 }
1948
1949 /*!
1950 \since 4.5
1951
1952 Returns the localized name of \a month that is used as a
1953 standalone text, in the format specified by \a type.
1954
1955 If the locale information doesn't specify the standalone month
1956 name then return value is the same as in monthName().
1957
1958 \sa monthName(), standaloneDayName()
1959 */
standaloneMonthName(int month,FormatType type) const1960 QString QLocale::standaloneMonthName(int month, FormatType type) const
1961 {
1962 if (month < 1 || month > 12)
1963 return QString();
1964
1965 #ifndef QT_NO_SYSTEMLOCALE
1966 if (d() == systemPrivate()) {
1967 QVariant res = systemLocale()->query(type == LongFormat
1968 ? QSystemLocale::StandaloneMonthNameLong : QSystemLocale::StandaloneMonthNameShort,
1969 month);
1970 if (!res.isNull())
1971 return res.toString();
1972 }
1973 #endif
1974
1975 quint32 idx, size;
1976 switch (type) {
1977 case QLocale::LongFormat:
1978 idx = d()->m_standalone_long_month_names_idx;
1979 size = d()->m_standalone_long_month_names_size;
1980 break;
1981 case QLocale::ShortFormat:
1982 idx = d()->m_standalone_short_month_names_idx;
1983 size = d()->m_standalone_short_month_names_size;
1984 break;
1985 case QLocale::NarrowFormat:
1986 idx = d()->m_standalone_narrow_month_names_idx;
1987 size = d()->m_standalone_narrow_month_names_size;
1988 break;
1989 default:
1990 return QString();
1991 }
1992 QString name = getLocaleListData(standalone_months_data + idx, size, month - 1);
1993 if (name.isEmpty())
1994 return monthName(month, type);
1995 return name;
1996 }
1997
1998 /*!
1999 \since 4.2
2000
2001 Returns the localized name of the \a day (where 1 represents
2002 Monday, 2 represents Tuesday and so on), in the format specified
2003 by \a type.
2004
2005 \sa monthName(), standaloneDayName()
2006 */
dayName(int day,FormatType type) const2007 QString QLocale::dayName(int day, FormatType type) const
2008 {
2009 if (day < 1 || day > 7)
2010 return QString();
2011
2012 #ifndef QT_NO_SYSTEMLOCALE
2013 if (d() == systemPrivate()) {
2014 QVariant res = systemLocale()->query(type == LongFormat
2015 ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort,
2016 day);
2017 if (!res.isNull())
2018 return res.toString();
2019 }
2020 #endif
2021 if (day == 7)
2022 day = 0;
2023
2024 quint32 idx, size;
2025 switch (type) {
2026 case QLocale::LongFormat:
2027 idx = d()->m_long_day_names_idx;
2028 size = d()->m_long_day_names_size;
2029 break;
2030 case QLocale::ShortFormat:
2031 idx = d()->m_short_day_names_idx;
2032 size = d()->m_short_day_names_size;
2033 break;
2034 case QLocale::NarrowFormat:
2035 idx = d()->m_narrow_day_names_idx;
2036 size = d()->m_narrow_day_names_size;
2037 break;
2038 default:
2039 return QString();
2040 }
2041 return getLocaleListData(days_data + idx, size, day);
2042 }
2043
2044 /*!
2045 \since 4.5
2046
2047 Returns the localized name of the \a day (where 1 represents
2048 Monday, 2 represents Tuesday and so on) that is used as a
2049 standalone text, in the format specified by \a type.
2050
2051 If the locale information does not specify the standalone day
2052 name then return value is the same as in dayName().
2053
2054 \sa dayName(), standaloneMonthName()
2055 */
standaloneDayName(int day,FormatType type) const2056 QString QLocale::standaloneDayName(int day, FormatType type) const
2057 {
2058 if (day < 1 || day > 7)
2059 return QString();
2060
2061 #ifndef QT_NO_SYSTEMLOCALE
2062 if (d() == systemPrivate()) {
2063 QVariant res = systemLocale()->query(type == LongFormat
2064 ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort,
2065 day);
2066 if (!res.isNull())
2067 return res.toString();
2068 }
2069 #endif
2070 if (day == 7)
2071 day = 0;
2072
2073 quint32 idx, size;
2074 switch (type) {
2075 case QLocale::LongFormat:
2076 idx = d()->m_standalone_long_day_names_idx;
2077 size = d()->m_standalone_long_day_names_size;
2078 break;
2079 case QLocale::ShortFormat:
2080 idx = d()->m_standalone_short_day_names_idx;
2081 size = d()->m_standalone_short_day_names_size;
2082 break;
2083 case QLocale::NarrowFormat:
2084 idx = d()->m_standalone_narrow_day_names_idx;
2085 size = d()->m_standalone_narrow_day_names_size;
2086 break;
2087 default:
2088 return QString();
2089 }
2090 QString name = getLocaleListData(days_data + idx, size, day);
2091 if (name.isEmpty())
2092 return dayName(day == 0 ? 7 : day, type);
2093 return name;
2094 }
2095
2096 /*!
2097 \since 4.8
2098
2099 Returns the first day of the week according to the current locale.
2100 */
firstDayOfWeek() const2101 Qt::DayOfWeek QLocale::firstDayOfWeek() const
2102 {
2103 #ifndef QT_NO_SYSTEMLOCALE
2104 if (d() == systemPrivate()) {
2105 QVariant res = systemLocale()->query(QSystemLocale::FirstDayOfWeek, QVariant());
2106 if (!res.isNull())
2107 return static_cast<Qt::DayOfWeek>(res.toUInt());
2108 }
2109 #endif
2110 return static_cast<Qt::DayOfWeek>(d()->m_first_day_of_week);
2111 }
2112
measurementSystem() const2113 QLocale::MeasurementSystem QLocalePrivate::measurementSystem() const
2114 {
2115 for (int i = 0; i < ImperialMeasurementSystemsCount; ++i) {
2116 if (ImperialMeasurementSystems[i].languageId == m_language_id
2117 && ImperialMeasurementSystems[i].countryId == m_country_id) {
2118 return QLocale::ImperialSystem;
2119 }
2120 }
2121 return QLocale::MetricSystem;
2122 }
2123
2124 /*!
2125 \since 4.8
2126
2127 Returns a list of days that are considered weekdays according to the current locale.
2128 */
weekdays() const2129 QList<Qt::DayOfWeek> QLocale::weekdays() const
2130 {
2131 #ifndef QT_NO_SYSTEMLOCALE
2132 if (d() == systemPrivate()) {
2133 QVariant res = systemLocale()->query(QSystemLocale::Weekdays, QVariant());
2134 if (!res.isNull())
2135 return static_cast<QList<Qt::DayOfWeek> >(res.value<QList<Qt::DayOfWeek> >());
2136 }
2137 #endif
2138 QList<Qt::DayOfWeek> weekdays;
2139 quint16 weekendStart = d()->m_weekend_start;
2140 quint16 weekendEnd = d()->m_weekend_end;
2141 for (int day = Qt::Monday; day <= Qt::Sunday; day++) {
2142 if ((weekendEnd >= weekendStart && (day < weekendStart || day > weekendEnd)) ||
2143 (weekendEnd < weekendStart && (day > weekendEnd && day < weekendStart)))
2144 weekdays << static_cast<Qt::DayOfWeek>(day);
2145 }
2146 return weekdays;
2147 }
2148
2149 /*!
2150 \since 4.4
2151
2152 Returns the measurement system for the locale.
2153 */
measurementSystem() const2154 QLocale::MeasurementSystem QLocale::measurementSystem() const
2155 {
2156 #ifndef QT_NO_SYSTEMLOCALE
2157 if (d() == systemPrivate()) {
2158 QVariant res = systemLocale()->query(QSystemLocale::MeasurementSystem, QVariant());
2159 if (!res.isNull())
2160 return MeasurementSystem(res.toInt());
2161 }
2162 #endif
2163
2164 return d()->measurementSystem();
2165 }
2166
2167 /*!
2168 \since 4.7
2169
2170 Returns the text direction of the language.
2171 */
textDirection() const2172 Qt::LayoutDirection QLocale::textDirection() const
2173 {
2174 Language lang = language();
2175 if (lang == QLocale::Arabic ||
2176 lang == QLocale::Hebrew ||
2177 lang == QLocale::Persian ||
2178 lang == QLocale::Urdu ||
2179 lang == QLocale::Syriac)
2180 return Qt::RightToLeft;
2181
2182 return Qt::LeftToRight;
2183 }
2184
2185 /*!
2186 \since 4.8
2187
2188 Returns an uppercase copy of \a str.
2189 */
toUpper(const QString & str) const2190 QString QLocale::toUpper(const QString &str) const
2191 {
2192 #ifdef QT_USE_ICU
2193 {
2194 QString result;
2195 if (qt_u_strToUpper(str, &result, *this))
2196 return result;
2197 // else fall through and use Qt's toUpper
2198 }
2199 #endif
2200 return str.toUpper();
2201 }
2202
2203 /*!
2204 \since 4.8
2205
2206 Returns a lowercase copy of \a str.
2207 */
toLower(const QString & str) const2208 QString QLocale::toLower(const QString &str) const
2209 {
2210 #ifdef QT_USE_ICU
2211 {
2212 QString result;
2213 if (qt_u_strToLower(str, &result, *this))
2214 return result;
2215 // else fall through and use Qt's toUpper
2216 }
2217 #endif
2218 return str.toLower();
2219 }
2220
2221
2222 /*!
2223 \since 4.5
2224
2225 Returns the localized name of the "AM" suffix for times specified using
2226 the conventions of the 12-hour clock.
2227
2228 \sa pmText()
2229 */
amText() const2230 QString QLocale::amText() const
2231 {
2232 #ifndef QT_NO_SYSTEMLOCALE
2233 if (d() == systemPrivate()) {
2234 QVariant res = systemLocale()->query(QSystemLocale::AMText, QVariant());
2235 if (!res.isNull())
2236 return res.toString();
2237 }
2238 #endif
2239 return getLocaleData(am_data + d()->m_am_idx, d()->m_am_size);
2240 }
2241
2242 /*!
2243 \since 4.5
2244
2245 Returns the localized name of the "PM" suffix for times specified using
2246 the conventions of the 12-hour clock.
2247
2248 \sa amText()
2249 */
pmText() const2250 QString QLocale::pmText() const
2251 {
2252 #ifndef QT_NO_SYSTEMLOCALE
2253 if (d() == systemPrivate()) {
2254 QVariant res = systemLocale()->query(QSystemLocale::PMText, QVariant());
2255 if (!res.isNull())
2256 return res.toString();
2257 }
2258 #endif
2259 return getLocaleData(pm_data + d()->m_pm_idx, d()->m_pm_size);
2260 }
2261
2262
dateTimeToString(const QString & format,const QDate * date,const QTime * time,const QLocale * q) const2263 QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *date, const QTime *time,
2264 const QLocale *q) const
2265 {
2266 Q_ASSERT(date || time);
2267 if ((date && !date->isValid()) || (time && !time->isValid()))
2268 return QString();
2269 const bool format_am_pm = time && timeFormatContainsAP(format);
2270
2271 enum { AM, PM } am_pm = AM;
2272 int hour12 = time ? time->hour() : -1;
2273 if (time) {
2274 if (hour12 == 0) {
2275 am_pm = AM;
2276 hour12 = 12;
2277 } else if (hour12 < 12) {
2278 am_pm = AM;
2279 } else if (hour12 == 12) {
2280 am_pm = PM;
2281 } else {
2282 am_pm = PM;
2283 hour12 -= 12;
2284 }
2285 }
2286
2287 QString result;
2288
2289 int i = 0;
2290 while (i < format.size()) {
2291 if (format.at(i).unicode() == '\'') {
2292 result.append(qt_readEscapedFormatString(format, &i));
2293 continue;
2294 }
2295
2296 const QChar c = format.at(i);
2297 int repeat = qt_repeatCount(format, i);
2298 bool used = false;
2299 if (date) {
2300 switch (c.unicode()) {
2301 case 'y':
2302 used = true;
2303 if (repeat >= 4)
2304 repeat = 4;
2305 else if (repeat >= 2)
2306 repeat = 2;
2307
2308 switch (repeat) {
2309 case 4:
2310 result.append(longLongToString(date->year()));
2311 break;
2312 case 2:
2313 result.append(longLongToString(date->year() % 100, -1, 10, 2,
2314 QLocalePrivate::ZeroPadded));
2315 break;
2316 default:
2317 repeat = 1;
2318 result.append(c);
2319 break;
2320 }
2321 break;
2322
2323 case 'M':
2324 used = true;
2325 repeat = qMin(repeat, 4);
2326 switch (repeat) {
2327 case 1:
2328 result.append(longLongToString(date->month()));
2329 break;
2330 case 2:
2331 result.append(longLongToString(date->month(), -1, 10, 2, QLocalePrivate::ZeroPadded));
2332 break;
2333 case 3:
2334 result.append(q->monthName(date->month(), QLocale::ShortFormat));
2335 break;
2336 case 4:
2337 result.append(q->monthName(date->month(), QLocale::LongFormat));
2338 break;
2339 }
2340 break;
2341
2342 case 'd':
2343 used = true;
2344 repeat = qMin(repeat, 4);
2345 switch (repeat) {
2346 case 1:
2347 result.append(longLongToString(date->day()));
2348 break;
2349 case 2:
2350 result.append(longLongToString(date->day(), -1, 10, 2, QLocalePrivate::ZeroPadded));
2351 break;
2352 case 3:
2353 result.append(q->dayName(date->dayOfWeek(), QLocale::ShortFormat));
2354 break;
2355 case 4:
2356 result.append(q->dayName(date->dayOfWeek(), QLocale::LongFormat));
2357 break;
2358 }
2359 break;
2360
2361 default:
2362 break;
2363 }
2364 }
2365 if (!used && time) {
2366 switch (c.unicode()) {
2367 case 'h': {
2368 used = true;
2369 repeat = qMin(repeat, 2);
2370 const int hour = format_am_pm ? hour12 : time->hour();
2371
2372 switch (repeat) {
2373 case 1:
2374 result.append(longLongToString(hour));
2375 break;
2376 case 2:
2377 result.append(longLongToString(hour, -1, 10, 2, QLocalePrivate::ZeroPadded));
2378 break;
2379 }
2380 break;
2381 }
2382 case 'H':
2383 used = true;
2384 repeat = qMin(repeat, 2);
2385 switch (repeat) {
2386 case 1:
2387 result.append(longLongToString(time->hour()));
2388 break;
2389 case 2:
2390 result.append(longLongToString(time->hour(), -1, 10, 2, QLocalePrivate::ZeroPadded));
2391 break;
2392 }
2393 break;
2394
2395 case 'm':
2396 used = true;
2397 repeat = qMin(repeat, 2);
2398 switch (repeat) {
2399 case 1:
2400 result.append(longLongToString(time->minute()));
2401 break;
2402 case 2:
2403 result.append(longLongToString(time->minute(), -1, 10, 2, QLocalePrivate::ZeroPadded));
2404 break;
2405 }
2406 break;
2407
2408 case 's':
2409 used = true;
2410 repeat = qMin(repeat, 2);
2411 switch (repeat) {
2412 case 1:
2413 result.append(longLongToString(time->second()));
2414 break;
2415 case 2:
2416 result.append(longLongToString(time->second(), -1, 10, 2, QLocalePrivate::ZeroPadded));
2417 break;
2418 }
2419 break;
2420
2421 case 'a':
2422 used = true;
2423 if (i + 1 < format.length() && format.at(i + 1).unicode() == 'p') {
2424 repeat = 2;
2425 } else {
2426 repeat = 1;
2427 }
2428 result.append(am_pm == AM ? q->amText().toLower() : q->pmText().toLower());
2429 break;
2430
2431 case 'A':
2432 used = true;
2433 if (i + 1 < format.length() && format.at(i + 1).unicode() == 'P') {
2434 repeat = 2;
2435 } else {
2436 repeat = 1;
2437 }
2438 result.append(am_pm == AM ? q->amText().toUpper() : q->pmText().toUpper());
2439 break;
2440
2441 case 'z':
2442 used = true;
2443 if (repeat >= 3) {
2444 repeat = 3;
2445 } else {
2446 repeat = 1;
2447 }
2448 switch (repeat) {
2449 case 1:
2450 result.append(longLongToString(time->msec()));
2451 break;
2452 case 3:
2453 result.append(longLongToString(time->msec(), -1, 10, 3, QLocalePrivate::ZeroPadded));
2454 break;
2455 }
2456 break;
2457
2458 case 't':
2459 used = true;
2460 repeat = 1;
2461 result.append(timeZone());
2462 break;
2463 default:
2464 break;
2465 }
2466 }
2467 if (!used) {
2468 result.append(QString(repeat, c));
2469 }
2470 i += repeat;
2471 }
2472
2473 return result;
2474 }
2475
doubleToString(double d,int precision,DoubleForm form,int width,unsigned flags) const2476 QString QLocalePrivate::doubleToString(double d,
2477 int precision,
2478 DoubleForm form,
2479 int width,
2480 unsigned flags) const
2481 {
2482 return QLocalePrivate::doubleToString(zero(), plus(), minus(), exponential(),
2483 group(), decimal(),
2484 d, precision, form, width, flags);
2485 }
2486
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)2487 QString QLocalePrivate::doubleToString(const QChar _zero, const QChar plus, const QChar minus,
2488 const QChar exponential, const QChar group, const QChar decimal,
2489 double d,
2490 int precision,
2491 DoubleForm form,
2492 int width,
2493 unsigned flags)
2494 {
2495 if (precision == -1)
2496 precision = 6;
2497 if (width == -1)
2498 width = 0;
2499
2500 bool negative = false;
2501 bool special_number = false; // nan, +/-inf
2502 QString num_str;
2503
2504 // Detect special numbers (nan, +/-inf)
2505 if (qt_is_inf(d)) {
2506 num_str = QString::fromLatin1("inf");
2507 special_number = true;
2508 negative = d < 0;
2509 } else if (qt_is_nan(d)) {
2510 num_str = QString::fromLatin1("nan");
2511 special_number = true;
2512 }
2513
2514 // Handle normal numbers
2515 if (!special_number) {
2516 int decpt, sign;
2517 QString digits;
2518
2519 #ifdef QT_QLOCALE_USES_FCVT
2520 // NOT thread safe!
2521 if (form == DFDecimal) {
2522 digits = QLatin1String(fcvt(d, precision, &decpt, &sign));
2523 } else {
2524 int pr = precision;
2525 if (form == DFExponent)
2526 ++pr;
2527 else if (form == DFSignificantDigits && pr == 0)
2528 pr = 1;
2529 digits = QLatin1String(ecvt(d, pr, &decpt, &sign));
2530
2531 // Chop trailing zeros
2532 if (digits.length() > 0) {
2533 int last_nonzero_idx = digits.length() - 1;
2534 while (last_nonzero_idx > 0
2535 && digits.unicode()[last_nonzero_idx] == QLatin1Char('0'))
2536 --last_nonzero_idx;
2537 digits.truncate(last_nonzero_idx + 1);
2538 }
2539
2540 }
2541
2542 #else
2543 int mode;
2544 if (form == DFDecimal)
2545 mode = 3;
2546 else
2547 mode = 2;
2548
2549 /* This next bit is a bit quirky. In DFExponent form, the precision
2550 is the number of digits after decpt. So that would suggest using
2551 mode=3 for qdtoa. But qdtoa behaves strangely when mode=3 and
2552 precision=0. So we get around this by using mode=2 and reasoning
2553 that we want precision+1 significant digits, since the decimal
2554 point in this mode is always after the first digit. */
2555 int pr = precision;
2556 if (form == DFExponent)
2557 ++pr;
2558
2559 char *rve = 0;
2560 char *buff = 0;
2561 QT_TRY {
2562 digits = QLatin1String(qdtoa(d, mode, pr, &decpt, &sign, &rve, &buff));
2563 } QT_CATCH(...) {
2564 if (buff != 0)
2565 free(buff);
2566 QT_RETHROW;
2567 }
2568 if (buff != 0)
2569 free(buff);
2570 #endif // QT_QLOCALE_USES_FCVT
2571
2572 if (_zero.unicode() != '0') {
2573 ushort z = _zero.unicode() - '0';
2574 for (int i = 0; i < digits.length(); ++i)
2575 reinterpret_cast<ushort *>(digits.data())[i] += z;
2576 }
2577
2578 bool always_show_decpt = (flags & Alternate || flags & ForcePoint);
2579 switch (form) {
2580 case DFExponent: {
2581 num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
2582 digits, decpt, precision, PMDecimalDigits,
2583 always_show_decpt);
2584 break;
2585 }
2586 case DFDecimal: {
2587 num_str = decimalForm(_zero, decimal, group,
2588 digits, decpt, precision, PMDecimalDigits,
2589 always_show_decpt, flags & ThousandsGroup);
2590 break;
2591 }
2592 case DFSignificantDigits: {
2593 PrecisionMode mode = (flags & Alternate) ?
2594 PMSignificantDigits : PMChopTrailingZeros;
2595
2596 if (decpt != digits.length() && (decpt <= -4 || decpt > precision))
2597 num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
2598 digits, decpt, precision, mode,
2599 always_show_decpt);
2600 else
2601 num_str = decimalForm(_zero, decimal, group,
2602 digits, decpt, precision, mode,
2603 always_show_decpt, flags & ThousandsGroup);
2604 break;
2605 }
2606 }
2607
2608 negative = sign != 0 && !isZero(d);
2609 }
2610
2611 // pad with zeros. LeftAdjusted overrides this flag). Also, we don't
2612 // pad special numbers
2613 if (flags & QLocalePrivate::ZeroPadded
2614 && !(flags & QLocalePrivate::LeftAdjusted)
2615 && !special_number) {
2616 int num_pad_chars = width - num_str.length();
2617 // leave space for the sign
2618 if (negative
2619 || flags & QLocalePrivate::AlwaysShowSign
2620 || flags & QLocalePrivate::BlankBeforePositive)
2621 --num_pad_chars;
2622
2623 for (int i = 0; i < num_pad_chars; ++i)
2624 num_str.prepend(_zero);
2625 }
2626
2627 // add sign
2628 if (negative)
2629 num_str.prepend(minus);
2630 else if (flags & QLocalePrivate::AlwaysShowSign)
2631 num_str.prepend(plus);
2632 else if (flags & QLocalePrivate::BlankBeforePositive)
2633 num_str.prepend(QLatin1Char(' '));
2634
2635 if (flags & QLocalePrivate::CapitalEorX)
2636 num_str = num_str.toUpper();
2637
2638 return num_str;
2639 }
2640
longLongToString(qlonglong l,int precision,int base,int width,unsigned flags) const2641 QString QLocalePrivate::longLongToString(qlonglong l, int precision,
2642 int base, int width,
2643 unsigned flags) const
2644 {
2645 return QLocalePrivate::longLongToString(zero(), group(), plus(), minus(),
2646 l, precision, base, width, flags);
2647 }
2648
longLongToString(const QChar zero,const QChar group,const QChar plus,const QChar minus,qlonglong l,int precision,int base,int width,unsigned flags)2649 QString QLocalePrivate::longLongToString(const QChar zero, const QChar group,
2650 const QChar plus, const QChar minus,
2651 qlonglong l, int precision,
2652 int base, int width,
2653 unsigned flags)
2654 {
2655 bool precision_not_specified = false;
2656 if (precision == -1) {
2657 precision_not_specified = true;
2658 precision = 1;
2659 }
2660
2661 bool negative = l < 0;
2662 if (base != 10) {
2663 // these are not supported by sprintf for octal and hex
2664 flags &= ~AlwaysShowSign;
2665 flags &= ~BlankBeforePositive;
2666 negative = false; // neither are negative numbers
2667 }
2668
2669 QString num_str;
2670 if (base == 10)
2671 num_str = qlltoa(l, base, zero);
2672 else
2673 num_str = qulltoa(l, base, zero);
2674
2675 uint cnt_thousand_sep = 0;
2676 if (flags & ThousandsGroup && base == 10) {
2677 for (int i = num_str.length() - 3; i > 0; i -= 3) {
2678 num_str.insert(i, group);
2679 ++cnt_thousand_sep;
2680 }
2681 }
2682
2683 for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
2684 num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
2685
2686 if ((flags & Alternate || flags & ShowBase)
2687 && base == 8
2688 && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
2689 num_str.prepend(QLatin1Char('0'));
2690
2691 // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
2692 // when precision is not specified in the format string
2693 bool zero_padded = flags & ZeroPadded
2694 && !(flags & LeftAdjusted)
2695 && precision_not_specified;
2696
2697 if (zero_padded) {
2698 int num_pad_chars = width - num_str.length();
2699
2700 // leave space for the sign
2701 if (negative
2702 || flags & AlwaysShowSign
2703 || flags & BlankBeforePositive)
2704 --num_pad_chars;
2705
2706 // leave space for optional '0x' in hex form
2707 if (base == 16 && (flags & Alternate || flags & ShowBase))
2708 num_pad_chars -= 2;
2709 // leave space for optional '0b' in binary form
2710 else if (base == 2 && (flags & Alternate || flags & ShowBase))
2711 num_pad_chars -= 2;
2712
2713 for (int i = 0; i < num_pad_chars; ++i)
2714 num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
2715 }
2716
2717 if (flags & CapitalEorX)
2718 num_str = num_str.toUpper();
2719
2720 if (base == 16 && (flags & Alternate || flags & ShowBase))
2721 num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
2722 if (base == 2 && (flags & Alternate || flags & ShowBase))
2723 num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
2724
2725 // add sign
2726 if (negative)
2727 num_str.prepend(minus);
2728 else if (flags & AlwaysShowSign)
2729 num_str.prepend(plus);
2730 else if (flags & BlankBeforePositive)
2731 num_str.prepend(QLatin1Char(' '));
2732
2733 return num_str;
2734 }
2735
unsLongLongToString(qulonglong l,int precision,int base,int width,unsigned flags) const2736 QString QLocalePrivate::unsLongLongToString(qulonglong l, int precision,
2737 int base, int width,
2738 unsigned flags) const
2739 {
2740 return QLocalePrivate::unsLongLongToString(zero(), group(), plus(),
2741 l, precision, base, width, flags);
2742 }
2743
unsLongLongToString(const QChar zero,const QChar group,const QChar plus,qulonglong l,int precision,int base,int width,unsigned flags)2744 QString QLocalePrivate::unsLongLongToString(const QChar zero, const QChar group,
2745 const QChar plus,
2746 qulonglong l, int precision,
2747 int base, int width,
2748 unsigned flags)
2749 {
2750 bool precision_not_specified = false;
2751 if (precision == -1) {
2752 precision_not_specified = true;
2753 precision = 1;
2754 }
2755
2756 QString num_str = qulltoa(l, base, zero);
2757
2758 uint cnt_thousand_sep = 0;
2759 if (flags & ThousandsGroup && base == 10) {
2760 for (int i = num_str.length() - 3; i > 0; i -=3) {
2761 num_str.insert(i, group);
2762 ++cnt_thousand_sep;
2763 }
2764 }
2765
2766 for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
2767 num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
2768
2769 if ((flags & Alternate || flags & ShowBase)
2770 && base == 8
2771 && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
2772 num_str.prepend(QLatin1Char('0'));
2773
2774 // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
2775 // when precision is not specified in the format string
2776 bool zero_padded = flags & ZeroPadded
2777 && !(flags & LeftAdjusted)
2778 && precision_not_specified;
2779
2780 if (zero_padded) {
2781 int num_pad_chars = width - num_str.length();
2782
2783 // leave space for optional '0x' in hex form
2784 if (base == 16 && flags & Alternate)
2785 num_pad_chars -= 2;
2786 // leave space for optional '0b' in binary form
2787 else if (base == 2 && flags & Alternate)
2788 num_pad_chars -= 2;
2789
2790 for (int i = 0; i < num_pad_chars; ++i)
2791 num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
2792 }
2793
2794 if (flags & CapitalEorX)
2795 num_str = num_str.toUpper();
2796
2797 if (base == 16 && (flags & Alternate || flags & ShowBase))
2798 num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
2799 else if (base == 2 && (flags & Alternate || flags & ShowBase))
2800 num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
2801
2802 // add sign
2803 if (flags & AlwaysShowSign)
2804 num_str.prepend(plus);
2805 else if (flags & BlankBeforePositive)
2806 num_str.prepend(QLatin1Char(' '));
2807
2808 return num_str;
2809 }
2810
2811 /*
2812 Converts a number in locale to its representation in the C locale.
2813 Only has to guarantee that a string that is a correct representation of
2814 a number will be converted. If junk is passed in, junk will be passed
2815 out and the error will be detected during the actual conversion to a
2816 number. We can't detect junk here, since we don't even know the base
2817 of the number.
2818 */
numberToCLocale(const QString & num,GroupSeparatorMode group_sep_mode,CharBuff * result) const2819 bool QLocalePrivate::numberToCLocale(const QString &num,
2820 GroupSeparatorMode group_sep_mode,
2821 CharBuff *result) const
2822 {
2823 const QChar *uc = num.unicode();
2824 int l = num.length();
2825 int idx = 0;
2826
2827 // Skip whitespace
2828 while (idx < l && uc[idx].isSpace())
2829 ++idx;
2830 if (idx == l)
2831 return false;
2832
2833 while (idx < l) {
2834 const QChar &in = uc[idx];
2835
2836 char out = digitToCLocale(in);
2837 if (out == 0) {
2838 if (in == list())
2839 out = ';';
2840 else if (in == percent())
2841 out = '%';
2842 // for handling base-x numbers
2843 else if (in.unicode() >= 'A' && in.unicode() <= 'Z')
2844 out = in.toLower().toLatin1();
2845 else if (in.unicode() >= 'a' && in.unicode() <= 'z')
2846 out = in.toLatin1();
2847 else
2848 break;
2849 }
2850
2851 result->append(out);
2852
2853 ++idx;
2854 }
2855
2856 // Check trailing whitespace
2857 for (; idx < l; ++idx) {
2858 if (!uc[idx].isSpace())
2859 return false;
2860 }
2861
2862 result->append('\0');
2863
2864 // Check separators
2865 if (group_sep_mode == ParseGroupSeparators
2866 && !removeGroupSeparators(result))
2867 return false;
2868
2869
2870 return true;
2871 }
2872
validateChars(const QString & str,NumberMode numMode,QByteArray * buff,int decDigits) const2873 bool QLocalePrivate::validateChars(const QString &str, NumberMode numMode, QByteArray *buff,
2874 int decDigits) const
2875 {
2876 buff->clear();
2877 buff->reserve(str.length());
2878
2879 const bool scientific = numMode == DoubleScientificMode;
2880 bool lastWasE = false;
2881 bool lastWasDigit = false;
2882 int eCnt = 0;
2883 int decPointCnt = 0;
2884 bool dec = false;
2885 int decDigitCnt = 0;
2886
2887 for (int i = 0; i < str.length(); ++i) {
2888 char c = digitToCLocale(str.at(i));
2889
2890 if (c >= '0' && c <= '9') {
2891 if (numMode != IntegerMode) {
2892 // If a double has too many digits after decpt, it shall be Invalid.
2893 if (dec && decDigits != -1 && decDigits < ++decDigitCnt)
2894 return false;
2895 }
2896 lastWasDigit = true;
2897 } else {
2898 switch (c) {
2899 case '.':
2900 if (numMode == IntegerMode) {
2901 // If an integer has a decimal point, it shall be Invalid.
2902 return false;
2903 } else {
2904 // If a double has more than one decimal point, it shall be Invalid.
2905 if (++decPointCnt > 1)
2906 return false;
2907 #if 0
2908 // If a double with no decimal digits has a decimal point, it shall be
2909 // Invalid.
2910 if (decDigits == 0)
2911 return false;
2912 #endif // On second thoughts, it shall be Valid.
2913
2914 dec = true;
2915 }
2916 break;
2917
2918 case '+':
2919 case '-':
2920 if (scientific) {
2921 // If a scientific has a sign that's not at the beginning or after
2922 // an 'e', it shall be Invalid.
2923 if (i != 0 && !lastWasE)
2924 return false;
2925 } else {
2926 // If a non-scientific has a sign that's not at the beginning,
2927 // it shall be Invalid.
2928 if (i != 0)
2929 return false;
2930 }
2931 break;
2932
2933 case ',':
2934 //it can only be placed after a digit which is before the decimal point
2935 if (!lastWasDigit || decPointCnt > 0)
2936 return false;
2937 break;
2938
2939 case 'e':
2940 if (scientific) {
2941 // If a scientific has more than one 'e', it shall be Invalid.
2942 if (++eCnt > 1)
2943 return false;
2944 dec = false;
2945 } else {
2946 // If a non-scientific has an 'e', it shall be Invalid.
2947 return false;
2948 }
2949 break;
2950
2951 default:
2952 // If it's not a valid digit, it shall be Invalid.
2953 return false;
2954 }
2955 lastWasDigit = false;
2956 }
2957
2958 lastWasE = c == 'e';
2959 if (c != ',')
2960 buff->append(c);
2961 }
2962
2963 return true;
2964 }
2965
stringToDouble(const QString & number,bool * ok,GroupSeparatorMode group_sep_mode) const2966 double QLocalePrivate::stringToDouble(const QString &number, bool *ok,
2967 GroupSeparatorMode group_sep_mode) const
2968 {
2969 CharBuff buff;
2970 if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
2971 group_sep_mode, &buff)) {
2972 if (ok != 0)
2973 *ok = false;
2974 return 0.0;
2975 }
2976 return bytearrayToDouble(buff.constData(), ok);
2977 }
2978
stringToLongLong(const QString & number,int base,bool * ok,GroupSeparatorMode group_sep_mode) const2979 qlonglong QLocalePrivate::stringToLongLong(const QString &number, int base,
2980 bool *ok, GroupSeparatorMode group_sep_mode) const
2981 {
2982 CharBuff buff;
2983 if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
2984 group_sep_mode, &buff)) {
2985 if (ok != 0)
2986 *ok = false;
2987 return 0;
2988 }
2989
2990 return bytearrayToLongLong(buff.constData(), base, ok);
2991 }
2992
stringToUnsLongLong(const QString & number,int base,bool * ok,GroupSeparatorMode group_sep_mode) const2993 qulonglong QLocalePrivate::stringToUnsLongLong(const QString &number, int base,
2994 bool *ok, GroupSeparatorMode group_sep_mode) const
2995 {
2996 CharBuff buff;
2997 if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
2998 group_sep_mode, &buff)) {
2999 if (ok != 0)
3000 *ok = false;
3001 return 0;
3002 }
3003
3004 return bytearrayToUnsLongLong(buff.constData(), base, ok);
3005 }
3006
3007
bytearrayToDouble(const char * num,bool * ok,bool * overflow)3008 double QLocalePrivate::bytearrayToDouble(const char *num, bool *ok, bool *overflow)
3009 {
3010 if (ok != 0)
3011 *ok = true;
3012 if (overflow != 0)
3013 *overflow = false;
3014
3015 if (*num == '\0') {
3016 if (ok != 0)
3017 *ok = false;
3018 return 0.0;
3019 }
3020
3021 if (qstrcmp(num, "nan") == 0)
3022 return qt_snan();
3023
3024 if (qstrcmp(num, "+inf") == 0 || qstrcmp(num, "inf") == 0)
3025 return qt_inf();
3026
3027 if (qstrcmp(num, "-inf") == 0)
3028 return -qt_inf();
3029
3030 bool _ok;
3031 const char *endptr;
3032 double d = qstrtod(num, &endptr, &_ok);
3033
3034 if (!_ok) {
3035 // the only way strtod can fail with *endptr != '\0' on a non-empty
3036 // input string is overflow
3037 if (ok != 0)
3038 *ok = false;
3039 if (overflow != 0)
3040 *overflow = *endptr != '\0';
3041 return 0.0;
3042 }
3043
3044 if (*endptr != '\0') {
3045 // we stopped at a non-digit character after converting some digits
3046 if (ok != 0)
3047 *ok = false;
3048 if (overflow != 0)
3049 *overflow = false;
3050 return 0.0;
3051 }
3052
3053 if (ok != 0)
3054 *ok = true;
3055 if (overflow != 0)
3056 *overflow = false;
3057 return d;
3058 }
3059
bytearrayToLongLong(const char * num,int base,bool * ok,bool * overflow)3060 qlonglong QLocalePrivate::bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow)
3061 {
3062 bool _ok;
3063 const char *endptr;
3064
3065 if (*num == '\0') {
3066 if (ok != 0)
3067 *ok = false;
3068 if (overflow != 0)
3069 *overflow = false;
3070 return 0;
3071 }
3072
3073 qlonglong l = qstrtoll(num, &endptr, base, &_ok);
3074
3075 if (!_ok) {
3076 if (ok != 0)
3077 *ok = false;
3078 if (overflow != 0) {
3079 // the only way qstrtoll can fail with *endptr != '\0' on a non-empty
3080 // input string is overflow
3081 *overflow = *endptr != '\0';
3082 }
3083 return 0;
3084 }
3085
3086 if (*endptr != '\0') {
3087 // we stopped at a non-digit character after converting some digits
3088 if (ok != 0)
3089 *ok = false;
3090 if (overflow != 0)
3091 *overflow = false;
3092 return 0;
3093 }
3094
3095 if (ok != 0)
3096 *ok = true;
3097 if (overflow != 0)
3098 *overflow = false;
3099 return l;
3100 }
3101
bytearrayToUnsLongLong(const char * num,int base,bool * ok)3102 qulonglong QLocalePrivate::bytearrayToUnsLongLong(const char *num, int base, bool *ok)
3103 {
3104 bool _ok;
3105 const char *endptr;
3106 qulonglong l = qstrtoull(num, &endptr, base, &_ok);
3107
3108 if (!_ok || *endptr != '\0') {
3109 if (ok != 0)
3110 *ok = false;
3111 return 0;
3112 }
3113
3114 if (ok != 0)
3115 *ok = true;
3116 return l;
3117 }
3118
3119 /*!
3120 \since 4.8
3121
3122 \enum QLocale::CurrencySymbolFormat
3123
3124 Specifies the format of the currency symbol.
3125
3126 \value CurrencyIsoCode a ISO-4217 code of the currency.
3127 \value CurrencySymbol a currency symbol.
3128 \value CurrencyDisplayName a user readable name of the currency.
3129 */
3130
3131 /*!
3132 \since 4.8
3133 Returns a currency symbol according to the \a format.
3134 */
currencySymbol(QLocale::CurrencySymbolFormat format) const3135 QString QLocale::currencySymbol(QLocale::CurrencySymbolFormat format) const
3136 {
3137 #ifndef QT_NO_SYSTEMLOCALE
3138 if (d() == systemPrivate()) {
3139 QVariant res = systemLocale()->query(QSystemLocale::CurrencySymbol, format);
3140 if (!res.isNull())
3141 return res.toString();
3142 }
3143 #endif
3144 quint32 idx, size;
3145 switch (format) {
3146 case CurrencySymbol:
3147 idx = d()->m_currency_symbol_idx;
3148 size = d()->m_currency_symbol_size;
3149 return getLocaleData(currency_symbol_data + idx, size);
3150 case CurrencyDisplayName:
3151 idx = d()->m_currency_display_name_idx;
3152 size = d()->m_currency_display_name_size;
3153 return getLocaleListData(currency_display_name_data + idx, size, 0);
3154 case CurrencyIsoCode: {
3155 int len = 0;
3156 const QLocalePrivate *d = this->d();
3157 for (; len < 3; ++len)
3158 if (!d->m_currency_iso_code[len])
3159 break;
3160 return len ? QString::fromLatin1(d->m_currency_iso_code, len) : QString();
3161 }
3162 }
3163 return QString();
3164 }
3165
3166 /*!
3167 \since 4.8
3168
3169 Returns a localized string representation of \a value as a currency.
3170 If the \a symbol is provided it is used instead of the default currency symbol.
3171
3172 \sa currencySymbol()
3173 */
toCurrencyString(qlonglong value,const QString & symbol) const3174 QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const
3175 {
3176 #ifndef QT_NO_SYSTEMLOCALE
3177 if (d() == systemPrivate()) {
3178 QSystemLocale::CurrencyToStringArgument arg(value, symbol);
3179 QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
3180 if (!res.isNull())
3181 return res.toString();
3182 }
3183 #endif
3184 const QLocalePrivate *d = this->d();
3185 quint8 idx = d->m_currency_format_idx;
3186 quint8 size = d->m_currency_format_size;
3187 if (d->m_currency_negative_format_size && value < 0) {
3188 idx = d->m_currency_negative_format_idx;
3189 size = d->m_currency_negative_format_size;
3190 value = -value;
3191 }
3192 QString str = d->longLongToString(value);
3193 QString sym = symbol.isNull() ? currencySymbol() : symbol;
3194 if (sym.isEmpty())
3195 sym = currencySymbol(QLocale::CurrencyIsoCode);
3196 QString format = getLocaleData(currency_format_data + idx, size);
3197 return format.arg(str, sym);
3198 }
3199
3200 /*!
3201 \since 4.8
3202 \overload
3203 */
toCurrencyString(qulonglong value,const QString & symbol) const3204 QString QLocale::toCurrencyString(qulonglong value, const QString &symbol) const
3205 {
3206 #ifndef QT_NO_SYSTEMLOCALE
3207 if (d() == systemPrivate()) {
3208 QSystemLocale::CurrencyToStringArgument arg(value, symbol);
3209 QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
3210 if (!res.isNull())
3211 return res.toString();
3212 }
3213 #endif
3214 const QLocalePrivate *d = this->d();
3215 quint8 idx = d->m_currency_format_idx;
3216 quint8 size = d->m_currency_format_size;
3217 QString str = d->unsLongLongToString(value);
3218 QString sym = symbol.isNull() ? currencySymbol() : symbol;
3219 if (sym.isEmpty())
3220 sym = currencySymbol(QLocale::CurrencyIsoCode);
3221 QString format = getLocaleData(currency_format_data + idx, size);
3222 return format.arg(str, sym);
3223 }
3224
3225 /*!
3226 \since 4.8
3227 \overload
3228 */
toCurrencyString(double value,const QString & symbol) const3229 QString QLocale::toCurrencyString(double value, const QString &symbol) const
3230 {
3231 #ifndef QT_NO_SYSTEMLOCALE
3232 if (d() == systemPrivate()) {
3233 QSystemLocale::CurrencyToStringArgument arg(value, symbol);
3234 QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
3235 if (!res.isNull())
3236 return res.toString();
3237 }
3238 #endif
3239 const QLocalePrivate *d = this->d();
3240 quint8 idx = d->m_currency_format_idx;
3241 quint8 size = d->m_currency_format_size;
3242 if (d->m_currency_negative_format_size && value < 0) {
3243 idx = d->m_currency_negative_format_idx;
3244 size = d->m_currency_negative_format_size;
3245 value = -value;
3246 }
3247 QString str = d->doubleToString(value, d->m_currency_digits,
3248 QLocalePrivate::DFDecimal);
3249 QString sym = symbol.isNull() ? currencySymbol() : symbol;
3250 if (sym.isEmpty())
3251 sym = currencySymbol(QLocale::CurrencyIsoCode);
3252 QString format = getLocaleData(currency_format_data + idx, size);
3253 return format.arg(str, sym);
3254 }
3255
3256 /*!
3257 \since 4.8
3258
3259 Returns an ordered list of locale names for translation purposes in
3260 preference order.
3261
3262 The return value represents locale names that the user expects to see the
3263 UI translation in.
3264
3265 Most like you do not need to use this function directly, but just pass the
3266 QLocale object to the QTranslator::load() function.
3267
3268 The first item in the list is the most preferred one.
3269
3270 \sa QTranslator, bcp47Name()
3271 */
uiLanguages() const3272 QStringList QLocale::uiLanguages() const
3273 {
3274 #ifndef QT_NO_SYSTEMLOCALE
3275 if (d() == systemPrivate()) {
3276 QVariant res = systemLocale()->query(QSystemLocale::UILanguages, QVariant());
3277 if (!res.isNull()) {
3278 QStringList result = res.toStringList();
3279 if (!result.isEmpty())
3280 return result;
3281 }
3282 }
3283 #endif
3284 return QStringList(bcp47Name());
3285 }
3286
3287 /*!
3288 \since 4.8
3289
3290 Returns a native name of the language for the locale. For example
3291 "Schwiizertüütsch" for Swiss-German locale.
3292
3293 \sa nativeCountryName(), languageToString()
3294 */
nativeLanguageName() const3295 QString QLocale::nativeLanguageName() const
3296 {
3297 #ifndef QT_NO_SYSTEMLOCALE
3298 if (d() == systemPrivate()) {
3299 QVariant res = systemLocale()->query(QSystemLocale::NativeLanguageName, QVariant());
3300 if (!res.isNull())
3301 return res.toString();
3302 }
3303 #endif
3304 return getLocaleData(endonyms_data + d()->m_language_endonym_idx, d()->m_language_endonym_size);
3305 }
3306
3307 /*!
3308 \since 4.8
3309
3310 Returns a native name of the country for the locale. For example
3311 "España" for Spanish/Spain locale.
3312
3313 \sa nativeLanguageName(), countryToString()
3314 */
nativeCountryName() const3315 QString QLocale::nativeCountryName() const
3316 {
3317 #ifndef QT_NO_SYSTEMLOCALE
3318 if (d() == systemPrivate()) {
3319 QVariant res = systemLocale()->query(QSystemLocale::NativeCountryName, QVariant());
3320 if (!res.isNull())
3321 return res.toString();
3322 }
3323 #endif
3324 return getLocaleData(endonyms_data + d()->m_country_endonym_idx, d()->m_country_endonym_size);
3325 }
3326
3327 QT_END_NAMESPACE
3328