summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorTarja Sundqvist <tarja.sundqvist@qt.io>2024-01-04 21:21:43 +0200
committerTarja Sundqvist <tarja.sundqvist@qt.io>2024-01-04 21:21:43 +0200
commit4e158f6bfa7d0747d8da70b3b15a44b52e35bb8a (patch)
tree84e20982138de5c9b6d319bf83ac79bd672f918f /src/corelib
parente4391422574aa9aa89fece74f16c07c609cbbae2 (diff)
parenta13fd415d689be046c13cc562cbbbb5df0e6506a (diff)
Merge remote-tracking branch 'origin/tqtc/lts-5.15.13' into tqtc/lts-5.15-opensourcev5.15.13-lts-lgpl5.15
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/doc/src/external-resources.qdoc30
-rw-r--r--src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc13
-rw-r--r--src/corelib/doc/src/io.qdoc2
-rw-r--r--src/corelib/io/qabstractfileengine_p.h2
-rw-r--r--src/corelib/io/qbuffer.cpp4
-rw-r--r--src/corelib/io/qdir.cpp19
-rw-r--r--src/corelib/io/qfile.cpp5
-rw-r--r--src/corelib/io/qfiledevice.cpp5
-rw-r--r--src/corelib/io/qfileinfo.cpp22
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp13
-rw-r--r--src/corelib/kernel/qcore_mac.mm8
-rw-r--r--src/corelib/text/qlocale_win.cpp14
-rw-r--r--src/corelib/text/qstring.h5
-rw-r--r--src/corelib/thread/qthreadpool.cpp4
-rw-r--r--src/corelib/time/qtimezone.cpp14
-rw-r--r--src/corelib/tools/qsharedpointer.cpp49
-rw-r--r--src/corelib/tools/qsharedpointer.h10
-rw-r--r--src/corelib/tools/qtools_p.h11
-rw-r--r--src/corelib/tools/qvarlengtharray.h29
19 files changed, 216 insertions, 43 deletions
diff --git a/src/corelib/doc/src/external-resources.qdoc b/src/corelib/doc/src/external-resources.qdoc
index f16a21d521..0096bca948 100644
--- a/src/corelib/doc/src/external-resources.qdoc
+++ b/src/corelib/doc/src/external-resources.qdoc
@@ -65,3 +65,33 @@
\externalpage http://marcmutz.wordpress.com/effective-qt/containers/
\title Understand the Qt Containers
*/
+
+/*!
+ \externalpage https://developer.android.com/training/data-storage/shared/documents-files
+ \title Android: Access documents and other files from shared storage
+*/
+
+/*!
+ \externalpage https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile#getParentFile()
+ \title Android: DocumentFile.getParentFile()
+*/
+
+/*!
+ \externalpage https://developer.android.com/guide/topics/providers/content-provider-basics#ContentURIs
+ \title Android: Content URIs
+*/
+
+/*!
+ \externalpage https://developer.android.com/training/data-storage#scoped-storage
+ \title Android: Scoped storage
+*/
+
+/*!
+ \externalpage https://developer.android.com/training/data-storage/use-cases
+ \title Android: storage best practices
+*/
+
+/*!
+ \externalpage https://developer.android.com/reference/android/provider/MediaStore
+ \title Android: MediaStore
+*/
diff --git a/src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc b/src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc
new file mode 100644
index 0000000000..f08086407e
--- /dev/null
+++ b/src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc
@@ -0,0 +1,13 @@
+On Android, some limitations apply when dealing with
+\l {Android: Content URIs}{content URIs}:
+\list
+ \li Access permissions might be needed by prompting the user through the
+ \l QFileDialog which implements
+ \l {Access documents and other files from shared storage}{Android's native file picker}.
+ \li Aim to follow the \l {Android: Scoped storage}{Scoped storage} guidelines,
+ such as using app specific directories instead of other public external directories.
+ For more information, also see
+ \l {Android: storage best practices}{storage best practices}.
+ \li Due to the design of Qt APIs (e.g. QFile), it's not possible to fully
+ integrate the latter APIs with Android's \l {Android: MediaStore}{MediaStore} APIs.
+\endlist
diff --git a/src/corelib/doc/src/io.qdoc b/src/corelib/doc/src/io.qdoc
index a1bbc623a1..6315a069aa 100644
--- a/src/corelib/doc/src/io.qdoc
+++ b/src/corelib/doc/src/io.qdoc
@@ -34,7 +34,7 @@
network handling.
These \l{Qt Core} classes are used to handle input and output to and from
- external devices, processes, files etc. as well as manipulating files and
+ external devices, processes, files etc., as well as manipulating files and
directories.
*/
diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h
index c88b66c7ce..37b7b822fd 100644
--- a/src/corelib/io/qabstractfileengine_p.h
+++ b/src/corelib/io/qabstractfileengine_p.h
@@ -237,7 +237,7 @@ public:
virtual QString currentFileName() const = 0;
virtual QFileInfo currentFileInfo() const;
- QString currentFilePath() const;
+ virtual QString currentFilePath() const;
protected:
enum EntryInfoType {
diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp
index 5c562623e2..8771ac3764 100644
--- a/src/corelib/io/qbuffer.cpp
+++ b/src/corelib/io/qbuffer.cpp
@@ -319,6 +319,10 @@ void QBuffer::setData(const QByteArray &data)
/*!
\reimp
+
+ Unlike QFile, opening a QBuffer QIODevice::WriteOnly does not truncate it.
+ However, pos() is set to 0. Use QIODevice::Append or QIODevice::Truncate to
+ change either behavior.
*/
bool QBuffer::open(OpenMode flags)
{
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 7a3e68a19a..b89e665d20 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -554,6 +554,10 @@ inline void QDirPrivate::initFileEngine()
\snippet qdir-listfiles/main.cpp 0
+ \section1 Platform Specific Issues
+
+ \include android-content-uri-limitations.qdocinc
+
\sa QFileInfo, QFile, QFileDialog, QCoreApplication::applicationDirPath(), {Find Files Example}
*/
@@ -673,8 +677,12 @@ QString QDir::path() const
QString QDir::absolutePath() const
{
const QDirPrivate* d = d_ptr.constData();
- d->resolveAbsoluteEntry();
- return d->absoluteDirEntry.filePath();
+ if (!d->fileEngine) {
+ d->resolveAbsoluteEntry();
+ return d->absoluteDirEntry.filePath();
+ }
+
+ return d->fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
}
/*!
@@ -717,7 +725,9 @@ QString QDir::canonicalPath() const
QString QDir::dirName() const
{
const QDirPrivate* d = d_ptr.constData();
- return d->dirEntry.fileName();
+ if (!d_ptr->fileEngine)
+ return d->dirEntry.fileName();
+ return d->fileEngine->fileName(QAbstractFileEngine::BaseName);
}
@@ -1037,6 +1047,9 @@ bool QDir::cd(const QString &dirName)
otherwise returns \c false. Note that the logical cdUp() operation is
not performed if the new directory does not exist.
+ \note On Android, this is not supported for content URIs. For more information,
+ see \l {Android: DocumentFile.getParentFile()}{DocumentFile.getParentFile()}.
+
\sa cd(), isReadable(), exists(), path()
*/
bool QDir::cdUp()
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 14ce49da56..3bf6ddbc41 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -229,6 +229,8 @@ QAbstractFileEngine *QFilePrivate::engine() const
function mostly useless for NTFS volumes. It may still be of use for USB
sticks that use VFAT file systems. POSIX ACLs are not manipulated, either.
+ \include android-content-uri-limitations.qdocinc
+
\sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System}
*/
@@ -961,6 +963,9 @@ QFile::copy(const QString &fileName, const QString &newName)
\note In \l{QIODevice::}{WriteOnly} or \l{QIODevice::}{ReadWrite}
mode, if the relevant file does not already exist, this function
will try to create a new file before opening it.
+ On Android, it's expected to have access permission to the parent
+ of the file name, otherwise, it won't be possible to create this
+ non-existing file.
\sa QIODevice::OpenMode, setFileName()
*/
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index b0aba3193c..d70b9f1c73 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -148,6 +148,11 @@ void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum)
decrementing \c qt_ntfs_permission_lookup by 1.
\snippet ntfsp.cpp 1
+
+ \note Since this is a non-atomic global variable, it is only safe
+ to increment or decrement \c qt_ntfs_permission_lookup before any
+ threads other than the main thread have started or after every thread
+ other than the main thread has ended.
*/
//************* QFileDevice
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index e73a6f4946..b5f5003f93 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -294,6 +294,11 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
\snippet ntfsp.cpp 1
+ \note Since this is a non-atomic global variable, it is only safe
+ to increment or decrement \c qt_ntfs_permission_lookup before any
+ threads other than the main thread have started or after every thread
+ other than the main thread has ended.
+
\section1 Performance Issues
Some of QFileInfo's functions query the file system, but for
@@ -312,6 +317,10 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
off a QFileInfo's caching and force it to access the file system
every time you request information from it call setCaching(false).
+ \section1 Platform Specific Issues
+
+ \include android-content-uri-limitations.qdocinc
+
\sa QDir, QFile
*/
@@ -767,7 +776,9 @@ QString QFileInfo::fileName() const
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
return QLatin1String("");
- return d->fileEntry.fileName();
+ if (!d->fileEngine)
+ return d->fileEntry.fileName();
+ return d->fileEngine->fileName(QAbstractFileEngine::BaseName);
}
/*!
@@ -811,7 +822,9 @@ QString QFileInfo::baseName() const
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
return QLatin1String("");
- return d->fileEntry.baseName();
+ if (!d->fileEngine)
+ return d->fileEntry.baseName();
+ return QFileSystemEntry(d->fileEngine->fileName(QAbstractFileEngine::BaseName)).baseName();
}
/*!
@@ -830,7 +843,10 @@ QString QFileInfo::completeBaseName() const
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
return QLatin1String("");
- return d->fileEntry.completeBaseName();
+ if (!d->fileEngine)
+ return d->fileEntry.completeBaseName();
+ const QString fileEngineBaseName = d->fileEngine->fileName(QAbstractFileEngine::BaseName);
+ return QFileSystemEntry(fileEngineBaseName).completeBaseName();
}
/*!
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 42739097f2..01aed7ad14 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -44,6 +44,7 @@
#include "qfile.h"
#include "qstorageinfo.h"
#include "qtextstream.h"
+#include "qurl.h"
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/private/qcore_unix_p.h>
@@ -1392,6 +1393,16 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
const QString targetPath = trashDir.filePath(filesDir) + uniqueTrashedName;
const QFileSystemEntry target(targetPath);
+ QString infoPath;
+ const QStorageInfo storageInfo(sourcePath);
+ if (storageInfo.isValid() && storageInfo.rootPath() != rootPath() && storageInfo != QStorageInfo(QDir::home())) {
+ infoPath = sourcePath.mid(storageInfo.rootPath().length());
+ if (infoPath.front() == u'/')
+ infoPath = infoPath.mid(1);
+ } else {
+ infoPath = sourcePath;
+ }
+
/*
We might fail to rename if source and target are on different file systems.
In that case, we don't try further, i.e. copying and removing the original
@@ -1408,7 +1419,7 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
out.setCodec("UTF-8");
#endif
out << "[Trash Info]" << Qt::endl;
- out << "Path=" << sourcePath << Qt::endl;
+ out << "Path=" << QUrl::toPercentEncoding(infoPath, "/") << Qt::endl;
out << "DeletionDate="
<< QDateTime::currentDateTime().toString(QLatin1String("yyyy-MM-ddThh:mm:ss")) << Qt::endl;
infoFile.close();
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm
index 99ad4ce666..0b64deff4b 100644
--- a/src/corelib/kernel/qcore_mac.mm
+++ b/src/corelib/kernel/qcore_mac.mm
@@ -606,6 +606,14 @@ void qt_apple_check_os_version()
const NSOperatingSystemVersion required = (NSOperatingSystemVersion){
version / 10000, version / 100 % 100, version % 100};
const NSOperatingSystemVersion current = NSProcessInfo.processInfo.operatingSystemVersion;
+
+#if defined(Q_OS_MACOS)
+ // Check for compatibility version, in which case we can't do a
+ // comparison to the deployment target, which might be e.g. 11.0
+ if (current.majorVersion == 10 && current.minorVersion >= 16)
+ return; // FIXME: Find a way to detect the real OS version
+#endif
+
if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:required]) {
NSDictionary *plist = NSBundle.mainBundle.infoDictionary;
NSString *applicationName = plist[@"CFBundleDisplayName"];
diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp
index ce060cbe9a..9d9cefecba 100644
--- a/src/corelib/text/qlocale_win.cpp
+++ b/src/corelib/text/qlocale_win.cpp
@@ -489,15 +489,17 @@ QVariant QSystemLocalePrivate::toString(QTime time, QLocale::FormatType type)
DWORD flags = 0;
// keep the same conditional as timeFormat() above
- if (type == QLocale::ShortFormat)
- flags = TIME_NOSECONDS;
+ const QString format = type == QLocale::ShortFormat
+ ? getLocaleInfo(LOCALE_SSHORTTIME)
+ : QString();
+ auto formatStr = reinterpret_cast<const wchar_t *>(format.isEmpty() ? nullptr : format.utf16());
wchar_t buf[255];
- if (getTimeFormat(flags, &st, NULL, buf, 255)) {
- QString format = QString::fromWCharArray(buf);
+ if (getTimeFormat(flags, &st, formatStr, buf, int(std::size(buf)))) {
+ QString text = QString::fromWCharArray(buf);
if (substitution() == SAlways)
- substituteDigits(format);
- return format;
+ substituteDigits(text);
+ return text;
}
return QString();
}
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 0fdab96e28..5bec5dffbe 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -361,14 +361,11 @@ public:
#endif
private:
template <typename T>
- struct is_convertible_to_view_or_qstring_helper
+ struct is_convertible_to_view_or_qstring
: std::integral_constant<bool,
std::is_convertible<T, QString>::value ||
std::is_convertible<T, QStringView>::value ||
std::is_convertible<T, QLatin1String>::value> {};
- template <typename T>
- struct is_convertible_to_view_or_qstring
- : is_convertible_to_view_or_qstring_helper<typename std::decay<T>::type> {};
public:
template <typename...Args>
Q_REQUIRED_RESULT
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index cdeb077233..5b1e4f4c33 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -602,8 +602,12 @@ bool QThreadPool::tryStart(std::function<void()> functionToRun)
return false;
QRunnable *runnable = QRunnable::create(std::move(functionToRun));
+ Q_ASSERT(runnable->ref == 0);
+ ++runnable->ref;
if (d->tryStart(runnable))
return true;
+ --runnable->ref;
+ Q_ASSERT(runnable->ref == 0);
delete runnable;
return false;
}
diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
index 0309e43e52..3d451696a1 100644
--- a/src/corelib/time/qtimezone.cpp
+++ b/src/corelib/time/qtimezone.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
+** Copyright (C) 2020 John Layt <jlayt@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -975,9 +975,15 @@ QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId,
}
#ifndef QT_NO_DATASTREAM
+// Invalid, as an IANA ID: too long, starts with - and has other invalid characters in it
+static inline QString invalidId() { return QStringLiteral("-No Time Zone Specified!"); }
+
QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz)
{
- tz.d->serialize(ds);
+ if (tz.isValid())
+ tz.d->serialize(ds);
+ else
+ ds << invalidId();
return ds;
}
@@ -985,7 +991,9 @@ QDataStream &operator>>(QDataStream &ds, QTimeZone &tz)
{
QString ianaId;
ds >> ianaId;
- if (ianaId == QLatin1String("OffsetFromUtc")) {
+ if (ianaId == invalidId()) {
+ tz = QTimeZone();
+ } else if (ianaId == QLatin1String("OffsetFromUtc")) {
int utcOffset;
QString name;
QString abbreviation;
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index 7becff8700..bc7a5f80d7 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -479,6 +479,46 @@
*/
/*!
+ \fn template <class T> QSharedPointer<T>::QSharedPointer(QSharedPointer &&other)
+
+ Move-constructs a QSharedPointer instance, making it point at the same
+ object that \a other was pointing to.
+
+ \since 5.4
+*/
+
+/*!
+ \fn template <class T> QSharedPointer<T>::operator=(QSharedPointer &&other)
+
+ Move-assigns \a other to this QSharedPointer instance.
+
+ \since 5.0
+*/
+
+/*!
+ \fn template <class T> template <class X> QSharedPointer<T>::QSharedPointer(QSharedPointer<X> &&other)
+
+ Move-constructs a QSharedPointer instance, making it point at the same
+ object that \a other was pointing to.
+
+ This constructor participates in overload resolution only if \c{X*}
+ implicitly converts to \c{T*}.
+
+ \since 5.6
+*/
+
+/*!
+ \fn template <class T> template <class X> QSharedPointer<T>::operator=(QSharedPointer<X> &&other)
+
+ Move-assigns \a other to this QSharedPointer instance.
+
+ This assignment operator participates in overload resolution only if \c{X*}
+ implicitly converts to \c{T*}.
+
+ \since 5.6
+*/
+
+/*!
\fn template <class T> QSharedPointer<T>::QSharedPointer(const QWeakPointer<T> &other)
Creates a QSharedPointer by promoting the weak reference \a other
@@ -932,6 +972,15 @@
*/
/*!
+ \fn template <class T> qHash(const QSharedPointer<T> &key, size_t seed)
+ \relates QSharedPointer
+
+ Returns the hash value for \a key, using \a seed to seed the calculation.
+
+ \since 5.0
+*/
+
+/*!
\fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QSharedPointer
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
index 5d47369687..72e48d8a16 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -82,7 +82,12 @@ public:
QSharedPointer<T> &operator=(const QSharedPointer<T> &other);
QSharedPointer<T> &operator=(const QWeakPointer<T> &other);
- void swap(QSharedPointer<T> &other);
+ template <class X>
+ QSharedPointer(QSharedPointer<X> && other) noexcept;
+ template <class X>
+ QSharedPointer &operator=(QSharedPointer<X> && other) noexcept;
+
+ void swap(QSharedPointer<T> &other) noexcept;
QWeakPointer<T> toWeakRef() const;
@@ -104,6 +109,9 @@ public:
};
template <class T>
+size_t qHash(const QSharedPointer<T> &key, size_t seed = 0) noexcept;
+
+template <class T>
class QWeakPointer
{
public:
diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
index d48318b474..ca52b15870 100644
--- a/src/corelib/tools/qtools_p.h
+++ b/src/corelib/tools/qtools_p.h
@@ -84,6 +84,17 @@ Q_DECL_CONSTEXPR inline int fromOct(uint c) noexcept
{
return ((c >= '0') && (c <= '7')) ? int(c - '0') : -1;
}
+
+constexpr inline char toAsciiLower(char ch) noexcept
+{
+ return (ch >= 'A' && ch <= 'Z') ? ch - 'A' + 'a' : ch;
+}
+
+constexpr inline char toAsciiUpper(char ch) noexcept
+{
+ return (ch >= 'a' && ch <= 'z') ? ch - 'a' + 'A' : ch;
+}
+
}
// We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size.
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index d8c229dea8..4b7e277187 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -475,28 +475,17 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
{
Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
- int offset = int(before - ptr);
- reserve(s + 1);
- if (!QTypeInfo<T>::isRelocatable) {
- T *b = ptr + offset;
- T *i = ptr + s;
- T *j = i + 1;
- // The new end-element needs to be constructed, the rest must be move assigned
- if (i != b) {
- new (--j) T(std::move(*--i));
- while (i != b)
- *--j = std::move(*--i);
- *b = std::move(t);
- } else {
- new (b) T(std::move(t));
- }
+ const int offset = int(before - ptr);
+ append(std::move(t));
+ const auto b = begin() + offset;
+ const auto e = end();
+ if (QTypeInfo<T>::isRelocatable) {
+ auto cast = [](T *p) { return reinterpret_cast<uchar*>(p); };
+ std::rotate(cast(b), cast(e - 1), cast(e));
} else {
- T *b = ptr + offset;
- memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (s - offset) * sizeof(T));
- new (b) T(std::move(t));
+ std::rotate(b, e - 1, e);
}
- s += 1;
- return ptr + offset;
+ return b;
}
template <class T, int Prealloc>