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 <edward.welbourne@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Thiago Macieira 2016-04-30 22:06:09 -07:00
parent 9466d0e633
commit 1a161c8ede
4 changed files with 66 additions and 71 deletions

View File

@ -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]));

View File

@ -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<QDate, QTime> 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);
}

View File

@ -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);

View File

@ -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
}