diff options
Diffstat (limited to 'src/corelib/text/qlocale_p.h')
-rw-r--r-- | src/corelib/text/qlocale_p.h | 525 |
1 files changed, 285 insertions, 240 deletions
diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h index 6e4073eaa3..3044d137b9 100644 --- a/src/corelib/text/qlocale_p.h +++ b/src/corelib/text/qlocale_p.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QLOCALE_P_H #define QLOCALE_P_H @@ -52,24 +16,98 @@ // We mean it. // -#include <QtCore/private/qglobal_p.h> -#include "QtCore/qstring.h" -#include "QtCore/qvarlengtharray.h" -#include "QtCore/qvariant.h" -#include "QtCore/qnumeric.h" -#include <QtCore/qcalendar.h> - #include "qlocale.h" +#include <QtCore/qcalendar.h> +#include <QtCore/qlist.h> +#include <QtCore/qnumeric.h> +#include <QtCore/private/qnumeric_p.h> +#include <QtCore/qstring.h> +#include <QtCore/qvariant.h> +#include <QtCore/qvarlengtharray.h> +#ifdef Q_OS_WASM +#include <private/qstdweb_p.h> +#endif + #include <limits> #include <cmath> +#include <string_view> QT_BEGIN_NAMESPACE -#ifndef QT_NO_SYSTEMLOCALE +template <typename T> struct QSimpleParsedNumber +{ + T result; + // When used < 0, -used is how much was used, but it was an error. + qsizetype used; + bool ok() const { return used > 0; } +}; + +template <typename MaskType, uchar Lowest> struct QCharacterSetMatch +{ + static constexpr int MaxRange = std::numeric_limits<MaskType>::digits; + MaskType mask; + + constexpr QCharacterSetMatch(std::string_view set) + : mask(0) + { + for (char c : set) { + int idx = uchar(c) - Lowest; + mask |= MaskType(1) << idx; + } + } + + constexpr bool matches(uchar c) const + { + unsigned idx = c - Lowest; + if (idx >= MaxRange) + return false; + return (mask >> idx) & 1; + } +}; + +namespace QtPrivate { +inline constexpr char ascii_space_chars[] = + "\t" // 9: HT - horizontal tab + "\n" // 10: LF - line feed + "\v" // 11: VT - vertical tab + "\f" // 12: FF - form feed + "\r" // 13: CR - carriage return + " "; // 32: space + +template <const char *Set, int ForcedLowest = -1> +inline constexpr auto makeCharacterSetMatch() +{ + constexpr auto view = std::string_view(Set); + constexpr uchar MinElement = *std::min_element(view.begin(), view.end()); + constexpr uchar MaxElement = *std::max_element(view.begin(), view.end()); + constexpr int Range = MaxElement - MinElement; + static_assert(Range < 64, "Characters in the set are 64 or more values apart"); + + if constexpr (ForcedLowest >= 0) { + // use the force + static_assert(ForcedLowest <= int(MinElement), "The force is not with you"); + using MaskType = std::conditional_t<MaxElement - ForcedLowest < 32, quint32, quint64>; + return QCharacterSetMatch<MaskType, ForcedLowest>(view); + } else if constexpr (MaxElement < std::numeric_limits<qregisteruint>::digits) { + // if we can use a Lowest of zero, we can remove a subtraction + // from the matches() code at runtime + using MaskType = std::conditional_t<(MaxElement < 32), quint32, qregisteruint>; + return QCharacterSetMatch<MaskType, 0>(view); + } else { + using MaskType = std::conditional_t<(Range < 32), quint32, quint64>; + return QCharacterSetMatch<MaskType, MinElement>(view); + } +} +} // QtPrivate + struct QLocaleData; +// Subclassed by Android platform plugin: class Q_CORE_EXPORT QSystemLocale { + Q_DISABLE_COPY_MOVE(QSystemLocale) + QSystemLocale *next = nullptr; // Maintains a stack. + public: QSystemLocale(); virtual ~QSystemLocale(); @@ -85,7 +123,7 @@ public: enum QueryType { LanguageId, // uint - CountryId, // uint + TerritoryId, // uint DecimalPoint, // QString GroupSeparator, // QString (empty QString means: don't group digits) ZeroDigit, // QString @@ -96,8 +134,10 @@ public: TimeFormatShort, // QString DayNameLong, // QString, in: int DayNameShort, // QString, in: int + DayNameNarrow, // QString, in: int MonthNameLong, // QString, in: int MonthNameShort, // QString, in: int + MonthNameNarrow, // QString, in: int DateToStringLong, // QString, in: QDate DateToStringShort, // QString in: QDate TimeToStringLong, // QString in: QTime @@ -122,21 +162,21 @@ public: ListToSeparatedString, // QString LocaleChanged, // system locale changed NativeLanguageName, // QString - NativeCountryName, // QString + NativeTerritoryName, // QString StandaloneMonthNameLong, // QString, in: int - StandaloneMonthNameShort // QString, in: int + StandaloneMonthNameShort, // QString, in: int + StandaloneMonthNameNarrow, // QString, in: int + StandaloneDayNameLong, // QString, in: int + StandaloneDayNameShort, // QString, in: int + StandaloneDayNameNarrow // QString, in: int }; - virtual QVariant query(QueryType type, QVariant in = QVariant()) const; + virtual QVariant query(QueryType type, QVariant &&in = QVariant()) const; virtual QLocale fallbackLocale() const; - inline uint fallbackLocaleIndex() const; -private: - QSystemLocale(bool); - friend class QSystemLocaleSingleton; + inline qsizetype fallbackLocaleIndex() const; }; Q_DECLARE_TYPEINFO(QSystemLocale::QueryType, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(QSystemLocale::CurrencyToStringArgument, Q_RELOCATABLE_TYPE); -#endif #if QT_CONFIG(icu) namespace QIcu { @@ -148,49 +188,64 @@ namespace QIcu { struct QLocaleId { - Q_CORE_EXPORT static QLocaleId fromName(const QString &name); - inline bool operator==(QLocaleId other) const - { return language_id == other.language_id && script_id == other.script_id && country_id == other.country_id; } - inline bool operator!=(QLocaleId other) const + [[nodiscard]] Q_AUTOTEST_EXPORT static QLocaleId fromName(QStringView name); + [[nodiscard]] inline bool operator==(QLocaleId other) const + { return language_id == other.language_id && script_id == other.script_id && territory_id == other.territory_id; } + [[nodiscard]] inline bool operator!=(QLocaleId other) const { return !operator==(other); } - inline bool isValid() const + [[nodiscard]] inline bool isValid() const { return language_id <= QLocale::LastLanguage && script_id <= QLocale::LastScript - && country_id <= QLocale::LastCountry; + && territory_id <= QLocale::LastTerritory; } - inline bool matchesAll() const + [[nodiscard]] inline bool matchesAll() const { - return !language_id && !script_id && !country_id; + return !language_id && !script_id && !territory_id; } // Use as: filter.accept...(candidate) - inline bool acceptLanguage(quint16 lang) const + [[nodiscard]] inline bool acceptLanguage(quint16 lang) const { // Always reject AnyLanguage (only used for last entry in locale_data array). // So, when searching for AnyLanguage, accept everything *but* AnyLanguage. return language_id ? lang == language_id : lang; } - inline bool acceptScriptCountry(QLocaleId other) const + [[nodiscard]] inline bool acceptScriptTerritory(QLocaleId other) const { - return (!country_id || other.country_id == country_id) + return (!territory_id || other.territory_id == territory_id) && (!script_id || other.script_id == script_id); } - QLocaleId withLikelySubtagsAdded() const; - QLocaleId withLikelySubtagsRemoved() const; + [[nodiscard]] QLocaleId withLikelySubtagsAdded() const; + [[nodiscard]] QLocaleId withLikelySubtagsRemoved() const; - QByteArray name(char separator = '-') const; + [[nodiscard]] QByteArray name(char separator = '-') const; - ushort language_id = 0, script_id = 0, country_id = 0; + ushort language_id = 0, script_id = 0, territory_id = 0; }; Q_DECLARE_TYPEINFO(QLocaleId, Q_PRIMITIVE_TYPE); + +using CharBuff = QVarLengthArray<char, 256>; + +struct ParsingResult +{ + enum State { // A duplicate of QValidator::State + Invalid, + Intermediate, + Acceptable + }; + + State state = Invalid; + CharBuff buff; +}; + struct QLocaleData { public: // Having an index for each locale enables us to have diverse sources of // data, e.g. calendar locales, as well as the main CLDR-derived data. - static int findLocaleIndex(QLocaleId localeId); - static const QLocaleData *c(); + [[nodiscard]] static qsizetype findLocaleIndex(QLocaleId localeId); + [[nodiscard]] static const QLocaleData *c(); enum DoubleForm { DFExponent = 0, @@ -217,8 +272,6 @@ public: enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode }; - typedef QVarLengthArray<char, 256> CharBuff; - private: enum PrecisionMode { PMDecimalDigits = 0x01, @@ -226,103 +279,146 @@ private: PMChopTrailingZeros = 0x03 }; - QString decimalForm(QString &&digits, int decpt, int precision, - PrecisionMode pm, bool mustMarkDecimal, - bool groupDigits) const; - QString exponentForm(QString &&digits, int decpt, int precision, - PrecisionMode pm, bool mustMarkDecimal, - int minExponentDigits) const; - QString signPrefix(bool negative, unsigned flags) const; - QString applyIntegerFormatting(QString &&numStr, bool negative, int precision, - int base, int width, unsigned flags) const; + [[nodiscard]] QString decimalForm(QString &&digits, int decpt, int precision, + PrecisionMode pm, bool mustMarkDecimal, + bool groupDigits) const; + [[nodiscard]] QString exponentForm(QString &&digits, int decpt, int precision, + PrecisionMode pm, bool mustMarkDecimal, + int minExponentDigits) const; + [[nodiscard]] QString signPrefix(bool negative, unsigned flags) const; + [[nodiscard]] QString applyIntegerFormatting(QString &&numStr, bool negative, int precision, + int base, int width, unsigned flags) const; public: - QString doubleToString(double d, - int precision = -1, - DoubleForm form = DFSignificantDigits, - int width = -1, - unsigned flags = NoFlags) const; - QString longLongToString(qint64 l, int precision = -1, - int base = 10, - int width = -1, - unsigned flags = NoFlags) const; - QString unsLongLongToString(quint64 l, int precision = -1, - int base = 10, - int width = -1, - unsigned flags = NoFlags) const; + [[nodiscard]] QString doubleToString(double d, + int precision = -1, + DoubleForm form = DFSignificantDigits, + int width = -1, + unsigned flags = NoFlags) const; + [[nodiscard]] QString longLongToString(qint64 l, int precision = -1, + int base = 10, + int width = -1, + unsigned flags = NoFlags) const; + [[nodiscard]] QString unsLongLongToString(quint64 l, int precision = -1, + int base = 10, + int width = -1, + unsigned flags = NoFlags) const; // this function is meant to be called with the result of stringToDouble or bytearrayToDouble - static float convertDoubleToFloat(double d, bool *ok) + // so *ok must have been properly set (if not null) + [[nodiscard]] static float convertDoubleToFloat(double d, bool *ok) { - if (qIsInf(d)) - return float(d); - if (std::fabs(d) > std::numeric_limits<float>::max()) { - if (ok) - *ok = false; - const float huge = std::numeric_limits<float>::infinity(); - return d < 0 ? -huge : huge; - } - if (d != 0 && float(d) == 0) { - // Values that underflow double already failed. Match them: - if (ok) - *ok = false; - return 0; - } - return float(d); + float result; + bool b = convertDoubleTo<float>(d, &result); + if (ok && *ok) + *ok = b; + return result; } - double stringToDouble(QStringView str, bool *ok, QLocale::NumberOptions options) const; - qint64 stringToLongLong(QStringView str, int base, bool *ok, QLocale::NumberOptions options) const; - quint64 stringToUnsLongLong(QStringView str, int base, bool *ok, QLocale::NumberOptions options) const; + [[nodiscard]] double stringToDouble(QStringView str, bool *ok, + QLocale::NumberOptions options) const; + [[nodiscard]] QSimpleParsedNumber<qint64> + stringToLongLong(QStringView str, int base, QLocale::NumberOptions options) const; + [[nodiscard]] QSimpleParsedNumber<quint64> + stringToUnsLongLong(QStringView str, int base, QLocale::NumberOptions options) const; // this function is used in QIntValidator (QtGui) - Q_CORE_EXPORT static qint64 bytearrayToLongLong(const char *num, int base, bool *ok); - static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok); + [[nodiscard]] Q_CORE_EXPORT + static QSimpleParsedNumber<qint64> bytearrayToLongLong(QByteArrayView num, int base); + [[nodiscard]] static QSimpleParsedNumber<quint64> + bytearrayToUnsLongLong(QByteArrayView num, int base); + + [[nodiscard]] bool numberToCLocale(QStringView s, QLocale::NumberOptions number_options, + NumberMode mode, CharBuff *result) const; - bool numberToCLocale(QStringView s, QLocale::NumberOptions number_options, - CharBuff *result) const; - inline char numericToCLocale(QStringView in) const; + struct NumericData + { +#ifndef QT_NO_SYSTEMLOCALE + // Only used for the system locale, to store data for the view to look at: + QString sysDecimal, sysGroup, sysMinus, sysPlus; +#endif + QStringView decimal, group, minus, plus, exponent; + char32_t zeroUcs = 0; + qint8 zeroLen = 0; + bool isC = false; // C locale sets this and nothing else. + bool exponentCyrillic = false; // True only for floating-point parsing of Cyrillic. + void setZero(QStringView zero) + { + // No known locale has digits that are more than one Unicode + // code-point, so we can safely deal with digits as plain char32_t. + switch (zero.size()) { + case 1: + Q_ASSERT(!zero.at(0).isSurrogate()); + zeroUcs = zero.at(0).unicode(); + zeroLen = 1; + break; + case 2: + Q_ASSERT(zero.at(0).isHighSurrogate()); + zeroUcs = QChar::surrogateToUcs4(zero.at(0), zero.at(1)); + zeroLen = 2; + break; + default: + Q_ASSERT(zero.size() == 0); // i.e. we got no value to use + break; + } + } + [[nodiscard]] bool isValid(NumberMode mode) const // Asserted as a sanity check. + { + if (isC) + return true; + if (exponentCyrillic && exponent != u"E" && exponent != u"\u0415") + return false; + return (zeroLen == 1 || zeroLen == 2) && zeroUcs > 0 + && (mode == IntegerMode || !decimal.isEmpty()) + // group may be empty (user config in system locale) + && !minus.isEmpty() && !plus.isEmpty() + && (mode != DoubleScientificMode || !exponent.isEmpty()); + } + }; + [[nodiscard]] inline NumericData numericData(NumberMode mode) const; // this function is used in QIntValidator (QtGui) - Q_CORE_EXPORT bool validateChars(QStringView str, NumberMode numMode, QByteArray *buff, int decDigits = -1, - QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const; + [[nodiscard]] Q_CORE_EXPORT ParsingResult + validateChars(QStringView str, NumberMode numMode, int decDigits = -1, + QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const; // Access to assorted data members: - QLocaleId id() const { return QLocaleId { m_language_id, m_script_id, m_country_id }; } - - QString decimalPoint() const; - QString groupSeparator() const; - QString listSeparator() const; - QString percentSign() const; - QString zeroDigit() const; - char32_t zeroUcs() const; - QString positiveSign() const; - QString negativeSign() const; - QString exponentSeparator() const; + [[nodiscard]] QLocaleId id() const + { return QLocaleId { m_language_id, m_script_id, m_territory_id }; } + + [[nodiscard]] QString decimalPoint() const; + [[nodiscard]] QString groupSeparator() const; + [[nodiscard]] QString listSeparator() const; + [[nodiscard]] QString percentSign() const; + [[nodiscard]] QString zeroDigit() const; + [[nodiscard]] char32_t zeroUcs() const; + [[nodiscard]] QString positiveSign() const; + [[nodiscard]] QString negativeSign() const; + [[nodiscard]] QString exponentSeparator() const; struct DataRange { quint16 offset; quint16 size; - QString getData(const char16_t *table) const + [[nodiscard]] QString getData(const char16_t *table) const { return size > 0 ? QString::fromRawData(reinterpret_cast<const QChar *>(table + offset), size) : QString(); } - QStringView viewData(const char16_t *table) const + [[nodiscard]] QStringView viewData(const char16_t *table) const { return { reinterpret_cast<const QChar *>(table + offset), size }; } - QString getListEntry(const char16_t *table, int index) const + [[nodiscard]] QString getListEntry(const char16_t *table, qsizetype index) const { return listEntry(table, index).getData(table); } - QStringView viewListEntry(const char16_t *table, int index) const + [[nodiscard]] QStringView viewListEntry(const char16_t *table, qsizetype index) const { return listEntry(table, index).viewData(table); } - char32_t ucsFirst(const char16_t *table) const + [[nodiscard]] char32_t ucsFirst(const char16_t *table) const { if (size && !QChar::isSurrogate(table[offset])) return table[offset]; @@ -331,7 +427,7 @@ public: return 0; } private: - DataRange listEntry(const char16_t *table, int index) const + [[nodiscard]] DataRange listEntry(const char16_t *table, qsizetype index) const { const char16_t separator = ';'; quint16 i = 0; @@ -359,15 +455,15 @@ public: X(byteCount) X(byteAmountSI) X(byteAmountIEC) \ X(currencySymbol) X(currencyDisplayName) \ X(currencyFormat) X(currencyFormatNegative) \ - X(endonymLanguage) X(endonymCountry) + X(endonymLanguage) X(endonymTerritory) #define rangeGetter(name) \ - DataRange name() const { return { m_ ## name ## _idx, m_ ## name ## _size }; } + [[nodiscard]] DataRange name() const { return { m_ ## name ## _idx, m_ ## name ## _size }; } ForEachQLocaleRange(rangeGetter) #undef rangeGetter public: - quint16 m_language_id, m_script_id, m_country_id; + quint16 m_language_id, m_script_id, m_territory_id; // Offsets, then sizes, for each range: #define rangeIndex(name) quint16 m_ ## name ## _idx; @@ -386,49 +482,60 @@ public: quint8 m_first_day_of_week : 3; quint8 m_weekend_start : 3; quint8 m_weekend_end : 3; - quint8 m_grouping_top : 2; // Must have this many before the first grouping separator + quint8 m_grouping_top : 2; // Don't group until more significant group has this many digits. quint8 m_grouping_higher : 3; // Number of digits between grouping separators quint8 m_grouping_least : 3; // Number of digits after last grouping separator (before decimal). }; -class Q_CORE_EXPORT QLocalePrivate +class QLocalePrivate { public: - constexpr QLocalePrivate(const QLocaleData *data, const uint index, + constexpr QLocalePrivate(const QLocaleData *data, qsizetype index, QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions, int refs = 0) : m_data(data), ref Q_BASIC_ATOMIC_INITIALIZER(refs), m_index(index), m_numberOptions(numberOptions) {} - quint16 languageId() const { return m_data->m_language_id; } - quint16 countryId() const { return m_data->m_country_id; } + [[nodiscard]] quint16 languageId() const { return m_data->m_language_id; } + [[nodiscard]] quint16 territoryId() const { return m_data->m_territory_id; } - QByteArray bcp47Name(char separator = '-') const; - QByteArray rawName(char separator = '-') const; + [[nodiscard]] QByteArray bcp47Name(char separator = '-') const; - inline QLatin1String languageCode() const { return languageToCode(QLocale::Language(m_data->m_language_id)); } - inline QLatin1String scriptCode() const { return scriptToCode(QLocale::Script(m_data->m_script_id)); } - inline QLatin1String countryCode() const { return countryToCode(QLocale::Country(m_data->m_country_id)); } - - static const QLocalePrivate *get(const QLocale &l) { return l.d; } - static QLatin1String languageToCode(QLocale::Language language); - static QLatin1String scriptToCode(QLocale::Script script); - static QLatin1String countryToCode(QLocale::Country country); - static QLocale::Language codeToLanguage(QStringView code) noexcept; - static QLocale::Script codeToScript(QStringView code) noexcept; - static QLocale::Country codeToCountry(QStringView code) noexcept; - - QLocale::MeasurementSystem measurementSystem() const; + [[nodiscard]] inline std::array<char, 4> + languageCode(QLocale::LanguageCodeTypes codeTypes = QLocale::AnyLanguageCode) const + { + return languageToCode(QLocale::Language(m_data->m_language_id), codeTypes); + } + [[nodiscard]] inline QLatin1StringView scriptCode() const + { return scriptToCode(QLocale::Script(m_data->m_script_id)); } + [[nodiscard]] inline QLatin1StringView territoryCode() const + { return territoryToCode(QLocale::Territory(m_data->m_territory_id)); } + + [[nodiscard]] static const QLocalePrivate *get(const QLocale &l) { return l.d; } + [[nodiscard]] static std::array<char, 4> + languageToCode(QLocale::Language language, + QLocale::LanguageCodeTypes codeTypes = QLocale::AnyLanguageCode); + [[nodiscard]] static QLatin1StringView scriptToCode(QLocale::Script script); + [[nodiscard]] static QLatin1StringView territoryToCode(QLocale::Territory territory); + [[nodiscard]] static QLocale::Language + codeToLanguage(QStringView code, + QLocale::LanguageCodeTypes codeTypes = QLocale::AnyLanguageCode) noexcept; + [[nodiscard]] static QLocale::Script codeToScript(QStringView code) noexcept; + [[nodiscard]] static QLocale::Territory codeToTerritory(QStringView code) noexcept; + + [[nodiscard]] QLocale::MeasurementSystem measurementSystem() const; // System locale has an m_data all its own; all others have m_data = locale_data + m_index const QLocaleData *const m_data; QBasicAtomicInt ref; - const uint m_index; + qsizetype m_index; // System locale needs this updated when m_data->id() changes. QLocale::NumberOptions m_numberOptions; + + static QBasicAtomicInt s_generation; }; #ifndef QT_NO_SYSTEMLOCALE -uint QSystemLocale::fallbackLocaleIndex() const { return fallbackLocale().d->m_index; } +qsizetype QSystemLocale::fallbackLocaleIndex() const { return fallbackLocale().d->m_index; } #endif template <> @@ -439,88 +546,26 @@ inline QLocalePrivate *QSharedDataPointer<QLocalePrivate>::clone() return new QLocalePrivate(d->m_data, d->m_index, d->m_numberOptions); } -inline char QLocaleData::numericToCLocale(QStringView in) const -{ - Q_ASSERT(in.size() == 1 || (in.size() == 2 && in.at(0).isHighSurrogate())); - - if (in == positiveSign() || in == u"+") - return '+'; - - if (in == negativeSign() || in == u"-" || in == u"\x2212") - return '-'; - - if (in == decimalPoint()) - return '.'; - - if (in.compare(exponentSeparator(), Qt::CaseInsensitive) == 0) - return 'e'; - - const QString group = groupSeparator(); - if (in == group) - return ','; - - // In several languages group() is a non-breaking space (U+00A0) or its thin - // version (U+202f), which look like spaces. People (and thus some of our - // tests) use a regular space instead and complain if it doesn't work. - // Should this be extended generally to any case where group is a space ? - if ((group == u"\xa0" || group == u"\x202f") && in == u" ") - return ','; - - const char32_t inUcs4 = in.size() == 2 - ? QChar::surrogateToUcs4(in.at(0), in.at(1)) : in.at(0).unicode(); - const char32_t zeroUcs4 = zeroUcs(); - // Must match qlocale_tools.h's unicodeForDigit() - if (zeroUcs4 == u'\u3007') { - // QTBUG-85409: Suzhou's digits aren't contiguous ! - if (inUcs4 == zeroUcs4) - return '0'; - if (inUcs4 > u'\u3020' && inUcs4 <= u'\u3029') - return inUcs4 - u'\u3020'; - } else if (zeroUcs4 <= inUcs4 && inUcs4 < zeroUcs4 + 10) { - return '0' + inUcs4 - zeroUcs4; - } - if ('0' <= inUcs4 && inUcs4 <= '9') - return inUcs4; +// Also used to merely skip over an escape in a format string, advancint idx to +// point after it (so not [[nodiscard]]): +QString qt_readEscapedFormatString(QStringView format, qsizetype *idx); +[[nodiscard]] bool qt_splitLocaleName(QStringView name, QStringView *lang = nullptr, + QStringView *script = nullptr, QStringView *cntry = nullptr); +[[nodiscard]] qsizetype qt_repeatCount(QStringView s); - return 0; -} - -QString qt_readEscapedFormatString(QStringView format, int *idx); -bool qt_splitLocaleName(QStringView name, QStringView *lang = nullptr, - QStringView *script = nullptr, QStringView *cntry = nullptr); -int qt_repeatCount(QStringView s); - -enum { AsciiSpaceMask = (1u << (' ' - 1)) | - (1u << ('\t' - 1)) | // 9: HT - horizontal tab - (1u << ('\n' - 1)) | // 10: LF - line feed - (1u << ('\v' - 1)) | // 11: VT - vertical tab - (1u << ('\f' - 1)) | // 12: FF - form feed - (1u << ('\r' - 1)) }; // 13: CR - carriage return -constexpr inline bool ascii_isspace(uchar c) +[[nodiscard]] constexpr inline bool ascii_isspace(uchar c) { - return c >= 1u && c <= 32u && (AsciiSpaceMask >> uint(c - 1)) & 1u; + constexpr auto matcher = QtPrivate::makeCharacterSetMatch<QtPrivate::ascii_space_chars>(); + return matcher.matches(c); } -static_assert(ascii_isspace(' ')); -static_assert(ascii_isspace('\t')); -static_assert(ascii_isspace('\n')); -static_assert(ascii_isspace('\v')); -static_assert(ascii_isspace('\f')); -static_assert(ascii_isspace('\r')); -static_assert(!ascii_isspace('\0')); -static_assert(!ascii_isspace('\a')); -static_assert(!ascii_isspace('a')); -static_assert(!ascii_isspace('\177')); -static_assert(!ascii_isspace(uchar('\200'))); -static_assert(!ascii_isspace(uchar('\xA0'))); -static_assert(!ascii_isspace(uchar('\377'))); - QT_END_NAMESPACE -Q_DECLARE_METATYPE(QStringView) -Q_DECLARE_METATYPE(QList<Qt::DayOfWeek>) +// ### move to qnamespace.h +QT_DECL_METATYPE_EXTERN_TAGGED(QList<Qt::DayOfWeek>, QList_Qt__DayOfWeek, Q_CORE_EXPORT) #ifndef QT_NO_SYSTEMLOCALE -Q_DECLARE_METATYPE(QSystemLocale::CurrencyToStringArgument) +QT_DECL_METATYPE_EXTERN_TAGGED(QSystemLocale::CurrencyToStringArgument, + QSystemLocale__CurrencyToStringArgument, Q_CORE_EXPORT) #endif #endif // QLOCALE_P_H |