diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/doc/snippets/hellotrmain.cpp | 4 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher.cpp | 13 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 13 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.h | 3 | ||||
-rw-r--r-- | src/corelib/kernel/qpointer.h | 15 | ||||
-rw-r--r-- | src/corelib/thread/qreadwritelock.cpp | 50 | ||||
-rw-r--r-- | src/corelib/thread/qreadwritelock_p.h | 32 | ||||
-rw-r--r-- | src/corelib/time/qdatetime.cpp | 53 | ||||
-rw-r--r-- | src/corelib/time/qtimezoneprivate_win.cpp | 42 |
9 files changed, 130 insertions, 95 deletions
diff --git a/src/corelib/doc/snippets/hellotrmain.cpp b/src/corelib/doc/snippets/hellotrmain.cpp index 2fab919a47..721a83240b 100644 --- a/src/corelib/doc/snippets/hellotrmain.cpp +++ b/src/corelib/doc/snippets/hellotrmain.cpp @@ -56,13 +56,13 @@ int main(int argc, char *argv[]) QTranslator translator; // look up e.g. :/translations/myapp_de.qm if (translator.load(QLocale(), QLatin1String("myapp"), QLatin1String("_"), QLatin1String(":/translations"))) - app.installTranslator(&translator); + QCoreApplication::installTranslator(&translator); QPushButton hello(QCoreApplication::translate("main", "Hello world!")); hello.resize(100, 30); hello.show(); - return app.exec(); + return QCoreApplication::exec(); } //! [0] diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 64c422c55a..a4705136a2 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -41,9 +41,9 @@ #include "qfilesystemwatcher_p.h" #include <qdatetime.h> -#include <qdebug.h> #include <qdir.h> #include <qfileinfo.h> +#include <qloggingcategory.h> #include <qset.h> #include <qtimer.h> @@ -67,6 +67,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcWatcher, "qt.core.filesystemwatcher") + QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject *parent) { #if defined(Q_OS_WIN) @@ -137,6 +139,7 @@ void QFileSystemWatcherPrivate::initPollerEngine() void QFileSystemWatcherPrivate::_q_fileChanged(const QString &path, bool removed) { Q_Q(QFileSystemWatcher); + qCDebug(lcWatcher) << "file changed" << path << "removed?" << removed << "watching?" << files.contains(path); if (!files.contains(path)) { // the path was removed after a change was detected, but before we delivered the signal return; @@ -149,6 +152,7 @@ void QFileSystemWatcherPrivate::_q_fileChanged(const QString &path, bool removed void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool removed) { Q_Q(QFileSystemWatcher); + qCDebug(lcWatcher) << "directory changed" << path << "removed?" << removed << "watching?" << directories.contains(path); if (!directories.contains(path)) { // perhaps the path was removed after a change was detected, but before we delivered the signal return; @@ -355,7 +359,7 @@ QStringList QFileSystemWatcher::addPaths(const QStringList &paths) qWarning("QFileSystemWatcher::addPaths: list is empty"); return p; } - + qCDebug(lcWatcher) << "adding" << paths; const auto selectEngine = [this, d]() -> QFileSystemWatcherEngine* { #ifdef QT_BUILD_INTERNAL const QString on = objectName(); @@ -364,11 +368,11 @@ QStringList QFileSystemWatcher::addPaths(const QStringList &paths) // Autotest override case - use the explicitly selected engine only const QStringRef forceName = on.midRef(26); if (forceName == QLatin1String("poller")) { - qDebug("QFileSystemWatcher: skipping native engine, using only polling engine"); + qCDebug(lcWatcher, "QFileSystemWatcher: skipping native engine, using only polling engine"); d_func()->initPollerEngine(); return d->poller; } else if (forceName == QLatin1String("native")) { - qDebug("QFileSystemWatcher: skipping polling engine, using only native engine"); + qCDebug(lcWatcher, "QFileSystemWatcher: skipping polling engine, using only native engine"); return d->native; } return nullptr; @@ -431,6 +435,7 @@ QStringList QFileSystemWatcher::removePaths(const QStringList &paths) qWarning("QFileSystemWatcher::removePaths: list is empty"); return p; } + qCDebug(lcWatcher) << "removing" << paths; if (d->native) p = d->native->removePaths(p, &d->files, &d->directories); diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 6647ea99f5..c537e8f51b 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2693,7 +2693,14 @@ Q_GLOBAL_STATIC(QRecursiveMutex, libraryPathMutex) QStringList QCoreApplication::libraryPaths() { QMutexLocker locker(libraryPathMutex()); + return libraryPathsLocked(); +} +/*! + \internal +*/ +QStringList QCoreApplication::libraryPathsLocked() +{ if (coreappdata()->manual_libpaths) return *(coreappdata()->manual_libpaths); @@ -2769,7 +2776,7 @@ void QCoreApplication::setLibraryPaths(const QStringList &paths) // When the application is constructed it should still amend the paths. So we keep the originals // around, and even create them if they don't exist, yet. if (!coreappdata()->app_libpaths) - libraryPaths(); + libraryPathsLocked(); if (coreappdata()->manual_libpaths) *(coreappdata()->manual_libpaths) = paths; @@ -2812,7 +2819,7 @@ void QCoreApplication::addLibraryPath(const QString &path) return; } else { // make sure that library paths are initialized - libraryPaths(); + libraryPathsLocked(); QStringList *app_libpaths = coreappdata()->app_libpaths.data(); if (app_libpaths->contains(canonicalPath)) return; @@ -2851,7 +2858,7 @@ void QCoreApplication::removeLibraryPath(const QString &path) return; } else { // make sure that library paths is initialized - libraryPaths(); + libraryPathsLocked(); QStringList *app_libpaths = coreappdata()->app_libpaths.data(); if (!app_libpaths->contains(canonicalPath)) return; diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index b7df004736..71ea124fbe 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -208,6 +208,9 @@ private: static bool notifyInternal2(QObject *receiver, QEvent *); static bool forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent = nullptr); #endif +#if QT_CONFIG(library) + static QStringList libraryPathsLocked(); +#endif static QCoreApplication *self; diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h index 7052bcf0d4..5efdb0b395 100644 --- a/src/corelib/kernel/qpointer.h +++ b/src/corelib/kernel/qpointer.h @@ -54,20 +54,11 @@ class QPointer { Q_STATIC_ASSERT_X(!std::is_pointer<T>::value, "QPointer's template type must not be a pointer type"); - template<typename U> - struct TypeSelector - { - typedef QObject Type; - }; - template<typename U> - struct TypeSelector<const U> - { - typedef const QObject Type; - }; - typedef typename TypeSelector<T>::Type QObjectType; + using QObjectType = + typename std::conditional<std::is_const<T>::value, const QObject, QObject>::type; QWeakPointer<QObjectType> wp; public: - inline QPointer() { } + QPointer() = default; inline QPointer(T *p) : wp(p, true) { } // compiler-generated copy/move ctor/assignment operators are fine! // compiler-generated dtor is fine! diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp index 30e9b95a52..5aba05c1b9 100644 --- a/src/corelib/thread/qreadwritelock.cpp +++ b/src/corelib/thread/qreadwritelock.cpp @@ -48,6 +48,9 @@ #include "qreadwritelock_p.h" #include "qelapsedtimer.h" #include "private/qfreelist_p.h" +#include "private/qlocking_p.h" + +#include <chrono> QT_BEGIN_NAMESPACE @@ -64,6 +67,9 @@ QT_BEGIN_NAMESPACE */ namespace { + +using ms = std::chrono::milliseconds; + enum { StateMask = 0x3, StateLockedForRead = 0x1, @@ -262,7 +268,7 @@ bool QReadWriteLock::tryLockForRead(int timeout) if (d->recursive) return d->recursiveLockForRead(timeout); - QMutexLocker lock(&d->mutex); + auto lock = qt_unique_lock(d->mutex); if (d != d_ptr.loadRelaxed()) { // d_ptr has changed: this QReadWriteLock was unlocked before we had // time to lock d->mutex. @@ -273,7 +279,7 @@ bool QReadWriteLock::tryLockForRead(int timeout) d = d_ptr.loadAcquire(); continue; } - return d->lockForRead(timeout); + return d->lockForRead(lock, timeout); } } @@ -369,7 +375,7 @@ bool QReadWriteLock::tryLockForWrite(int timeout) if (d->recursive) return d->recursiveLockForWrite(timeout); - QMutexLocker lock(&d->mutex); + auto lock = qt_unique_lock(d->mutex); if (d != d_ptr.loadRelaxed()) { // The mutex was unlocked before we had time to lock the mutex. // We are holding to a mutex within a QReadWriteLockPrivate that is already released @@ -377,7 +383,7 @@ bool QReadWriteLock::tryLockForWrite(int timeout) d = d_ptr.loadAcquire(); continue; } - return d->lockForWrite(timeout); + return d->lockForWrite(lock, timeout); } } @@ -418,7 +424,7 @@ void QReadWriteLock::unlock() return; } - QMutexLocker locker(&d->mutex); + const auto lock = qt_scoped_lock(d->mutex); if (d->writerCount) { Q_ASSERT(d->writerCount == 1); Q_ASSERT(d->readerCount == 0); @@ -460,9 +466,9 @@ QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() co } -bool QReadWriteLockPrivate::lockForRead(int timeout) +bool QReadWriteLockPrivate::lockForRead(std::unique_lock<std::mutex> &lock, int timeout) { - Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function + Q_ASSERT(!mutex.try_lock()); // mutex must be locked when entering this function QElapsedTimer t; if (timeout > 0) @@ -476,10 +482,10 @@ bool QReadWriteLockPrivate::lockForRead(int timeout) if (elapsed > timeout) return false; waitingReaders++; - readerCond.wait(&mutex, timeout - elapsed); + readerCond.wait_for(lock, ms{timeout - elapsed}); } else { waitingReaders++; - readerCond.wait(&mutex); + readerCond.wait(lock); } waitingReaders--; } @@ -488,9 +494,9 @@ bool QReadWriteLockPrivate::lockForRead(int timeout) return true; } -bool QReadWriteLockPrivate::lockForWrite(int timeout) +bool QReadWriteLockPrivate::lockForWrite(std::unique_lock<std::mutex> &lock, int timeout) { - Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function + Q_ASSERT(!mutex.try_lock()); // mutex must be locked when entering this function QElapsedTimer t; if (timeout > 0) @@ -505,15 +511,15 @@ bool QReadWriteLockPrivate::lockForWrite(int timeout) if (waitingReaders && !waitingWriters && !writerCount) { // We timed out and now there is no more writers or waiting writers, but some // readers were queueud (probably because of us). Wake the waiting readers. - readerCond.wakeAll(); + readerCond.notify_all(); } return false; } waitingWriters++; - writerCond.wait(&mutex, timeout - elapsed); + writerCond.wait_for(lock, ms{timeout - elapsed}); } else { waitingWriters++; - writerCond.wait(&mutex); + writerCond.wait(lock); } waitingWriters--; } @@ -526,17 +532,17 @@ bool QReadWriteLockPrivate::lockForWrite(int timeout) void QReadWriteLockPrivate::unlock() { - Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function + Q_ASSERT(!mutex.try_lock()); // mutex must be locked when entering this function if (waitingWriters) - writerCond.wakeOne(); + writerCond.notify_one(); else if (waitingReaders) - readerCond.wakeAll(); + readerCond.notify_all(); } bool QReadWriteLockPrivate::recursiveLockForRead(int timeout) { Q_ASSERT(recursive); - QMutexLocker lock(&mutex); + auto lock = qt_unique_lock(mutex); Qt::HANDLE self = QThread::currentThreadId(); @@ -546,7 +552,7 @@ bool QReadWriteLockPrivate::recursiveLockForRead(int timeout) return true; } - if (!lockForRead(timeout)) + if (!lockForRead(lock, timeout)) return false; currentReaders.insert(self, 1); @@ -556,7 +562,7 @@ bool QReadWriteLockPrivate::recursiveLockForRead(int timeout) bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout) { Q_ASSERT(recursive); - QMutexLocker lock(&mutex); + auto lock = qt_unique_lock(mutex); Qt::HANDLE self = QThread::currentThreadId(); if (currentWriter == self) { @@ -564,7 +570,7 @@ bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout) return true; } - if (!lockForWrite(timeout)) + if (!lockForWrite(lock, timeout)) return false; currentWriter = self; @@ -574,7 +580,7 @@ bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout) void QReadWriteLockPrivate::recursiveUnlock() { Q_ASSERT(recursive); - QMutexLocker lock(&mutex); + auto lock = qt_unique_lock(mutex); Qt::HANDLE self = QThread::currentThreadId(); if (self == currentWriter) { diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h index 31da2401c0..b2e782f9ee 100644 --- a/src/corelib/thread/qreadwritelock_p.h +++ b/src/corelib/thread/qreadwritelock_p.h @@ -54,7 +54,9 @@ #include <QtCore/private/qglobal_p.h> #include <QtCore/qhash.h> -#include <QtCore/qwaitcondition.h> + +#include <mutex> +#include <condition_variable> QT_REQUIRE_CONFIG(thread); @@ -63,38 +65,36 @@ QT_BEGIN_NAMESPACE class QReadWriteLockPrivate { public: - QReadWriteLockPrivate(bool isRecursive = false) - : readerCount(0), writerCount(0), waitingReaders(0), waitingWriters(0), - recursive(isRecursive), id(0), currentWriter(nullptr) {} + explicit QReadWriteLockPrivate(bool isRecursive = false) + : recursive(isRecursive) {} - QMutex mutex; - QWaitCondition writerCond; - QWaitCondition readerCond; - int readerCount; - int writerCount; - int waitingReaders; - int waitingWriters; + std::mutex mutex; + std::condition_variable writerCond; + std::condition_variable readerCond; + int readerCount = 0; + int writerCount = 0; + int waitingReaders = 0; + int waitingWriters = 0; const bool recursive; //Called with the mutex locked - bool lockForWrite(int timeout); - bool lockForRead(int timeout); + bool lockForWrite(std::unique_lock<std::mutex> &lock, int timeout); + bool lockForRead(std::unique_lock<std::mutex> &lock, int timeout); void unlock(); //memory management - int id; + int id = 0; void release(); static QReadWriteLockPrivate *allocate(); // Recusive mutex handling - Qt::HANDLE currentWriter; + Qt::HANDLE currentWriter = {}; QHash<Qt::HANDLE, int> currentReaders; // called with the mutex unlocked bool recursiveLockForWrite(int timeout); bool recursiveLockForRead(int timeout); void recursiveUnlock(); - }; QT_END_NAMESPACE diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 8b1665e7dd..13a54c1210 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -3432,15 +3432,15 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT datetime by adding a number of seconds, days, months, or years. QDateTime can describe datetimes with respect to \l{Qt::LocalTime}{local - time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset - from UTC} or to a specified \l{Qt::TimeZone}{time zone}, in conjunction - with the QTimeZone class. For example, a time zone of "Europe/Berlin" will - apply the daylight-saving rules as used in Germany since 1970. In contrast, - an offset from UTC of +3600 seconds is one hour ahead of UTC (usually - written in ISO standard notation as "UTC+01:00"), with no daylight-saving - offset or changes. When using either local time or a specified time zone, - time-zone transitions such as the starts and ends of daylight-saving time - (DST) are taken into account. The choice of system used to represent a + time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset from + UTC} or to a specified \l{Qt::TimeZone}{time zone}, in conjunction with the + QTimeZone class. For example, a time zone of "Europe/Berlin" will apply the + daylight-saving rules as used in Germany since 1970. In contrast, an offset + from UTC of +3600 seconds is one hour ahead of UTC (usually written in ISO + standard notation as "UTC+01:00"), with no daylight-saving offset or + changes. When using either local time or a specified time zone, time-zone + transitions such as the starts and ends of daylight-saving time (DST; but + see below) are taken into account. The choice of system used to represent a datetime is described as its "timespec". A QDateTime object is typically created either by giving a date and time @@ -3528,11 +3528,13 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT The range of valid dates taking DST into account is 1970-01-01 to the present, and rules are in place for handling DST correctly until 2037-12-31, - but these could change. For dates falling outside that range, QDateTime - makes a \e{best guess} using the rules for year 1970 or 2037, but we can't - guarantee accuracy. This means QDateTime doesn't take into account changes - in a time zone before 1970, even if the system's time zone database provides - that information. + but these could change. For dates after 2037, QDateTime makes a \e{best + guess} using the rules for year 2037, but we can't guarantee accuracy; + indeed, for \e{any} future date, the time-zone may change its rules before + that date comes around. For dates before 1970, QDateTime doesn't take DST + changes into account, even if the system's time zone database provides that + information, although it does take into account changes to the time-zone's + standard offset, where this information is available. \section2 Offsets From UTC @@ -3797,17 +3799,22 @@ QTimeZone QDateTime::timeZone() const /*! \since 5.2 - Returns the current Offset From UTC in seconds. + Returns this date-time's Offset From UTC in seconds. - If the timeSpec() is Qt::OffsetFromUTC this will be the value originally set. - - If the timeSpec() is Qt::TimeZone this will be the offset effective in the - Time Zone including any Daylight-Saving Offset. - - If the timeSpec() is Qt::LocalTime this will be the difference between the - Local Time and UTC including any Daylight-Saving Offset. + The result depends on timeSpec(): + \list + \li \c Qt::UTC The offset is 0. + \li \c Qt::OffsetFromUTC The offset is the value originally set. + \li \c Qt::LocalTime The local time's offset from UTC is returned. + \li \c Qt::TimeZone The offset used by the time-zone is returned. + \endlist - If the timeSpec() is Qt::UTC this will be 0. + For the last two, the offset at this date and time will be returned, taking + account of Daylight-Saving Offset unless the date precedes the start of + 1970. The offset is the difference between the local time or time in the + given time-zone and UTC time; it is positive in time-zones ahead of UTC + (East of The Prime Meridian), negative for those behind UTC (West of The + Prime Meridian). \sa setOffsetFromUtc() */ diff --git a/src/corelib/time/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp index 1bf2366748..5a480222e0 100644 --- a/src/corelib/time/qtimezoneprivate_win.cpp +++ b/src/corelib/time/qtimezoneprivate_win.cpp @@ -371,6 +371,7 @@ QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year) // Otherwise, the rule date is annual and relative: const int dayOfWeek = rule.wDayOfWeek == 0 ? 7 : rule.wDayOfWeek; QDate date(year, rule.wMonth, 1); + Q_ASSERT(date.isValid()); // How many days before was last dayOfWeek before target month ? int adjust = dayOfWeek - date.dayOfWeek(); // -6 <= adjust < 7 if (adjust >= 0) // Ensure -7 <= adjust < 0: @@ -401,6 +402,7 @@ qint64 calculateTransitionForYear(const SYSTEMTIME &rule, int year, int bias) { // TODO Consider caching the calculated values - i.e. replace SYSTEMTIME in // WinTransitionRule; do this in init() once and store the results. + Q_ASSERT(year); const QDate date = calculateTransitionLocalDate(rule, year); const QTime time = QTime(rule.wHour, rule.wMinute, rule.wSecond); if (date.isValid() && time.isValid()) @@ -479,6 +481,7 @@ struct TransitionTimePair int yearEndOffset(const QWinTimeZonePrivate::QWinTransitionRule &rule, int year) { + Q_ASSERT(year); int offset = rule.standardTimeBias; // Only needed to help another TransitionTimePair work out year + 1's start // offset; and the oldYearOffset we use only affects an alleged transition @@ -743,11 +746,12 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons const QWinTransitionRule &rule = m_tranRules.at(ruleIndex); // Does this rule's period include any transition at all ? if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) { - const int endYear = qMax(rule.startYear, year - 1); + int prior = year == 1 ? -1 : year - 1; // No year 0. + const int endYear = qMax(rule.startYear, prior); while (year >= endYear) { const int newYearOffset = (year <= rule.startYear && ruleIndex > 0) - ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1) - : yearEndOffset(rule, year - 1); + ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior) + : yearEndOffset(rule, prior); const TransitionTimePair pair(rule, year, newYearOffset); bool isDst = false; if (pair.std != invalidMSecs() && pair.std <= forMSecsSinceEpoch) { @@ -755,7 +759,8 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons } else if (pair.dst != invalidMSecs() && pair.dst <= forMSecsSinceEpoch) { isDst = true; } else { - --year; // Try an earlier year for this rule (once). + year = prior; // Try an earlier year for this rule (once). + prior = year == 1 ? -1 : year - 1; // No year 0. continue; } return ruleToData(rule, forMSecsSinceEpoch, @@ -767,8 +772,11 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons // No transition, no DST, use the year's standard time. return ruleToData(rule, forMSecsSinceEpoch, QTimeZone::StandardTime); } - if (year >= rule.startYear) + if (year >= rule.startYear) { year = rule.startYear - 1; // Seek last transition in new rule. + if (!year) + --year; + } } // We don't have relevant data :-( return invalidData(); @@ -795,9 +803,10 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinc year = rule.startYear; // Seek first transition in this rule. const int endYear = ruleIndex + 1 < m_tranRules.count() ? qMin(m_tranRules.at(ruleIndex + 1).startYear, year + 2) : (year + 2); + int prior = year == 1 ? -1 : year - 1; // No year 0. int newYearOffset = (year <= rule.startYear && ruleIndex > 0) - ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1) - : yearEndOffset(rule, year - 1); + ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior) + : yearEndOffset(rule, prior); while (year < endYear) { const TransitionTimePair pair(rule, year, newYearOffset); bool isDst = false; @@ -810,7 +819,9 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinc newYearOffset = rule.standardTimeBias; if (pair.dst > pair.std) newYearOffset += rule.daylightTimeBias; - ++year; // Try a later year for this rule (once). + // Try a later year for this rule (once). + prior = year; + year = year == -1 ? 1 : year + 1; // No year 0 continue; } @@ -837,11 +848,12 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSec const QWinTransitionRule &rule = m_tranRules.at(ruleIndex); // Does this rule's period include any transition at all ? if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) { - const int endYear = qMax(rule.startYear, year - 1); + int prior = year == 1 ? -1 : year - 1; // No year 0. + const int endYear = qMax(rule.startYear, prior); while (year >= endYear) { const int newYearOffset = (year <= rule.startYear && ruleIndex > 0) - ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1) - : yearEndOffset(rule, year - 1); + ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior) + : yearEndOffset(rule, prior); const TransitionTimePair pair(rule, year, newYearOffset); bool isDst = false; if (pair.std != invalidMSecs() && pair.std < beforeMSecsSinceEpoch) { @@ -849,7 +861,8 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSec } else if (pair.dst != invalidMSecs() && pair.dst < beforeMSecsSinceEpoch) { isDst = true; } else { - --year; // Try an earlier year for this rule (once). + year = prior; // Try an earlier year for this rule (once). + prior = year == 1 ? -1 : year - 1; // No year 0. continue; } if (isDst) @@ -863,8 +876,11 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSec // rule: return ruleToData(rule, startOfTime, QTimeZone::StandardTime, false); } // else: no transition during rule's period - if (year >= rule.startYear) + if (year >= rule.startYear) { year = rule.startYear - 1; // Seek last transition in new rule + if (!year) + --year; + } } // Apparently no transition before the given time: return invalidData(); |