diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.h | 8 | ||||
-rw-r--r-- | src/corelib/serialization/qdatastream.cpp | 1 | ||||
-rw-r--r-- | src/corelib/text/qbytearray.cpp | 11 | ||||
-rw-r--r-- | src/corelib/thread/qsemaphore.h | 7 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition_p.h | 153 | ||||
-rw-r--r-- | src/corelib/thread/thread.pri | 1 | ||||
-rw-r--r-- | src/corelib/time/qtimezone.cpp | 23 | ||||
-rw-r--r-- | src/corelib/time/qtimezoneprivate.cpp | 48 | ||||
-rw-r--r-- | src/corelib/time/qtimezoneprivate_p.h | 3 | ||||
-rw-r--r-- | src/corelib/tools/qarraydata.cpp | 2 |
11 files changed, 231 insertions, 30 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 43a3fb1db0..705cae6cf4 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2254,10 +2254,10 @@ QVariant::QVariant(const QRegularExpression &re) : d(RegularExpression) { v_construct<QRegularExpression>(&d, re); } #endif // QT_CONFIG(regularexpression) -#ifndef QT_BOOTSTRAPPED QVariant::QVariant(const QUuid &uuid) : d(Uuid) { v_construct<QUuid>(&d, uuid); } +#ifndef QT_BOOTSTRAPPED QVariant::QVariant(const QJsonValue &jsonValue) : d(QMetaType::QJsonValue) { v_construct<QJsonValue>(&d, jsonValue); } @@ -3011,7 +3011,6 @@ QPersistentModelIndex QVariant::toPersistentModelIndex() const } #endif // QT_CONFIG(itemmodel) -#ifndef QT_BOOTSTRAPPED /*! \since 5.0 @@ -3026,6 +3025,7 @@ QUuid QVariant::toUuid() const return qVariantToHelper<QUuid>(d, handlerManager); } +#ifndef QT_BOOTSTRAPPED /*! \since 5.0 diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index e7d3d9c835..86c7414704 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -256,12 +256,12 @@ class Q_CORE_EXPORT QVariant #if QT_CONFIG(regularexpression) QVariant(const QRegularExpression &re); #endif // QT_CONFIG(regularexpression) -#ifndef QT_BOOTSTRAPPED - QVariant(const QUrl &url); #if QT_CONFIG(easingcurve) QVariant(const QEasingCurve &easing); #endif QVariant(const QUuid &uuid); +#ifndef QT_BOOTSTRAPPED + QVariant(const QUrl &url); QVariant(const QJsonValue &jsonValue); QVariant(const QJsonObject &jsonObject); QVariant(const QJsonArray &jsonArray); @@ -332,12 +332,12 @@ class Q_CORE_EXPORT QVariant #if QT_CONFIG(regularexpression) QRegularExpression toRegularExpression() const; #endif // QT_CONFIG(regularexpression) -#ifndef QT_BOOTSTRAPPED - QUrl toUrl() const; #if QT_CONFIG(easingcurve) QEasingCurve toEasingCurve() const; #endif QUuid toUuid() const; +#ifndef QT_BOOTSTRAPPED + QUrl toUrl() const; QJsonValue toJsonValue() const; QJsonObject toJsonObject() const; QJsonArray toJsonArray() const; diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp index b3330d6cea..5082a8cb0d 100644 --- a/src/corelib/serialization/qdatastream.cpp +++ b/src/corelib/serialization/qdatastream.cpp @@ -566,6 +566,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_12 Version 18 (Qt 5.12) \value Qt_5_13 Version 19 (Qt 5.13) \value Qt_5_14 Same as Qt_5_13 + \value Qt_5_15 Same as Qt_5_13 \omitvalue Qt_DefaultCompiledVersion \sa setVersion(), version() diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index c50e087c10..444980e9c0 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -1775,12 +1775,7 @@ void QByteArray::resize(int size) return; } - if (size == 0 && !d->capacityReserved) { - Data *x = Data::allocate(0); - if (!d->ref.deref()) - Data::deallocate(d); - d = x; - } else if (d->size == 0 && d->ref.isStatic()) { + if (d->size == 0 && d->ref.isStatic()) { // // Optimize the idiom: // QByteArray a; @@ -1795,9 +1790,7 @@ void QByteArray::resize(int size) x->data()[size] = '\0'; d = x; } else { - if (d->ref.isShared() || uint(size) + 1u > d->alloc - || (!d->capacityReserved && size < d->size - && uint(size) + 1u < uint(d->alloc >> 1))) + if (d->ref.isShared() || uint(size) + 1u > d->alloc) reallocData(uint(size) + 1u, d->detachFlags() | Data::Grow); if (d->alloc) { d->size = size; diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h index 58c12997ad..b3b9b52052 100644 --- a/src/corelib/thread/qsemaphore.h +++ b/src/corelib/thread/qsemaphore.h @@ -80,8 +80,7 @@ public: explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) noexcept : m_sem(sem), m_n(n) {} QSemaphoreReleaser(QSemaphoreReleaser &&other) noexcept - : m_sem(other.m_sem), m_n(other.m_n) - { other.m_sem = nullptr; } + : m_sem(other.cancel()), m_n(other.m_n) {} QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) noexcept { QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; } @@ -102,9 +101,7 @@ public: QSemaphore *cancel() noexcept { - QSemaphore *old = m_sem; - m_sem = nullptr; - return old; + return qExchange(m_sem, nullptr); } private: diff --git a/src/corelib/thread/qwaitcondition_p.h b/src/corelib/thread/qwaitcondition_p.h new file mode 100644 index 0000000000..5133e52e92 --- /dev/null +++ b/src/corelib/thread/qwaitcondition_p.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QWAITCONDITION_P_H +#define QWAITCONDITION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qmutex.cpp, qmutex_unix.cpp, and qmutex_win.cpp. This header +// file may change from version to version without notice, or even be +// removed. +// +// We mean it. +// + +#include <QtCore/QWaitCondition> +#include <QtCore/QMutex> +#include <QtCore/QDeadlineTimer> + +#include <condition_variable> +#include <mutex> + +QT_BEGIN_NAMESPACE + +namespace QtPrivate +{ + +#if defined(Q_OS_INTEGRITY) + +class condition_variable; + +class mutex : private QMutex +{ + friend class QtPrivate::condition_variable; +public: + // all special member functions are ok! + // do not expose the (QMutex::Recursive) ctor + // don't use 'using QMutex::lock;' etc as those have the wrong noexcept + + void lock() { return QMutex::lock(); } + void unlock() { return QMutex::unlock(); } + bool try_lock() { return QMutex::tryLock(); } +}; + +class condition_variable : private QWaitCondition +{ +public: + // all special member functions are ok! + + void notify_one() { QWaitCondition::wakeOne(); } + void notify_all() { QWaitCondition::wakeAll(); } + + void wait(std::unique_lock<QtPrivate::mutex> &lock) { QWaitCondition::wait(lock.mutex()); } + template <class Predicate> + void wait(std::unique_lock<QtPrivate::mutex> &lock, Predicate p) + { + while (!p()) + wait(lock); + } + + template <typename Rep, typename Period> + std::cv_status wait_for(std::unique_lock<QtPrivate::mutex> &lock, + const std::chrono::duration<Rep, Period> &d) + { + return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{d}) + ? std::cv_status::no_timeout + : std::cv_status::timeout; + } + template <typename Rep, typename Period, typename Predicate> + bool wait_for(std::unique_lock<QtPrivate::mutex> &lock, + const std::chrono::duration<Rep, Period> &d, Predicate p) + { + const auto timer = QDeadlineTimer{d}; + while (!p()) { + if (!QWaitCondition::wait(lock.mutex(), timer)) + return p(); + } + return true; + } + + template <typename Clock, typename Duration> + std::cv_status wait_until(std::unique_lock<QtPrivate::mutex> &lock, + const std::chrono::time_point<Clock, Duration> &t) + { + return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{t}) + ? std::cv_status::no_timeout + : std::cv_status::timeout; + } + + template <typename Clock, typename Duration, typename Predicate> + bool wait_until(std::unique_lock<QtPrivate::mutex> &lock, + const std::chrono::time_point<Clock, Duration> &t, Predicate p) + { + const auto timer = QDeadlineTimer{t}; + while (!p()) { + if (!QWaitCondition::wait(lock.mutex(), timer)) + return p(); + } + return true; + } + +}; + +#else // Integrity + +using mutex = std::mutex; +using condition_variable = std::condition_variable; + +#endif // Integrity + +} // namespace QtPrivate + +QT_END_NAMESPACE + +#endif /* QWAITCONDITION_P_H */ diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 9fc9af0e65..25cf68a324 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -6,6 +6,7 @@ HEADERS += \ thread/qrunnable.h \ thread/qthread.h \ thread/qthreadstorage.h \ + thread/qwaitcondition_p.h \ thread/qwaitcondition.h SOURCES += \ diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp index ef323de14a..410a16e3c5 100644 --- a/src/corelib/time/qtimezone.cpp +++ b/src/corelib/time/qtimezone.cpp @@ -325,20 +325,33 @@ QTimeZone::QTimeZone() noexcept /*! Creates an instance of the requested time zone \a ianaId. - The ID must be one of the available system IDs otherwise an invalid - time zone will be returned. + The ID must be one of the available system IDs or a valid UTC-with-offset + ID, otherwise an invalid time zone will be returned. \sa availableTimeZoneIds() */ QTimeZone::QTimeZone(const QByteArray &ianaId) { - // Try and see if it's a valid UTC offset ID, just as quick to try create as look-up + // Try and see if it's a CLDR UTC offset ID - just as quick by creating as + // by looking up. d = new QUtcTimeZonePrivate(ianaId); - // If not a valid UTC offset ID then try create it with the system backend - // Relies on backend not creating valid tz with invalid name + // If not a CLDR UTC offset ID then try creating it with the system backend. + // Relies on backend not creating valid TZ with invalid name. if (!d->isValid()) d = newBackendTimeZone(ianaId); + // Can also handle UTC with arbitrary (valid) offset, but only do so as + // fall-back, since either of the above may handle it more informatively. + if (!d->isValid()) { + qint64 offset = QUtcTimeZonePrivate::offsetFromUtcString(ianaId); + if (offset != QTimeZonePrivate::invalidSeconds()) { + // Should have abs(offset) < 24 * 60 * 60 = 86400. + qint32 seconds = qint32(offset); + Q_ASSERT(qint64(seconds) == offset); + // NB: this canonicalises the name, so it might not match ianaId + d = new QUtcTimeZonePrivate(seconds); + } + } } /*! diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp index 569b343187..72a0e3c24e 100644 --- a/src/corelib/time/qtimezoneprivate.cpp +++ b/src/corelib/time/qtimezoneprivate.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2013 John Layt <jlayt@kde.org> ** Contact: https://www.qt.io/licensing/ ** @@ -761,6 +762,39 @@ QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &id) } } +qint64 QUtcTimeZonePrivate::offsetFromUtcString(const QByteArray &id) +{ + // Convert reasonable UTC[+-]\d+(:\d+){,2} to offset in seconds. + // Assumption: id has already been tried as a CLDR UTC offset ID (notably + // including plain "UTC" itself) and a system offset ID; it's neither. + if (!id.startsWith("UTC") || id.size() < 5) + return invalidSeconds(); // Doesn't match + const char signChar = id.at(3); + if (signChar != '-' && signChar != '+') + return invalidSeconds(); // No sign + const int sign = signChar == '-' ? -1 : 1; + + const auto offsets = id.mid(4).split(':'); + if (offsets.isEmpty() || offsets.size() > 3) + return invalidSeconds(); // No numbers, or too many. + + qint32 seconds = 0; + int prior = 0; // Number of fields parsed thus far + for (const auto &offset : offsets) { + bool ok = false; + unsigned short field = offset.toUShort(&ok); + // Bound hour above at 24, minutes and seconds at 60: + if (!ok || field >= (prior ? 60 : 24)) + return invalidSeconds(); + seconds = seconds * 60 + field; + ++prior; + } + while (prior++ < 3) + seconds *= 60; + + return seconds * sign; +} + // Create offset from UTC QUtcTimeZonePrivate::QUtcTimeZonePrivate(qint32 offsetSeconds) { @@ -874,22 +908,25 @@ 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) { + if (utcId(data) == ianaId) return true; - } } + // But see offsetFromUtcString(), which lets us accept some "unavailable" IDs. return false; } 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)); - std::sort(result.begin(), result.end()); // ### or already sorted?? + // Not guaranteed to be sorted, so sort: + std::sort(result.begin(), result.end()); // ### assuming no duplicates return result; } @@ -904,13 +941,16 @@ QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(QLocale::Country cou QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds) const { + // 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); } - std::sort(result.begin(), result.end()); // ### or already sorted?? + // Not guaranteed to be sorted, so sort: + std::sort(result.begin(), result.end()); // ### assuming no duplicates return result; } diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h index 5f6491ef81..a57f61f381 100644 --- a/src/corelib/time/qtimezoneprivate_p.h +++ b/src/corelib/time/qtimezoneprivate_p.h @@ -188,6 +188,9 @@ public: QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other); virtual ~QUtcTimeZonePrivate(); + // Fall-back for UTC[+-]\d+(:\d+){,2} IDs. + static qint64 offsetFromUtcString(const QByteArray &id); + QUtcTimeZonePrivate *clone() const override; Data data(qint64 forMSecsSinceEpoch) const override; diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 234a44f6b6..36a221f728 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -143,7 +143,7 @@ qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t heade } result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize); - result.size = bytes; + result.size = result.elementCount * elementSize + headerSize; return result; } |