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