From 1a161c8ede4ea8c18c1d33d97a847387ca2c770e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 30 Apr 2016 22:06:09 -0700 Subject: QDateTimePrivate: merge the time spec, DST status and validity flags Storing them in a single byte is the first step towards the Short QDateTime Optimization. The bump in the "private version" by 10 is to accommodate possible changes in the Qt 5.7 branch. Change-Id: Id5480807d25e49e78b79ffff144a59420457bcf0 Reviewed-by: Edward Welbourne Reviewed-by: Lars Knoll --- src/corelib/global/qhooks.cpp | 2 +- src/corelib/tools/qdatetime.cpp | 79 ++++++++++++------------ src/corelib/tools/qdatetime_p.h | 35 +++++++---- tests/auto/other/toolsupport/tst_toolsupport.cpp | 21 +------ 4 files changed, 66 insertions(+), 71 deletions(-) diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp index da401ffd78..2ec1714cd2 100644 --- a/src/corelib/global/qhooks.cpp +++ b/src/corelib/global/qhooks.cpp @@ -67,7 +67,7 @@ quintptr Q_CORE_EXPORT qtHookData[] = { // The required sizes and offsets are tested in tests/auto/other/toolsupport. // When this fails and the change was intentional, adjust the test and // adjust this value here. - 4 + 14 }; Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0])); diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index a223aa1490..7be3f56d60 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2487,9 +2487,8 @@ static qint64 localMSecsToEpochMSecs(qint64 localMsecs, QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec, int offsetSeconds) : m_msecs(0), - m_spec(Qt::LocalTime), - m_offsetFromUtc(0), - m_status(0) + m_status(0), + m_offsetFromUtc(0) { setTimeSpec(toSpec, offsetSeconds); setDateTime(toDate, toTime); @@ -2498,11 +2497,11 @@ QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime, Qt: #ifndef QT_BOOTSTRAPPED QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime, const QTimeZone &toTimeZone) - : m_spec(Qt::TimeZone), + : m_status(0), m_offsetFromUtc(0), - m_timeZone(toTimeZone), - m_status(0) + m_timeZone(toTimeZone) { + setSpec(Qt::TimeZone); setDateTime(toDate, toTime); } #endif // QT_BOOTSTRAPPED @@ -2519,21 +2518,21 @@ void QDateTimePrivate::setTimeSpec(Qt::TimeSpec spec, int offsetSeconds) switch (spec) { case Qt::OffsetFromUTC: if (offsetSeconds == 0) { - m_spec = Qt::UTC; + setSpec(Qt::UTC); m_offsetFromUtc = 0; } else { - m_spec = Qt::OffsetFromUTC; + setSpec(Qt::OffsetFromUTC); m_offsetFromUtc = offsetSeconds; } break; case Qt::TimeZone: // Use system time zone instead - m_spec = Qt::LocalTime; + setSpec(Qt::LocalTime); m_offsetFromUtc = 0; break; case Qt::UTC: case Qt::LocalTime: - m_spec = spec; + setSpec(spec); m_offsetFromUtc = 0; break; } @@ -2564,7 +2563,8 @@ void QDateTimePrivate::setDateTime(const QDate &date, const QTime &time) // Set msecs serial value m_msecs = (days * MSECS_PER_DAY) + ds; - m_status = newStatus; + m_status &= ~(ValidityMask | DaylightMask); + m_status |= newStatus; // Set if date and time are valid checkValidDateTime(); @@ -2587,14 +2587,11 @@ QPair QDateTimePrivate::getDateTime() const // Set the Daylight Status if LocalTime set via msecs void QDateTimePrivate::setDaylightStatus(QDateTimePrivate::DaylightStatus status) { + clearSetToDaylightStatus(); if (status == DaylightTime) { - m_status = m_status & ~SetToStandardTime; m_status = m_status | SetToDaylightTime; } else if (status == StandardTime) { - m_status = m_status & ~SetToDaylightTime; m_status = m_status | SetToStandardTime; - } else { - clearSetToDaylightStatus(); } } @@ -2610,7 +2607,7 @@ QDateTimePrivate::DaylightStatus QDateTimePrivate::daylightStatus() const qint64 QDateTimePrivate::toMSecsSinceEpoch() const { - switch (m_spec) { + switch (spec()) { case Qt::OffsetFromUTC: case Qt::UTC: return (m_msecs - (m_offsetFromUtc * 1000)); @@ -2635,7 +2632,7 @@ qint64 QDateTimePrivate::toMSecsSinceEpoch() const // Check the UTC / offsetFromUTC validity void QDateTimePrivate::checkValidDateTime() { - switch (m_spec) { + switch (spec()) { case Qt::OffsetFromUTC: case Qt::UTC: // for these, a valid date and a valid time imply a valid QDateTime @@ -2656,7 +2653,7 @@ void QDateTimePrivate::checkValidDateTime() // Refresh the LocalTime validity and offset void QDateTimePrivate::refreshDateTime() { - switch (m_spec) { + switch (spec()) { case Qt::OffsetFromUTC: case Qt::UTC: // Always set by setDateTime so just return @@ -2675,7 +2672,7 @@ void QDateTimePrivate::refreshDateTime() #ifndef QT_BOOTSTRAPPED // If not valid time zone then is invalid - if (m_spec == Qt::TimeZone && !m_timeZone.isValid()) { + if (spec() == Qt::TimeZone && !m_timeZone.isValid()) { clearValidDateTime(); m_offsetFromUtc = 0; return; @@ -2688,7 +2685,7 @@ void QDateTimePrivate::refreshDateTime() QDate testDate; QTime testTime; qint64 epochMSecs = 0; - if (m_spec == Qt::LocalTime) { + if (spec() == Qt::LocalTime) { DaylightStatus status = daylightStatus(); epochMSecs = localMSecsToEpochMSecs(m_msecs, &status, &testDate, &testTime); #ifndef QT_BOOTSTRAPPED @@ -3038,7 +3035,7 @@ QTime QDateTime::time() const Qt::TimeSpec QDateTime::timeSpec() const { - return d->m_spec; + return d->spec(); } #ifndef QT_BOOTSTRAPPED @@ -3056,7 +3053,7 @@ Qt::TimeSpec QDateTime::timeSpec() const QTimeZone QDateTime::timeZone() const { - switch (d->m_spec) { + switch (d->spec()) { case Qt::UTC: return QTimeZone::utc(); case Qt::OffsetFromUTC: @@ -3117,7 +3114,7 @@ int QDateTime::offsetFromUtc() const QString QDateTime::timeZoneAbbreviation() const { - switch (d->m_spec) { + switch (d->spec()) { case Qt::UTC: return QTimeZonePrivate::utcQString(); case Qt::OffsetFromUTC: @@ -3151,7 +3148,7 @@ QString QDateTime::timeZoneAbbreviation() const bool QDateTime::isDaylightTime() const { - switch (d->m_spec) { + switch (d->spec()) { case Qt::UTC: case Qt::OffsetFromUTC: return false; @@ -3261,7 +3258,7 @@ void QDateTime::setOffsetFromUtc(int offsetSeconds) void QDateTime::setTimeZone(const QTimeZone &toZone) { QDateTimePrivate *d = this->d.data(); // detaches (and shadows d) - d->m_spec = Qt::TimeZone; + d->setSpec(Qt::TimeZone); d->m_offsetFromUtc = 0; d->m_timeZone = toZone; d->refreshDateTime(); @@ -3338,8 +3335,8 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs) { QDateTimePrivate *d = this->d.data(); // detaches (and shadows d) - d->m_status = 0; - switch (d->m_spec) { + d->m_status &= ~QDateTimePrivate::ValidityMask; + switch (d->spec()) { case Qt::UTC: d->m_msecs = msecs; d->m_status = d->m_status @@ -3484,7 +3481,7 @@ QString QDateTime::toString(Qt::DateFormat format) const .arg(dt.year()); if (timeSpec() != Qt::LocalTime) { buf += QStringLiteral(" GMT"); - if (d->m_spec == Qt::OffsetFromUTC) + if (d->spec() == Qt::OffsetFromUTC) buf += toOffsetString(Qt::TextDate, d->m_offsetFromUtc); } return buf; @@ -3499,7 +3496,7 @@ QString QDateTime::toString(Qt::DateFormat format) const return QString(); // failed to convert buf += QLatin1Char('T'); buf += tm.toString(Qt::ISODate); - switch (d->m_spec) { + switch (d->spec()) { case Qt::UTC: buf += QLatin1Char('Z'); break; @@ -3648,7 +3645,7 @@ QDateTime QDateTime::addDays(qint64 ndays) const QDate &date = p.first; QTime &time = p.second; date = date.addDays(ndays); - MASSAGEADJUSTEDDATETIME(d->m_spec, d->m_timeZone, &date, &time); + MASSAGEADJUSTEDDATETIME(d->spec(), d->m_timeZone, &date, &time); dt.d->setDateTime(date, time); return dt; } @@ -3674,7 +3671,7 @@ QDateTime QDateTime::addMonths(int nmonths) const QDate &date = p.first; QTime &time = p.second; date = date.addMonths(nmonths); - MASSAGEADJUSTEDDATETIME(d->m_spec, d->m_timeZone, &date, &time); + MASSAGEADJUSTEDDATETIME(d->spec(), d->m_timeZone, &date, &time); dt.d->setDateTime(date, time); return dt; } @@ -3700,7 +3697,7 @@ QDateTime QDateTime::addYears(int nyears) const QDate &date = p.first; QTime &time = p.second; date = date.addYears(nyears); - MASSAGEADJUSTEDDATETIME(d->m_spec, d->m_timeZone, &date, &time); + MASSAGEADJUSTEDDATETIME(d->spec(), d->m_timeZone, &date, &time); dt.d->setDateTime(date, time); return dt; } @@ -3736,12 +3733,12 @@ QDateTime QDateTime::addMSecs(qint64 msecs) const return QDateTime(); QDateTime dt(*this); - if (d->m_spec == Qt::LocalTime || d->m_spec == Qt::TimeZone) + if (d->spec() == Qt::LocalTime || d->spec() == Qt::TimeZone) // Convert to real UTC first in case crosses DST transition dt.setMSecsSinceEpoch(d->toMSecsSinceEpoch() + msecs); else // No need to convert, just add on - dt.d->m_msecs = dt.d->m_msecs + msecs; + dt.d->m_msecs += msecs; return dt; } @@ -3830,7 +3827,7 @@ qint64 QDateTime::msecsTo(const QDateTime &other) const QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const { - if (d->m_spec == spec && (spec == Qt::UTC || spec == Qt::LocalTime)) + if (d->spec() == spec && (spec == Qt::UTC || spec == Qt::LocalTime)) return *this; if (!isValid()) { @@ -3857,7 +3854,7 @@ QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const { - if (d->m_spec == Qt::OffsetFromUTC && d->m_offsetFromUtc == offsetSeconds) + if (d->spec() == Qt::OffsetFromUTC && d->m_offsetFromUtc == offsetSeconds) return *this; if (!isValid()) { @@ -3880,7 +3877,7 @@ QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const { - if (d->m_spec == Qt::TimeZone && d->m_timeZone == timeZone) + if (d->spec() == Qt::TimeZone && d->m_timeZone == timeZone) return *this; if (!isValid()) { @@ -3902,8 +3899,8 @@ QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const bool QDateTime::operator==(const QDateTime &other) const { - if (d->m_spec == Qt::LocalTime - && other.d->m_spec == Qt::LocalTime + if (d->spec() == Qt::LocalTime + && other.d->spec() == Qt::LocalTime && d->m_status == other.d->m_status) { return (d->m_msecs == other.d->m_msecs); } @@ -3930,8 +3927,8 @@ bool QDateTime::operator==(const QDateTime &other) const bool QDateTime::operator<(const QDateTime &other) const { - if (d->m_spec == Qt::LocalTime - && other.d->m_spec == Qt::LocalTime + if (d->spec() == Qt::LocalTime + && other.d->spec() == Qt::LocalTime && d->m_status == other.d->m_status) { return (d->m_msecs < other.d->m_msecs); } diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h index fd55575834..65905765fc 100644 --- a/src/corelib/tools/qdatetime_p.h +++ b/src/corelib/tools/qdatetime_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 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. @@ -83,21 +84,30 @@ public: // Status of date/time enum StatusFlag { - NullDate = 0x01, - NullTime = 0x02, - ValidDate = 0x04, // just the date field - ValidTime = 0x08, // just the time field - ValidDateTime = 0x10, // the whole object (including timezone) + ShortData = 0x01, + + ValidDate = 0x02, + ValidTime = 0x04, + ValidDateTime = 0x08, + + TimeSpecMask = 0x30, + SetToStandardTime = 0x40, SetToDaylightTime = 0x80 }; Q_DECLARE_FLAGS(StatusFlags, StatusFlag) + enum { + TimeSpecShift = 4, + ValidityMask = ValidDate | ValidTime | ValidDateTime, + DaylightMask = SetToStandardTime | SetToDaylightTime + }; + QDateTimePrivate() : m_msecs(0), - m_spec(Qt::LocalTime), - m_offsetFromUtc(0), - m_status(NullDate | NullTime) - {} + m_status(StatusFlag(Qt::LocalTime << TimeSpecShift)), + m_offsetFromUtc(0) + { + } QDateTimePrivate(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec, int offsetSeconds); @@ -110,12 +120,11 @@ public: // 4 bytes padding qint64 m_msecs; - Qt::TimeSpec m_spec; + StatusFlags m_status; int m_offsetFromUtc; #ifndef QT_BOOTSTRAPPED QTimeZone m_timeZone; #endif // QT_BOOTSTRAPPED - StatusFlags m_status; void setTimeSpec(Qt::TimeSpec spec, int offsetSeconds); void setDateTime(const QDate &date, const QTime &time); @@ -140,6 +149,10 @@ public: inline void clearValidDateTime() { m_status &= ~ValidDateTime; } inline void clearSetToDaylightStatus() { m_status &= ~(SetToStandardTime | SetToDaylightTime); } + inline Qt::TimeSpec spec() const { return Qt::TimeSpec((m_status & TimeSpecMask) >> TimeSpecShift); } + inline void setSpec(Qt::TimeSpec spec) + { m_status &= ~TimeSpecMask; m_status |= StatusFlag(uint(spec) << TimeSpecShift); } + #ifndef QT_BOOTSTRAPPED static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone, QDate *localDate = 0, QTime *localTime = 0); diff --git a/tests/auto/other/toolsupport/tst_toolsupport.cpp b/tests/auto/other/toolsupport/tst_toolsupport.cpp index 7942a84615..f93c8f825b 100644 --- a/tests/auto/other/toolsupport/tst_toolsupport.cpp +++ b/tests/auto/other/toolsupport/tst_toolsupport.cpp @@ -129,29 +129,14 @@ void tst_toolsupport::offsets_data() #endif { -#ifdef Q_OS_WIN QTest::newRow("QDateTimePrivate::m_msecs") - << pmm_to_offsetof(&QDateTimePrivate::m_msecs) << 8 << 8; - QTest::newRow("QDateTimePrivate::m_spec") - << pmm_to_offsetof(&QDateTimePrivate::m_spec) << 16 << 16; - QTest::newRow("QDateTimePrivate::m_offsetFromUtc") - << pmm_to_offsetof(&QDateTimePrivate::m_offsetFromUtc) << 20 << 20; - QTest::newRow("QDateTimePrivate::m_timeZone") - << pmm_to_offsetof(&QDateTimePrivate::m_timeZone) << 24 << 24; + << pmm_to_offsetof(&QDateTimePrivate::m_msecs) << 0 << 0; QTest::newRow("QDateTimePrivate::m_status") - << pmm_to_offsetof(&QDateTimePrivate::m_status) << 28 << 32; -#else - QTest::newRow("QDateTimePrivate::m_msecs") - << pmm_to_offsetof(&QDateTimePrivate::m_msecs) << 4 << 8; - QTest::newRow("QDateTimePrivate::m_spec") - << pmm_to_offsetof(&QDateTimePrivate::m_spec) << 12 << 16; + << pmm_to_offsetof(&QDateTimePrivate::m_status) << 8 << 8; QTest::newRow("QDateTimePrivate::m_offsetFromUtc") - << pmm_to_offsetof(&QDateTimePrivate::m_offsetFromUtc) << 16 << 20; + << pmm_to_offsetof(&QDateTimePrivate::m_offsetFromUtc) << 12 << 12; QTest::newRow("QDateTimePrivate::m_timeZone") << pmm_to_offsetof(&QDateTimePrivate::m_timeZone) << 20 << 24; - QTest::newRow("QDateTimePrivate::m_status") - << pmm_to_offsetof(&QDateTimePrivate::m_status) << 24 << 32; -#endif } #endif // RUN_MEMBER_OFFSET_TEST } -- cgit v1.2.3