diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2019-05-27 19:13:54 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2019-07-10 17:05:30 +0200 |
commit | a9aa206b7b8ac4e69f8c46233b4080e00e845ff5 (patch) | |
tree | 0d19cb1f1a3b9d79d322e6e63f6f72160977ca67 /src/corelib/tools/qlocale.cpp | |
parent | 85d3061c1cd4617ef09cb381320611c27da205a5 (diff) |
Move text-related code out of corelib/tools/ to corelib/text/
This includes byte array, string, char, unicode, locale, collation and
regular expressions.
Change-Id: I8b125fa52c8c513eb57a0f1298b91910e5a0d786
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/corelib/tools/qlocale.cpp')
-rw-r--r-- | src/corelib/tools/qlocale.cpp | 4223 |
1 files changed, 0 insertions, 4223 deletions
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp deleted file mode 100644 index 939f8eb34d..0000000000 --- a/src/corelib/tools/qlocale.cpp +++ /dev/null @@ -1,4223 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2019 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglobal.h" - -#if !defined(QWS) && defined(Q_OS_MAC) -# include "private/qcore_mac_p.h" -# include <CoreFoundation/CoreFoundation.h> -#endif - -#include "qplatformdefs.h" - -#include "qdatastream.h" -#include "qdebug.h" -#include "qhashfunctions.h" -#include "qstring.h" -#include "qlocale.h" -#include "qlocale_p.h" -#include "qlocale_tools_p.h" -#if QT_CONFIG(datetimeparser) -#include "private/qdatetimeparser_p.h" -#endif -#include "qnamespace.h" -#include "qdatetime.h" -#include "qstringlist.h" -#include "qvariant.h" -#include "qstringbuilder.h" -#include "private/qnumeric_p.h" -#include <cmath> -#ifndef QT_NO_SYSTEMLOCALE -# include "qmutex.h" -#endif -#ifdef Q_OS_WIN -# include <qt_windows.h> -# include <time.h> -#endif - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_SYSTEMLOCALE -static QSystemLocale *_systemLocale = 0; -class QSystemLocaleSingleton: public QSystemLocale -{ -public: - QSystemLocaleSingleton() : QSystemLocale(true) {} -}; - -Q_GLOBAL_STATIC(QSystemLocaleSingleton, QSystemLocale_globalSystemLocale) -static QLocaleData globalLocaleData; -#endif - -/****************************************************************************** -** Helpers for accessing Qt locale database -*/ - -QT_BEGIN_INCLUDE_NAMESPACE -#include "qlocale_data_p.h" -QT_END_INCLUDE_NAMESPACE - -QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) noexcept -{ - const auto len = code.size(); - if (len != 2 && len != 3) - return QLocale::C; - ushort uc1 = code[0].toLower().unicode(); - ushort uc2 = code[1].toLower().unicode(); - ushort uc3 = len > 2 ? code[2].toLower().unicode() : 0; - - const unsigned char *c = language_code_list; - for (; *c != 0; c += 3) { - if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2]) - return QLocale::Language((c - language_code_list)/3); - } - - if (uc3 == 0) { - // legacy codes - if (uc1 == 'n' && uc2 == 'o') { // no -> nb - Q_STATIC_ASSERT(QLocale::Norwegian == QLocale::NorwegianBokmal); - return QLocale::Norwegian; - } - if (uc1 == 't' && uc2 == 'l') { // tl -> fil - Q_STATIC_ASSERT(QLocale::Tagalog == QLocale::Filipino); - return QLocale::Tagalog; - } - if (uc1 == 's' && uc2 == 'h') { // sh -> sr[_Latn] - Q_STATIC_ASSERT(QLocale::SerboCroatian == QLocale::Serbian); - return QLocale::SerboCroatian; - } - if (uc1 == 'm' && uc2 == 'o') { // mo -> ro - Q_STATIC_ASSERT(QLocale::Moldavian == QLocale::Romanian); - return QLocale::Moldavian; - } - // Android uses the following deprecated codes - if (uc1 == 'i' && uc2 == 'w') // iw -> he - return QLocale::Hebrew; - if (uc1 == 'i' && uc2 == 'n') // in -> id - return QLocale::Indonesian; - if (uc1 == 'j' && uc2 == 'i') // ji -> yi - return QLocale::Yiddish; - } - return QLocale::C; -} - -QLocale::Script QLocalePrivate::codeToScript(QStringView code) noexcept -{ - const auto len = code.size(); - if (len != 4) - return QLocale::AnyScript; - - // script is titlecased in our data - unsigned char c0 = code[0].toUpper().toLatin1(); - unsigned char c1 = code[1].toLower().toLatin1(); - unsigned char c2 = code[2].toLower().toLatin1(); - unsigned char c3 = code[3].toLower().toLatin1(); - - const unsigned char *c = script_code_list; - for (int i = 0; i < QLocale::LastScript; ++i, c += 4) { - if (c0 == c[0] && c1 == c[1] && c2 == c[2] && c3 == c[3]) - return QLocale::Script(i); - } - return QLocale::AnyScript; -} - -QLocale::Country QLocalePrivate::codeToCountry(QStringView code) noexcept -{ - const auto len = code.size(); - if (len != 2 && len != 3) - return QLocale::AnyCountry; - - ushort uc1 = code[0].toUpper().unicode(); - ushort uc2 = code[1].toUpper().unicode(); - ushort uc3 = len > 2 ? code[2].toUpper().unicode() : 0; - - const unsigned char *c = country_code_list; - for (; *c != 0; c += 3) { - if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2]) - return QLocale::Country((c - country_code_list)/3); - } - - return QLocale::AnyCountry; -} - -QLatin1String QLocalePrivate::languageToCode(QLocale::Language language) -{ - if (language == QLocale::AnyLanguage) - return QLatin1String(); - if (language == QLocale::C) - return QLatin1String("C"); - - const unsigned char *c = language_code_list + 3*(uint(language)); - - return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3); - -} - -QLatin1String QLocalePrivate::scriptToCode(QLocale::Script script) -{ - if (script == QLocale::AnyScript || script > QLocale::LastScript) - return QLatin1String(); - const unsigned char *c = script_code_list + 4*(uint(script)); - return QLatin1String(reinterpret_cast<const char *>(c), 4); -} - -QLatin1String QLocalePrivate::countryToCode(QLocale::Country country) -{ - if (country == QLocale::AnyCountry) - return QLatin1String(); - - const unsigned char *c = country_code_list + 3*(uint(country)); - - return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3); -} - -// http://www.unicode.org/reports/tr35/#Likely_Subtags -static bool addLikelySubtags(QLocaleId &localeId) -{ - // ### optimize with bsearch - const int likely_subtags_count = sizeof(likely_subtags) / sizeof(likely_subtags[0]); - const QLocaleId *p = likely_subtags; - const QLocaleId *const e = p + likely_subtags_count; - for ( ; p < e; p += 2) { - if (localeId == p[0]) { - localeId = p[1]; - return true; - } - } - return false; -} - -QLocaleId QLocaleId::withLikelySubtagsAdded() const -{ - // language_script_region - if (language_id || script_id || country_id) { - QLocaleId id = QLocaleId::fromIds(language_id, script_id, country_id); - if (addLikelySubtags(id)) - return id; - } - // language_region - if (script_id) { - QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id); - if (addLikelySubtags(id)) { - id.script_id = script_id; - return id; - } - } - // language_script - if (country_id) { - QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0); - if (addLikelySubtags(id)) { - id.country_id = country_id; - return id; - } - } - // language - if (script_id && country_id) { - QLocaleId id = QLocaleId::fromIds(language_id, 0, 0); - if (addLikelySubtags(id)) { - id.script_id = script_id; - id.country_id = country_id; - return id; - } - } - // und_script - if (language_id) { - QLocaleId id = QLocaleId::fromIds(0, script_id, 0); - if (addLikelySubtags(id)) { - id.language_id = language_id; - return id; - } - } - return *this; -} - -QLocaleId QLocaleId::withLikelySubtagsRemoved() const -{ - QLocaleId max = withLikelySubtagsAdded(); - // language - { - QLocaleId id = QLocaleId::fromIds(language_id, 0, 0); - if (id.withLikelySubtagsAdded() == max) - return id; - } - // language_region - if (country_id) { - QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id); - if (id.withLikelySubtagsAdded() == max) - return id; - } - // language_script - if (script_id) { - QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0); - if (id.withLikelySubtagsAdded() == max) - return id; - } - return max; -} - -QByteArray QLocaleId::name(char separator) const -{ - if (language_id == QLocale::AnyLanguage) - return QByteArray(); - if (language_id == QLocale::C) - return QByteArrayLiteral("C"); - - const unsigned char *lang = language_code_list + 3 * language_id; - const unsigned char *script = - (script_id != QLocale::AnyScript ? script_code_list + 4 * script_id : nullptr); - const unsigned char *country = - (country_id != QLocale::AnyCountry ? country_code_list + 3 * country_id : nullptr); - char len = (lang[2] != 0 ? 3 : 2) + (script ? 4+1 : 0) + (country ? (country[2] != 0 ? 3 : 2)+1 : 0); - QByteArray name(len, Qt::Uninitialized); - char *uc = name.data(); - *uc++ = lang[0]; - *uc++ = lang[1]; - if (lang[2] != 0) - *uc++ = lang[2]; - if (script) { - *uc++ = separator; - *uc++ = script[0]; - *uc++ = script[1]; - *uc++ = script[2]; - *uc++ = script[3]; - } - if (country) { - *uc++ = separator; - *uc++ = country[0]; - *uc++ = country[1]; - if (country[2] != 0) - *uc++ = country[2]; - } - return name; -} - -QByteArray QLocalePrivate::bcp47Name(char separator) const -{ - if (m_data->m_language_id == QLocale::AnyLanguage) - return QByteArray(); - if (m_data->m_language_id == QLocale::C) - return QByteArrayLiteral("en"); - - QLocaleId localeId = QLocaleId::fromIds(m_data->m_language_id, m_data->m_script_id, m_data->m_country_id); - return localeId.withLikelySubtagsRemoved().name(separator); -} - -static const QLocaleData *findLocaleDataById(const QLocaleId &localeId) -{ - const uint idx = locale_index[localeId.language_id]; - - const QLocaleData *data = locale_data + idx; - - if (idx == 0) // default language has no associated script or country - return data; - - Q_ASSERT(data->m_language_id == localeId.language_id); - - if (localeId.script_id == QLocale::AnyScript && localeId.country_id == QLocale::AnyCountry) - return data; - - if (localeId.script_id == QLocale::AnyScript) { - do { - if (data->m_country_id == localeId.country_id) - return data; - ++data; - } while (data->m_language_id && data->m_language_id == localeId.language_id); - } else if (localeId.country_id == QLocale::AnyCountry) { - do { - if (data->m_script_id == localeId.script_id) - return data; - ++data; - } while (data->m_language_id && data->m_language_id == localeId.language_id); - } else { - do { - if (data->m_script_id == localeId.script_id && data->m_country_id == localeId.country_id) - return data; - ++data; - } while (data->m_language_id && data->m_language_id == localeId.language_id); - } - - return nullptr; -} - -const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script, QLocale::Country country) -{ - QLocaleId localeId = QLocaleId::fromIds(language, script, country); - QLocaleId likelyId = localeId.withLikelySubtagsAdded(); - - const uint idx = locale_index[likelyId.language_id]; - - // Try a straight match with the likely data: - if (const QLocaleData *const data = findLocaleDataById(likelyId)) - return data; - QList<QLocaleId> tried; - tried.push_back(likelyId); - - // No match; try again with raw data: - if (!tried.contains(localeId)) { - if (const QLocaleData *const data = findLocaleDataById(localeId)) - return data; - tried.push_back(localeId); - } - - // No match; try again with likely country - if (country != QLocale::AnyCountry - && (language != QLocale::AnyLanguage || script != QLocale::AnyScript)) { - localeId = QLocaleId::fromIds(language, script, QLocale::AnyCountry); - likelyId = localeId.withLikelySubtagsAdded(); - if (!tried.contains(likelyId)) { - if (const QLocaleData *const data = findLocaleDataById(likelyId)) - return data; - tried.push_back(likelyId); - } - - // No match; try again with any country - if (!tried.contains(localeId)) { - if (const QLocaleData *const data = findLocaleDataById(localeId)) - return data; - tried.push_back(localeId); - } - } - - // No match; try again with likely script - if (script != QLocale::AnyScript - && (language != QLocale::AnyLanguage || country != QLocale::AnyCountry)) { - localeId = QLocaleId::fromIds(language, QLocale::AnyScript, country); - likelyId = localeId.withLikelySubtagsAdded(); - if (!tried.contains(likelyId)) { - if (const QLocaleData *const data = findLocaleDataById(likelyId)) - return data; - tried.push_back(likelyId); - } - - // No match; try again with any script - if (!tried.contains(localeId)) { - if (const QLocaleData *const data = findLocaleDataById(localeId)) - return data; - tried.push_back(localeId); - } - } - - // No match; return data at original index - return locale_data + idx; -} - -static bool parse_locale_tag(const QString &input, int &i, QString *result, const QString &separators) -{ - *result = QString(8, Qt::Uninitialized); // worst case according to BCP47 - QChar *pch = result->data(); - const QChar *uc = input.data() + i; - const int l = input.length(); - int size = 0; - for (; i < l && size < 8; ++i, ++size) { - if (separators.contains(*uc)) - break; - if (! ((uc->unicode() >= 'a' && uc->unicode() <= 'z') || - (uc->unicode() >= 'A' && uc->unicode() <= 'Z') || - (uc->unicode() >= '0' && uc->unicode() <= '9')) ) // latin only - return false; - *pch++ = *uc++; - } - result->truncate(size); - return true; -} - -bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry) -{ - const int length = name.length(); - - lang = script = cntry = QString(); - - const QString separators = QStringLiteral("_-.@"); - enum ParserState { NoState, LangState, ScriptState, CountryState }; - ParserState state = LangState; - for (int i = 0; i < length && state != NoState; ) { - QString value; - if (!parse_locale_tag(name, i, &value, separators) ||value.isEmpty()) - break; - QChar sep = i < length ? name.at(i) : QChar(); - switch (state) { - case LangState: - if (!sep.isNull() && !separators.contains(sep)) { - state = NoState; - break; - } - lang = value; - if (i == length) { - // just language was specified - state = NoState; - break; - } - state = ScriptState; - break; - case ScriptState: { - QString scripts = QString::fromLatin1((const char *)script_code_list, sizeof(script_code_list) - 1); - if (value.length() == 4 && scripts.indexOf(value) % 4 == 0) { - // script name is always 4 characters - script = value; - state = CountryState; - } else { - // it wasn't a script, maybe it is a country then? - cntry = value; - state = NoState; - } - break; - } - case CountryState: - cntry = value; - state = NoState; - break; - case NoState: - // shouldn't happen - qWarning("QLocale: This should never happen"); - break; - } - ++i; - } - return lang.length() == 2 || lang.length() == 3; -} - -void QLocalePrivate::getLangAndCountry(const QString &name, QLocale::Language &lang, - QLocale::Script &script, QLocale::Country &cntry) -{ - lang = QLocale::C; - script = QLocale::AnyScript; - cntry = QLocale::AnyCountry; - - QString lang_code; - QString script_code; - QString cntry_code; - if (!qt_splitLocaleName(name, lang_code, script_code, cntry_code)) - return; - - lang = QLocalePrivate::codeToLanguage(lang_code); - if (lang == QLocale::C) - return; - script = QLocalePrivate::codeToScript(script_code); - cntry = QLocalePrivate::codeToCountry(cntry_code); -} - -static const QLocaleData *findLocaleData(const QString &name) -{ - QLocale::Language lang; - QLocale::Script script; - QLocale::Country cntry; - QLocalePrivate::getLangAndCountry(name, lang, script, cntry); - - return QLocaleData::findLocaleData(lang, script, cntry); -} - -QString qt_readEscapedFormatString(QStringView format, int *idx) -{ - int &i = *idx; - - Q_ASSERT(format.at(i) == QLatin1Char('\'')); - ++i; - if (i == format.size()) - return QString(); - if (format.at(i).unicode() == '\'') { // "''" outside of a quoted stirng - ++i; - return QLatin1String("'"); - } - - QString result; - - while (i < format.size()) { - if (format.at(i).unicode() == '\'') { - if (i + 1 < format.size() && format.at(i + 1).unicode() == '\'') { - // "''" inside of a quoted string - result.append(QLatin1Char('\'')); - i += 2; - } else { - break; - } - } else { - result.append(format.at(i++)); - } - } - if (i < format.size()) - ++i; - - return result; -} - -/*! - \internal - - Counts the number of identical leading characters in \a s. - - If \a s is empty, returns 0. - - Otherwise, returns the number of consecutive \c{s.front()} - characters at the start of \a s. - - \code - qt_repeatCount(u"a"); // == 1 - qt_repeatCount(u"ab"); // == 1 - qt_repeatCount(u"aab"); // == 2 - \endcode -*/ -int qt_repeatCount(QStringView s) -{ - if (s.isEmpty()) - return 0; - const QChar c = s.front(); - qsizetype j = 1; - while (j < s.size() && s.at(j) == c) - ++j; - return int(j); -} - -static const QLocaleData *default_data = nullptr; -static QLocale::NumberOptions default_number_options = QLocale::DefaultNumberOptions; - -static const QLocaleData *const c_data = locale_data; -static QLocalePrivate *c_private() -{ - static QLocalePrivate c_locale = { c_data, Q_BASIC_ATOMIC_INITIALIZER(1), QLocale::OmitGroupSeparator }; - return &c_locale; -} - -#ifndef QT_NO_SYSTEMLOCALE -/****************************************************************************** -** Default system locale behavior -*/ - -/*! - Constructs a QSystemLocale object. - - The constructor will automatically install this object as the system locale, - if there's not one active. It also resets the flag that'll prompt - QLocale::system() to re-initialize its data, so that instantiating a - QSystemLocale transiently (doesn't install the transient as system locale if - there was one already and) triggers an update to the system locale's data. -*/ -QSystemLocale::QSystemLocale() -{ - if (!_systemLocale) - _systemLocale = this; - - globalLocaleData.m_language_id = 0; -} - -/*! - \internal -*/ -QSystemLocale::QSystemLocale(bool) -{ } - -/*! - Deletes the object. -*/ -QSystemLocale::~QSystemLocale() -{ - if (_systemLocale == this) { - _systemLocale = 0; - - globalLocaleData.m_language_id = 0; - } -} - -static const QSystemLocale *systemLocale() -{ - if (_systemLocale) - return _systemLocale; - return QSystemLocale_globalSystemLocale(); -} - -static void updateSystemPrivate() -{ - // This function is NOT thread-safe! - // It *should not* be called by anything but systemData() - const QSystemLocale *sys_locale = systemLocale(); - - // tell the object that the system locale has changed. - sys_locale->query(QSystemLocale::LocaleChanged, QVariant()); - - // Populate global with fallback as basis: - globalLocaleData = *sys_locale->fallbackUiLocaleData(); - - QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant()); - if (!res.isNull()) { - globalLocaleData.m_language_id = res.toInt(); - globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility - } - res = sys_locale->query(QSystemLocale::CountryId, QVariant()); - if (!res.isNull()) { - globalLocaleData.m_country_id = res.toInt(); - globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility - } - res = sys_locale->query(QSystemLocale::ScriptId, QVariant()); - if (!res.isNull()) - globalLocaleData.m_script_id = res.toInt(); - - res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant()); - if (!res.isNull()) - globalLocaleData.m_decimal = res.toString().at(0).unicode(); - - res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant()); - if (!res.isNull()) - globalLocaleData.m_group = res.toString().at(0).unicode(); - - res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant()); - if (!res.isNull()) - globalLocaleData.m_zero = res.toString().at(0).unicode(); - - res = sys_locale->query(QSystemLocale::NegativeSign, QVariant()); - if (!res.isNull()) - globalLocaleData.m_minus = res.toString().at(0).unicode(); - - res = sys_locale->query(QSystemLocale::PositiveSign, QVariant()); - if (!res.isNull()) - globalLocaleData.m_plus = res.toString().at(0).unicode(); -} -#endif // !QT_NO_SYSTEMLOCALE - -static const QLocaleData *systemData() -{ -#ifndef QT_NO_SYSTEMLOCALE - /* - Copy over the information from the fallback locale and modify. - - This modifies (cross-thread) global state, so take care to only call it in - one thread. - */ - { - static QBasicMutex systemDataMutex; - systemDataMutex.lock(); - if (globalLocaleData.m_language_id == 0) - updateSystemPrivate(); - systemDataMutex.unlock(); - } - - return &globalLocaleData; -#else - return locale_data; -#endif -} - -static const QLocaleData *defaultData() -{ - if (!default_data) - default_data = systemData(); - return default_data; -} - -const QLocaleData *QLocaleData::c() -{ - Q_ASSERT(locale_index[QLocale::C] == 0); - return c_data; -} - -static inline QString getLocaleData(const ushort *data, int size) -{ - return size > 0 ? QString::fromRawData(reinterpret_cast<const QChar *>(data), size) : QString(); -} - -static QString getLocaleListData(const ushort *data, int size, int index) -{ - static const ushort separator = ';'; - while (index && size > 0) { - while (*data != separator) - ++data, --size; - --index; - ++data; - --size; - } - const ushort *end = data; - while (size > 0 && *end != separator) - ++end, --size; - return getLocaleData(data, end - data); -} - - -#ifndef QT_NO_DATASTREAM -QDataStream &operator<<(QDataStream &ds, const QLocale &l) -{ - ds << l.name(); - return ds; -} - -QDataStream &operator>>(QDataStream &ds, QLocale &l) -{ - QString s; - ds >> s; - l = QLocale(s); - return ds; -} -#endif // QT_NO_DATASTREAM - - -static const int locale_data_size = sizeof(locale_data)/sizeof(QLocaleData) - 1; - -Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate, - (QLocalePrivate::create(defaultData(), default_number_options))) -Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<QLocalePrivate>, systemLocalePrivate, - (QLocalePrivate::create(systemData()))) - -static QLocalePrivate *localePrivateByName(const QString &name) -{ - if (name == QLatin1String("C")) - return c_private(); - const QLocaleData *data = findLocaleData(name); - return QLocalePrivate::create(data, data->m_language_id == QLocale::C ? - QLocale::OmitGroupSeparator : QLocale::DefaultNumberOptions); -} - -static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Script script, - QLocale::Country country) -{ - if (language == QLocale::C) - return c_private(); - - const QLocaleData *data = QLocaleData::findLocaleData(language, script, country); - - QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions; - - // If not found, should default to system - if (data->m_language_id == QLocale::C && language != QLocale::C) { - numberOptions = default_number_options; - data = defaultData(); - } - return QLocalePrivate::create(data, numberOptions); -} - - -/*! - \internal -*/ -QLocale::QLocale(QLocalePrivate &dd) - : d(&dd) -{} - - -/*! - Constructs a QLocale object with the specified \a name, - which has the format - "language[_script][_country][.codeset][@modifier]" or "C", where: - - \list - \li language is a lowercase, two-letter, ISO 639 language code (also some three-letter codes), - \li script is a titlecase, four-letter, ISO 15924 script code, - \li country is an uppercase, two-letter, ISO 3166 country code (also "419" as defined by United Nations), - \li and codeset and modifier are ignored. - \endlist - - The separator can be either underscore or a minus sign. - - If the string violates the locale format, or language is not - a valid ISO 639 code, the "C" locale is used instead. If country - is not present, or is not a valid ISO 3166 code, the most - appropriate country is chosen for the specified language. - - The language, script and country codes are converted to their respective - \c Language, \c Script and \c Country enums. After this conversion is - performed, the constructor behaves exactly like QLocale(Country, Script, - Language). - - This constructor is much slower than QLocale(Country, Script, Language). - - \sa bcp47Name() -*/ - -QLocale::QLocale(const QString &name) - : d(localePrivateByName(name)) -{ -} - -/*! - Constructs a QLocale object initialized with the default locale. If - no default locale was set using setDefault(), this locale will - be the same as the one returned by system(). - - \sa setDefault() -*/ - -QLocale::QLocale() - : d(*defaultLocalePrivate) -{ - // Make sure system data is up to date - systemData(); -} - -/*! - Constructs a QLocale object with the specified \a language and \a - country. - - \list - \li If the language/country pair is found in the database, it is used. - \li If the language is found but the country is not, or if the country - is \c AnyCountry, the language is used with the most - appropriate available country (for example, Germany for German), - \li If neither the language nor the country are found, QLocale - defaults to the default locale (see setDefault()). - \endlist - - The language and country that are actually used can be queried - using language() and country(). - - \sa setDefault(), language(), country() -*/ - -QLocale::QLocale(Language language, Country country) - : d(findLocalePrivate(language, QLocale::AnyScript, country)) -{ -} - -/*! - \since 4.8 - - Constructs a QLocale object with the specified \a language, \a script and - \a country. - - \list - \li If the language/script/country is found in the database, it is used. - \li If both \a script is AnyScript and \a country is AnyCountry, the - language is used with the most appropriate available script and country - (for example, Germany for German), - \li If either \a script is AnyScript or \a country is AnyCountry, the - language is used with the first locale that matches the given \a script - and \a country. - \li If neither the language nor the country are found, QLocale - defaults to the default locale (see setDefault()). - \endlist - - The language, script and country that are actually used can be queried - using language(), script() and country(). - - \sa setDefault(), language(), script(), country() -*/ - -QLocale::QLocale(Language language, Script script, Country country) - : d(findLocalePrivate(language, script, country)) -{ -} - -/*! - Constructs a QLocale object as a copy of \a other. -*/ - -QLocale::QLocale(const QLocale &other) -{ - d = other.d; -} - -/*! - Destructor -*/ - -QLocale::~QLocale() -{ -} - -/*! - Assigns \a other to this QLocale object and returns a reference - to this QLocale object. -*/ - -QLocale &QLocale::operator=(const QLocale &other) -{ - d = other.d; - return *this; -} - -bool QLocale::operator==(const QLocale &other) const -{ - return d->m_data == other.d->m_data && d->m_numberOptions == other.d->m_numberOptions; -} - -bool QLocale::operator!=(const QLocale &other) const -{ - return d->m_data != other.d->m_data || d->m_numberOptions != other.d->m_numberOptions; -} - -/*! - \fn void QLocale::swap(QLocale &other) - \since 5.6 - - Swaps locale \a other with this locale. This operation is very fast and - never fails. -*/ - -/*! - \since 5.6 - \relates QLocale - - Returns the hash value for \a key, using - \a seed to seed the calculation. -*/ -uint qHash(const QLocale &key, uint seed) noexcept -{ - QtPrivate::QHashCombine hash; - seed = hash(seed, key.d->m_data); - seed = hash(seed, key.d->m_numberOptions); - return seed; -} - -/*! - \since 4.2 - - Sets the \a options related to number conversions for this - QLocale instance. -*/ -void QLocale::setNumberOptions(NumberOptions options) -{ - d->m_numberOptions = options; -} - -/*! - \since 4.2 - - Returns the options related to number conversions for this - QLocale instance. - - By default, no options are set for the standard locales. -*/ -QLocale::NumberOptions QLocale::numberOptions() const -{ - return static_cast<NumberOptions>(d->m_numberOptions); -} - -/*! - \since 4.8 - - Returns \a str quoted according to the current locale using the given - quotation \a style. -*/ -QString QLocale::quoteString(const QString &str, QuotationStyle style) const -{ - return quoteString(QStringRef(&str), style); -} - -/*! - \since 4.8 - - \overload -*/ -QString QLocale::quoteString(const QStringRef &str, QuotationStyle style) const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res; - if (style == QLocale::AlternateQuotation) - res = systemLocale()->query(QSystemLocale::StringToAlternateQuotation, QVariant::fromValue(str)); - if (res.isNull() || style == QLocale::StandardQuotation) - res = systemLocale()->query(QSystemLocale::StringToStandardQuotation, QVariant::fromValue(str)); - if (!res.isNull()) - return res.toString(); - } -#endif - - if (style == QLocale::StandardQuotation) - return QChar(d->m_data->m_quotation_start) % str % QChar(d->m_data->m_quotation_end); - else - return QChar(d->m_data->m_alternate_quotation_start) % str % QChar(d->m_data->m_alternate_quotation_end); -} - -/*! - \since 4.8 - - Returns a string that represents a join of a given \a list of strings with - a separator defined by the locale. -*/ -QString QLocale::createSeparatedList(const QStringList &list) const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res; - res = systemLocale()->query(QSystemLocale::ListToSeparatedString, QVariant::fromValue(list)); - - if (!res.isNull()) - return res.toString(); - } -#endif - - const int size = list.size(); - if (size == 1) { - return list.at(0); - } else if (size == 2) { - QString format = getLocaleData(list_pattern_part_data + d->m_data->m_list_pattern_part_two_idx, d->m_data->m_list_pattern_part_two_size); - return format.arg(list.at(0), list.at(1)); - } else if (size > 2) { - QString formatStart = getLocaleData(list_pattern_part_data + d->m_data->m_list_pattern_part_start_idx, d->m_data->m_list_pattern_part_start_size); - QString formatMid = getLocaleData(list_pattern_part_data + d->m_data->m_list_pattern_part_mid_idx, d->m_data->m_list_pattern_part_mid_size); - QString formatEnd = getLocaleData(list_pattern_part_data + d->m_data->m_list_pattern_part_end_idx, d->m_data->m_list_pattern_part_end_size); - QString result = formatStart.arg(list.at(0), list.at(1)); - for (int i = 2; i < size - 1; ++i) - result = formatMid.arg(result, list.at(i)); - result = formatEnd.arg(result, list.at(size - 1)); - return result; - } - - return QString(); -} - -/*! - \nonreentrant - - Sets the global default locale to \a locale. These - values are used when a QLocale object is constructed with - no arguments. If this function is not called, the system's - locale is used. - - \warning In a multithreaded application, the default locale - should be set at application startup, before any non-GUI threads - are created. - - \sa system(), c() -*/ - -void QLocale::setDefault(const QLocale &locale) -{ - default_data = locale.d->m_data; - default_number_options = locale.numberOptions(); - - if (defaultLocalePrivate.exists()) { - // update the cached private - *defaultLocalePrivate = locale.d; - } -} - -/*! - Returns the language of this locale. - - \sa script(), country(), languageToString(), bcp47Name() -*/ -QLocale::Language QLocale::language() const -{ - return Language(d->languageId()); -} - -/*! - \since 4.8 - - Returns the script of this locale. - - \sa language(), country(), languageToString(), scriptToString(), bcp47Name() -*/ -QLocale::Script QLocale::script() const -{ - return Script(d->m_data->m_script_id); -} - -/*! - Returns the country of this locale. - - \sa language(), script(), countryToString(), bcp47Name() -*/ -QLocale::Country QLocale::country() const -{ - return Country(d->countryId()); -} - -/*! - Returns the language and country of this locale as a - string of the form "language_country", where - language is a lowercase, two-letter ISO 639 language code, - and country is an uppercase, two- or three-letter ISO 3166 country code. - - Note that even if QLocale object was constructed with an explicit script, - name() will not contain it for compatibility reasons. Use bcp47Name() instead - if you need a full locale name. - - \sa QLocale(), language(), script(), country(), bcp47Name() -*/ - -QString QLocale::name() const -{ - Language l = language(); - if (l == C) - return d->languageCode(); - - Country c = country(); - if (c == AnyCountry) - return d->languageCode(); - - return d->languageCode() + QLatin1Char('_') + d->countryCode(); -} - -static qlonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok, - QLocale::NumberOptions mode, qlonglong) -{ - return d->stringToLongLong(str, 10, ok, mode); -} - -static qulonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok, - QLocale::NumberOptions mode, qulonglong) -{ - return d->stringToUnsLongLong(str, 10, ok, mode); -} - -template <typename T> static inline -T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok) -{ - using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type; - - // we select the right overload by the last, unused parameter - Int64 val = toIntegral_helper(d->m_data, str, ok, d->m_numberOptions, Int64()); - if (T(val) != val) { - if (ok != nullptr) - *ok = false; - val = 0; - } - return T(val); -} - - -/*! - \since 4.8 - - Returns the dash-separated language, script and country (and possibly other BCP47 fields) - of this locale as a string. - - Unlike the uiLanguages() the returned value of the bcp47Name() represents - the locale name of the QLocale data but not the language the user-interface - should be in. - - This function tries to conform the locale name to BCP47. - - \sa language(), country(), script(), uiLanguages() -*/ -QString QLocale::bcp47Name() const -{ - return QString::fromLatin1(d->bcp47Name()); -} - -/*! - Returns a QString containing the name of \a language. - - \sa countryToString(), scriptToString(), bcp47Name() -*/ - -QString QLocale::languageToString(Language language) -{ - if (uint(language) > uint(QLocale::LastLanguage)) - return QLatin1String("Unknown"); - return QLatin1String(language_name_list + language_name_index[language]); -} - -/*! - Returns a QString containing the name of \a country. - - \sa languageToString(), scriptToString(), country(), bcp47Name() -*/ - -QString QLocale::countryToString(Country country) -{ - if (uint(country) > uint(QLocale::LastCountry)) - return QLatin1String("Unknown"); - return QLatin1String(country_name_list + country_name_index[country]); -} - -/*! - \since 4.8 - - Returns a QString containing the name of \a script. - - \sa languageToString(), countryToString(), script(), bcp47Name() -*/ -QString QLocale::scriptToString(QLocale::Script script) -{ - if (uint(script) > uint(QLocale::LastScript)) - return QLatin1String("Unknown"); - return QLatin1String(script_name_list + script_name_index[script]); -} - -#if QT_STRINGVIEW_LEVEL < 2 -/*! - Returns the short int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toUShort(), toString() -*/ - -short QLocale::toShort(const QString &s, bool *ok) const -{ - return toIntegral_helper<short>(d, s, ok); -} - -/*! - Returns the unsigned short int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toShort(), toString() -*/ - -ushort QLocale::toUShort(const QString &s, bool *ok) const -{ - return toIntegral_helper<ushort>(d, s, ok); -} - -/*! - Returns the int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toUInt(), toString() -*/ - -int QLocale::toInt(const QString &s, bool *ok) const -{ - return toIntegral_helper<int>(d, s, ok); -} - -/*! - Returns the unsigned int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toInt(), toString() -*/ - -uint QLocale::toUInt(const QString &s, bool *ok) const -{ - return toIntegral_helper<uint>(d, s, ok); -} - -/*! - Returns the long int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toInt(), toULong(), toDouble(), toString() - - \since 5.13 - */ - - -long QLocale::toLong(const QString &s, bool *ok) const -{ - return toIntegral_helper<long>(d, s, ok); -} - -/*! - Returns the unsigned long int represented by the localized - string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toLong(), toInt(), toDouble(), toString() - - \since 5.13 -*/ - -ulong QLocale::toULong(const QString &s, bool *ok) const -{ - return toIntegral_helper<ulong>(d, s, ok); -} - -/*! - Returns the long long int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toInt(), toULongLong(), toDouble(), toString() -*/ - - -qlonglong QLocale::toLongLong(const QString &s, bool *ok) const -{ - return toIntegral_helper<qlonglong>(d, s, ok); -} - -/*! - Returns the unsigned long long int represented by the localized - string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toLongLong(), toInt(), toDouble(), toString() -*/ - -qulonglong QLocale::toULongLong(const QString &s, bool *ok) const -{ - return toIntegral_helper<qulonglong>(d, s, ok); -} - -/*! - Returns the float represented by the localized string \a s. - - Returns an infinity if the conversion overflows or 0.0 if the - conversion fails for any other reason (e.g. underflow). - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function does not fall back to the 'C' locale if the string - cannot be interpreted in this locale. - - This function ignores leading and trailing whitespace. - - \sa toDouble(), toInt(), toString() -*/ - -float QLocale::toFloat(const QString &s, bool *ok) const -{ - return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok); -} - -/*! - Returns the double represented by the localized string \a s. - - Returns an infinity if the conversion overflows or 0.0 if the - conversion fails for any other reason (e.g. underflow). - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function does not fall back to the 'C' locale if the string - cannot be interpreted in this locale. - - \snippet code/src_corelib_tools_qlocale.cpp 3 - - Notice that the last conversion returns 1234.0, because '.' is the - thousands group separator in the German locale. - - This function ignores leading and trailing whitespace. - - \sa toFloat(), toInt(), toString() -*/ - -double QLocale::toDouble(const QString &s, bool *ok) const -{ - return d->m_data->stringToDouble(s, ok, d->m_numberOptions); -} - -/*! - Returns the short int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toUShort(), toString() - - \since 5.1 -*/ - -short QLocale::toShort(const QStringRef &s, bool *ok) const -{ - return toIntegral_helper<short>(d, s, ok); -} - -/*! - Returns the unsigned short int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toShort(), toString() - - \since 5.1 -*/ - -ushort QLocale::toUShort(const QStringRef &s, bool *ok) const -{ - return toIntegral_helper<ushort>(d, s, ok); -} - -/*! - Returns the int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toUInt(), toString() - - \since 5.1 -*/ - -int QLocale::toInt(const QStringRef &s, bool *ok) const -{ - return toIntegral_helper<int>(d, s, ok); -} - -/*! - Returns the unsigned int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toInt(), toString() - - \since 5.1 -*/ - -uint QLocale::toUInt(const QStringRef &s, bool *ok) const -{ - return toIntegral_helper<uint>(d, s, ok); -} - -/*! - Returns the long int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toInt(), toULong(), toDouble(), toString() - - \since 5.13 - */ - - -long QLocale::toLong(const QStringRef &s, bool *ok) const -{ - return toIntegral_helper<long>(d, s, ok); -} - -/*! - Returns the unsigned long int represented by the localized - string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toLong(), toInt(), toDouble(), toString() - - \since 5.13 - */ - -ulong QLocale::toULong(const QStringRef &s, bool *ok) const -{ - return toIntegral_helper<ulong>(d, s, ok); -} - -/*! - Returns the long long int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toInt(), toULongLong(), toDouble(), toString() - - \since 5.1 -*/ - - -qlonglong QLocale::toLongLong(const QStringRef &s, bool *ok) const -{ - return toIntegral_helper<qlonglong>(d, s, ok); -} - -/*! - Returns the unsigned long long int represented by the localized - string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toLongLong(), toInt(), toDouble(), toString() - - \since 5.1 -*/ - -qulonglong QLocale::toULongLong(const QStringRef &s, bool *ok) const -{ - return toIntegral_helper<qulonglong>(d, s, ok); -} - -/*! - Returns the float represented by the localized string \a s. - - Returns an infinity if the conversion overflows or 0.0 if the - conversion fails for any other reason (e.g. underflow). - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function does not fall back to the 'C' locale if the string - cannot be interpreted in this locale. - - This function ignores leading and trailing whitespace. - - \sa toDouble(), toInt(), toString() - - \since 5.1 -*/ - -float QLocale::toFloat(const QStringRef &s, bool *ok) const -{ - return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok); -} - -/*! - Returns the double represented by the localized string \a s. - - Returns an infinity if the conversion overflows or 0.0 if the - conversion fails for any other reason (e.g. underflow). - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function does not fall back to the 'C' locale if the string - cannot be interpreted in this locale. - - \snippet code/src_corelib_tools_qlocale.cpp 3 - - Notice that the last conversion returns 1234.0, because '.' is the - thousands group separator in the German locale. - - This function ignores leading and trailing whitespace. - - \sa toFloat(), toInt(), toString() - - \since 5.1 -*/ - -double QLocale::toDouble(const QStringRef &s, bool *ok) const -{ - return d->m_data->stringToDouble(s, ok, d->m_numberOptions); -} -#endif // QT_STRINGVIEW_LEVEL < 2 - -/*! - Returns the short int represented by the localized string \a s. - - If the conversion fails, the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toUShort(), toString() - - \since 5.10 -*/ - -short QLocale::toShort(QStringView s, bool *ok) const -{ - return toIntegral_helper<short>(d, s, ok); -} - -/*! - Returns the unsigned short int represented by the localized string \a s. - - If the conversion fails, the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toShort(), toString() - - \since 5.10 -*/ - -ushort QLocale::toUShort(QStringView s, bool *ok) const -{ - return toIntegral_helper<ushort>(d, s, ok); -} - -/*! - Returns the int represented by the localized string \a s. - - If the conversion fails, the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toUInt(), toString() - - \since 5.10 -*/ - -int QLocale::toInt(QStringView s, bool *ok) const -{ - return toIntegral_helper<int>(d, s, ok); -} - -/*! - Returns the unsigned int represented by the localized string \a s. - - If the conversion fails, the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toInt(), toString() - - \since 5.10 -*/ - -uint QLocale::toUInt(QStringView s, bool *ok) const -{ - return toIntegral_helper<uint>(d, s, ok); -} - -/*! - Returns the long int represented by the localized string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toInt(), toULong(), toDouble(), toString() - - \since 5.13 - */ - - -long QLocale::toLong(QStringView s, bool *ok) const -{ - return toIntegral_helper<long>(d, s, ok); -} - -/*! - Returns the unsigned long int represented by the localized - string \a s. - - If the conversion fails the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toLong(), toInt(), toDouble(), toString() - - \since 5.13 - */ - -ulong QLocale::toULong(QStringView s, bool *ok) const -{ - return toIntegral_helper<ulong>(d, s, ok); -} - -/*! - Returns the long long int represented by the localized string \a s. - - If the conversion fails, the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toInt(), toULongLong(), toDouble(), toString() - - \since 5.10 -*/ - - -qlonglong QLocale::toLongLong(QStringView s, bool *ok) const -{ - return toIntegral_helper<qlonglong>(d, s, ok); -} - -/*! - Returns the unsigned long long int represented by the localized - string \a s. - - If the conversion fails, the function returns 0. - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toLongLong(), toInt(), toDouble(), toString() - - \since 5.10 -*/ - -qulonglong QLocale::toULongLong(QStringView s, bool *ok) const -{ - return toIntegral_helper<qulonglong>(d, s, ok); -} - -/*! - Returns the float represented by the localized string \a s. - - Returns an infinity if the conversion overflows or 0.0 if the - conversion fails for any other reason (e.g. underflow). - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - This function ignores leading and trailing whitespace. - - \sa toDouble(), toInt(), toString() - - \since 5.10 -*/ - -float QLocale::toFloat(QStringView s, bool *ok) const -{ - return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok); -} - -/*! - Returns the double represented by the localized string \a s. - - Returns an infinity if the conversion overflows or 0.0 if the - conversion fails for any other reason (e.g. underflow). - - If \a ok is not \nullptr, failure is reported by setting *\a{ok} - to \c false, and success by setting *\a{ok} to \c true. - - Unlike QString::toDouble(), this function does not fall back to - the "C" locale if the string cannot be interpreted in this - locale. - - \snippet code/src_corelib_tools_qlocale.cpp 3-qstringview - - Notice that the last conversion returns 1234.0, because '.' is the - thousands group separator in the German locale. - - This function ignores leading and trailing whitespace. - - \sa toFloat(), toInt(), toString() - - \since 5.10 -*/ - -double QLocale::toDouble(QStringView s, bool *ok) const -{ - return d->m_data->stringToDouble(s, ok, d->m_numberOptions); -} - -/*! - Returns a localized string representation of \a i. - - \sa toLongLong() -*/ - -QString QLocale::toString(qlonglong i) const -{ - int flags = d->m_numberOptions & OmitGroupSeparator - ? 0 - : QLocaleData::ThousandsGroup; - - return d->m_data->longLongToString(i, -1, 10, -1, flags); -} - -/*! - \overload - - \sa toULongLong() -*/ - -QString QLocale::toString(qulonglong i) const -{ - int flags = d->m_numberOptions & OmitGroupSeparator - ? 0 - : QLocaleData::ThousandsGroup; - - return d->m_data->unsLongLongToString(i, -1, 10, -1, flags); -} - -#if QT_STRINGVIEW_LEVEL < 2 -/*! - Returns a localized string representation of the given \a date in the - specified \a format. - If \a format is an empty string, an empty string is returned. - - \sa QDate::toString() -*/ - -QString QLocale::toString(const QDate &date, const QString &format) const -{ - return d->dateTimeToString(format, QDateTime(), date, QTime(), this); -} -#endif - -/*! - \since 5.10 - - Returns a localized string representation of the given \a date in the - specified \a format. - If \a format is an empty string, an empty string is returned. - - \sa QDate::toString() -*/ -QString QLocale::toString(const QDate &date, QStringView format) const -{ - return d->dateTimeToString(format, QDateTime(), date, QTime(), this); -} - -/*! - Returns a localized string representation of the given \a date according - to the specified \a format. -*/ - -QString QLocale::toString(const QDate &date, FormatType format) const -{ - if (!date.isValid()) - return QString(); - -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::DateToStringLong : QSystemLocale::DateToStringShort, - date); - if (!res.isNull()) - return res.toString(); - } -#endif - - QString format_str = dateFormat(format); - return toString(date, format_str); -} - -static bool timeFormatContainsAP(QStringView format) -{ - int i = 0; - while (i < format.size()) { - if (format.at(i).unicode() == '\'') { - qt_readEscapedFormatString(format, &i); - continue; - } - - if (format.at(i).toLower().unicode() == 'a') - return true; - - ++i; - } - return false; -} - -#if QT_STRINGVIEW_LEVEL < 2 -/*! - Returns a localized string representation of the given \a time according - to the specified \a format. - If \a format is an empty string, an empty string is returned. - - \sa QTime::toString() -*/ -QString QLocale::toString(const QTime &time, const QString &format) const -{ - return d->dateTimeToString(format, QDateTime(), QDate(), time, this); -} -#endif - -/*! - \since 5.10 - - Returns a localized string representation of the given \a time according - to the specified \a format. - If \a format is an empty string, an empty string is returned. - - \sa QTime::toString() -*/ -QString QLocale::toString(const QTime &time, QStringView format) const -{ - return d->dateTimeToString(format, QDateTime(), QDate(), time, this); -} - -#if QT_STRINGVIEW_LEVEL < 2 -/*! - \since 4.4 - - Returns a localized string representation of the given \a dateTime according - to the specified \a format. - If \a format is an empty string, an empty string is returned. - - \sa QDateTime::toString(), QDate::toString(), QTime::toString() -*/ - -QString QLocale::toString(const QDateTime &dateTime, const QString &format) const -{ - return d->dateTimeToString(format, dateTime, QDate(), QTime(), this); -} -#endif - -/*! - \since 5.10 - - Returns a localized string representation of the given \a dateTime according - to the specified \a format. - If \a format is an empty string, an empty string is returned. - - \sa QDateTime::toString(), QDate::toString(), QTime::toString() -*/ -QString QLocale::toString(const QDateTime &dateTime, QStringView format) const -{ - return d->dateTimeToString(format, dateTime, QDate(), QTime(), this); -} - -/*! - \since 4.4 - - Returns a localized string representation of the given \a dateTime according - to the specified \a format. -*/ - -QString QLocale::toString(const QDateTime &dateTime, FormatType format) const -{ - if (!dateTime.isValid()) - return QString(); - -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::DateTimeToStringLong - : QSystemLocale::DateTimeToStringShort, - dateTime); - if (!res.isNull()) - return res.toString(); - } -#endif - - const QString format_str = dateTimeFormat(format); - return toString(dateTime, format_str); -} - - -/*! - Returns a localized string representation of the given \a time in the - specified \a format. -*/ - -QString QLocale::toString(const QTime &time, FormatType format) const -{ - if (!time.isValid()) - return QString(); - -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::TimeToStringLong : QSystemLocale::TimeToStringShort, - time); - if (!res.isNull()) - return res.toString(); - } -#endif - - QString format_str = timeFormat(format); - return toString(time, format_str); -} - -/*! - \since 4.1 - - Returns the date format used for the current locale. - - If \a format is LongFormat the format will be a long version. - Otherwise it uses a shorter version. - - \sa QDate::toString(), QDate::fromString() -*/ - -QString QLocale::dateFormat(FormatType format) const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::DateFormatLong : QSystemLocale::DateFormatShort, - QVariant()); - if (!res.isNull()) - return res.toString(); - } -#endif - - quint32 idx, size; - switch (format) { - case LongFormat: - idx = d->m_data->m_long_date_format_idx; - size = d->m_data->m_long_date_format_size; - break; - default: - idx = d->m_data->m_short_date_format_idx; - size = d->m_data->m_short_date_format_size; - break; - } - return getLocaleData(date_format_data + idx, size); -} - -/*! - \since 4.1 - - Returns the time format used for the current locale. - - If \a format is LongFormat the format will be a long version. - Otherwise it uses a shorter version. - - \sa QTime::toString(), QTime::fromString() -*/ - -QString QLocale::timeFormat(FormatType format) const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::TimeFormatLong : QSystemLocale::TimeFormatShort, - QVariant()); - if (!res.isNull()) - return res.toString(); - } -#endif - - quint32 idx, size; - switch (format) { - case LongFormat: - idx = d->m_data->m_long_time_format_idx; - size = d->m_data->m_long_time_format_size; - break; - default: - idx = d->m_data->m_short_time_format_idx; - size = d->m_data->m_short_time_format_size; - break; - } - return getLocaleData(time_format_data + idx, size); -} - -/*! - \since 4.4 - - Returns the date time format used for the current locale. - - If \a format is ShortFormat the format will be a short version. - Otherwise it uses a longer version. - - \sa QDateTime::toString(), QDateTime::fromString() -*/ - -QString QLocale::dateTimeFormat(FormatType format) const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::DateTimeFormatLong - : QSystemLocale::DateTimeFormatShort, - QVariant()); - if (!res.isNull()) { - return res.toString(); - } - } -#endif - return dateFormat(format) + QLatin1Char(' ') + timeFormat(format); -} - -/*! - \since 4.4 - - Parses the time string given in \a string and returns the - time. The format of the time string is chosen according to the - \a format parameter (see timeFormat()). - - If the time could not be parsed, returns an invalid time. - - \sa timeFormat(), toDate(), toDateTime(), QTime::fromString() -*/ -#if QT_CONFIG(datestring) -QTime QLocale::toTime(const QString &string, FormatType format) const -{ - return toTime(string, timeFormat(format)); -} -#endif - -/*! - \since 4.4 - - Parses the date string given in \a string and returns the - date. The format of the date string is chosen according to the - \a format parameter (see dateFormat()). - - If the date could not be parsed, returns an invalid date. - - \sa dateFormat(), toTime(), toDateTime(), QDate::fromString() -*/ -#if QT_CONFIG(datestring) -QDate QLocale::toDate(const QString &string, FormatType format) const -{ - return toDate(string, dateFormat(format)); -} -#endif - -/*! - \since 4.4 - - Parses the date/time string given in \a string and returns the - time. The format of the date/time string is chosen according to the - \a format parameter (see dateTimeFormat()). - - If the string could not be parsed, returns an invalid QDateTime. - - \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString() -*/ - -#if QT_CONFIG(datestring) -QDateTime QLocale::toDateTime(const QString &string, FormatType format) const -{ - return toDateTime(string, dateTimeFormat(format)); -} -#endif - -/*! - \since 4.4 - - Parses the time string given in \a string and returns the - time. See QTime::fromString() for information on what is a valid - format string. - - If the time could not be parsed, returns an invalid time. - - \sa timeFormat(), toDate(), toDateTime(), QTime::fromString() -*/ -#if QT_CONFIG(datestring) -QTime QLocale::toTime(const QString &string, const QString &format) const -{ - QTime time; -#if QT_CONFIG(datetimeparser) - QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString); - dt.setDefaultLocale(*this); - if (dt.parseFormat(format)) - dt.fromString(string, 0, &time); -#else - Q_UNUSED(string); - Q_UNUSED(format); -#endif - return time; -} -#endif - -/*! - \since 4.4 - - Parses the date string given in \a string and returns the - date. See QDate::fromString() for information on the expressions - that can be used with this function. - - This function searches month names and the names of the days of - the week in the current locale. - - If the date could not be parsed, returns an invalid date. - - \sa dateFormat(), toTime(), toDateTime(), QDate::fromString() -*/ -#if QT_CONFIG(datestring) -QDate QLocale::toDate(const QString &string, const QString &format) const -{ - QDate date; -#if QT_CONFIG(datetimeparser) - QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString); - dt.setDefaultLocale(*this); - if (dt.parseFormat(format)) - dt.fromString(string, &date, 0); -#else - Q_UNUSED(string); - Q_UNUSED(format); -#endif - return date; -} -#endif - -/*! - \since 4.4 - - Parses the date/time string given in \a string and returns the - time. See QDateTime::fromString() for information on the expressions - that can be used with this function. - - \note The month and day names used must be given in the user's local - language. - - If the string could not be parsed, returns an invalid QDateTime. - - \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString() -*/ -#if QT_CONFIG(datestring) -QDateTime QLocale::toDateTime(const QString &string, const QString &format) const -{ -#if QT_CONFIG(datetimeparser) - QTime time; - QDate date; - - QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString); - dt.setDefaultLocale(*this); - if (dt.parseFormat(format) && dt.fromString(string, &date, &time)) - return QDateTime(date, time); -#else - Q_UNUSED(string); - Q_UNUSED(format); -#endif - return QDateTime(QDate(), QTime(-1, -1, -1)); -} -#endif - - -/*! - \since 4.1 - - Returns the decimal point character of this locale. -*/ -QChar QLocale::decimalPoint() const -{ - return d->decimal(); -} - -/*! - \since 4.1 - - Returns the group separator character of this locale. -*/ -QChar QLocale::groupSeparator() const -{ - return d->group(); -} - -/*! - \since 4.1 - - Returns the percent character of this locale. -*/ -QChar QLocale::percent() const -{ - return d->percent(); -} - -/*! - \since 4.1 - - Returns the zero digit character of this locale. -*/ -QChar QLocale::zeroDigit() const -{ - return d->zero(); -} - -/*! - \since 4.1 - - Returns the negative sign character of this locale. -*/ -QChar QLocale::negativeSign() const -{ - return d->minus(); -} - -/*! - \since 4.5 - - Returns the positive sign character of this locale. -*/ -QChar QLocale::positiveSign() const -{ - return d->plus(); -} - -/*! - \since 4.1 - - Returns the exponential character of this locale. -*/ -QChar QLocale::exponential() const -{ - return d->exponential(); -} - -static bool qIsUpper(char c) -{ - return c >= 'A' && c <= 'Z'; -} - -static char qToLower(char c) -{ - if (c >= 'A' && c <= 'Z') - return c - 'A' + 'a'; - else - return c; -} - -/*! - \overload - - \a f and \a prec have the same meaning as in QString::number(double, char, int). - - \sa toDouble() -*/ - -QString QLocale::toString(double i, char f, int prec) const -{ - QLocaleData::DoubleForm form = QLocaleData::DFDecimal; - uint flags = 0; - - if (qIsUpper(f)) - flags = QLocaleData::CapitalEorX; - f = qToLower(f); - - switch (f) { - case 'f': - form = QLocaleData::DFDecimal; - break; - case 'e': - form = QLocaleData::DFExponent; - break; - case 'g': - form = QLocaleData::DFSignificantDigits; - break; - default: - break; - } - - if (!(d->m_numberOptions & OmitGroupSeparator)) - flags |= QLocaleData::ThousandsGroup; - if (!(d->m_numberOptions & OmitLeadingZeroInExponent)) - flags |= QLocaleData::ZeroPadExponent; - if (d->m_numberOptions & IncludeTrailingZeroesAfterDot) - flags |= QLocaleData::AddTrailingZeroes; - return d->m_data->doubleToString(i, prec, form, -1, flags); -} - -/*! - \fn QLocale QLocale::c() - - Returns a QLocale object initialized to the "C" locale. - - This locale is based on en_US but with various quirks of its own, such as - simplified number formatting and its own date formatting. It implements the - POSIX standards that describe the behavior of standard library functions of - the "C" programming language. - - Among other things, this means its collation order is based on the ASCII - values of letters, so that (for case-sensitive sorting) all upper-case - letters sort before any lower-case one (rather than each letter's upper- and - lower-case forms sorting adjacent to one another, before the next letter's - two forms). - - \sa system() -*/ - -/*! - Returns a QLocale object initialized to the system locale. - - On Windows and Mac, this locale will use the decimal/grouping characters and date/time - formats specified in the system configuration panel. - - \sa c() -*/ - -QLocale QLocale::system() -{ - QT_PREPEND_NAMESPACE(systemData)(); // trigger updating of the system data if necessary - if (systemLocalePrivate.isDestroyed()) - return QLocale(QLocale::C); - return QLocale(*systemLocalePrivate->data()); -} - - -/*! - \since 4.8 - - Returns a list of valid locale objects that match the given \a language, \a - script and \a country. - - Getting a list of all locales: - QList<QLocale> allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry); - - Getting a list of locales suitable for Russia: - QList<QLocale> locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::Russia); -*/ -QList<QLocale> QLocale::matchingLocales(QLocale::Language language, - QLocale::Script script, - QLocale::Country country) -{ - if (uint(language) > QLocale::LastLanguage || uint(script) > QLocale::LastScript || - uint(country) > QLocale::LastCountry) - return QList<QLocale>(); - - if (language == QLocale::C) - return QList<QLocale>() << QLocale(QLocale::C); - - QList<QLocale> result; - if (language == QLocale::AnyLanguage && script == QLocale::AnyScript && country == QLocale::AnyCountry) - result.reserve(locale_data_size); - const QLocaleData *data = locale_data + locale_index[language]; - while ( (data != locale_data + locale_data_size) - && (language == QLocale::AnyLanguage || data->m_language_id == uint(language))) { - if ((script == QLocale::AnyScript || data->m_script_id == uint(script)) - && (country == QLocale::AnyCountry || data->m_country_id == uint(country))) { - result.append(QLocale(*(data->m_language_id == C ? c_private() - : QLocalePrivate::create(data)))); - } - ++data; - } - return result; -} - -/*! - \obsolete - \since 4.3 - - Returns the list of countries that have entries for \a language in Qt's locale - database. If the result is an empty list, then \a language is not represented in - Qt's locale database. - - \sa matchingLocales() -*/ -QList<QLocale::Country> QLocale::countriesForLanguage(Language language) -{ - QList<Country> result; - if (language == C) { - result << AnyCountry; - return result; - } - - unsigned language_id = language; - const QLocaleData *data = locale_data + locale_index[language_id]; - while (data->m_language_id == language_id) { - const QLocale::Country country = static_cast<Country>(data->m_country_id); - if (!result.contains(country)) - result.append(country); - ++data; - } - - return result; -} - -/*! - \since 4.2 - - Returns the localized name of \a month, in the format specified - by \a type. - - \sa dayName(), standaloneMonthName() -*/ -QString QLocale::monthName(int month, FormatType type) const -{ - if (month < 1 || month > 12) - return QString(); - -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(type == LongFormat - ? QSystemLocale::MonthNameLong : QSystemLocale::MonthNameShort, - month); - if (!res.isNull()) - return res.toString(); - } -#endif - - quint32 idx, size; - switch (type) { - case QLocale::LongFormat: - idx = d->m_data->m_long_month_names_idx; - size = d->m_data->m_long_month_names_size; - break; - case QLocale::ShortFormat: - idx = d->m_data->m_short_month_names_idx; - size = d->m_data->m_short_month_names_size; - break; - case QLocale::NarrowFormat: - idx = d->m_data->m_narrow_month_names_idx; - size = d->m_data->m_narrow_month_names_size; - break; - default: - return QString(); - } - return getLocaleListData(months_data + idx, size, month - 1); -} - -/*! - \since 4.5 - - Returns the localized name of \a month that is used as a - standalone text, in the format specified by \a type. - - If the locale information doesn't specify the standalone month - name then return value is the same as in monthName(). - - \sa monthName(), standaloneDayName() -*/ -QString QLocale::standaloneMonthName(int month, FormatType type) const -{ - if (month < 1 || month > 12) - return QString(); - -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(type == LongFormat - ? QSystemLocale::StandaloneMonthNameLong : QSystemLocale::StandaloneMonthNameShort, - month); - if (!res.isNull()) - return res.toString(); - } -#endif - - quint32 idx, size; - switch (type) { - case QLocale::LongFormat: - idx = d->m_data->m_standalone_long_month_names_idx; - size = d->m_data->m_standalone_long_month_names_size; - break; - case QLocale::ShortFormat: - idx = d->m_data->m_standalone_short_month_names_idx; - size = d->m_data->m_standalone_short_month_names_size; - break; - case QLocale::NarrowFormat: - idx = d->m_data->m_standalone_narrow_month_names_idx; - size = d->m_data->m_standalone_narrow_month_names_size; - break; - default: - return QString(); - } - QString name = getLocaleListData(months_data + idx, size, month - 1); - if (name.isEmpty()) - return monthName(month, type); - return name; -} - -/*! - \since 4.2 - - Returns the localized name of the \a day (where 1 represents - Monday, 2 represents Tuesday and so on), in the format specified - by \a type. - - \sa monthName(), standaloneDayName() -*/ -QString QLocale::dayName(int day, FormatType type) const -{ - if (day < 1 || day > 7) - return QString(); - -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(type == LongFormat - ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort, - day); - if (!res.isNull()) - return res.toString(); - } -#endif - if (day == 7) - day = 0; - - quint32 idx, size; - switch (type) { - case QLocale::LongFormat: - idx = d->m_data->m_long_day_names_idx; - size = d->m_data->m_long_day_names_size; - break; - case QLocale::ShortFormat: - idx = d->m_data->m_short_day_names_idx; - size = d->m_data->m_short_day_names_size; - break; - case QLocale::NarrowFormat: - idx = d->m_data->m_narrow_day_names_idx; - size = d->m_data->m_narrow_day_names_size; - break; - default: - return QString(); - } - return getLocaleListData(days_data + idx, size, day); -} - -/*! - \since 4.5 - - Returns the localized name of the \a day (where 1 represents - Monday, 2 represents Tuesday and so on) that is used as a - standalone text, in the format specified by \a type. - - If the locale information does not specify the standalone day - name then return value is the same as in dayName(). - - \sa dayName(), standaloneMonthName() -*/ -QString QLocale::standaloneDayName(int day, FormatType type) const -{ - if (day < 1 || day > 7) - return QString(); - -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(type == LongFormat - ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort, - day); - if (!res.isNull()) - return res.toString(); - } -#endif - if (day == 7) - day = 0; - - quint32 idx, size; - switch (type) { - case QLocale::LongFormat: - idx = d->m_data->m_standalone_long_day_names_idx; - size = d->m_data->m_standalone_long_day_names_size; - break; - case QLocale::ShortFormat: - idx = d->m_data->m_standalone_short_day_names_idx; - size = d->m_data->m_standalone_short_day_names_size; - break; - case QLocale::NarrowFormat: - idx = d->m_data->m_standalone_narrow_day_names_idx; - size = d->m_data->m_standalone_narrow_day_names_size; - break; - default: - return QString(); - } - QString name = getLocaleListData(days_data + idx, size, day); - if (name.isEmpty()) - return dayName(day == 0 ? 7 : day, type); - return name; -} - -/*! - \since 4.8 - - Returns the first day of the week according to the current locale. -*/ -Qt::DayOfWeek QLocale::firstDayOfWeek() const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(QSystemLocale::FirstDayOfWeek, QVariant()); - if (!res.isNull()) - return static_cast<Qt::DayOfWeek>(res.toUInt()); - } -#endif - return static_cast<Qt::DayOfWeek>(d->m_data->m_first_day_of_week); -} - -QLocale::MeasurementSystem QLocalePrivate::measurementSystem() const -{ - for (int i = 0; i < ImperialMeasurementSystemsCount; ++i) { - if (ImperialMeasurementSystems[i].languageId == m_data->m_language_id - && ImperialMeasurementSystems[i].countryId == m_data->m_country_id) { - return ImperialMeasurementSystems[i].system; - } - } - return QLocale::MetricSystem; -} - -/*! - \since 4.8 - - Returns a list of days that are considered weekdays according to the current locale. -*/ -QList<Qt::DayOfWeek> QLocale::weekdays() const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(QSystemLocale::Weekdays, QVariant()); - if (!res.isNull()) - return static_cast<QList<Qt::DayOfWeek> >(res.value<QList<Qt::DayOfWeek> >()); - } -#endif - QList<Qt::DayOfWeek> weekdays; - quint16 weekendStart = d->m_data->m_weekend_start; - quint16 weekendEnd = d->m_data->m_weekend_end; - for (int day = Qt::Monday; day <= Qt::Sunday; day++) { - if ((weekendEnd >= weekendStart && (day < weekendStart || day > weekendEnd)) || - (weekendEnd < weekendStart && (day > weekendEnd && day < weekendStart))) - weekdays << static_cast<Qt::DayOfWeek>(day); - } - return weekdays; -} - -/*! - \since 4.4 - - Returns the measurement system for the locale. -*/ -QLocale::MeasurementSystem QLocale::measurementSystem() const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(QSystemLocale::MeasurementSystem, QVariant()); - if (!res.isNull()) - return MeasurementSystem(res.toInt()); - } -#endif - - return d->measurementSystem(); -} - -/*! - \since 4.7 - - Returns the text direction of the language. -*/ -Qt::LayoutDirection QLocale::textDirection() const -{ - switch (script()) { - case QLocale::AdlamScript: - case QLocale::ArabicScript: - case QLocale::AvestanScript: - case QLocale::CypriotScript: - case QLocale::HatranScript: - case QLocale::HebrewScript: - case QLocale::ImperialAramaicScript: - case QLocale::InscriptionalPahlaviScript: - case QLocale::InscriptionalParthianScript: - case QLocale::KharoshthiScript: - case QLocale::LydianScript: - case QLocale::MandaeanScript: - case QLocale::ManichaeanScript: - case QLocale::MendeKikakuiScript: - case QLocale::MeroiticCursiveScript: - case QLocale::MeroiticScript: - case QLocale::NabataeanScript: - case QLocale::NkoScript: - case QLocale::OldHungarianScript: - case QLocale::OldNorthArabianScript: - case QLocale::OldSouthArabianScript: - case QLocale::OrkhonScript: - case QLocale::PalmyreneScript: - case QLocale::PhoenicianScript: - case QLocale::PsalterPahlaviScript: - case QLocale::SamaritanScript: - case QLocale::SyriacScript: - case QLocale::ThaanaScript: - return Qt::RightToLeft; - default: - break; - } - return Qt::LeftToRight; -} - -/*! - \since 4.8 - - Returns an uppercase copy of \a str. - - If Qt Core is using the ICU libraries, they will be used to perform - the transformation according to the rules of the current locale. - Otherwise the conversion may be done in a platform-dependent manner, - with QString::toUpper() as a generic fallback. - - \sa QString::toUpper() -*/ -QString QLocale::toUpper(const QString &str) const -{ -#if QT_CONFIG(icu) - bool ok = true; - QString result = QIcu::toUpper(d->bcp47Name('_'), str, &ok); - if (ok) - return result; - // else fall through and use Qt's toUpper -#endif - return str.toUpper(); -} - -/*! - \since 4.8 - - Returns a lowercase copy of \a str. - - If Qt Core is using the ICU libraries, they will be used to perform - the transformation according to the rules of the current locale. - Otherwise the conversion may be done in a platform-dependent manner, - with QString::toLower() as a generic fallback. - - \sa QString::toLower() -*/ -QString QLocale::toLower(const QString &str) const -{ -#if QT_CONFIG(icu) - bool ok = true; - const QString result = QIcu::toLower(d->bcp47Name('_'), str, &ok); - if (ok) - return result; - // else fall through and use Qt's toUpper -#endif - return str.toLower(); -} - - -/*! - \since 4.5 - - Returns the localized name of the "AM" suffix for times specified using - the conventions of the 12-hour clock. - - \sa pmText() -*/ -QString QLocale::amText() const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(QSystemLocale::AMText, QVariant()); - if (!res.isNull()) - return res.toString(); - } -#endif - return getLocaleData(am_data + d->m_data->m_am_idx, d->m_data->m_am_size); -} - -/*! - \since 4.5 - - Returns the localized name of the "PM" suffix for times specified using - the conventions of the 12-hour clock. - - \sa amText() -*/ -QString QLocale::pmText() const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(QSystemLocale::PMText, QVariant()); - if (!res.isNull()) - return res.toString(); - } -#endif - return getLocaleData(pm_data + d->m_data->m_pm_idx, d->m_data->m_pm_size); -} - - -QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &datetime, - const QDate &dateOnly, const QTime &timeOnly, - const QLocale *q) const -{ - QDate date; - QTime time; - bool formatDate = false; - bool formatTime = false; - if (datetime.isValid()) { - date = datetime.date(); - time = datetime.time(); - formatDate = true; - formatTime = true; - } else if (dateOnly.isValid()) { - date = dateOnly; - formatDate = true; - } else if (timeOnly.isValid()) { - time = timeOnly; - formatTime = true; - } else { - return QString(); - } - - QString result; - - int i = 0; - while (i < format.size()) { - if (format.at(i).unicode() == '\'') { - result.append(qt_readEscapedFormatString(format, &i)); - continue; - } - - const QChar c = format.at(i); - int repeat = qt_repeatCount(format.mid(i)); - bool used = false; - if (formatDate) { - switch (c.unicode()) { - case 'y': - used = true; - if (repeat >= 4) - repeat = 4; - else if (repeat >= 2) - repeat = 2; - - switch (repeat) { - case 4: { - const int yr = date.year(); - const int len = (yr < 0) ? 5 : 4; - result.append(m_data->longLongToString(yr, -1, 10, len, QLocaleData::ZeroPadded)); - break; - } - case 2: - result.append(m_data->longLongToString(date.year() % 100, -1, 10, 2, - QLocaleData::ZeroPadded)); - break; - default: - repeat = 1; - result.append(c); - break; - } - break; - - case 'M': - used = true; - repeat = qMin(repeat, 4); - switch (repeat) { - case 1: - result.append(m_data->longLongToString(date.month())); - break; - case 2: - result.append(m_data->longLongToString(date.month(), -1, 10, 2, QLocaleData::ZeroPadded)); - break; - case 3: - result.append(q->monthName(date.month(), QLocale::ShortFormat)); - break; - case 4: - result.append(q->monthName(date.month(), QLocale::LongFormat)); - break; - } - break; - - case 'd': - used = true; - repeat = qMin(repeat, 4); - switch (repeat) { - case 1: - result.append(m_data->longLongToString(date.day())); - break; - case 2: - result.append(m_data->longLongToString(date.day(), -1, 10, 2, QLocaleData::ZeroPadded)); - break; - case 3: - result.append(q->dayName(date.dayOfWeek(), QLocale::ShortFormat)); - break; - case 4: - result.append(q->dayName(date.dayOfWeek(), QLocale::LongFormat)); - break; - } - break; - - default: - break; - } - } - if (!used && formatTime) { - switch (c.unicode()) { - case 'h': { - used = true; - repeat = qMin(repeat, 2); - int hour = time.hour(); - if (timeFormatContainsAP(format)) { - if (hour > 12) - hour -= 12; - else if (hour == 0) - hour = 12; - } - - switch (repeat) { - case 1: - result.append(m_data->longLongToString(hour)); - break; - case 2: - result.append(m_data->longLongToString(hour, -1, 10, 2, QLocaleData::ZeroPadded)); - break; - } - break; - } - case 'H': - used = true; - repeat = qMin(repeat, 2); - switch (repeat) { - case 1: - result.append(m_data->longLongToString(time.hour())); - break; - case 2: - result.append(m_data->longLongToString(time.hour(), -1, 10, 2, QLocaleData::ZeroPadded)); - break; - } - break; - - case 'm': - used = true; - repeat = qMin(repeat, 2); - switch (repeat) { - case 1: - result.append(m_data->longLongToString(time.minute())); - break; - case 2: - result.append(m_data->longLongToString(time.minute(), -1, 10, 2, QLocaleData::ZeroPadded)); - break; - } - break; - - case 's': - used = true; - repeat = qMin(repeat, 2); - switch (repeat) { - case 1: - result.append(m_data->longLongToString(time.second())); - break; - case 2: - result.append(m_data->longLongToString(time.second(), -1, 10, 2, QLocaleData::ZeroPadded)); - break; - } - break; - - case 'a': - used = true; - if (i + 1 < format.size() && format.at(i + 1).unicode() == 'p') { - repeat = 2; - } else { - repeat = 1; - } - result.append(time.hour() < 12 ? q->amText().toLower() : q->pmText().toLower()); - break; - - case 'A': - used = true; - if (i + 1 < format.size() && format.at(i + 1).unicode() == 'P') { - repeat = 2; - } else { - repeat = 1; - } - result.append(time.hour() < 12 ? q->amText().toUpper() : q->pmText().toUpper()); - break; - - case 'z': - used = true; - if (repeat >= 3) { - repeat = 3; - } else { - repeat = 1; - } - - // note: the millisecond component is treated like the decimal part of the seconds - // so ms == 2 is always printed as "002", but ms == 200 can be either "2" or "200" - result.append(m_data->longLongToString(time.msec(), -1, 10, 3, QLocaleData::ZeroPadded)); - if (repeat == 1) { - if (result.endsWith(zero())) - result.chop(1); - if (result.endsWith(zero())) - result.chop(1); - } - - break; - - case 't': - used = true; - repeat = 1; - // If we have a QDateTime use the time spec otherwise use the current system tzname - if (formatDate) { - result.append(datetime.timeZoneAbbreviation()); - } else { - result.append(QDateTime::currentDateTime().timeZoneAbbreviation()); - } - break; - - default: - break; - } - } - if (!used) { - result.append(QString(repeat, c)); - } - i += repeat; - } - - return result; -} - -QString QLocaleData::doubleToString(double d, int precision, DoubleForm form, - int width, unsigned flags) const -{ - return doubleToString(m_zero, m_plus, m_minus, m_exponential, m_group, m_decimal, - d, precision, form, width, flags); -} - -QString QLocaleData::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) -{ - if (precision != QLocale::FloatingPointShortest && precision < 0) - precision = 6; - if (width < 0) - width = 0; - - bool negative = false; - QString num_str; - - int decpt; - int bufSize = 1; - if (precision == QLocale::FloatingPointShortest) - bufSize += DoubleMaxSignificant; - else if (form == DFDecimal) // optimize for numbers between -512k and 512k - bufSize += ((d > (1 << 19) || d < -(1 << 19)) ? DoubleMaxDigitsBeforeDecimal : 6) + - precision; - else // Add extra digit due to different interpretations of precision. Also, "nan" has to fit. - bufSize += qMax(2, precision) + 1; - - QVarLengthArray<char> buf(bufSize); - int length; - - qt_doubleToAscii(d, form, precision, buf.data(), bufSize, negative, length, decpt); - - if (qstrncmp(buf.data(), "inf", 3) == 0 || qstrncmp(buf.data(), "nan", 3) == 0) { - num_str = QString::fromLatin1(buf.data(), length); - } else { // Handle normal numbers - QString digits = QString::fromLatin1(buf.data(), length); - - if (_zero.unicode() != '0') { - ushort z = _zero.unicode() - '0'; - for (int i = 0; i < digits.length(); ++i) - reinterpret_cast<ushort *>(digits.data())[i] += z; - } - - bool always_show_decpt = (flags & ForcePoint); - switch (form) { - case DFExponent: { - num_str = exponentForm(_zero, decimal, exponential, group, plus, minus, - digits, decpt, precision, PMDecimalDigits, - always_show_decpt, flags & ZeroPadExponent); - break; - } - case DFDecimal: { - num_str = decimalForm(_zero, decimal, group, - digits, decpt, precision, PMDecimalDigits, - always_show_decpt, flags & ThousandsGroup); - break; - } - case DFSignificantDigits: { - PrecisionMode mode = (flags & AddTrailingZeroes) ? - PMSignificantDigits : PMChopTrailingZeros; - - int cutoff = precision < 0 ? 6 : precision; - // Find out which representation is shorter - if (precision == QLocale::FloatingPointShortest && decpt > 0) { - cutoff = digits.length() + 4; // 'e', '+'/'-', one digit exponent - if (decpt <= 10) { - ++cutoff; - } else { - cutoff += decpt > 100 ? 2 : 1; - } - if (!always_show_decpt && digits.length() > decpt) - ++cutoff; // decpt shown in exponent form, but not in decimal form - } - - if (decpt != digits.length() && (decpt <= -4 || decpt > cutoff)) - num_str = exponentForm(_zero, decimal, exponential, group, plus, minus, - digits, decpt, precision, mode, - always_show_decpt, flags & ZeroPadExponent); - else - num_str = decimalForm(_zero, decimal, group, - digits, decpt, precision, mode, - always_show_decpt, flags & ThousandsGroup); - break; - } - } - - if (isZero(d)) - negative = false; - - // pad with zeros. LeftAdjusted overrides this flag). Also, we don't - // pad special numbers - if (flags & QLocaleData::ZeroPadded && !(flags & QLocaleData::LeftAdjusted)) { - int num_pad_chars = width - num_str.length(); - // leave space for the sign - if (negative - || flags & QLocaleData::AlwaysShowSign - || flags & QLocaleData::BlankBeforePositive) - --num_pad_chars; - - for (int i = 0; i < num_pad_chars; ++i) - num_str.prepend(_zero); - } - } - - // add sign - if (negative) - num_str.prepend(minus); - else if (flags & QLocaleData::AlwaysShowSign) - num_str.prepend(plus); - else if (flags & QLocaleData::BlankBeforePositive) - num_str.prepend(QLatin1Char(' ')); - - if (flags & QLocaleData::CapitalEorX) - num_str = std::move(num_str).toUpper(); - - return num_str; -} - -QString QLocaleData::longLongToString(qlonglong l, int precision, - int base, int width, - unsigned flags) const -{ - return longLongToString(m_zero, m_group, m_plus, m_minus, - l, precision, base, width, flags); -} - -QString QLocaleData::longLongToString(const QChar zero, const QChar group, - const QChar plus, const QChar minus, - qlonglong l, int precision, - int base, int width, - unsigned flags) -{ - bool precision_not_specified = false; - if (precision == -1) { - precision_not_specified = true; - precision = 1; - } - - bool negative = l < 0; - if (base != 10) { - // these are not supported by sprintf for octal and hex - flags &= ~AlwaysShowSign; - flags &= ~BlankBeforePositive; - negative = false; // neither are negative numbers - } - -QT_WARNING_PUSH - /* "unary minus operator applied to unsigned type, result still unsigned" */ -QT_WARNING_DISABLE_MSVC(4146) - /* - Negating std::numeric_limits<qlonglong>::min() hits undefined behavior, so - taking an absolute value has to cast to unsigned to change sign. - */ - QString num_str = qulltoa(negative ? -qulonglong(l) : qulonglong(l), base, zero); -QT_WARNING_POP - - uint cnt_thousand_sep = 0; - if (flags & ThousandsGroup && base == 10) { - for (int i = num_str.length() - 3; i > 0; i -= 3) { - num_str.insert(i, group); - ++cnt_thousand_sep; - } - } - - for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i) - num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0')); - - if ((flags & ShowBase) - && base == 8 - && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0'))) - num_str.prepend(QLatin1Char('0')); - - // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds - // when precision is not specified in the format string - bool zero_padded = flags & ZeroPadded - && !(flags & LeftAdjusted) - && precision_not_specified; - - if (zero_padded) { - int num_pad_chars = width - num_str.length(); - - // leave space for the sign - if (negative - || flags & AlwaysShowSign - || flags & BlankBeforePositive) - --num_pad_chars; - - // leave space for optional '0x' in hex form - if (base == 16 && (flags & ShowBase)) - num_pad_chars -= 2; - // leave space for optional '0b' in binary form - else if (base == 2 && (flags & ShowBase)) - num_pad_chars -= 2; - - for (int i = 0; i < num_pad_chars; ++i) - num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0')); - } - - if (flags & CapitalEorX) - num_str = std::move(num_str).toUpper(); - - if (base == 16 && (flags & ShowBase)) - num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x")); - if (base == 2 && (flags & ShowBase)) - num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b")); - - // add sign - if (negative) - num_str.prepend(minus); - else if (flags & AlwaysShowSign) - num_str.prepend(plus); - else if (flags & BlankBeforePositive) - num_str.prepend(QLatin1Char(' ')); - - return num_str; -} - -QString QLocaleData::unsLongLongToString(qulonglong l, int precision, - int base, int width, - unsigned flags) const -{ - return unsLongLongToString(m_zero, m_group, m_plus, - l, precision, base, width, flags); -} - -QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group, - const QChar plus, - qulonglong l, int precision, - int base, int width, - unsigned flags) -{ - const QChar resultZero = base == 10 ? zero : QChar(QLatin1Char('0')); - QString num_str = l ? qulltoa(l, base, zero) : QString(resultZero); - - bool precision_not_specified = false; - if (precision == -1) { - if (flags == NoFlags) - return num_str; // fast-path: nothing below applies, so we're done. - - precision_not_specified = true; - precision = 1; - } - - uint cnt_thousand_sep = 0; - if (flags & ThousandsGroup && base == 10) { - for (int i = num_str.length() - 3; i > 0; i -=3) { - num_str.insert(i, group); - ++cnt_thousand_sep; - } - } - - const int zeroPadding = precision - num_str.length()/* + cnt_thousand_sep*/; - if (zeroPadding > 0) - num_str.prepend(QString(zeroPadding, resultZero)); - - if ((flags & ShowBase) - && base == 8 - && (num_str.isEmpty() || num_str.at(0).unicode() != QLatin1Char('0'))) - num_str.prepend(QLatin1Char('0')); - - // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds - // when precision is not specified in the format string - bool zero_padded = flags & ZeroPadded - && !(flags & LeftAdjusted) - && precision_not_specified; - - if (zero_padded) { - int num_pad_chars = width - num_str.length(); - - // leave space for optional '0x' in hex form - if (base == 16 && flags & ShowBase) - num_pad_chars -= 2; - // leave space for optional '0b' in binary form - else if (base == 2 && flags & ShowBase) - num_pad_chars -= 2; - - if (num_pad_chars > 0) - num_str.prepend(QString(num_pad_chars, resultZero)); - } - - if (flags & CapitalEorX) - num_str = std::move(num_str).toUpper(); - - if (base == 16 && flags & ShowBase) - num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x")); - else if (base == 2 && flags & ShowBase) - num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b")); - - // add sign - if (flags & AlwaysShowSign) - num_str.prepend(plus); - else if (flags & BlankBeforePositive) - num_str.prepend(QLatin1Char(' ')); - - return num_str; -} - -/* - Converts a number in locale to its representation in the C locale. - Only has to guarantee that a string that is a correct representation of - a number will be converted. If junk is passed in, junk will be passed - out and the error will be detected during the actual conversion to a - number. We can't detect junk here, since we don't even know the base - of the number. -*/ -bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_options, - CharBuff *result) const -{ - const QChar *uc = s.data(); - auto l = s.size(); - decltype(l) idx = 0; - - // Skip whitespace - while (idx < l && uc[idx].isSpace()) - ++idx; - if (idx == l) - return false; - - // Check trailing whitespace - for (; idx < l; --l) { - if (!uc[l - 1].isSpace()) - break; - } - - int group_cnt = 0; // counts number of group chars - int decpt_idx = -1; - int last_separator_idx = -1; - int start_of_digits_idx = -1; - int exponent_idx = -1; - - while (idx < l) { - const QChar in = uc[idx]; - - char out = digitToCLocale(in); - if (out == 0) { - if (in == m_list) - out = ';'; - else if (in == m_percent) - out = '%'; - // for handling base-x numbers - else if (in.unicode() >= 'A' && in.unicode() <= 'Z') - out = in.toLower().toLatin1(); - else if (in.unicode() >= 'a' && in.unicode() <= 'z') - out = in.toLatin1(); - else - break; - } else if (out == '.') { - // Fail if more than one decimal point or point after e - if (decpt_idx != -1 || exponent_idx != -1) - return false; - decpt_idx = idx; - } else if (out == 'e' || out == 'E') { - exponent_idx = idx; - } - - if (number_options & QLocale::RejectLeadingZeroInExponent) { - if (exponent_idx != -1 && out == '0' && idx < l - 1) { - // After the exponent there can only be '+', '-' or digits. - // If we find a '0' directly after some non-digit, then that is a leading zero. - if (result->last() < '0' || result->last() > '9') - return false; - } - } - - if (number_options & QLocale::RejectTrailingZeroesAfterDot) { - // If we've seen a decimal point and the last character after the exponent is 0, then - // that is a trailing zero. - if (decpt_idx >= 0 && idx == exponent_idx && result->last() == '0') - return false; - } - - if (!(number_options & QLocale::RejectGroupSeparator)) { - if (start_of_digits_idx == -1 && out >= '0' && out <= '9') { - start_of_digits_idx = idx; - } else if (out == ',') { - // Don't allow group chars after the decimal point or exponent - if (decpt_idx != -1 || exponent_idx != -1) - return false; - - // check distance from the last separator or from the beginning of the digits - // ### FIXME: Some locales allow other groupings! See https://en.wikipedia.org/wiki/Thousands_separator - if (last_separator_idx != -1 && idx - last_separator_idx != 4) - return false; - if (last_separator_idx == -1 && (start_of_digits_idx == -1 || idx - start_of_digits_idx > 3)) - return false; - - last_separator_idx = idx; - ++group_cnt; - - // don't add the group separator - ++idx; - continue; - } else if (out == '.' || out == 'e' || out == 'E') { - // check distance from the last separator - // ### FIXME: Some locales allow other groupings! See https://en.wikipedia.org/wiki/Thousands_separator - if (last_separator_idx != -1 && idx - last_separator_idx != 4) - return false; - - // stop processing separators - last_separator_idx = -1; - } - } - - result->append(out); - - ++idx; - } - - if (!(number_options & QLocale::RejectGroupSeparator)) { - // group separator post-processing - // did we end in a separator? - if (last_separator_idx + 1 == idx) - return false; - // were there enough digits since the last separator? - if (last_separator_idx != -1 && idx - last_separator_idx != 4) - return false; - } - - if (number_options & QLocale::RejectTrailingZeroesAfterDot) { - // In decimal form, the last character can be a trailing zero if we've seen a decpt. - if (decpt_idx != -1 && exponent_idx == -1 && result->last() == '0') - return false; - } - - result->append('\0'); - return idx == l; -} - -bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray *buff, - int decDigits, QLocale::NumberOptions number_options) const -{ - buff->clear(); - buff->reserve(str.length()); - - const bool scientific = numMode == DoubleScientificMode; - bool lastWasE = false; - bool lastWasDigit = false; - int eCnt = 0; - int decPointCnt = 0; - bool dec = false; - int decDigitCnt = 0; - - for (qsizetype i = 0; i < str.size(); ++i) { - char c = digitToCLocale(str.at(i)); - - if (c >= '0' && c <= '9') { - if (numMode != IntegerMode) { - // If a double has too many digits after decpt, it shall be Invalid. - if (dec && decDigits != -1 && decDigits < ++decDigitCnt) - return false; - } - - // The only non-digit character after the 'e' can be '+' or '-'. - // If a zero is directly after that, then the exponent is zero-padded. - if ((number_options & QLocale::RejectLeadingZeroInExponent) && c == '0' && eCnt > 0 && - !lastWasDigit) - return false; - - lastWasDigit = true; - } else { - switch (c) { - case '.': - if (numMode == IntegerMode) { - // If an integer has a decimal point, it shall be Invalid. - return false; - } else { - // If a double has more than one decimal point, it shall be Invalid. - if (++decPointCnt > 1) - return false; -#if 0 - // If a double with no decimal digits has a decimal point, it shall be - // Invalid. - if (decDigits == 0) - return false; -#endif // On second thoughts, it shall be Valid. - - dec = true; - } - break; - - case '+': - case '-': - if (scientific) { - // If a scientific has a sign that's not at the beginning or after - // an 'e', it shall be Invalid. - if (i != 0 && !lastWasE) - return false; - } else { - // If a non-scientific has a sign that's not at the beginning, - // it shall be Invalid. - if (i != 0) - return false; - } - break; - - case ',': - //it can only be placed after a digit which is before the decimal point - if ((number_options & QLocale::RejectGroupSeparator) || !lastWasDigit || - decPointCnt > 0) - return false; - break; - - case 'e': - if (scientific) { - // If a scientific has more than one 'e', it shall be Invalid. - if (++eCnt > 1) - return false; - dec = false; - } else { - // If a non-scientific has an 'e', it shall be Invalid. - return false; - } - break; - - default: - // If it's not a valid digit, it shall be Invalid. - return false; - } - lastWasDigit = false; - } - - lastWasE = c == 'e'; - if (c != ',') - buff->append(c); - } - - return true; -} - -double QLocaleData::stringToDouble(QStringView str, bool *ok, - QLocale::NumberOptions number_options) const -{ - CharBuff buff; - if (!numberToCLocale(str, number_options, &buff)) { - if (ok != nullptr) - *ok = false; - return 0.0; - } - int processed = 0; - bool nonNullOk = false; - double d = qt_asciiToDouble(buff.constData(), buff.length() - 1, nonNullOk, processed); - if (ok != nullptr) - *ok = nonNullOk; - return d; -} - -qlonglong QLocaleData::stringToLongLong(QStringView str, int base, bool *ok, - QLocale::NumberOptions number_options) const -{ - CharBuff buff; - if (!numberToCLocale(str, number_options, &buff)) { - if (ok != nullptr) - *ok = false; - return 0; - } - - return bytearrayToLongLong(buff.constData(), base, ok); -} - -qulonglong QLocaleData::stringToUnsLongLong(QStringView str, int base, bool *ok, - QLocale::NumberOptions number_options) const -{ - CharBuff buff; - if (!numberToCLocale(str, number_options, &buff)) { - if (ok != nullptr) - *ok = false; - return 0; - } - - return bytearrayToUnsLongLong(buff.constData(), base, ok); -} - -double QLocaleData::bytearrayToDouble(const char *num, bool *ok) -{ - bool nonNullOk = false; - int len = static_cast<int>(strlen(num)); - Q_ASSERT(len >= 0); - int processed = 0; - double d = qt_asciiToDouble(num, len, nonNullOk, processed); - if (ok != nullptr) - *ok = nonNullOk; - return d; -} - -qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok) -{ - bool _ok; - const char *endptr; - - if (*num == '\0') { - if (ok != nullptr) - *ok = false; - return 0; - } - - qlonglong l = qstrtoll(num, &endptr, base, &_ok); - - if (!_ok) { - if (ok != nullptr) - *ok = false; - return 0; - } - - if (*endptr != '\0') { - while (ascii_isspace(*endptr)) - ++endptr; - } - - if (*endptr != '\0') { - // we stopped at a non-digit character after converting some digits - if (ok != nullptr) - *ok = false; - return 0; - } - - if (ok != nullptr) - *ok = true; - return l; -} - -qulonglong QLocaleData::bytearrayToUnsLongLong(const char *num, int base, bool *ok) -{ - bool _ok; - const char *endptr; - qulonglong l = qstrtoull(num, &endptr, base, &_ok); - - if (!_ok) { - if (ok != nullptr) - *ok = false; - return 0; - } - - if (*endptr != '\0') { - while (ascii_isspace(*endptr)) - ++endptr; - } - - if (*endptr != '\0') { - if (ok != nullptr) - *ok = false; - return 0; - } - - if (ok != nullptr) - *ok = true; - return l; -} - -/*! - \since 4.8 - - \enum QLocale::CurrencySymbolFormat - - Specifies the format of the currency symbol. - - \value CurrencyIsoCode a ISO-4217 code of the currency. - \value CurrencySymbol a currency symbol. - \value CurrencyDisplayName a user readable name of the currency. -*/ - -/*! - \since 4.8 - Returns a currency symbol according to the \a format. -*/ -QString QLocale::currencySymbol(QLocale::CurrencySymbolFormat format) const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(QSystemLocale::CurrencySymbol, format); - if (!res.isNull()) - return res.toString(); - } -#endif - quint32 idx, size; - switch (format) { - case CurrencySymbol: - idx = d->m_data->m_currency_symbol_idx; - size = d->m_data->m_currency_symbol_size; - return getLocaleData(currency_symbol_data + idx, size); - case CurrencyDisplayName: - idx = d->m_data->m_currency_display_name_idx; - size = d->m_data->m_currency_display_name_size; - return getLocaleListData(currency_display_name_data + idx, size, 0); - case CurrencyIsoCode: { - int len = 0; - const QLocaleData *data = this->d->m_data; - for (; len < 3; ++len) - if (!data->m_currency_iso_code[len]) - break; - return len ? QString::fromLatin1(data->m_currency_iso_code, len) : QString(); - } - } - return QString(); -} - -/*! - \since 4.8 - - Returns a localized string representation of \a value as a currency. - If the \a symbol is provided it is used instead of the default currency symbol. - - \sa currencySymbol() -*/ -QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QSystemLocale::CurrencyToStringArgument arg(value, symbol); - QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg)); - if (!res.isNull()) - return res.toString(); - } -#endif - const QLocalePrivate *d = this->d; - quint8 idx = d->m_data->m_currency_format_idx; - quint8 size = d->m_data->m_currency_format_size; - if (d->m_data->m_currency_negative_format_size && value < 0) { - idx = d->m_data->m_currency_negative_format_idx; - size = d->m_data->m_currency_negative_format_size; - value = -value; - } - QString str = toString(value); - QString sym = symbol.isNull() ? currencySymbol() : symbol; - if (sym.isEmpty()) - sym = currencySymbol(QLocale::CurrencyIsoCode); - QString format = getLocaleData(currency_format_data + idx, size); - return format.arg(str, sym); -} - -/*! - \since 4.8 - \overload -*/ -QString QLocale::toCurrencyString(qulonglong value, const QString &symbol) const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QSystemLocale::CurrencyToStringArgument arg(value, symbol); - QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg)); - if (!res.isNull()) - return res.toString(); - } -#endif - const QLocaleData *data = this->d->m_data; - quint8 idx = data->m_currency_format_idx; - quint8 size = data->m_currency_format_size; - QString str = toString(value); - QString sym = symbol.isNull() ? currencySymbol() : symbol; - if (sym.isEmpty()) - sym = currencySymbol(QLocale::CurrencyIsoCode); - QString format = getLocaleData(currency_format_data + idx, size); - return format.arg(str, sym); -} - -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) -/*! - \since 4.8 - \overload -*/ -QString QLocale::toCurrencyString(double value, const QString &symbol) const -{ - return toCurrencyString(value, symbol, d->m_data->m_currency_digits); -} -#endif - -/*! - \since 5.7 - \overload toCurrencyString() - - Returns a localized string representation of \a value as a currency. - If the \a symbol is provided it is used instead of the default currency symbol. - If the \a precision is provided it is used to set the precision of the currency value. - - \sa currencySymbol() - */ -QString QLocale::toCurrencyString(double value, const QString &symbol, int precision) const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QSystemLocale::CurrencyToStringArgument arg(value, symbol); - QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg)); - if (!res.isNull()) - return res.toString(); - } -#endif - const QLocaleData *data = this->d->m_data; - quint8 idx = data->m_currency_format_idx; - quint8 size = data->m_currency_format_size; - if (data->m_currency_negative_format_size && value < 0) { - idx = data->m_currency_negative_format_idx; - size = data->m_currency_negative_format_size; - value = -value; - } - QString str = toString(value, 'f', precision == -1 ? d->m_data->m_currency_digits : precision); - QString sym = symbol.isNull() ? currencySymbol() : symbol; - if (sym.isEmpty()) - sym = currencySymbol(QLocale::CurrencyIsoCode); - QString format = getLocaleData(currency_format_data + idx, size); - return format.arg(str, sym); -} - -/*! - \fn QString QLocale::toCurrencyString(float i, const QString &symbol) const - \fn QString QLocale::toCurrencyString(float i, const QString &symbol, int precision) const - \overload toCurrencyString() -*/ - -/*! - \since 5.10 - - \enum QLocale::DataSizeFormat - - Specifies the format for representation of data quantities. - - \omitvalue DataSizeBase1000 - \omitvalue DataSizeSIQuantifiers - \value DataSizeIecFormat format using base 1024 and IEC prefixes: KiB, MiB, GiB, ... - \value DataSizeTraditionalFormat format using base 1024 and SI prefixes: kB, MB, GB, ... - \value DataSizeSIFormat format using base 1000 and SI prefixes: kB, MB, GB, ... - - \sa formattedDataSize() -*/ - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -/*! - \obsolete - - Use the const version instead. -*/ -QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) -{ - const auto *that = this; - return that->formattedDataSize(bytes, precision, format); -} -#endif - -/*! - \since 5.10 - - Converts a size in bytes to a human-readable localized string, comprising a - number and a quantified unit. The quantifier is chosen such that the number - is at least one, and as small as possible. For example if \a bytes is - 16384, \a precision is 2, and \a format is \l DataSizeIecFormat (the - default), this function returns "16.00 KiB"; for 1330409069609 bytes it - returns "1.21 GiB"; and so on. If \a format is \l DataSizeIecFormat or - \l DataSizeTraditionalFormat, the given number of bytes is divided by a - power of 1024, with result less than 1024; for \l DataSizeSIFormat, it is - divided by a power of 1000, with result less than 1000. - \c DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so on, - whereas \c DataSizeSIFormat uses the older SI quantifiers k, M, etc., and - \c DataSizeTraditionalFormat abuses them. -*/ -QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) const -{ - int power, base = 1000; - if (!bytes) { - power = 0; - } else if (format & DataSizeBase1000) { - power = int(std::log10(qAbs(bytes)) / 3); - } else { // Compute log2(bytes) / 10: - power = int((63 - qCountLeadingZeroBits(quint64(qAbs(bytes)))) / 10); - base = 1024; - } - // Only go to doubles if we'll be using a quantifier: - const QString number = power - ? toString(bytes / std::pow(double(base), power), 'f', qMin(precision, 3 * power)) - : toString(bytes); - - // We don't support sizes in units larger than exbibytes because - // the number of bytes would not fit into qint64. - Q_ASSERT(power <= 6 && power >= 0); - QString unit; - if (power > 0) { - quint16 index, size; - if (format & DataSizeSIQuantifiers) { - index = d->m_data->m_byte_si_quantified_idx; - size = d->m_data->m_byte_si_quantified_size; - } else { - index = d->m_data->m_byte_iec_quantified_idx; - size = d->m_data->m_byte_iec_quantified_size; - } - unit = getLocaleListData(byte_unit_data + index, size, power - 1); - } else { - unit = getLocaleData(byte_unit_data + d->m_data->m_byte_idx, d->m_data->m_byte_size); - } - - return number + QLatin1Char(' ') + unit; -} - -/*! - \since 4.8 - - Returns an ordered list of locale names for translation purposes in - preference order (like "en-Latn-US", "en-US", "en"). - - The return value represents locale names that the user expects to see the - UI translation in. - - Most like you do not need to use this function directly, but just pass the - QLocale object to the QTranslator::load() function. - - The first item in the list is the most preferred one. - - \sa QTranslator, bcp47Name() -*/ -QStringList QLocale::uiLanguages() const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(QSystemLocale::UILanguages, QVariant()); - if (!res.isNull()) { - QStringList result = res.toStringList(); - if (!result.isEmpty()) - return result; - } - } -#endif - QLocaleId id = QLocaleId::fromIds(d->m_data->m_language_id, d->m_data->m_script_id, d->m_data->m_country_id); - const QLocaleId max = id.withLikelySubtagsAdded(); - const QLocaleId min = max.withLikelySubtagsRemoved(); - - QStringList uiLanguages; - uiLanguages.append(QString::fromLatin1(min.name())); - if (id.script_id) { - id.script_id = 0; - if (id != min && id.withLikelySubtagsAdded() == max) - uiLanguages.append(QString::fromLatin1(id.name())); - } - if (max != min && max != id) - uiLanguages.append(QString::fromLatin1(max.name())); - return uiLanguages; -} - -/*! - \since 5.13 - - Returns the locale to use for collation. - - The result is usually this locale; however, the system locale (which is - commonly the default locale) will return the system collation locale. - The result is suitable for passing to QCollator's constructor. - - \sa QCollator -*/ -QLocale QLocale::collation() const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QString res = systemLocale()->query(QSystemLocale::Collation, QVariant()).toString(); - if (!res.isEmpty()) - return QLocale(res); - } -#endif - return *this; -} - -/*! - \since 4.8 - - Returns a native name of the language for the locale. For example - "Schwiizertüütsch" for Swiss-German locale. - - \sa nativeCountryName(), languageToString() -*/ -QString QLocale::nativeLanguageName() const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(QSystemLocale::NativeLanguageName, QVariant()); - if (!res.isNull()) - return res.toString(); - } -#endif - return getLocaleData(endonyms_data + d->m_data->m_language_endonym_idx, d->m_data->m_language_endonym_size); -} - -/*! - \since 4.8 - - Returns a native name of the country for the locale. For example - "España" for Spanish/Spain locale. - - \sa nativeLanguageName(), countryToString() -*/ -QString QLocale::nativeCountryName() const -{ -#ifndef QT_NO_SYSTEMLOCALE - if (d->m_data == systemData()) { - QVariant res = systemLocale()->query(QSystemLocale::NativeCountryName, QVariant()); - if (!res.isNull()) - return res.toString(); - } -#endif - return getLocaleData(endonyms_data + d->m_data->m_country_endonym_idx, d->m_data->m_country_endonym_size); -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const QLocale &l) -{ - QDebugStateSaver saver(dbg); - dbg.nospace().noquote() - << "QLocale(" << QLocale::languageToString(l.language()) - << ", " << QLocale::scriptToString(l.script()) - << ", " << QLocale::countryToString(l.country()) << ')'; - return dbg; -} -#endif -QT_END_NAMESPACE - -#ifndef QT_NO_QOBJECT -#include "moc_qlocale.cpp" -#endif |