QDateTimePrivate refactor: static'fy access to d->m_status

This commit changes most accesses to the d->m_status (including
d->spec() and d->setSpec() uses) to use new static functions. This is
done in preparation to the "Short QDateTime Optimization" as the status
byte will be kept in the short data.

Change-Id: I06bae9392f534e45b3f1ffff144dbd795d03227a
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Thiago Macieira 2016-05-11 23:14:46 -07:00
parent b726751cd1
commit 97eae54083
2 changed files with 109 additions and 89 deletions

View File

@ -2480,6 +2480,52 @@ static qint64 localMSecsToEpochMSecs(qint64 localMsecs,
}
}
static Q_DECL_CONSTEXPR inline
QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
{
return QDateTimePrivate::StatusFlags((status & ~QDateTimePrivate::TimeSpecMask) |
(int(spec) << QDateTimePrivate::TimeSpecShift));
}
static Q_DECL_CONSTEXPR inline Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
{
return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask) >> QDateTimePrivate::TimeSpecShift);
}
// Set the Daylight Status if LocalTime set via msecs
static Q_DECL_RELAXED_CONSTEXPR inline QDateTimePrivate::StatusFlags
mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
{
sf &= ~QDateTimePrivate::DaylightMask;
if (status == QDateTimePrivate::DaylightTime) {
sf |= QDateTimePrivate::SetToDaylightTime;
} else if (status == QDateTimePrivate::StandardTime) {
sf |= QDateTimePrivate::SetToStandardTime;
}
return sf;
}
// Get the DST Status if LocalTime set via msecs
static Q_DECL_RELAXED_CONSTEXPR inline
QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
{
if (status & QDateTimePrivate::SetToDaylightTime)
return QDateTimePrivate::DaylightTime;
if (status & QDateTimePrivate::SetToStandardTime)
return QDateTimePrivate::StandardTime;
return QDateTimePrivate::UnknownDaylightTime;
}
static inline QDateTimePrivate::StatusFlags getStatus(const QDateTimePrivate *d)
{
return d->m_status;
}
static inline Qt::TimeSpec getSpec(const QDateTimePrivate *d)
{
return extractSpec(getStatus(d));
}
/*****************************************************************************
QDateTimePrivate member functions
*****************************************************************************/
@ -2498,20 +2544,19 @@ QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime, Qt:
#ifndef QT_BOOTSTRAPPED
QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime,
const QTimeZone &toTimeZone)
: m_status(0),
: m_status(mergeSpec(0, Qt::TimeZone)),
m_offsetFromUtc(0),
ref(0),
m_timeZone(toTimeZone)
{
setSpec(Qt::TimeZone);
setDateTime(toDate, toTime);
}
#endif // QT_BOOTSTRAPPED
void QDateTimePrivate::setTimeSpec(Qt::TimeSpec spec, int offsetSeconds)
{
clearValidDateTime();
clearSetToDaylightStatus();
auto status = m_status;
status &= ~(ValidDateTime | DaylightMask | TimeSpecMask);
switch (spec) {
case Qt::OffsetFromUTC:
@ -2528,7 +2573,8 @@ void QDateTimePrivate::setTimeSpec(Qt::TimeSpec spec, int offsetSeconds)
break;
}
setSpec(spec);
status = mergeSpec(status, spec);
m_status = status;
m_offsetFromUtc = offsetSeconds;
#ifndef QT_BOOTSTRAPPED
m_timeZone = QTimeZone();
@ -2570,49 +2616,33 @@ void QDateTimePrivate::setDateTime(const QDate &date, const QTime &time)
QPair<QDate, QTime> QDateTimePrivate::getDateTime() const
{
QPair<QDate, QTime> result;
msecsToTime(m_msecs, &result.first, &result.second);
qint64 msecs = m_msecs;
auto status = m_status;
msecsToTime(msecs, &result.first, &result.second);
if (!isValidDate())
if (!status.testFlag(ValidDate))
result.first = QDate();
if (!isValidTime())
if (!status.testFlag(ValidTime))
result.second = QTime();
return result;
}
// Set the Daylight Status if LocalTime set via msecs
void QDateTimePrivate::setDaylightStatus(QDateTimePrivate::DaylightStatus status)
{
clearSetToDaylightStatus();
if (status == DaylightTime) {
m_status = m_status | SetToDaylightTime;
} else if (status == StandardTime) {
m_status = m_status | SetToStandardTime;
}
}
// Get the DST Status if LocalTime set via msecs
QDateTimePrivate::DaylightStatus QDateTimePrivate::daylightStatus() const
{
if ((m_status & SetToDaylightTime) == SetToDaylightTime)
return DaylightTime;
if ((m_status & SetToStandardTime) == SetToStandardTime)
return StandardTime;
return UnknownDaylightTime;
}
// Check the UTC / offsetFromUTC validity
void QDateTimePrivate::checkValidDateTime()
{
switch (spec()) {
auto status = m_status;
auto spec = extractSpec(status);
switch (spec) {
case Qt::OffsetFromUTC:
case Qt::UTC:
// for these, a valid date and a valid time imply a valid QDateTime
if (isValidDate() && isValidTime())
setValidDateTime();
if ((status & ValidDate) && (status & ValidTime))
status |= ValidDateTime;
else
clearValidDateTime();
status &= ~ValidDateTime;
m_status = status;
break;
case Qt::TimeZone:
case Qt::LocalTime:
@ -2627,15 +2657,16 @@ void QDateTimePrivate::checkValidDateTime()
void QDateTimePrivate::refreshDateTime()
{
auto status = m_status;
const auto spec = extractSpec(status);
qint64 epochMSecs = 0;
int offsetFromUtc = 0;
QDate testDate;
QTime testTime;
Q_ASSERT(spec() == Qt::TimeZone || spec() == Qt::LocalTime);
Q_ASSERT(spec == Qt::TimeZone || spec == Qt::LocalTime);
#ifndef QT_BOOTSTRAPPED
// If not valid time zone then is invalid
if (spec() == Qt::TimeZone) {
if (spec == Qt::TimeZone) {
if (!m_timeZone.isValid())
status &= ~ValidDateTime;
else
@ -2644,7 +2675,7 @@ void QDateTimePrivate::refreshDateTime()
#endif // QT_BOOTSTRAPPED
// If not valid date and time then is invalid
if (!(status & ValidDate) && !(status & ValidTime)) {
if (!(status & ValidDate) || !(status & ValidTime)) {
status &= ~ValidDateTime;
m_status = status;
m_offsetFromUtc = 0;
@ -2654,9 +2685,9 @@ void QDateTimePrivate::refreshDateTime()
// We have a valid date and time and a Qt::LocalTime or Qt::TimeZone that needs calculating
// LocalTime and TimeZone might fall into a "missing" DST transition hour
// Calling toEpochMSecs will adjust the returned date/time if it does
if (spec() == Qt::LocalTime) {
DaylightStatus status = daylightStatus();
epochMSecs = localMSecsToEpochMSecs(m_msecs, &status, &testDate, &testTime);
if (spec == Qt::LocalTime) {
auto dstStatus = extractDaylightStatus(status);
epochMSecs = localMSecsToEpochMSecs(m_msecs, &dstStatus, &testDate, &testTime);
}
if (timeToMSecs(testDate, testTime) == m_msecs) {
status |= ValidDateTime;
@ -2944,7 +2975,9 @@ QDateTime &QDateTime::operator=(const QDateTime &other)
bool QDateTime::isNull() const
{
return !d->isValidDate() && !d->isValidTime();
auto status = getStatus(d);
return !status.testFlag(QDateTimePrivate::ValidDate) &&
!status.testFlag(QDateTimePrivate::ValidTime);
}
/*!
@ -2961,7 +2994,8 @@ bool QDateTime::isNull() const
bool QDateTime::isValid() const
{
return (d->isValidDateTime());
auto status = getStatus(d);
return status & QDateTimePrivate::ValidDateTime;
}
/*!
@ -2972,7 +3006,8 @@ bool QDateTime::isValid() const
QDate QDateTime::date() const
{
if (!d->isValidDate())
auto status = getStatus(d);
if (!status.testFlag(QDateTimePrivate::ValidDate))
return QDate();
QDate dt;
msecsToTime(d->m_msecs, &dt, 0);
@ -2987,7 +3022,8 @@ QDate QDateTime::date() const
QTime QDateTime::time() const
{
if (!d->isValidTime())
auto status = getStatus(d);
if (!status.testFlag(QDateTimePrivate::ValidTime))
return QTime();
QTime tm;
msecsToTime(d->m_msecs, 0, &tm);
@ -3002,7 +3038,7 @@ QTime QDateTime::time() const
Qt::TimeSpec QDateTime::timeSpec() const
{
return d->spec();
return getSpec(d);
}
#ifndef QT_BOOTSTRAPPED
@ -3020,7 +3056,7 @@ Qt::TimeSpec QDateTime::timeSpec() const
QTimeZone QDateTime::timeZone() const
{
switch (d->spec()) {
switch (getSpec(d)) {
case Qt::UTC:
return QTimeZone::utc();
case Qt::OffsetFromUTC:
@ -3081,7 +3117,7 @@ int QDateTime::offsetFromUtc() const
QString QDateTime::timeZoneAbbreviation() const
{
switch (d->spec()) {
switch (getSpec(d)) {
case Qt::UTC:
return QTimeZonePrivate::utcQString();
case Qt::OffsetFromUTC:
@ -3094,7 +3130,7 @@ QString QDateTime::timeZoneAbbreviation() const
#endif // QT_BOOTSTRAPPED
case Qt::LocalTime: {
QString abbrev;
QDateTimePrivate::DaylightStatus status = d->daylightStatus();
auto status = extractDaylightStatus(getStatus(d));
localMSecsToEpochMSecs(d->m_msecs, &status, 0, 0, &abbrev);
return abbrev;
}
@ -3115,7 +3151,7 @@ QString QDateTime::timeZoneAbbreviation() const
bool QDateTime::isDaylightTime() const
{
switch (d->spec()) {
switch (getSpec(d)) {
case Qt::UTC:
case Qt::OffsetFromUTC:
return false;
@ -3126,7 +3162,7 @@ bool QDateTime::isDaylightTime() const
return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
#endif // QT_BOOTSTRAPPED
case Qt::LocalTime: {
QDateTimePrivate::DaylightStatus status = d->daylightStatus();
auto status = extractDaylightStatus(getStatus(d));
if (status == QDateTimePrivate::UnknownDaylightTime)
localMSecsToEpochMSecs(d->m_msecs, &status);
return (status == QDateTimePrivate::DaylightTime);
@ -3225,7 +3261,7 @@ void QDateTime::setOffsetFromUtc(int offsetSeconds)
void QDateTime::setTimeZone(const QTimeZone &toZone)
{
QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
d->setSpec(Qt::TimeZone);
d->m_status = mergeSpec(d->m_status, Qt::TimeZone);
d->m_offsetFromUtc = 0;
d->m_timeZone = toZone;
d->refreshDateTime();
@ -3249,14 +3285,14 @@ void QDateTime::setTimeZone(const QTimeZone &toZone)
*/
qint64 QDateTime::toMSecsSinceEpoch() const
{
switch (d->spec()) {
case Qt::OffsetFromUTC:
switch (getSpec(d)) {
case Qt::UTC:
return (d->m_msecs - (d->m_offsetFromUtc * 1000));
case Qt::OffsetFromUTC:
return d->m_msecs - (d->m_offsetFromUtc * 1000);
case Qt::LocalTime: {
// recalculate the local timezone
auto status = d->daylightStatus();
auto status = extractDaylightStatus(getStatus(d));
return localMSecsToEpochMSecs(d->m_msecs, &status);
}
@ -3320,8 +3356,8 @@ uint QDateTime::toTime_t() const
void QDateTime::setMSecsSinceEpoch(qint64 msecs)
{
QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
const auto spec = d->spec();
auto status = d->m_status;
const auto spec = getSpec(d);
auto status = getStatus(d);
status &= ~QDateTimePrivate::ValidityMask;
switch (spec) {
@ -3359,9 +3395,8 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs)
QDateTimePrivate::DaylightStatus dstStatus;
epochMSecsToLocalTime(msecs, &dt, &tm, &dstStatus);
d->setDateTime(dt, tm);
d->setDaylightStatus(dstStatus);
msecs = d->m_msecs;
status = d->m_status;
status = mergeDaylightStatus(getStatus(d), dstStatus);
break;
}
}
@ -3474,7 +3509,7 @@ QString QDateTime::toString(Qt::DateFormat format) const
.arg(dt.year());
if (timeSpec() != Qt::LocalTime) {
buf += QStringLiteral(" GMT");
if (d->spec() == Qt::OffsetFromUTC)
if (getSpec(d) == Qt::OffsetFromUTC)
buf += toOffsetString(Qt::TextDate, d->m_offsetFromUtc);
}
return buf;
@ -3489,7 +3524,7 @@ QString QDateTime::toString(Qt::DateFormat format) const
return QString(); // failed to convert
buf += QLatin1Char('T');
buf += tm.toString(Qt::ISODate);
switch (d->spec()) {
switch (getSpec(d)) {
case Qt::UTC:
buf += QLatin1Char('Z');
break;
@ -3593,11 +3628,11 @@ static inline void massageAdjustedDateTime(const QDateTimePrivate *d, QDate *dat
to its DST-ness); but for a time in spring's missing hour it'll adjust the
time while picking a DST-ness. (Handling of autumn is trickier, as either
DST-ness is valid, without adjusting the time. We might want to propagate
d->daylightStatus() in that case, but it's hard to do so without breaking
the daylight status in that case, but it's hard to do so without breaking
(far more common) other cases; and it makes little difference, as the two
answers do then differ only in DST-ness.)
*/
auto spec = d->spec();
auto spec = getSpec(d);
if (spec == Qt::LocalTime) {
QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime;
localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time);
@ -3716,7 +3751,8 @@ QDateTime QDateTime::addMSecs(qint64 msecs) const
return QDateTime();
QDateTime dt(*this);
if (d->spec() == Qt::LocalTime || d->spec() == Qt::TimeZone)
auto spec = getSpec(d);
if (spec == Qt::LocalTime || spec == Qt::TimeZone)
// Convert to real UTC first in case crosses DST transition
dt.setMSecsSinceEpoch(toMSecsSinceEpoch() + msecs);
else
@ -3810,7 +3846,7 @@ qint64 QDateTime::msecsTo(const QDateTime &other) const
QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
{
if (d->spec() == spec && (spec == Qt::UTC || spec == Qt::LocalTime))
if (getSpec(d) == spec && (spec == Qt::UTC || spec == Qt::LocalTime))
return *this;
if (!isValid()) {
@ -3837,7 +3873,8 @@ QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
{
if (d->spec() == Qt::OffsetFromUTC && d->m_offsetFromUtc == offsetSeconds)
if (getSpec(d) == Qt::OffsetFromUTC
&& d->m_offsetFromUtc == offsetSeconds)
return *this;
if (!isValid()) {
@ -3860,7 +3897,7 @@ QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
{
if (d->spec() == Qt::TimeZone && d->m_timeZone == timeZone)
if (getSpec(d) == Qt::TimeZone && d->m_timeZone == timeZone)
return *this;
if (!isValid()) {
@ -3882,10 +3919,9 @@ QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
bool QDateTime::operator==(const QDateTime &other) const
{
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);
if (getSpec(d) == Qt::LocalTime
&& getStatus(d) == getStatus(other.d)) {
return d->m_msecs == other.d->m_msecs;
}
// Convert to UTC and compare
return (toMSecsSinceEpoch() == other.toMSecsSinceEpoch());
@ -3910,10 +3946,9 @@ bool QDateTime::operator==(const QDateTime &other) const
bool QDateTime::operator<(const QDateTime &other) const
{
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);
if (getSpec(d) == Qt::LocalTime
&& getStatus(d) == getStatus(other.d)) {
return d->m_msecs < other.d->m_msecs;
}
// Convert to UTC and compare
return (toMSecsSinceEpoch() < other.toMSecsSinceEpoch());

View File

@ -129,24 +129,9 @@ public:
void setDateTime(const QDate &date, const QTime &time);
QPair<QDate, QTime> getDateTime() const;
void setDaylightStatus(DaylightStatus status);
DaylightStatus daylightStatus() const;
void checkValidDateTime();
void refreshDateTime();
// Get/set date and time status
inline bool isValidDate() const { return m_status & ValidDate; }
inline bool isValidTime() const { return m_status & ValidTime; }
inline bool isValidDateTime() const { return m_status & ValidDateTime; }
inline void setValidDateTime() { m_status |= ValidDateTime; }
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);