summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/kernel/qvariant.cpp4
-rw-r--r--src/corelib/kernel/qvariant.h8
-rw-r--r--src/corelib/serialization/qdatastream.cpp1
-rw-r--r--src/corelib/text/qbytearray.cpp11
-rw-r--r--src/corelib/thread/qsemaphore.h7
-rw-r--r--src/corelib/thread/qwaitcondition_p.h153
-rw-r--r--src/corelib/thread/thread.pri1
-rw-r--r--src/corelib/time/qtimezone.cpp23
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp48
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h3
-rw-r--r--src/corelib/tools/qarraydata.cpp2
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;
}