summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qlocale.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text/qlocale.cpp')
-rw-r--r--src/corelib/text/qlocale.cpp650
1 files changed, 301 insertions, 349 deletions
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index 6e33e27276..9e3043046d 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -661,9 +661,8 @@ static QLocalePrivate *c_private()
}
static const QLocaleData *systemData();
-static QLocale::NumberOptions system_number_options = QLocale::DefaultNumberOptions;
Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<QLocalePrivate>, systemLocalePrivate,
- (QLocalePrivate::create(systemData(), system_number_options)))
+ (QLocalePrivate::create(systemData())))
#ifndef QT_NO_SYSTEMLOCALE
/******************************************************************************
@@ -724,14 +723,11 @@ static void updateSystemPrivate()
// Populate global with fallback as basis:
globalLocaleData = *sys_locale->fallbackUiLocaleData();
- system_number_options = QLocale::DefaultNumberOptions;
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
- if (globalLocaleData.m_language_id == QLocale::C)
- system_number_options = QLocale::OmitGroupSeparator;
}
res = sys_locale->query(QSystemLocale::CountryId, QVariant());
if (!res.isNull()) {
@@ -742,46 +738,7 @@ static void updateSystemPrivate()
if (!res.isNull())
globalLocaleData.m_script_id = res.toInt();
- res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant());
- if (!res.isNull() && !res.toString().isEmpty())
- globalLocaleData.m_decimal = res.toString().at(0).unicode();
-
- // System may supply empty group separator to say we should omit grouping;
- // and it makes no sense to use the same separator for decimal and grouping
- // (which might happen by system supplying, as decimal, what CLDR has given
- // us for grouping; or the other way round). Assume, at least, that each of
- // system and CLDR has decimal != group, all the same.
- res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant());
- if (res.isNull()) {
- // The case where system over-rides decimal but not group, and its
- // decimal clashes with CLDR's group.
- if (globalLocaleData.m_group == globalLocaleData.m_decimal)
- system_number_options |= QLocale::OmitGroupSeparator;
- } else if (res.toString().isEmpty()) {
- system_number_options |= QLocale::OmitGroupSeparator;
- } else {
- const ushort group = res.toString().at(0).unicode();
- if (group != globalLocaleData.m_decimal)
- globalLocaleData.m_group = group;
- else if (group == globalLocaleData.m_group)
- qWarning("System-supplied decimal and grouping character are both 0x%hx", group);
- }
-
- res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant());
- if (!res.isNull() && !res.toString().isEmpty())
- globalLocaleData.m_zero = res.toString().at(0).unicode();
-
- res = sys_locale->query(QSystemLocale::NegativeSign, QVariant());
- if (!res.isNull() && !res.toString().isEmpty())
- globalLocaleData.m_minus = res.toString().at(0).unicode();
-
- res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
- if (!res.isNull() && !res.toString().isEmpty())
- globalLocaleData.m_plus = res.toString().at(0).unicode();
-
- if (systemLocalePrivate.exists())
- systemLocalePrivate->data()->m_numberOptions = system_number_options;
- // else: system_number_options will be passed to create() when constructing.
+ // Should we replace Any values based on likely sub-tags ?
}
#endif // !QT_NO_SYSTEMLOCALE
@@ -821,28 +778,6 @@ const QLocaleData *QLocaleData::c()
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)
{
@@ -897,6 +832,97 @@ static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Sc
return QLocalePrivate::create(data, offset, numberOptions);
}
+QString QLocaleData::decimalPoint() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (this == systemData()) {
+ QVariant res = systemLocale()->query(QSystemLocale::DecimalPoint, QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ return decimalSeparator().getData(single_character_data);
+}
+
+QString QLocaleData::groupSeparator() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (this == systemData()) {
+ QVariant res = systemLocale()->query(QSystemLocale::GroupSeparator, QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ return groupDelim().getData(single_character_data);
+}
+
+QString QLocaleData::percentSign() const
+{
+ return percent().getData(single_character_data);
+}
+
+QString QLocaleData::listSeparator() const
+{
+ return listDelimit().getData(single_character_data);
+}
+
+QString QLocaleData::zeroDigit() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (this == systemData()) {
+ QVariant res = systemLocale()->query(QSystemLocale::ZeroDigit, QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ return zero().getData(single_character_data);
+}
+
+uint QLocaleData::zeroUcs() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (this == systemData()) {
+ QVariant res = systemLocale()->query(QSystemLocale::ZeroDigit, QVariant());
+ if (!res.isNull()) {
+ const QString text = res.toString();
+ if (text.size() == 1 && !text.at(0).isSurrogate())
+ return text.at(0).unicode();
+ if (text.size() == 2 && text.at(0).isHighSurrogate())
+ return QChar::surrogateToUcs4(text.at(0), text.at(1));
+ }
+ }
+#endif
+ return zero().ucsFirst(single_character_data);
+}
+
+QString QLocaleData::negativeSign() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (this == systemData()) {
+ QVariant res = systemLocale()->query(QSystemLocale::NegativeSign, QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ return minus().getData(single_character_data);
+}
+
+QString QLocaleData::positiveSign() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (this == systemData()) {
+ QVariant res = systemLocale()->query(QSystemLocale::PositiveSign, QVariant());
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+ return plus().getData(single_character_data);
+}
+
+QString QLocaleData::exponentSeparator() const
+{
+ return exponential().getData(single_character_data);
+}
/*!
\internal
@@ -1132,11 +1158,16 @@ QString QLocale::quoteString(const QStringRef &str, QuotationStyle style) const
}
#endif
- if (style == QLocale::StandardQuotation)
- return QChar(d->m_data->m_quotation_start) % str % QChar(d->m_data->m_quotation_end);
+ QLocaleData::DataRange start, end;
+ if (style == QLocale::StandardQuotation) {
+ start = d->m_data->quoteStart();
+ end = d->m_data->quoteEnd();
+ } else {
+ start = d->m_data->quoteStartAlternate();
+ end = d->m_data->quoteEndAlternate();
+ }
- return QChar(d->m_data->m_alternate_quotation_start)
- % str % QChar(d->m_data->m_alternate_quotation_end);
+ return start.viewData(single_character_data) % str % end.viewData(single_character_data);
}
/*!
@@ -1158,31 +1189,24 @@ QString QLocale::createSeparatedList(const QStringList &list) const
#endif
const int size = list.size();
- if (size == 1) {
+ if (size < 1)
+ return QString();
+
+ 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();
+ if (size == 2)
+ return d->m_data->pairListPattern().getData(
+ list_pattern_part_data).arg(list.at(0), list.at(1));
+
+ QStringView formatStart = d->m_data->startListPattern().viewData(list_pattern_part_data);
+ QStringView formatMid = d->m_data->midListPattern().viewData(list_pattern_part_data);
+ QStringView formatEnd = d->m_data->endListPattern().viewData(list_pattern_part_data);
+ 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;
}
/*!
@@ -2030,7 +2054,7 @@ QString QLocale::toString(qulonglong i) const
\sa QDate::toString()
*/
-QString QLocale::toString(const QDate &date, const QString &format) const
+QString QLocale::toString(QDate date, const QString &format) const
{
return QCalendar().dateTimeToString(format, QDateTime(), date, QTime(), *this);
}
@@ -2045,7 +2069,7 @@ QString QLocale::toString(const QDate &date, const QString &format) const
\sa QDate::toString()
*/
-QString QLocale::toString(const QDate &date, QStringView format) const
+QString QLocale::toString(QDate date, QStringView format) const
{
return QCalendar().dateTimeToString(format, QDateTime(), date, QTime(), *this);
}
@@ -2058,7 +2082,7 @@ QString QLocale::toString(const QDate &date, QStringView format) const
represent.
*/
-QString QLocale::toString(const QDate &date, FormatType format) const
+QString QLocale::toString(QDate date, FormatType format) const
{
if (!date.isValid())
return QString();
@@ -2103,7 +2127,7 @@ static bool timeFormatContainsAP(QStringView format)
\sa QTime::toString()
*/
-QString QLocale::toString(const QTime &time, const QString &format) const
+QString QLocale::toString(QTime time, const QString &format) const
{
return QCalendar().dateTimeToString(format, QDateTime(), QDate(), time, *this);
}
@@ -2118,7 +2142,7 @@ QString QLocale::toString(const QTime &time, const QString &format) const
\sa QTime::toString()
*/
-QString QLocale::toString(const QTime &time, QStringView format) const
+QString QLocale::toString(QTime time, QStringView format) const
{
return QCalendar().dateTimeToString(format, QDateTime(), QDate(), time, *this);
}
@@ -2154,12 +2178,12 @@ QString QLocale::toString(const QDateTime &dateTime, QStringView format) const
return QCalendar().dateTimeToString(format, dateTime, QDate(), QTime(), *this);
}
-QString QLocale::toString(const QDate &date, QStringView format, QCalendar cal) const
+QString QLocale::toString(QDate date, QStringView format, QCalendar cal) const
{
return cal.dateTimeToString(format, QDateTime(), date, QTime(), *this);
}
-QString QLocale::toString(const QDate &date, QLocale::FormatType format, QCalendar cal) const
+QString QLocale::toString(QDate date, QLocale::FormatType format, QCalendar cal) const
{
if (!date.isValid())
return QString();
@@ -2241,7 +2265,7 @@ QString QLocale::toString(const QDateTime &dateTime, FormatType format) const
specified \a format.
*/
-QString QLocale::toString(const QTime &time, FormatType format) const
+QString QLocale::toString(QTime time, FormatType format) const
{
if (!time.isValid())
return QString();
@@ -2285,18 +2309,10 @@ QString QLocale::dateFormat(FormatType format) const
}
#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);
+ return (format == LongFormat
+ ? d->m_data->longDateFormat()
+ : d->m_data->shortDateFormat()
+ ).getData(date_format_data);
}
/*!
@@ -2323,18 +2339,10 @@ QString QLocale::timeFormat(FormatType format) const
}
#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);
+ return (format == LongFormat
+ ? d->m_data->longTimeFormat()
+ : d->m_data->shortTimeFormat()
+ ).getData(time_format_data);
}
/*!
@@ -2580,15 +2588,11 @@ QDateTime QLocale::toDateTime(const QString &string, const QString &format, QCal
Returns the decimal point character of this locale.
- \note This function shall change to return a QString instead of QChar in
- Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
- convert early in preparation for this.
-
\sa groupSeparator(), toString()
*/
-QChar QLocale::decimalPoint() const
+QString QLocale::decimalPoint() const
{
- return d->decimal();
+ return d->m_data->decimalPoint();
}
/*!
@@ -2596,15 +2600,11 @@ QChar QLocale::decimalPoint() const
Returns the group separator character of this locale.
- \note This function shall change to return a QString instead of QChar in
- Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
- convert early in preparation for this.
-
\sa decimalPoint(), toString()
*/
-QChar QLocale::groupSeparator() const
+QString QLocale::groupSeparator() const
{
- return d->group();
+ return d->m_data->groupSeparator();
}
/*!
@@ -2612,15 +2612,11 @@ QChar QLocale::groupSeparator() const
Returns the percent character of this locale.
- \note This function shall change to return a QString instead of QChar in
- Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
- convert early in preparation for this.
-
\sa toString()
*/
-QChar QLocale::percent() const
+QString QLocale::percent() const
{
- return d->percent();
+ return d->m_data->percentSign();
}
/*!
@@ -2628,15 +2624,11 @@ QChar QLocale::percent() const
Returns the zero digit character of this locale.
- \note This function shall change to return a QString instead of QChar in
- Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
- convert early in preparation for this.
-
\sa toString()
*/
-QChar QLocale::zeroDigit() const
+QString QLocale::zeroDigit() const
{
- return d->zero();
+ return d->m_data->zeroDigit();
}
/*!
@@ -2644,15 +2636,11 @@ QChar QLocale::zeroDigit() const
Returns the negative sign character of this locale.
- \note This function shall change to return a QString instead of QChar in
- Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
- convert early in preparation for this.
-
\sa positiveSign(), toString()
*/
-QChar QLocale::negativeSign() const
+QString QLocale::negativeSign() const
{
- return d->minus();
+ return d->m_data->negativeSign();
}
/*!
@@ -2660,15 +2648,11 @@ QChar QLocale::negativeSign() const
Returns the positive sign character of this locale.
- \note This function shall change to return a QString instead of QChar in
- Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
- convert early in preparation for this.
-
\sa negativeSign(), toString()
*/
-QChar QLocale::positiveSign() const
+QString QLocale::positiveSign() const
{
- return d->plus();
+ return d->m_data->positiveSign();
}
/*!
@@ -2677,15 +2661,11 @@ QChar QLocale::positiveSign() const
Returns the exponential character of this locale, used to separate exponent
from mantissa in some floating-point numeric representations.
- \note This function shall change to return a QString instead of QChar in
- Qt6. Callers are encouraged to exploit the QString(QChar) constructor to
- convert early in preparation for this.
-
\sa toString(double, char, int)
*/
-QChar QLocale::exponential() const
+QString QLocale::exponential() const
{
- return d->exponential();
+ return d->m_data->exponentSeparator();
}
static bool qIsUpper(char c)
@@ -2918,27 +2898,24 @@ QString QLocale::standaloneDayName(int day, FormatType type) const
*/
static QString rawMonthName(const QCalendarLocale &localeData,
- const ushort *monthsData, int month,
+ const char16_t *monthsData, int month,
QLocale::FormatType type)
{
- quint32 idx, size;
+ QLocaleData::DataRange range;
switch (type) {
case QLocale::LongFormat:
- idx = localeData.m_long.index;
- size = localeData.m_long.size;
- break;
+ range = localeData.longMonth();
+ break;
case QLocale::ShortFormat:
- idx = localeData.m_short.index;
- size = localeData.m_short.size;
- break;
+ range = localeData.shortMonth();
+ break;
case QLocale::NarrowFormat:
- idx = localeData.m_narrow.index;
- size = localeData.m_narrow.size;
- break;
+ range = localeData.narrowMonth();
+ break;
default:
- return QString();
+ return QString();
}
- return getLocaleListData(monthsData + idx, size, month - 1);
+ return range.getListEntry(monthsData, month - 1);
}
/*!
@@ -2946,27 +2923,24 @@ static QString rawMonthName(const QCalendarLocale &localeData,
*/
static QString rawStandaloneMonthName(const QCalendarLocale &localeData,
- const ushort *monthsData, int month,
+ const char16_t *monthsData, int month,
QLocale::FormatType type)
{
- quint32 idx, size;
+ QLocaleData::DataRange range;
switch (type) {
case QLocale::LongFormat:
- idx = localeData.m_standalone_long.index;
- size = localeData.m_standalone_long.size;
+ range = localeData.longMonthStandalone();
break;
case QLocale::ShortFormat:
- idx = localeData.m_standalone_short.index;
- size = localeData.m_standalone_short.size;
+ range = localeData.shortMonthStandalone();
break;
case QLocale::NarrowFormat:
- idx = localeData.m_standalone_narrow.index;
- size = localeData.m_standalone_narrow.size;
+ range = localeData.narrowMonthStandalone();
break;
default:
return QString();
}
- QString name = getLocaleListData(monthsData + idx, size, month - 1);
+ QString name = range.getListEntry(monthsData, month - 1);
return name.isEmpty() ? rawMonthName(localeData, monthsData, month, type) : name;
}
@@ -2977,24 +2951,21 @@ static QString rawStandaloneMonthName(const QCalendarLocale &localeData,
static QString rawWeekDayName(const QLocaleData *data, const int day,
QLocale::FormatType type)
{
- quint32 idx, size;
+ QLocaleData::DataRange range;
switch (type) {
case QLocale::LongFormat:
- idx = data->m_long_day_names_idx;
- size = data->m_long_day_names_size;
+ range = data->longDayNames();
break;
case QLocale::ShortFormat:
- idx = data->m_short_day_names_idx;
- size = data->m_short_day_names_size;
+ range = data->shortDayNames();
break;
case QLocale::NarrowFormat:
- idx = data->m_narrow_day_names_idx;
- size = data->m_narrow_day_names_size;
+ range = data->narrowDayNames();
break;
default:
return QString();
}
- return getLocaleListData(days_data + idx, size, day == 7 ? 0 : day);
+ return range.getListEntry(days_data, day == 7 ? 0 : day);
}
/*!
@@ -3004,24 +2975,21 @@ static QString rawWeekDayName(const QLocaleData *data, const int day,
static QString rawStandaloneWeekDayName(const QLocaleData *data, const int day,
QLocale::FormatType type)
{
- quint32 idx, size;
+ QLocaleData::DataRange range;
switch (type) {
case QLocale::LongFormat:
- idx = data->m_standalone_long_day_names_idx;
- size = data->m_standalone_long_day_names_size;
+ range =data->longDayNamesStandalone();
break;
case QLocale::ShortFormat:
- idx = data->m_standalone_short_day_names_idx;
- size = data->m_standalone_short_day_names_size;
+ range = data->shortDayNamesStandalone();
break;
case QLocale::NarrowFormat:
- idx = data->m_standalone_narrow_day_names_idx;
- size = data->m_standalone_narrow_day_names_size;
+ range = data->narrowDayNamesStandalone();
break;
default:
return QString();
}
- QString name = getLocaleListData(days_data + idx, size, day == 7 ? 0 : day);
+ QString name = range.getListEntry(days_data, day == 7 ? 0 : day);
if (name.isEmpty())
return rawWeekDayName(data, day, type);
return name;
@@ -3305,7 +3273,7 @@ QString QLocale::amText() const
return res.toString();
}
#endif
- return getLocaleData(am_data + d->m_data->m_am_idx, d->m_data->m_am_size);
+ return d->m_data->anteMeridiem().getData(am_data);
}
/*!
@@ -3325,13 +3293,13 @@ QString QLocale::pmText() const
return res.toString();
}
#endif
- return getLocaleData(pm_data + d->m_data->m_pm_idx, d->m_data->m_pm_size);
+ return d->m_data->postMeridiem().getData(pm_data);
}
// Another intrusion from QCalendar, using some of the tools above:
QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &datetime,
- const QDate &dateOnly, const QTime &timeOnly,
+ QDate dateOnly, QTime timeOnly,
const QLocale &locale) const
{
QDate date;
@@ -3536,9 +3504,9 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
result.append(locale.d->m_data->longLongToString(time.msec(), -1, 10, 3,
QLocaleData::ZeroPadded));
if (repeat == 1) {
- if (result.endsWith(locale.d->zero()))
+ if (result.endsWith(locale.zeroDigit()))
result.chop(1);
- if (result.endsWith(locale.d->zero()))
+ if (result.endsWith(locale.zeroDigit()))
result.chop(1);
}
break;
@@ -3568,12 +3536,14 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
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,
+ return doubleToString(zeroDigit(), positiveSign(), negativeSign(),
+ exponentSeparator(), groupSeparator(), decimalPoint(),
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,
+QString QLocaleData::doubleToString(const QString &zero, const QString &plus, const QString &minus,
+ const QString &exponential,
+ const QString &group, const QString &decimal,
double d, int precision, DoubleForm form, int width,
unsigned flags)
{
@@ -3605,8 +3575,23 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
} else { // Handle normal numbers
QString digits = QString::fromLatin1(buf.data(), length);
- if (_zero.unicode() != '0') {
- ushort z = _zero.unicode() - '0';
+ if (zero == u"0") {
+ // No need to convert digits.
+ } else if (zero.size() == 2 && zero.at(0).isHighSurrogate()) {
+ const uint zeroUcs4 = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
+ QString converted;
+ converted.reserve(2 * digits.size());
+ for (int i = 0; i < digits.length(); ++i) {
+ const uint digit = zeroUcs4 - '0' + digits.at(i).unicode();
+ Q_ASSERT(QChar::requiresSurrogates(digit));
+ converted.append(QChar::highSurrogate(digit));
+ converted.append(QChar::lowSurrogate(digit));
+ }
+ digits = converted;
+ } else {
+ Q_ASSERT(zero.size() == 1);
+ Q_ASSERT(!zero.at(0).isSurrogate());
+ ushort z = zero.at(0).unicode() - '0';
for (int i = 0; i < digits.length(); ++i)
reinterpret_cast<ushort *>(digits.data())[i] += z;
}
@@ -3614,13 +3599,13 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
bool always_show_decpt = (flags & ForcePoint);
switch (form) {
case DFExponent: {
- num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
+ 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,
+ num_str = decimalForm(zero, decimal, group,
digits, decpt, precision, PMDecimalDigits,
always_show_decpt, flags & ThousandsGroup);
break;
@@ -3629,25 +3614,25 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
PrecisionMode mode = (flags & AddTrailingZeroes) ?
PMSignificantDigits : PMChopTrailingZeros;
+ const auto digitWidth = zero.size();
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 = digits.length() / digitWidth + 4; // 'e', '+'/'-', one digit exponent
+ if (decpt <= 10)
++cutoff;
- } else {
+ else
cutoff += decpt > 100 ? 2 : 1;
- }
- if (!always_show_decpt && digits.length() > decpt)
+ if (!always_show_decpt && digits.length() / digitWidth > 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,
+ if (decpt != digits.length() / digitWidth && (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,
+ num_str = decimalForm(zero, decimal, group,
digits, decpt, precision, mode,
always_show_decpt, flags & ThousandsGroup);
break;
@@ -3657,10 +3642,10 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
if (isZero(d))
negative = false;
- // pad with zeros. LeftAdjusted overrides this flag). Also, we don't
+ // 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();
+ int num_pad_chars = width - num_str.length() / zero.length();
// leave space for the sign
if (negative
|| flags & QLocaleData::AlwaysShowSign
@@ -3668,7 +3653,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
--num_pad_chars;
for (int i = 0; i < num_pad_chars; ++i)
- num_str.prepend(_zero);
+ num_str.prepend(zero);
}
}
@@ -3687,18 +3672,16 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
}
QString QLocaleData::longLongToString(qlonglong l, int precision,
- int base, int width,
- unsigned flags) const
+ int base, int width, unsigned flags) const
{
- return longLongToString(m_zero, m_group, m_plus, m_minus,
- l, precision, base, width, flags);
+ return longLongToString(zeroDigit(), groupSeparator(), positiveSign(), negativeSign(),
+ 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)
+QString QLocaleData::longLongToString(const QString &zero, const QString &group,
+ const QString &plus, const QString &minus,
+ qlonglong l, int precision,
+ int base, int width, unsigned flags)
{
bool precision_not_specified = false;
if (precision == -1) {
@@ -3724,17 +3707,19 @@ QT_WARNING_DISABLE_MSVC(4146)
QString num_str = qulltoa(negative ? -qulonglong(l) : qulonglong(l), base, zero);
QT_WARNING_POP
+ const QString resultZero = base == 10 ? zero : QStringLiteral("0");
+ const auto digitWidth = resultZero.size();
uint cnt_thousand_sep = 0;
- if (base == 10){
+ if (base == 10) {
if (flags & ThousandsGroup) {
- for (int i = num_str.length() - 3; i > 0; i -= 3) {
+ for (int i = num_str.length() / digitWidth - 3; i > 0; i -= 3 * digitWidth) {
num_str.insert(i, group);
++cnt_thousand_sep;
}
} else if (flags & IndianNumberGrouping) {
- if (num_str.length() > 3)
- num_str.insert(num_str.length() - 3 , group);
- for (int i = num_str.length() - 6; i > 0; i -= 2) {
+ if (num_str.length() > 3 * digitWidth)
+ num_str.insert(num_str.length() - 3 * digitWidth , group);
+ for (int i = num_str.length() - 6 * digitWidth; i > 0; i -= 2 * digitWidth) {
num_str.insert(i, group);
++cnt_thousand_sep;
}
@@ -3742,7 +3727,7 @@ QT_WARNING_POP
}
for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
- num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
+ num_str.prepend(resultZero);
if ((flags & ShowBase)
&& base == 8
@@ -3756,7 +3741,7 @@ QT_WARNING_POP
&& precision_not_specified;
if (zero_padded) {
- int num_pad_chars = width - num_str.length();
+ int num_pad_chars = width - num_str.length() / digitWidth;
// leave space for the sign
if (negative
@@ -3771,8 +3756,8 @@ QT_WARNING_POP
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'));
+ while (num_pad_chars-- > 0)
+ num_str.prepend(resultZero);
}
if (flags & CapitalEorX)
@@ -3795,21 +3780,19 @@ QT_WARNING_POP
}
QString QLocaleData::unsLongLongToString(qulonglong l, int precision,
- int base, int width,
- unsigned flags) const
+ int base, int width, unsigned flags) const
{
- return unsLongLongToString(m_zero, m_group, m_plus,
- l, precision, base, width, flags);
+ return unsLongLongToString(zeroDigit(), groupSeparator(), positiveSign(),
+ 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)
+QString QLocaleData::unsLongLongToString(const QString &zero, const QString &group,
+ const QString &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);
+ const QString resultZero = base == 10 ? zero : QStringLiteral("0");
+ QString num_str = l ? qulltoa(l, base, zero) : resultZero;
bool precision_not_specified = false;
if (precision == -1) {
@@ -3820,26 +3803,27 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
precision = 1;
}
+ const auto digitWidth = resultZero.size();
uint cnt_thousand_sep = 0;
if (base == 10) {
if (flags & ThousandsGroup) {
- for (int i = num_str.length() - 3; i > 0; i -=3) {
+ for (int i = num_str.length() - 3 * digitWidth; i > 0; i -= 3 * digitWidth) {
num_str.insert(i, group);
++cnt_thousand_sep;
}
} else if (flags & IndianNumberGrouping) {
- if (num_str.length() > 3)
- num_str.insert(num_str.length() - 3 , group);
- for (int i = num_str.length() - 6; i > 0; i -= 2) {
+ if (num_str.length() > 3 * digitWidth)
+ num_str.insert(num_str.length() - 3 * digitWidth , group);
+ for (int i = num_str.length() - 6 * digitWidth; i > 0; i -= 2 * digitWidth) {
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));
+ int zeroPadding = precision - num_str.length() / digitWidth /* + cnt_thousand_sep*/;
+ while (zeroPadding-- > 0)
+ num_str.prepend(resultZero);
if ((flags & ShowBase)
&& base == 8
@@ -3853,7 +3837,7 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
&& precision_not_specified;
if (zero_padded) {
- int num_pad_chars = width - num_str.length();
+ int num_pad_chars = width - num_str.length() / digitWidth;
// leave space for optional '0x' in hex form
if (base == 16 && flags & ShowBase)
@@ -3862,8 +3846,8 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
else if (base == 2 && flags & ShowBase)
num_pad_chars -= 2;
- if (num_pad_chars > 0)
- num_str.prepend(QString(num_pad_chars, resultZero));
+ while (num_pad_chars-- > 0)
+ num_str.prepend(resultZero);
}
if (flags & CapitalEorX)
@@ -3894,21 +3878,13 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
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)
+ s = s.trimmed();
+ if (s.size() < 1)
return false;
- // Check trailing whitespace
- for (; idx < l; --l) {
- if (!uc[l - 1].isSpace())
- break;
- }
+ const QChar *uc = s.data();
+ auto length = s.size();
+ decltype(length) idx = 0;
int group_cnt = 0; // counts number of group chars
int decpt_idx = -1;
@@ -3916,20 +3892,21 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o
int start_of_digits_idx = -1;
int exponent_idx = -1;
- while (idx < l) {
- const QChar in = uc[idx];
+ while (idx < length) {
+ const QStringView in = QStringView(uc + idx, uc[idx].isHighSurrogate() ? 2 : 1);
- char out = digitToCLocale(in);
+ char out = numericToCLocale(in);
if (out == 0) {
- if (in == m_list)
+ const QChar simple(in.size() == 1 ? in.front() : QChar(0));
+ if (in == listSeparator())
out = ';';
- else if (in == m_percent)
+ else if (in == percentSign())
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 if (simple.toLatin1() >= 'A' && simple.toLatin1() <= 'Z')
+ out = simple.toLower().toLatin1();
+ else if (simple.toLatin1() >= 'a' && simple.toLatin1() <= 'z')
+ out = simple.toLatin1();
else
break;
} else if (out == '.') {
@@ -3937,12 +3914,12 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o
if (decpt_idx != -1 || exponent_idx != -1)
return false;
decpt_idx = idx;
- } else if (out == 'e' || out == 'E') {
+ } else if (out == 'e') {
exponent_idx = idx;
}
if (number_options & QLocale::RejectLeadingZeroInExponent) {
- if (exponent_idx != -1 && out == '0' && idx < l - 1) {
+ if (exponent_idx != -1 && out == '0' && idx < length - 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')
@@ -3982,9 +3959,9 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o
++group_cnt;
// don't add the group separator
- ++idx;
+ idx += in.size();
continue;
- } else if (out == '.' || out == 'e' || out == 'E') {
+ } else if (out == '.' || idx == exponent_idx) {
// check distance from the last separator
// ### FIXME: Some locales allow other groupings!
// See https://en.wikipedia.org/wiki/Thousands_separator
@@ -3997,8 +3974,7 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o
}
result->append(out);
-
- ++idx;
+ idx += in.size();
}
if (!(number_options & QLocale::RejectGroupSeparator)) {
@@ -4018,7 +3994,7 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o
}
result->append('\0');
- return idx == l;
+ return idx == length;
}
bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray *buff,
@@ -4035,8 +4011,9 @@ bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray
bool dec = false;
int decDigitCnt = 0;
- for (qsizetype i = 0; i < str.size(); ++i) {
- char c = digitToCLocale(str.at(i));
+ for (qsizetype i = 0; i < str.size();) {
+ const QStringView in = str.mid(i, str.at(i).isHighSurrogate() ? 2 : 1);
+ char c = numericToCLocale(in);
if (c >= '0' && c <= '9') {
if (numMode != IntegerMode) {
@@ -4118,6 +4095,8 @@ bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray
lastWasE = c == 'e';
if (c != ',')
buff->append(c);
+
+ i += in.size();
}
return true;
@@ -4267,23 +4246,16 @@ QString QLocale::currencySymbol(QLocale::CurrencySymbolFormat format) const
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);
+ return d->m_data->currencySymbol().getData(currency_symbol_data);
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);
+ return d->m_data->currencyDisplayName().getListEntry(currency_display_name_data, 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();
+ const char *code = d->m_data->m_currency_iso_code;
+ if (int len = qstrnlen(code, 3))
+ return QString::fromLatin1(code, len);
+ break;
}
}
return QString();
@@ -4308,20 +4280,16 @@ QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const
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;
+ QLocaleData::DataRange range = d->m_data->currencyFormatNegative();
+ if (!range.size || value >= 0)
+ range = d->m_data->currencyFormat();
+ else
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);
+ return range.getData(currency_format_data).arg(str, sym);
}
/*!
@@ -4339,15 +4307,11 @@ QString QLocale::toCurrencyString(qulonglong value, const QString &symbol) const
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);
+ return d->m_data->currencyFormat().getData(currency_format_data).arg(str, sym);
}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
@@ -4382,20 +4346,16 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci
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;
+ QLocaleData::DataRange range = d->m_data->currencyFormatNegative();
+ if (!range.size || value >= 0)
+ range = d->m_data->currencyFormat();
+ else
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);
+ return range.getData(currency_format_data).arg(str, sym);
}
/*!
@@ -4470,17 +4430,11 @@ QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats
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);
+ QLocaleData::DataRange range = (format & DataSizeSIQuantifiers)
+ ? d->m_data->byteAmountSI() : d->m_data->byteAmountIEC();
+ unit = range.getListEntry(byte_unit_data, power - 1);
} else {
- unit = getLocaleData(byte_unit_data + d->m_data->m_byte_idx, d->m_data->m_byte_size);
+ unit = d->m_data->byteCount().getData(byte_unit_data);
}
return number + QLatin1Char(' ') + unit;
@@ -4606,8 +4560,7 @@ QString QLocale::nativeLanguageName() const
return res.toString();
}
#endif
- return getLocaleData(endonyms_data + d->m_data->m_language_endonym_idx,
- d->m_data->m_language_endonym_size);
+ return d->m_data->endonymLanguage().getData(endonyms_data);
}
/*!
@@ -4627,8 +4580,7 @@ QString QLocale::nativeCountryName() const
return res.toString();
}
#endif
- return getLocaleData(endonyms_data + d->m_data->m_country_endonym_idx,
- d->m_data->m_country_endonym_size);
+ return d->m_data->endonymCountry().getData(endonyms_data);
}
#ifndef QT_NO_DEBUG_STREAM