Modernise and simplify handling of qtimezoneprivate_data_p.h's data

Add some trivial inline methods to the classes that populate the
tables to simplify access to their data. Use ranged-for loops to
iterate those tables (now that they no longer have bogus all-zero
entries at the end).

In the process, noticed windowsIdToDefaultIanaId() doing a double
iteration of the windowsDataTable, first via toWindowsIdKey() to map a
windowsId to a key, then again to map that key to the matching ianaId;
inline the former and use the table row from which it got the key to
extract its ianaId instead.

Change-Id: I76267f53c7e6f5c593e33b6146b8f98bfb6d042f
Reviewed-by: Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Edward Welbourne 2021-09-09 18:17:32 +02:00
parent ce868ffb7c
commit 9ba4ce0102
2 changed files with 68 additions and 120 deletions

View File

@ -55,67 +55,20 @@ QT_BEGIN_NAMESPACE
Static utilities for looking up Windows ID tables
*/
static const qsizetype windowsDataTableSize = std::size(windowsDataTable);
static const qsizetype zoneDataTableSize = std::size(zoneDataTable);
static const qsizetype utcDataTableSize = std::size(utcDataTable);
static const QZoneData *zoneData(quint16 index)
{
Q_ASSERT(index < zoneDataTableSize);
return &zoneDataTable[index];
}
static const QWindowsData *windowsData(quint16 index)
{
Q_ASSERT(index < windowsDataTableSize);
return &windowsDataTable[index];
}
static const QUtcData *utcData(quint16 index)
{
Q_ASSERT(index < utcDataTableSize);
return &utcDataTable[index];
}
// Return the Windows ID literal for a given QWindowsData
static QByteArrayView windowsId(const QWindowsData *windowsData)
{
return (windowsIdData + windowsData->windowsIdIndex);
}
// Return the IANA ID literal for a given QWindowsData
static QByteArray ianaId(const QWindowsData *windowsData)
{
return (ianaIdData + windowsData->ianaIdIndex);
}
// Return the IANA ID literal for a given QZoneData
static QByteArrayView ianaId(const QZoneData *zoneData)
{
return (ianaIdData + zoneData->ianaIdIndex);
}
static QByteArrayView utcId(const QUtcData *utcData)
{
return (ianaIdData + utcData->ianaIdIndex);
}
static quint16 toWindowsIdKey(const QByteArray &winId)
{
for (quint16 i = 0; i < windowsDataTableSize; ++i) {
const QWindowsData *data = windowsData(i);
if (windowsId(data) == winId)
return data->windowsIdKey;
for (const QWindowsData &data : windowsDataTable) {
if (data.windowsId() == winId)
return data.windowsIdKey;
}
return 0;
}
static QByteArray toWindowsIdLiteral(quint16 windowsIdKey)
{
for (quint16 i = 0; i < windowsDataTableSize; ++i) {
const QWindowsData *data = windowsData(i);
if (data->windowsIdKey == windowsIdKey)
return windowsId(data).toByteArray();
for (const QWindowsData &data : windowsDataTable) {
if (data.windowsIdKey == windowsIdKey)
return data.windowsId().toByteArray();
}
return QByteArray();
}
@ -168,12 +121,11 @@ QByteArray QTimeZonePrivate::id() const
QLocale::Territory QTimeZonePrivate::territory() const
{
// Default fall-back mode, use the zoneTable to find Region of known Zones
for (int i = 0; i < zoneDataTableSize; ++i) {
const QZoneData *data = zoneData(i);
QLatin1String view(ianaId(data));
for (QLatin1String token : view.tokenize(QLatin1String(" "))) {
if (token == QLatin1String(m_id.data(), m_id.size()))
return QLocale::Territory(data->territory);
const QLatin1String sought(m_id.data(), m_id.size());
for (const QZoneData &data : zoneDataTable) {
for (QLatin1String token : data.ids()) {
if (token == sought)
return QLocale::Territory(data.territory);
}
}
return QLocale::AnyTerritory;
@ -529,10 +481,9 @@ QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(QLocale::Territory terr
QList<QByteArray> regions;
// First get all Zones in the Zones table belonging to the Region
for (int i = 0; i < zoneDataTableSize; ++i) {
if (zoneData(i)->territory == territory) {
QLatin1String l1Id(ianaId(zoneData(i)));
for (auto l1 : l1Id.tokenize(QLatin1String(" ")))
for (const QZoneData &data : zoneDataTable) {
if (data.territory == territory) {
for (auto l1 : data.ids())
regions << QByteArray(l1.data(), l1.size());
}
}
@ -554,14 +505,11 @@ QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) cons
// Default fall-back mode, use the zoneTable to find Offset of know Zones
QList<QByteArray> offsets;
// First get all Zones in the table using the Offset
for (int i = 0; i < windowsDataTableSize; ++i) {
const QWindowsData *winData = windowsData(i);
if (winData->offsetFromUtc == offsetFromUtc) {
for (int j = 0; j < zoneDataTableSize; ++j) {
const QZoneData *data = zoneData(j);
if (data->windowsIdKey == winData->windowsIdKey) {
QLatin1String l1Id(ianaId(data));
for (auto l1 : l1Id.tokenize(QLatin1String(" ")))
for (const QWindowsData &winData : windowsDataTable) {
if (winData.offsetFromUtc == offsetFromUtc) {
for (const QZoneData &data : zoneDataTable) {
if (data.windowsIdKey == winData.windowsIdKey) {
for (auto l1 : data.ids())
offsets << QByteArray(l1.data(), l1.size());
}
}
@ -718,12 +666,10 @@ QString QTimeZonePrivate::isoOffsetFormat(int offsetFromUtc, QTimeZone::NameType
QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id)
{
for (int i = 0; i < zoneDataTableSize; ++i) {
const QZoneData *data = zoneData(i);
QLatin1String l1Id(ianaId(data));
for (auto l1 : l1Id.tokenize(QLatin1String(" "))) {
for (const QZoneData &data : zoneDataTable) {
for (auto l1 : data.ids()) {
if (l1 == QByteArrayView(id))
return toWindowsIdLiteral(data->windowsIdKey);
return toWindowsIdLiteral(data.windowsIdKey);
}
}
return QByteArray();
@ -731,23 +677,18 @@ QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id)
QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId)
{
const quint16 windowsIdKey = toWindowsIdKey(windowsId);
for (int i = 0; i < windowsDataTableSize; ++i) {
const QWindowsData *data = windowsData(i);
if (data->windowsIdKey == windowsIdKey)
return ianaId(data);
for (const QWindowsData &data : windowsDataTable) {
if (data.windowsId() == windowsId)
return data.ianaId().toByteArray();
}
return QByteArray();
}
QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId,
QLocale::Territory territory)
QLocale::Territory territory)
{
const QList<QByteArray> list = windowsIdToIanaIds(windowsId, territory);
if (list.count() > 0)
return list.first();
else
return QByteArray();
return list.count() > 0 ? list.first() : QByteArray();
}
QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId)
@ -755,11 +696,9 @@ QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windows
const quint16 windowsIdKey = toWindowsIdKey(windowsId);
QList<QByteArray> list;
for (int i = 0; i < zoneDataTableSize; ++i) {
const QZoneData *data = zoneData(i);
if (data->windowsIdKey == windowsIdKey) {
QLatin1String l1Id(ianaId(data));
for (auto l1 : l1Id.tokenize(QLatin1String(" ")))
for (const QZoneData &data : zoneDataTable) {
if (data.windowsIdKey == windowsIdKey) {
for (auto l1 : data.ids())
list << QByteArray(l1.data(), l1.size());
}
}
@ -770,17 +709,15 @@ QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windows
}
QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId,
QLocale::Territory territory)
QLocale::Territory territory)
{
const quint16 windowsIdKey = toWindowsIdKey(windowsId);
for (int i = 0; i < zoneDataTableSize; ++i) {
const QZoneData *data = zoneData(i);
const qint16 land = static_cast<quint16>(territory);
for (const QZoneData &data : zoneDataTable) {
// Return the region matches in preference order
if (data->windowsIdKey == windowsIdKey
&& data->territory == static_cast<quint16>(territory)) {
QLatin1String l1Id(ianaId(data));
if (data.windowsIdKey == windowsIdKey && data.territory == land) {
QList<QByteArray> list;
for (auto l1 : l1Id.tokenize(QLatin1String(" ")))
for (auto l1 : data.ids())
list << QByteArray(l1.data(), l1.size());
return list;
}
@ -811,12 +748,10 @@ QUtcTimeZonePrivate::QUtcTimeZonePrivate()
QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &id)
{
// Look for the name in the UTC list, if found set the values
for (int i = 0; i < utcDataTableSize; ++i) {
const QUtcData *data = utcData(i);
const QByteArrayView uid = utcId(data);
if (uid == id) {
for (const QUtcData &data : utcDataTable) {
if (data.id() == id) {
QString name = QString::fromUtf8(id);
init(id, data->offsetFromUtc, name, name, QLocale::AnyTerritory, name);
init(id, data.offsetFromUtc, name, name, QLocale::AnyTerritory, name);
break;
}
}
@ -963,9 +898,8 @@ QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const
bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
{
// Only the zone IDs supplied by CLDR and recognized by constructor.
for (int i = 0; i < utcDataTableSize; ++i) {
const QUtcData *data = utcData(i);
if (utcId(data) == ianaId)
for (const QUtcData &data : utcDataTable) {
if (data.id() == ianaId)
return true;
}
// But see offsetFromUtcString(), which lets us accept some "unavailable" IDs.
@ -976,9 +910,9 @@ QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const
{
// Only the zone IDs supplied by CLDR and recognized by constructor.
QList<QByteArray> result;
result.reserve(utcDataTableSize);
for (int i = 0; i < utcDataTableSize; ++i)
result << utcId(utcData(i)).toByteArray();
result.reserve(std::size(utcDataTable));
for (const QUtcData &data : utcDataTable)
result << data.id().toByteArray();
// Not guaranteed to be sorted, so sort:
std::sort(result.begin(), result.end());
// ### assuming no duplicates
@ -998,10 +932,9 @@ QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds
// Only if it's present in CLDR. (May get more than one ID: UTC, UTC+00:00
// and UTC-00:00 all have the same offset.)
QList<QByteArray> result;
for (int i = 0; i < utcDataTableSize; ++i) {
const QUtcData *data = utcData(i);
if (data->offsetFromUtc == offsetSeconds)
result << utcId(data).toByteArray();
for (const QUtcData &data : utcDataTable) {
if (data.offsetFromUtc == offsetSeconds)
result << data.id().toByteArray();
}
// Not guaranteed to be sorted, so sort:
std::sort(result.begin(), result.end());

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2013 John Layt <jlayt@kde.org>
** Contact: https://www.qt.io/licensing/
**
@ -54,6 +54,8 @@
//
#include <QtCore/private/qglobal_p.h>
#include "qbytearrayview.h"
#include "qstring.h"
QT_BEGIN_NAMESPACE
@ -73,22 +75,30 @@ QT_BEGIN_NAMESPACE
table removed
*/
struct QZoneData {
struct QZoneData
{
quint16 windowsIdKey; // Windows ID Key
quint16 territory; // Territory of IANA ID's, AnyTerritory means No Territory
quint16 ianaIdIndex; // All IANA ID's for the Windows ID and Country, space separated
quint16 ianaIdIndex; // All IANA ID's for the Windows ID and Country, space separated
inline QLatin1String id() const;
inline auto ids() const { return id().tokenize(QLatin1String(" ")); }
};
struct QWindowsData {
struct QWindowsData
{
quint16 windowsIdKey; // Windows ID Key
quint16 windowsIdIndex; // Windows ID Literal
quint16 ianaIdIndex; // Default IANA ID for the Windows ID
quint16 ianaIdIndex; // Default IANA ID for the Windows ID
qint32 offsetFromUtc; // Standard Time Offset from UTC, used for quick look-ups
inline QByteArrayView windowsId() const;
inline QByteArrayView ianaId() const;
};
struct QUtcData {
quint16 ianaIdIndex; // IANA ID's
struct QUtcData
{
quint16 ianaIdIndex; // IANA ID
qint32 offsetFromUtc; // Offset form UTC is seconds
inline QByteArrayView id() const;
};
/*
@ -1257,6 +1267,11 @@ static const char ianaIdData[] = {
};
// GENERATED PART ENDS HERE
inline QByteArrayView QWindowsData::windowsId() const { return windowsIdData + windowsIdIndex; }
inline QByteArrayView QWindowsData::ianaId() const { return ianaIdData + ianaIdIndex; }
inline QByteArrayView QUtcData::id() const { return ianaIdData + ianaIdIndex; }
inline QLatin1String QZoneData::id() const { return QLatin1String(ianaIdData + ianaIdIndex); }
QT_END_NAMESPACE
#endif // QTIMEZONEPRIVATE_DATA_P_H