Refactor QLocale's data access to be less verbose

Add QLocaleData::DataRange and methods returning it, to package each
of the m_*_idx, m_*_size pairs of data members, to simplify access to
these data. This extends the experiment started in QCalendarLocale,
which is now adapted to use the new DataRange also. Two static
functions of qlocale.cpp are replaced by methods of DataRange, saving
considerable duplication of long member names in callers.

Change-Id: Iad9899ba72f00522594b55a0402baec47491999c
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Edward Welbourne 2020-01-08 14:17:09 +01:00
parent 4e84a8b29f
commit c0f041fcdf
3 changed files with 147 additions and 163 deletions

View File

@ -791,28 +791,6 @@ const QLocaleData *QLocaleData::c()
return c_data; 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 #ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &ds, const QLocale &l) QDataStream &operator<<(QDataStream &ds, const QLocale &l)
{ {
@ -1130,31 +1108,24 @@ QString QLocale::createSeparatedList(const QStringList &list) const
#endif #endif
const int size = list.size(); const int size = list.size();
if (size == 1) { if (size < 1)
return QString();
if (size == 1)
return list.at(0); return list.at(0);
} else if (size == 2) {
QString format = getLocaleData( if (size == 2)
list_pattern_part_data + d->m_data->m_list_pattern_part_two_idx, return d->m_data->pairListPattern().getData(
d->m_data->m_list_pattern_part_two_size); list_pattern_part_data).arg(list.at(0), list.at(1));
return format.arg(list.at(0), list.at(1));
} else if (size > 2) { QStringView formatStart = d->m_data->startListPattern().viewData(list_pattern_part_data);
QString formatStart = getLocaleData( QStringView formatMid = d->m_data->midListPattern().viewData(list_pattern_part_data);
list_pattern_part_data + d->m_data->m_list_pattern_part_start_idx, QStringView formatEnd = d->m_data->endListPattern().viewData(list_pattern_part_data);
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)); QString result = formatStart.arg(list.at(0), list.at(1));
for (int i = 2; i < size - 1; ++i) for (int i = 2; i < size - 1; ++i)
result = formatMid.arg(result, list.at(i)); result = formatMid.arg(result, list.at(i));
result = formatEnd.arg(result, list.at(size - 1)); result = formatEnd.arg(result, list.at(size - 1));
return result; return result;
}
return QString();
} }
/*! /*!
@ -2251,18 +2222,10 @@ QString QLocale::dateFormat(FormatType format) const
} }
#endif #endif
quint32 idx, size; return (format == LongFormat
switch (format) { ? d->m_data->longDateFormat()
case LongFormat: : d->m_data->shortDateFormat()
idx = d->m_data->m_long_date_format_idx; ).getData(date_format_data);
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);
} }
/*! /*!
@ -2289,18 +2252,10 @@ QString QLocale::timeFormat(FormatType format) const
} }
#endif #endif
quint32 idx, size; return (format == LongFormat
switch (format) { ? d->m_data->longTimeFormat()
case LongFormat: : d->m_data->shortTimeFormat()
idx = d->m_data->m_long_time_format_idx; ).getData(time_format_data);
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);
} }
/*! /*!
@ -2869,24 +2824,21 @@ static QString rawMonthName(const QCalendarLocale &localeData,
const ushort *monthsData, int month, const ushort *monthsData, int month,
QLocale::FormatType type) QLocale::FormatType type)
{ {
quint32 idx, size; QLocaleData::DataRange range;
switch (type) { switch (type) {
case QLocale::LongFormat: case QLocale::LongFormat:
idx = localeData.m_long.index; range = localeData.m_long;
size = localeData.m_long.size;
break; break;
case QLocale::ShortFormat: case QLocale::ShortFormat:
idx = localeData.m_short.index; range = localeData.m_short;
size = localeData.m_short.size;
break; break;
case QLocale::NarrowFormat: case QLocale::NarrowFormat:
idx = localeData.m_narrow.index; range = localeData.m_narrow;
size = localeData.m_narrow.size;
break; break;
default: default:
return QString(); return QString();
} }
return getLocaleListData(monthsData + idx, size, month - 1); return range.getListEntry(monthsData, month - 1);
} }
/*! /*!
@ -2897,24 +2849,21 @@ static QString rawStandaloneMonthName(const QCalendarLocale &localeData,
const ushort *monthsData, int month, const ushort *monthsData, int month,
QLocale::FormatType type) QLocale::FormatType type)
{ {
quint32 idx, size; QLocaleData::DataRange range;
switch (type) { switch (type) {
case QLocale::LongFormat: case QLocale::LongFormat:
idx = localeData.m_standalone_long.index; range = localeData.m_standalone_long;
size = localeData.m_standalone_long.size;
break; break;
case QLocale::ShortFormat: case QLocale::ShortFormat:
idx = localeData.m_standalone_short.index; range = localeData.m_standalone_short;
size = localeData.m_standalone_short.size;
break; break;
case QLocale::NarrowFormat: case QLocale::NarrowFormat:
idx = localeData.m_standalone_narrow.index; range = localeData.m_standalone_narrow;
size = localeData.m_standalone_narrow.size;
break; break;
default: default:
return QString(); 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; return name.isEmpty() ? rawMonthName(localeData, monthsData, month, type) : name;
} }
@ -2925,24 +2874,21 @@ static QString rawStandaloneMonthName(const QCalendarLocale &localeData,
static QString rawWeekDayName(const QLocaleData *data, const int day, static QString rawWeekDayName(const QLocaleData *data, const int day,
QLocale::FormatType type) QLocale::FormatType type)
{ {
quint32 idx, size; QLocaleData::DataRange range;
switch (type) { switch (type) {
case QLocale::LongFormat: case QLocale::LongFormat:
idx = data->m_long_day_names_idx; range = data->longDayNames();
size = data->m_long_day_names_size;
break; break;
case QLocale::ShortFormat: case QLocale::ShortFormat:
idx = data->m_short_day_names_idx; range = data->shortDayNames();
size = data->m_short_day_names_size;
break; break;
case QLocale::NarrowFormat: case QLocale::NarrowFormat:
idx = data->m_narrow_day_names_idx; range = data->narrowDayNames();
size = data->m_narrow_day_names_size;
break; break;
default: default:
return QString(); return QString();
} }
return getLocaleListData(days_data + idx, size, day == 7 ? 0 : day); return range.getListEntry(days_data, day == 7 ? 0 : day);
} }
/*! /*!
@ -2952,24 +2898,21 @@ static QString rawWeekDayName(const QLocaleData *data, const int day,
static QString rawStandaloneWeekDayName(const QLocaleData *data, const int day, static QString rawStandaloneWeekDayName(const QLocaleData *data, const int day,
QLocale::FormatType type) QLocale::FormatType type)
{ {
quint32 idx, size; QLocaleData::DataRange range;
switch (type) { switch (type) {
case QLocale::LongFormat: case QLocale::LongFormat:
idx = data->m_standalone_long_day_names_idx; range =data->longDayNamesStandalone();
size = data->m_standalone_long_day_names_size;
break; break;
case QLocale::ShortFormat: case QLocale::ShortFormat:
idx = data->m_standalone_short_day_names_idx; range = data->shortDayNamesStandalone();
size = data->m_standalone_short_day_names_size;
break; break;
case QLocale::NarrowFormat: case QLocale::NarrowFormat:
idx = data->m_standalone_narrow_day_names_idx; range = data->narrowDayNamesStandalone();
size = data->m_standalone_narrow_day_names_size;
break; break;
default: default:
return QString(); 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()) if (name.isEmpty())
return rawWeekDayName(data, day, type); return rawWeekDayName(data, day, type);
return name; return name;
@ -3253,7 +3196,7 @@ QString QLocale::amText() const
return res.toString(); return res.toString();
} }
#endif #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);
} }
/*! /*!
@ -3273,7 +3216,7 @@ QString QLocale::pmText() const
return res.toString(); return res.toString();
} }
#endif #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: // Another intrusion from QCalendar, using some of the tools above:
@ -4215,23 +4158,16 @@ QString QLocale::currencySymbol(QLocale::CurrencySymbolFormat format) const
return res.toString(); return res.toString();
} }
#endif #endif
quint32 idx, size;
switch (format) { switch (format) {
case CurrencySymbol: case CurrencySymbol:
idx = d->m_data->m_currency_symbol_idx; return d->m_data->currencySymbol().getData(currency_symbol_data);
size = d->m_data->m_currency_symbol_size;
return getLocaleData(currency_symbol_data + idx, size);
case CurrencyDisplayName: case CurrencyDisplayName:
idx = d->m_data->m_currency_display_name_idx; return d->m_data->currencyDisplayName().getListEntry(currency_display_name_data, 0);
size = d->m_data->m_currency_display_name_size;
return getLocaleListData(currency_display_name_data + idx, size, 0);
case CurrencyIsoCode: { case CurrencyIsoCode: {
int len = 0; const char *code = d->m_data->m_currency_iso_code;
const QLocaleData *data = this->d->m_data; if (int len = qstrnlen(code, 3))
for (; len < 3; ++len) return QString::fromLatin1(code, len);
if (!data->m_currency_iso_code[len])
break; break;
return len ? QString::fromLatin1(data->m_currency_iso_code, len) : QString();
} }
} }
return QString(); return QString();
@ -4257,19 +4193,16 @@ QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const
} }
#endif #endif
const QLocalePrivate *d = this->d; const QLocalePrivate *d = this->d;
quint8 idx = d->m_data->m_currency_format_idx; QLocaleData::DataRange range = d->m_data->currencyFormatNegative();
quint8 size = d->m_data->m_currency_format_size; if (!range.size || value >= 0)
if (d->m_data->m_currency_negative_format_size && value < 0) { range = d->m_data->currencyFormat();
idx = d->m_data->m_currency_negative_format_idx; else
size = d->m_data->m_currency_negative_format_size;
value = -value; value = -value;
}
QString str = toString(value); QString str = toString(value);
QString sym = symbol.isNull() ? currencySymbol() : symbol; QString sym = symbol.isNull() ? currencySymbol() : symbol;
if (sym.isEmpty()) if (sym.isEmpty())
sym = currencySymbol(QLocale::CurrencyIsoCode); sym = currencySymbol(QLocale::CurrencyIsoCode);
QString format = getLocaleData(currency_format_data + idx, size); return range.getData(currency_format_data).arg(str, sym);
return format.arg(str, sym);
} }
/*! /*!
@ -4287,15 +4220,11 @@ QString QLocale::toCurrencyString(qulonglong value, const QString &symbol) const
return res.toString(); return res.toString();
} }
#endif #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 str = toString(value);
QString sym = symbol.isNull() ? currencySymbol() : symbol; QString sym = symbol.isNull() ? currencySymbol() : symbol;
if (sym.isEmpty()) if (sym.isEmpty())
sym = currencySymbol(QLocale::CurrencyIsoCode); sym = currencySymbol(QLocale::CurrencyIsoCode);
QString format = getLocaleData(currency_format_data + idx, size); return d->m_data->currencyFormat().getData(currency_format_data).arg(str, sym);
return format.arg(str, sym);
} }
#if QT_VERSION < QT_VERSION_CHECK(6,0,0) #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
@ -4330,20 +4259,16 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci
return res.toString(); return res.toString();
} }
#endif #endif
const QLocaleData *data = this->d->m_data; QLocaleData::DataRange range = d->m_data->currencyFormatNegative();
quint8 idx = data->m_currency_format_idx; if (!range.size || value >= 0)
quint8 size = data->m_currency_format_size; range = d->m_data->currencyFormat();
if (data->m_currency_negative_format_size && value < 0) { else
idx = data->m_currency_negative_format_idx;
size = data->m_currency_negative_format_size;
value = -value; value = -value;
}
QString str = toString(value, 'f', precision == -1 ? d->m_data->m_currency_digits : precision); QString str = toString(value, 'f', precision == -1 ? d->m_data->m_currency_digits : precision);
QString sym = symbol.isNull() ? currencySymbol() : symbol; QString sym = symbol.isNull() ? currencySymbol() : symbol;
if (sym.isEmpty()) if (sym.isEmpty())
sym = currencySymbol(QLocale::CurrencyIsoCode); sym = currencySymbol(QLocale::CurrencyIsoCode);
QString format = getLocaleData(currency_format_data + idx, size); return range.getData(currency_format_data).arg(str, sym);
return format.arg(str, sym);
} }
/*! /*!
@ -4418,17 +4343,11 @@ QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats
Q_ASSERT(power <= 6 && power >= 0); Q_ASSERT(power <= 6 && power >= 0);
QString unit; QString unit;
if (power > 0) { if (power > 0) {
quint16 index, size; QLocaleData::DataRange range = (format & DataSizeSIQuantifiers)
if (format & DataSizeSIQuantifiers) { ? d->m_data->byteAmountSI() : d->m_data->byteAmountIEC();
index = d->m_data->m_byte_si_quantified_idx; unit = range.getListEntry(byte_unit_data, power - 1);
size = d->m_data->m_byte_si_quantified_size;
} else { } else {
index = d->m_data->m_byte_iec_quantified_idx; unit = d->m_data->byteCount().getData(byte_unit_data);
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; return number + QLatin1Char(' ') + unit;
@ -4554,8 +4473,7 @@ QString QLocale::nativeLanguageName() const
return res.toString(); return res.toString();
} }
#endif #endif
return getLocaleData(endonyms_data + d->m_data->m_language_endonym_idx, return d->m_data->endonymLanguage().getData(endonyms_data);
d->m_data->m_language_endonym_size);
} }
/*! /*!
@ -4575,8 +4493,7 @@ QString QLocale::nativeCountryName() const
return res.toString(); return res.toString();
} }
#endif #endif
return getLocaleData(endonyms_data + d->m_data->m_country_endonym_idx, return d->m_data->endonymCountry().getData(endonyms_data);
d->m_data->m_country_endonym_size);
} }
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation. ** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -288,6 +288,75 @@ public:
Q_CORE_EXPORT bool validateChars(QStringView str, NumberMode numMode, QByteArray *buff, int decDigits = -1, Q_CORE_EXPORT bool validateChars(QStringView str, NumberMode numMode, QByteArray *buff, int decDigits = -1,
QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const; QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const;
struct DataRange
{
quint16 offset;
quint16 size;
QString getData(const ushort *table) const
{
return size > 0
? QString::fromRawData(reinterpret_cast<const QChar *>(table + offset), size)
: QString();
}
QStringView viewData(const ushort *table) const
{
return { reinterpret_cast<const QChar *>(table + offset), size };
}
QString getListEntry(const ushort *table, int index) const
{
return listEntry(table, index).getData(table);
}
QStringView viewListEntry(const ushort *table, int index) const
{
return listEntry(table, index).viewData(table);
}
private:
DataRange listEntry(const ushort *table, int index) const
{
const ushort separator = ';';
quint16 i = 0;
while (index > 0 && i < size) {
if (table[offset + i] == separator)
index--;
i++;
}
quint16 end = i;
while (end < size && table[offset + end] != separator)
end++;
return { quint16(offset + i), quint16(end - i) };
}
};
#define rangeGetter(name, stem) \
DataRange name() const { return { m_ ## stem ## _idx, m_ ## stem ## _size }; }
rangeGetter(startListPattern, list_pattern_part_start)
rangeGetter(midListPattern, list_pattern_part_mid)
rangeGetter(endListPattern, list_pattern_part_end)
rangeGetter(pairListPattern, list_pattern_part_two)
rangeGetter(shortDateFormat, short_date_format)
rangeGetter(longDateFormat, long_date_format)
rangeGetter(shortTimeFormat, short_time_format)
rangeGetter(longTimeFormat, long_time_format)
rangeGetter(narrowDayNamesStandalone, standalone_narrow_day_names)
rangeGetter(shortDayNamesStandalone, standalone_short_day_names)
rangeGetter(longDayNamesStandalone, standalone_long_day_names)
rangeGetter(narrowDayNames, narrow_day_names)
rangeGetter(shortDayNames, short_day_names)
rangeGetter(longDayNames, long_day_names)
rangeGetter(anteMeridiem, am)
rangeGetter(postMeridiem, pm)
rangeGetter(byteCount, byte)
rangeGetter(byteAmountSI, byte_si_quantified)
rangeGetter(byteAmountIEC, byte_iec_quantified)
rangeGetter(currencySymbol, currency_symbol)
rangeGetter(currencyDisplayName, currency_display_name)
rangeGetter(currencyFormat, currency_format)
rangeGetter(currencyFormatNegative, currency_negative_format)
rangeGetter(endonymLanguage, language_endonym)
rangeGetter(endonymCountry, country_endonym)
#undef rangeGetter
public: public:
quint16 m_language_id, m_script_id, m_country_id; quint16 m_language_id, m_script_id, m_country_id;

View File

@ -56,23 +56,21 @@
#include <QtCore/qstringlist.h> #include <QtCore/qstringlist.h>
#include <QtCore/qstring.h> #include <QtCore/qstring.h>
#include <QtCore/qmap.h> #include <QtCore/qmap.h>
#include <QtCore/private/qlocale_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
// Locale-related parts, mostly handled in ../text/qlocale.cpp // Locale-related parts, mostly handled in ../text/qlocale.cpp
struct QLocaleDataEntry {
quint16 index, size;
};
struct QCalendarLocale { struct QCalendarLocale {
quint16 m_language_id, m_script_id, m_country_id; quint16 m_language_id, m_script_id, m_country_id;
// Month name indexes: // Month name indexes:
QLocaleDataEntry m_standalone_short; QLocaleData::DataRange m_standalone_short;
QLocaleDataEntry m_standalone_long; QLocaleData::DataRange m_standalone_long;
QLocaleDataEntry m_standalone_narrow; QLocaleData::DataRange m_standalone_narrow;
QLocaleDataEntry m_short; QLocaleData::DataRange m_short;
QLocaleDataEntry m_long; QLocaleData::DataRange m_long;
QLocaleDataEntry m_narrow; QLocaleData::DataRange m_narrow;
}; };
// Partial implementation, of methods with common forms, in qcalendar.cpp // Partial implementation, of methods with common forms, in qcalendar.cpp