summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/configure.json6
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp8
-rw-r--r--src/corelib/doc/snippets/qstring/main.cpp8
-rw-r--r--src/corelib/doc/src/containers.qdoc134
-rw-r--r--src/corelib/doc/src/datastreamformat.qdoc1
-rw-r--r--src/corelib/doc/src/dontdocument.qdoc2
-rw-r--r--src/corelib/global/qcompilerdetection.h22
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h1
-rw-r--r--src/corelib/global/qendian.cpp2
-rw-r--r--src/corelib/global/qglobal.cpp16
-rw-r--r--src/corelib/global/qglobal.h58
-rw-r--r--src/corelib/global/qlibraryinfo.cpp2
-rw-r--r--src/corelib/global/qlibraryinfo.h1
-rw-r--r--src/corelib/global/qlogging.cpp2
-rw-r--r--src/corelib/global/qnamespace.h200
-rw-r--r--src/corelib/global/qnumeric_p.h6
-rw-r--r--src/corelib/global/qrandom.cpp4
-rw-r--r--src/corelib/global/qrandom.h2
-rw-r--r--src/corelib/global/qtypeinfo.h1
-rw-r--r--src/corelib/io/qdebug.h6
-rw-r--r--src/corelib/io/qfileselector.cpp7
-rw-r--r--src/corelib/io/qfilesystemiterator_unix.cpp2
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp2
-rw-r--r--src/corelib/io/qresource.cpp10
-rw-r--r--src/corelib/io/qsettings.cpp8
-rw-r--r--src/corelib/io/qstandardpaths.cpp2
-rw-r--r--src/corelib/io/qurl.cpp2
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp32
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h1
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.h6
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.h2
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp6
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp2
-rw-r--r--src/corelib/kernel/qmetaobject.cpp55
-rw-r--r--src/corelib/kernel/qmetaobject.h3
-rw-r--r--src/corelib/kernel/qmetaobject_moc_p.h3
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp22
-rw-r--r--src/corelib/kernel/qmetatype.cpp51
-rw-r--r--src/corelib/kernel/qmetatype.h48
-rw-r--r--src/corelib/kernel/qmetatype_p.h3
-rw-r--r--src/corelib/kernel/qobject.cpp85
-rw-r--r--src/corelib/kernel/qobject.h30
-rw-r--r--src/corelib/kernel/qobject_p.h12
-rw-r--r--src/corelib/kernel/qobjectdefs.h192
-rw-r--r--src/corelib/kernel/qtmetamacros.h234
-rw-r--r--src/corelib/kernel/qtranslator.cpp8
-rw-r--r--src/corelib/kernel/qvariant.cpp156
-rw-r--r--src/corelib/kernel/qvariant.h16
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp4
-rw-r--r--src/corelib/mimetypes/qmimedatabase_p.h1
-rw-r--r--src/corelib/plugin/qlibrary.cpp4
-rw-r--r--src/corelib/serialization/qbinaryjsonvalue.cpp18
-rw-r--r--src/corelib/serialization/qbinaryjsonvalue_p.h4
-rw-r--r--src/corelib/serialization/qcborvalue_p.h17
-rw-r--r--src/corelib/serialization/qdatastream.h19
-rw-r--r--src/corelib/serialization/qjsonarray.h1
-rw-r--r--src/corelib/serialization/qjsoncbor.cpp24
-rw-r--r--src/corelib/serialization/qjsonparser.cpp12
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp94
-rw-r--r--src/corelib/serialization/qjsonvalue.h1
-rw-r--r--src/corelib/serialization/qjsonwriter.cpp14
-rw-r--r--src/corelib/statemachine/qsignaleventgenerator_p.h7
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp92
-rw-r--r--src/corelib/text/qbytearray.cpp606
-rw-r--r--src/corelib/text/qbytearray.h240
-rw-r--r--src/corelib/text/qbytearray_p.h2
-rw-r--r--src/corelib/text/qbytearraylist.h19
-rw-r--r--src/corelib/text/qbytearraymatcher.h2
-rw-r--r--src/corelib/text/qchar.h1
-rw-r--r--src/corelib/text/qstring.cpp520
-rw-r--r--src/corelib/text/qstring.h274
-rw-r--r--src/corelib/text/qstringbuilder.cpp4
-rw-r--r--src/corelib/text/qstringbuilder.h10
-rw-r--r--src/corelib/text/qstringlist.h74
-rw-r--r--src/corelib/text/qstringliteral.h44
-rw-r--r--src/corelib/thread/qfutureinterface.cpp7
-rw-r--r--src/corelib/thread/qfutureinterface.h13
-rw-r--r--src/corelib/thread/qthread.cpp2
-rw-r--r--src/corelib/thread/qthread.h33
-rw-r--r--src/corelib/thread/qthread_unix.cpp28
-rw-r--r--src/corelib/thread/qthread_win.cpp2
-rw-r--r--src/corelib/time/qdatetimeparser_p.h4
-rw-r--r--src/corelib/tools/qarraydata.cpp111
-rw-r--r--src/corelib/tools/qarraydata.h231
-rw-r--r--src/corelib/tools/qarraydataops.h413
-rw-r--r--src/corelib/tools/qarraydatapointer.h169
-rw-r--r--src/corelib/tools/qbitarray.cpp32
-rw-r--r--src/corelib/tools/qbitarray.h4
-rw-r--r--src/corelib/tools/qcontainerfwd.h2
-rw-r--r--src/corelib/tools/qcontiguouscache.h5
-rw-r--r--src/corelib/tools/qeasingcurve.cpp5
-rw-r--r--src/corelib/tools/qeasingcurve.h7
-rw-r--r--src/corelib/tools/qflatmap_p.h982
-rw-r--r--src/corelib/tools/qhash.h25
-rw-r--r--src/corelib/tools/qlinkedlist.h3
-rw-r--r--src/corelib/tools/qlist.cpp2025
-rw-r--r--src/corelib/tools/qlist.h1151
-rw-r--r--src/corelib/tools/qmap.h36
-rw-r--r--src/corelib/tools/qrefcount.h25
-rw-r--r--src/corelib/tools/qset.h33
-rw-r--r--src/corelib/tools/qvector.h1229
-rw-r--r--src/corelib/tools/qvector_msvc.cpp7
-rw-r--r--src/corelib/tools/tools.pri2
103 files changed, 3582 insertions, 6594 deletions
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index eb60ad213c..c8e650ca9f 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -826,6 +826,12 @@
],
"output": [ "publicFeature", "feature" ]
},
+ "shortcut": {
+ "label": "QShortcut",
+ "purpose": "Provides keyboard accelerators and shortcuts.",
+ "section": "Kernel",
+ "output": [ "publicFeature", "feature" ]
+ },
"systemsemaphore": {
"label": "QSystemSemaphore",
"purpose": "Provides a general counting system semaphore.",
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
index 01f620cf08..9c07a2e92c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
@@ -372,16 +372,13 @@ a = str.toFloat(&ok); // a == 0, ok == false
//! [39]
QByteArray text("Qt is great!");
text.toBase64(); // returns "UXQgaXMgZ3JlYXQh"
-//! [39]
-//! [39bis]
QByteArray text("<p>Hello?</p>");
text.toBase64(QByteArray::Base64Encoding | QByteArray::OmitTrailingEquals); // returns "PHA+SGVsbG8/PC9wPg"
text.toBase64(QByteArray::Base64Encoding); // returns "PHA+SGVsbG8/PC9wPg=="
text.toBase64(QByteArray::Base64UrlEncoding); // returns "PHA-SGVsbG8_PC9wPg=="
text.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); // returns "PHA-SGVsbG8_PC9wPg"
-//! [39bis]
-
+//! [39]
//! [40]
QByteArray ba;
@@ -422,9 +419,7 @@ QDataStream in(&data, QIODevice::ReadOnly);
//! [44]
QByteArray text = QByteArray::fromBase64("UXQgaXMgZ3JlYXQh");
text.data(); // returns "Qt is great!"
-//! [44]
-//! [44bis]
QByteArray::fromBase64("PHA+SGVsbG8/PC9wPg==", QByteArray::Base64Encoding); // returns "<p>Hello?</p>"
QByteArray::fromBase64("PHA-SGVsbG8_PC9wPg==", QByteArray::Base64UrlEncoding); // returns "<p>Hello?</p>"
//! [44bis]
@@ -442,7 +437,6 @@ if (result.decodingStatus == QByteArray::Base64DecodingStatus::Ok)
process(result.decoded);
//! [44quater]
-
//! [45]
QByteArray text = QByteArray::fromHex("517420697320677265617421");
text.data(); // returns "Qt is great!"
diff --git a/src/corelib/doc/snippets/qstring/main.cpp b/src/corelib/doc/snippets/qstring/main.cpp
index ac7fc7d078..f797890e5d 100644
--- a/src/corelib/doc/snippets/qstring/main.cpp
+++ b/src/corelib/doc/snippets/qstring/main.cpp
@@ -433,14 +433,12 @@ void Widget::firstIndexOfFunction()
//! [93]
QString str = "the minimum";
str.indexOf(QRegularExpression("m[aeiou]"), 0); // returns 4
- //! [93]
- //! [99]
QString str = "the minimum";
QRegularExpressionMatch match;
str.indexOf(QRegularExpression("m[aeiou]"), 0, &match); // returns 4
// match.captured() == mi
- //! [99]
+ //! [93]
}
void Widget::insertFunction()
@@ -490,14 +488,12 @@ void Widget::lastIndexOfFunction()
//! [94]
QString str = "the minimum";
str.lastIndexOf(QRegularExpression("m[aeiou]")); // returns 8
- //! [94]
- //! [100]
QString str = "the minimum";
QRegularExpressionMatch match;
str.lastIndexOf(QRegularExpression("m[aeiou]"), -1, &match); // returns 8
// match.captured() == mu
- //! [100]
+ //! [94]
}
void Widget::leftFunction()
diff --git a/src/corelib/doc/src/containers.qdoc b/src/corelib/doc/src/containers.qdoc
index d0bb251e81..8373ad4b4e 100644
--- a/src/corelib/doc/src/containers.qdoc
+++ b/src/corelib/doc/src/containers.qdoc
@@ -74,12 +74,10 @@
\section1 The Container Classes
- Qt provides the following sequential containers: QList,
- QLinkedList, QVector, QStack, and QQueue. For most
- applications, QList is the best type to use. Although it is
- implemented as an array-list, it provides very fast prepends and
- appends. If you really need a linked-list, use QLinkedList; if you
- want your items to occupy consecutive memory locations, use QVector.
+ Qt provides the following sequential containers: QVector,
+ QLinkedList, QStack, and QQueue. For most
+ applications, QVector is the best type to use. It provides very fast
+ appends. If you really need a linked-list, use QLinkedList.
QStack and QQueue are convenience classes that provide LIFO and
FIFO semantics.
@@ -95,30 +93,19 @@
\table
\header \li Class \li Summary
- \row \li \l{QList}<T>
- \li This is by far the most commonly used container class. It
- stores a list of values of a given type (T) that can be accessed
- by index. Internally, the QList is implemented using an array,
- ensuring that index-based access is very fast.
-
- Items can be added at either end of the list using
- QList::append() and QList::prepend(), or they can be inserted in
- the middle using QList::insert(). More than any other container
- class, QList is highly optimized to expand to as little code as
- possible in the executable. QStringList inherits from
- QList<QString>.
-
\row \li \l{QLinkedList}<T>
- \li This is similar to QList, except that it uses
- iterators rather than integer indexes to access items. It also
- provides better performance than QList when inserting in the
+ \li This class implements a doubly linked list. It
+ provides better performance than QVector when inserting in the
middle of a huge list, and it has nicer iterator semantics.
(Iterators pointing to an item in a QLinkedList remain valid as
- long as the item exists, whereas iterators to a QList can become
+ long as the item exists, whereas iterators to a QVector can become
invalid after any insertion or removal.)
\row \li \l{QVector}<T>
- \li This stores an array of values of a given type at adjacent
+ \li This is by far the most commonly used container class. It
+ stores a list of values of a given type (T) that can be accessed
+ by index. Internally, it stores an array of values of a
+ given type at adjacent
positions in memory. Inserting at the front or in the middle of
a vector can be quite slow, because it can lead to large numbers
of items having to be moved by one position in memory.
@@ -131,9 +118,9 @@
and \l{QStack::top()}{top()}.
\row \li \l{QQueue}<T>
- \li This is a convenience subclass of QList that provides
+ \li This is a convenience subclass of QVector that provides
"first in, first out" (FIFO) semantics. It adds the following
- functions to those already present in QList:
+ functions to those already present in QQVector:
\l{QQueue::enqueue()}{enqueue()},
\l{QQueue::dequeue()}{dequeue()}, and \l{QQueue::head()}{head()}.
@@ -164,8 +151,8 @@
\endtable
Containers can be nested. For example, it is perfectly possible
- to use a QMap<QString, QList<int>>, where the key type is
- QString and the value type QList<int>.
+ to use a QMap<QString, QVector<int>>, where the key type is
+ QString and the value type QVector<int>.
The containers are defined in individual header files with the
same name as the container (e.g., \c <QLinkedList>). For
@@ -184,10 +171,10 @@
double, pointer types, and Qt data types such as QString, QDate,
and QTime, but it doesn't cover QObject or any QObject subclass
(QWidget, QDialog, QTimer, etc.). If you attempt to instantiate a
- QList<QWidget>, the compiler will complain that QWidget's copy
+ QVector<QWidget>, the compiler will complain that QWidget's copy
constructor and assignment operators are disabled. If you want to
store these kinds of objects in a container, store them as
- pointers, for example as QList<QWidget *>.
+ pointers, for example as QVector<QWidget *>.
Here's an example custom data type that meets the requirement of
an assignable data type:
@@ -260,11 +247,10 @@
\table
\header \li Containers \li Read-only iterator
\li Read-write iterator
- \row \li QList<T>, QQueue<T> \li QListIterator<T>
\li QMutableListIterator<T>
\row \li QLinkedList<T> \li QLinkedListIterator<T>
\li QMutableLinkedListIterator<T>
- \row \li QVector<T>, QStack<T> \li QVectorIterator<T>
+ \row \li QVector<T>, QStack<T>, QQueue<T> \li QVectorIterator<T>
\li QMutableVectorIterator<T>
\row \li QSet<T> \li QSetIterator<T>
\li QMutableSetIterator<T>
@@ -274,9 +260,9 @@
\li QMutableHashIterator<Key, T>
\endtable
- In this discussion, we will concentrate on QList and QMap. The
+ In this discussion, we will concentrate on QVector and QMap. The
iterator types for QLinkedList, QVector, and QSet have exactly
- the same interface as QList's iterators; similarly, the iterator
+ the same interface as QVector's iterators; similarly, the iterator
types for QHash have the same interface as QMap's iterators.
Unlike STL-style iterators (covered \l{STL-style
@@ -291,59 +277,59 @@
\image javaiterators1.png
Here's a typical loop for iterating through all the elements of a
- QList<QString> in order and printing them to the console:
+ QVector<QString> in order and printing them to the console:
\snippet code/doc_src_containers.cpp 1
- It works as follows: The QList to iterate over is passed to the
- QListIterator constructor. At that point, the iterator is located
+ It works as follows: The QVector to iterate over is passed to the
+ QVectorIterator constructor. At that point, the iterator is located
just in front of the first item in the list (before item "A").
- Then we call \l{QListIterator::hasNext()}{hasNext()} to
+ Then we call \l{QVectorIterator::hasNext()}{hasNext()} to
check whether there is an item after the iterator. If there is, we
- call \l{QListIterator::next()}{next()} to jump over that
+ call \l{QVectorIterator::next()}{next()} to jump over that
item. The next() function returns the item that it jumps over. For
- a QList<QString>, that item is of type QString.
+ a QVector<QString>, that item is of type QString.
- Here's how to iterate backward in a QList:
+ Here's how to iterate backward in a QVector:
\snippet code/doc_src_containers.cpp 2
The code is symmetric with iterating forward, except that we
- start by calling \l{QListIterator::toBack()}{toBack()}
+ start by calling \l{QVectorIterator::toBack()}{toBack()}
to move the iterator after the last item in the list.
The diagram below illustrates the effect of calling
- \l{QListIterator::next()}{next()} and
- \l{QListIterator::previous()}{previous()} on an iterator:
+ \l{QVectorIterator::next()}{next()} and
+ \l{QVectorIterator::previous()}{previous()} on an iterator:
\image javaiterators2.png
- The following table summarizes the QListIterator API:
+ The following table summarizes the QVectorIterator API:
\table
\header \li Function \li Behavior
- \row \li \l{QListIterator::toFront()}{toFront()}
+ \row \li \l{QVectorIterator::toFront()}{toFront()}
\li Moves the iterator to the front of the list (before the first item)
- \row \li \l{QListIterator::toBack()}{toBack()}
+ \row \li \l{QVectorIterator::toBack()}{toBack()}
\li Moves the iterator to the back of the list (after the last item)
- \row \li \l{QListIterator::hasNext()}{hasNext()}
+ \row \li \l{QVectorIterator::hasNext()}{hasNext()}
\li Returns \c true if the iterator isn't at the back of the list
- \row \li \l{QListIterator::next()}{next()}
+ \row \li \l{QVectorIterator::next()}{next()}
\li Returns the next item and advances the iterator by one position
- \row \li \l{QListIterator::peekNext()}{peekNext()}
+ \row \li \l{QVectorIterator::peekNext()}{peekNext()}
\li Returns the next item without moving the iterator
- \row \li \l{QListIterator::hasPrevious()}{hasPrevious()}
+ \row \li \l{QVectorIterator::hasPrevious()}{hasPrevious()}
\li Returns \c true if the iterator isn't at the front of the list
- \row \li \l{QListIterator::previous()}{previous()}
+ \row \li \l{QVectorIterator::previous()}{previous()}
\li Returns the previous item and moves the iterator back by one position
- \row \li \l{QListIterator::peekPrevious()}{peekPrevious()}
+ \row \li \l{QVectorIterator::peekPrevious()}{peekPrevious()}
\li Returns the previous item without moving the iterator
\endtable
- QListIterator provides no functions to insert or remove items
+ QVectorIterator provides no functions to insert or remove items
from the list as we iterate. To accomplish this, you must use
QMutableListIterator. Here's an example where we remove all
- odd numbers from a QList<int> using QMutableListIterator:
+ odd numbers from a QVector<int> using QMutableListIterator:
\snippet code/doc_src_containers.cpp 3
@@ -377,11 +363,11 @@
\snippet code/doc_src_containers.cpp 6
As mentioned above, QLinkedList's, QVector's, and QSet's iterator
- classes have exactly the same API as QList's. We will now turn to
+ classes have exactly the same API as QVector's. We will now turn to
QMapIterator, which is somewhat different because it iterates on
(key, value) pairs.
- Like QListIterator, QMapIterator provides
+ Like QVectorIterator, QMapIterator provides
\l{QMapIterator::toFront()}{toFront()},
\l{QMapIterator::toBack()}{toBack()},
\l{QMapIterator::hasNext()}{hasNext()},
@@ -429,11 +415,9 @@
\table
\header \li Containers \li Read-only iterator
\li Read-write iterator
- \row \li QList<T>, QQueue<T> \li QList<T>::const_iterator
- \li QList<T>::iterator
\row \li QLinkedList<T> \li QLinkedList<T>::const_iterator
\li QLinkedList<T>::iterator
- \row \li QVector<T>, QStack<T> \li QVector<T>::const_iterator
+ \row \li QVector<T>, QStack<T>, QQueue<T> \li QVector<T>::const_iterator
\li QVector<T>::iterator
\row \li QSet<T> \li QSet<T>::const_iterator
\li QSet<T>::iterator
@@ -452,24 +436,24 @@
and the \l{QVector::iterator}{const_iterator} type is
just a typedef for \c{const T *}.
- In this discussion, we will concentrate on QList and QMap. The
+ In this discussion, we will concentrate on QVector and QMap. The
iterator types for QLinkedList, QVector, and QSet have exactly
- the same interface as QList's iterators; similarly, the iterator
+ the same interface as QVector's iterators; similarly, the iterator
types for QHash have the same interface as QMap's iterators.
Here's a typical loop for iterating through all the elements of a
- QList<QString> in order and converting them to lowercase:
+ QVector<QString> in order and converting them to lowercase:
\snippet code/doc_src_containers.cpp 10
Unlike \l{Java-style iterators}, STL-style iterators point
- directly at items. The \l{QList::begin()}{begin()} function of a container returns an
+ directly at items. The \l{QVector::begin()}{begin()} function of a container returns an
iterator that points to the first item in the container. The
- \l{QList::end()}{end()} function of a container returns an iterator to the
+ \l{QVector::end()}{end()} function of a container returns an iterator to the
imaginary item one position past the last item in the container.
- \l {QList::end()}{end()} marks an invalid position; it must never be dereferenced.
+ \l {QVector::end()}{end()} marks an invalid position; it must never be dereferenced.
It is typically used in a loop's break condition. If the list is
- empty, \l{QList::begin}{begin()} equals \l{QList::end()}{end()}, so we never execute the loop.
+ empty, \l{QVector::begin}{begin()} equals \l{QVector::end()}{end()}, so we never execute the loop.
The diagram below shows the valid iterator positions as red
arrows for a vector containing four items:
@@ -486,8 +470,8 @@
compilers also allow us to write \c{i->toLower()}, but some
don't.
- For read-only access, you can use const_iterator, \l{QList::constBegin}{constBegin()},
- and \l{QList::constEnd()}{constEnd()}. For example:
+ For read-only access, you can use const_iterator, \l{QVector::constBegin}{constBegin()},
+ and \l{QVector::constEnd()}{constEnd()}. For example:
\snippet code/doc_src_containers.cpp 12
@@ -525,7 +509,7 @@
Thanks to \l{implicit sharing}, it is very inexpensive for a
function to return a container per value. The Qt API contains
- dozens of functions that return a QList or QStringList per value
+ dozens of functions that return a QVector or QStringList per value
(e.g., QSplitter::sizes()). If you want to iterate over these
using an STL iterator, you should always take a copy of the
container and iterate over the copy. For example:
@@ -695,7 +679,6 @@
\table
\header \li \li Index lookup \li Insertion \li Prepending \li Appending
\row \li QLinkedList<T> \li O(\e n) \li O(1) \li O(1) \li O(1)
- \row \li QList<T> \li O(1) \li O(n) \li Amort. O(1) \li Amort. O(1)
\row \li QVector<T> \li O(1) \li O(n) \li O(n) \li Amort. O(1)
\endtable
@@ -726,11 +709,8 @@
\section1 Growth Strategies
QVector<T>, QString, and QByteArray store their items
- contiguously in memory; QList<T> maintains an array of pointers
- to the items it stores to provide fast index-based access (unless
- T is a pointer type or a basic type of the size of a pointer, in
- which case the value itself is stored in the array); QHash<Key,
- T> keeps a hash table whose size is proportional to the number
+ contiguously in memory; QHash<Key, T> keeps a
+ hash table whose size is proportional to the number
of items in the hash. To avoid reallocating the data every single
time an item is added at the end of the container, these classes
typically allocate more memory than necessary.
@@ -764,7 +744,7 @@
on the first and last pages actually needs to be copied.
\endlist
- QByteArray and QList<T> use more or less the same algorithm as
+ QByteArray uses more or less the same algorithm as
QString.
QVector<T> also uses that algorithm for data types that can be
diff --git a/src/corelib/doc/src/datastreamformat.qdoc b/src/corelib/doc/src/datastreamformat.qdoc
index d6b60f10ce..def9021350 100644
--- a/src/corelib/doc/src/datastreamformat.qdoc
+++ b/src/corelib/doc/src/datastreamformat.qdoc
@@ -67,7 +67,6 @@
\li QImage
\li QKeySequence
\li QLinkedList<T>
- \li QList<T>
\li QMap<Key, T>
\li QMargins
\li QMatrix4x4
diff --git a/src/corelib/doc/src/dontdocument.qdoc b/src/corelib/doc/src/dontdocument.qdoc
index ff0aa98709..5fe05997cc 100644
--- a/src/corelib/doc/src/dontdocument.qdoc
+++ b/src/corelib/doc/src/dontdocument.qdoc
@@ -29,7 +29,7 @@
\dontdocument (QMacAutoReleasePool QIncompatibleFlag QGenericAtomicOps QAtomicTraits
QAtomicOps QBasicAtomicInteger QBasicAtomicPointer QBasicMutex QInternal
QArgument QReturnArgument QArrayData QTypedArrayData QStaticByteArrayData
- QByteRef QStaticStringData QListSpecialMethods QListData QScopedPointerDeleter
+ QStaticStringData QListSpecialMethods QListData QScopedPointerDeleter
QScopedPointerArrayDeleter QScopedPointerPodDeleter QScopedPointerObjectDeleteLater
QMetaTypeId2 QObjectData QObjectUserData QMapNodeBase QMapNode QMapDataBase
QMapData QHashData QHashNode QArrayDataPointer QTextStreamManipulator
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index aa38ef18c0..99a30e941b 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -91,8 +91,6 @@
# define Q_OUTOFLINE_TEMPLATE inline
# define Q_COMPILER_MANGLES_RETURN_TYPE
# define Q_FUNC_INFO __FUNCSIG__
-# define Q_ALIGNOF(type) __alignof(type)
-# define Q_DECL_ALIGN(n) __declspec(align(n))
# define Q_ASSUME_IMPL(expr) __assume(expr)
# define Q_UNREACHABLE_IMPL() __assume(0)
# define Q_NORETURN __declspec(noreturn)
@@ -222,10 +220,8 @@
# endif
# define Q_FUNC_INFO __PRETTY_FUNCTION__
-# define Q_ALIGNOF(type) __alignof__(type)
# define Q_TYPEOF(expr) __typeof__(expr)
# define Q_DECL_DEPRECATED __attribute__ ((__deprecated__))
-# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
# define Q_DECL_UNUSED __attribute__((__unused__))
# define Q_LIKELY(expr) __builtin_expect(!!(expr), true)
# define Q_UNLIKELY(expr) __builtin_expect(!!(expr), false)
@@ -272,9 +268,7 @@
# if __xlC__ < 0x400
# error "Compiler not supported"
# elif __xlC__ >= 0x0600
-# define Q_ALIGNOF(type) __alignof__(type)
# define Q_TYPEOF(expr) __typeof__(expr)
-# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
# define Q_PACKED __attribute__((__packed__))
# endif
@@ -352,7 +346,6 @@
# define Q_PACKED __attribute__ ((__packed__))
# define Q_FUNC_INFO __PRETTY_FUNCTION__
# define Q_TYPEOF(expr) __typeof__(expr)
-# define Q_ALIGNOF(type) __alignof__(type)
# define Q_UNREACHABLE_IMPL()
# if defined(__cplusplus)
# define Q_COMPILER_AUTO_TYPE
@@ -449,9 +442,7 @@
# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
/* see http://developers.sun.com/sunstudio/support/Ccompare.html */
# if __SUNPRO_CC >= 0x590
-# define Q_ALIGNOF(type) __alignof__(type)
# define Q_TYPEOF(expr) __typeof__(expr)
-# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
# endif
# if __SUNPRO_CC >= 0x550
# define Q_DECL_EXPORT __global
@@ -488,9 +479,6 @@
# define Q_DECL_EXPORT __declspec(dllexport)
# define Q_DECL_IMPORT __declspec(dllimport)
# endif
-# if __HP_aCC-0 >= 061200
-# define Q_DECL_ALIGN(n) __attribute__((aligned(n)))
-# endif
# if __HP_aCC-0 >= 062000
# define Q_DECL_EXPORT __attribute__((visibility("default")))
# define Q_DECL_HIDDEN __attribute__((visibility("hidden")))
@@ -1133,14 +1121,12 @@
#endif
#define Q_DECL_NOTHROW Q_DECL_NOEXCEPT
-#if defined(Q_COMPILER_ALIGNOF)
-# undef Q_ALIGNOF
-# define Q_ALIGNOF(x) alignof(x)
+#ifndef Q_ALIGNOF
+# define Q_ALIGNOF(x) alignof(x)
#endif
-#if defined(Q_COMPILER_ALIGNAS)
-# undef Q_DECL_ALIGN
-# define Q_DECL_ALIGN(n) alignas(n)
+#ifndef Q_DECL_ALIGN
+# define Q_DECL_ALIGN(n) alignas(n)
#endif
#if __has_cpp_attribute(nodiscard) && !defined(Q_CC_CLANG) // P0188R1
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index b3daf43c04..4a8a4598a0 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -112,6 +112,7 @@
# define QT_FEATURE_renameat2 -1
#endif
#define QT_FEATURE_sharedmemory -1
+#define QT_FEATURE_shortcut -1
#define QT_FEATURE_signaling_nan -1
#define QT_FEATURE_slog2 -1
#ifdef __GLIBC_PREREQ
diff --git a/src/corelib/global/qendian.cpp b/src/corelib/global/qendian.cpp
index eb08b2f848..c69572cccf 100644
--- a/src/corelib/global/qendian.cpp
+++ b/src/corelib/global/qendian.cpp
@@ -764,7 +764,7 @@ QT_BEGIN_NAMESPACE
#if defined(__SSSE3__)
using ShuffleMask = uchar[16];
-Q_DECL_ALIGN(16) static const ShuffleMask shuffleMasks[3] = {
+alignas(16) static const ShuffleMask shuffleMasks[3] = {
// 16-bit
{1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14},
// 32-bit
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 0f7ba8580e..c9e155555c 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1215,11 +1215,14 @@ bool qSharedBuild() noexcept
the application is compiled (32 or 64).
*/
+#if QT_DEPRECATED_SINCE(5, 9)
/*!
\deprecated
\variable QSysInfo::WindowsVersion
\brief the version of the Windows operating system on which the
application is run.
+
+ Use QOperatingSystemVersion::current() instead.
*/
/*!
@@ -1227,6 +1230,8 @@ bool qSharedBuild() noexcept
\fn QSysInfo::WindowsVersion QSysInfo::windowsVersion()
\since 4.4
+ Use QOperatingSystemVersion::current() instead.
+
Returns the version of the Windows operating system on which the
application is run, or WV_None if the operating system is not
Windows.
@@ -1237,16 +1242,21 @@ bool qSharedBuild() noexcept
\variable QSysInfo::MacintoshVersion
\brief the version of the Macintosh operating system on which
the application is run.
+
+ Use QOperatingSystemVersion::current() instead.
*/
/*!
\deprecated
\fn QSysInfo::MacVersion QSysInfo::macVersion()
+ Use QOperatingSystemVersion::current() instead.
+
Returns the version of Darwin (\macos or iOS) on which the
application is run, or MV_None if the operating system
is not a version of Darwin.
*/
+#endif
/*!
\enum QSysInfo::Endian
@@ -1257,10 +1267,13 @@ bool qSharedBuild() noexcept
the platform's byte order.
*/
+#if QT_DEPRECATED_SINCE(5, 9)
/*!
\deprecated
\enum QSysInfo::WinVersion
+ Use the versions defined in QOperatingSystemVersion instead.
+
This enum provides symbolic names for the various versions of the
Windows operating system. On Windows, the
QSysInfo::WindowsVersion variable gives the version of the system
@@ -1318,6 +1331,8 @@ bool qSharedBuild() noexcept
\deprecated
\enum QSysInfo::MacVersion
+ Use the versions defined in QOperatingSystemVersion instead.
+
This enum provides symbolic names for the various versions of the
Darwin operating system, covering both \macos and iOS. The
QSysInfo::MacintoshVersion variable gives the version of the
@@ -1388,6 +1403,7 @@ bool qSharedBuild() noexcept
\sa WinVersion
*/
+#endif
/*!
\macro Q_OS_DARWIN
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 35c0482768..c1fcc12cfb 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -86,14 +86,9 @@
#define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1)
#define QT_REQUIRE_CONFIG(feature) Q_STATIC_ASSERT_X(QT_FEATURE_##feature == 1, "Required feature " #feature " for file " __FILE__ " not available.")
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
-# define QT_NO_UNSHARABLE_CONTAINERS
-# define QT6_VIRTUAL virtual
-# define QT6_NOT_VIRTUAL
-#else
-# define QT6_VIRTUAL
-# define QT6_NOT_VIRTUAL virtual
-#endif
+// ### Clean those up, once all code is adjusted
+#define QT6_VIRTUAL virtual
+#define QT6_NOT_VIRTUAL
/* These two macros makes it possible to turn the builtin line expander into a
* string literal. */
@@ -498,53 +493,6 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion(void) Q_DECL_NOEXCEPT;
# define Q_DESTRUCTOR_FUNCTION(AFUNC) Q_DESTRUCTOR_FUNCTION0(AFUNC)
#endif
-namespace QtPrivate {
- template <class T>
- struct AlignOfHelper
- {
- char c;
- T type;
-
- AlignOfHelper();
- ~AlignOfHelper();
- };
-
- template <class T>
- struct AlignOf_Default
- {
- enum { Value = sizeof(AlignOfHelper<T>) - sizeof(T) };
- };
-
- template <class T> struct AlignOf : AlignOf_Default<T> { };
- template <class T> struct AlignOf<T &> : AlignOf<T> {};
- template <class T> struct AlignOf<T &&> : AlignOf<T> {};
- template <size_t N, class T> struct AlignOf<T[N]> : AlignOf<T> {};
-
-#if defined(Q_PROCESSOR_X86_32) && !defined(Q_OS_WIN)
- template <class T> struct AlignOf_WorkaroundForI386Abi { enum { Value = sizeof(T) }; };
-
- // x86 ABI weirdness
- // Alignment of naked type is 8, but inside struct has alignment 4.
- template <> struct AlignOf<double> : AlignOf_WorkaroundForI386Abi<double> {};
- template <> struct AlignOf<qint64> : AlignOf_WorkaroundForI386Abi<qint64> {};
- template <> struct AlignOf<quint64> : AlignOf_WorkaroundForI386Abi<quint64> {};
-#ifdef Q_CC_CLANG
- // GCC and Clang seem to disagree wrt to alignment of arrays
- template <size_t N> struct AlignOf<double[N]> : AlignOf_Default<double> {};
- template <size_t N> struct AlignOf<qint64[N]> : AlignOf_Default<qint64> {};
- template <size_t N> struct AlignOf<quint64[N]> : AlignOf_Default<quint64> {};
-#endif
-#endif
-} // namespace QtPrivate
-
-#define QT_EMULATED_ALIGNOF(T) \
- (size_t(QT_PREPEND_NAMESPACE(QtPrivate)::AlignOf<T>::Value))
-
-#ifndef Q_ALIGNOF
-#define Q_ALIGNOF(T) QT_EMULATED_ALIGNOF(T)
-#endif
-
-
/*
quintptr and qptrdiff is guaranteed to be the same size as a pointer, i.e.
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index fa2098c757..9fab49a73e 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -419,7 +419,6 @@ static const struct {
#endif
{ "Binaries", "bin" },
{ "Plugins", "plugins" }, // should be ${ArchData}/plugins
- { "Imports", "imports" }, // should be ${ArchData}/imports
{ "Qml2Imports", "qml" }, // should be ${ArchData}/qml
{ "ArchData", "." },
{ "Data", "." },
@@ -886,7 +885,6 @@ QStringList QLibraryInfo::platformPluginArguments(const QString &platformName)
\value LibraryExecutablesPath The location of installed executables required by libraries at runtime.
\value BinariesPath The location of installed Qt binaries (tools and applications).
\value PluginsPath The location of installed Qt plugins.
- \value ImportsPath The location of installed QML extensions to import (QML 1.x).
\value Qml2ImportsPath The location of installed QML extensions to import (QML 2.x).
\value ArchDataPath The location of general architecture-dependent Qt data.
\value DataPath The location of general architecture-independent Qt data.
diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h
index ed60b170a5..031dfe37e2 100644
--- a/src/corelib/global/qlibraryinfo.h
+++ b/src/corelib/global/qlibraryinfo.h
@@ -79,7 +79,6 @@ public:
LibraryExecutablesPath,
BinariesPath,
PluginsPath,
- ImportsPath,
Qml2ImportsPath,
ArchDataPath,
DataPath,
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index c1a45476f9..ca4d8dbd11 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1307,7 +1307,7 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
QString function = m.captured(2);
// skip the trace from QtCore that are because of the qDebug itself
- if (!numberPrinted && library.contains(QLatin1String("Qt5Core"))
+ if (!numberPrinted && library.contains(QLatin1String("Qt6Core"))
&& (function.isEmpty() || function.contains(QLatin1String("Message"), Qt::CaseInsensitive)
|| function.contains(QLatin1String("QDebug")))) {
continue;
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 8f40393a7e..f278850ccf 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -41,6 +41,7 @@
#define QNAMESPACE_H
#include <QtCore/qglobal.h>
+#include <QtCore/qtmetamacros.h>
#if defined(__OBJC__) && !defined(__cplusplus)
# warning "File built in Objective-C mode (.m), but using Qt requires Objective-C++ (.mm)"
@@ -48,29 +49,10 @@
QT_BEGIN_NAMESPACE
-#if !defined(Q_QDOC) && !defined(Q_MOC_RUN)
struct QMetaObject;
-const QMetaObject *qt_getQtMetaObject() noexcept; // defined in qobject.h (which can't be included here)
-#define QT_Q_ENUM(ENUM) \
- inline const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return qt_getQtMetaObject(); } \
- inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
-#define QT_Q_FLAG(ENUM) QT_Q_ENUM(ENUM)
-#else
-#define QT_Q_ENUM Q_ENUM
-#define QT_Q_FLAG Q_FLAG
-#endif
-
-#ifndef Q_MOC_RUN
-namespace
-#else
-class Q_CORE_EXPORT
-#endif
-Qt {
-#if defined(Q_MOC_RUN)
- Q_OBJECT
-public:
-#endif
+namespace Qt {
+ Q_NAMESPACE_EXPORT(Q_CORE_EXPORT)
enum GlobalColor {
color0,
@@ -1771,102 +1753,96 @@ public:
enum ReturnByValue_t { ReturnByValue }; // ### Qt 7: Remove me
#ifndef Q_QDOC
- // NOTE: Generally, do not add QT_Q_ENUM if a corresponding Q_Q_FLAG exists.
- QT_Q_ENUM(ScrollBarPolicy)
- QT_Q_ENUM(FocusPolicy)
- QT_Q_ENUM(ContextMenuPolicy)
- QT_Q_ENUM(ArrowType)
- QT_Q_ENUM(ToolButtonStyle)
- QT_Q_ENUM(PenStyle)
- QT_Q_ENUM(PenCapStyle)
- QT_Q_ENUM(PenJoinStyle)
- QT_Q_ENUM(BrushStyle)
- QT_Q_ENUM(FillRule)
- QT_Q_ENUM(MaskMode)
- QT_Q_ENUM(BGMode)
- QT_Q_ENUM(ClipOperation)
- QT_Q_ENUM(SizeMode)
- QT_Q_ENUM(Axis)
- QT_Q_ENUM(Corner)
- QT_Q_ENUM(Edge)
- QT_Q_ENUM(LayoutDirection)
- QT_Q_ENUM(SizeHint)
- QT_Q_ENUM(Orientation)
- QT_Q_ENUM(DropAction)
- QT_Q_FLAG(Alignment)
- QT_Q_ENUM(TextFlag)
- QT_Q_FLAG(Orientations)
- QT_Q_FLAG(SplitBehavior)
- QT_Q_FLAG(DropActions)
- QT_Q_FLAG(Edges)
- QT_Q_FLAG(DockWidgetAreas)
- QT_Q_FLAG(ToolBarAreas)
- QT_Q_ENUM(DockWidgetArea)
- QT_Q_ENUM(ToolBarArea)
- QT_Q_ENUM(TextFormat)
- QT_Q_ENUM(TextElideMode)
- QT_Q_ENUM(DateFormat)
- QT_Q_ENUM(TimeSpec)
- QT_Q_ENUM(DayOfWeek)
- QT_Q_ENUM(CursorShape)
- QT_Q_ENUM(GlobalColor)
- QT_Q_ENUM(AspectRatioMode)
- QT_Q_ENUM(TransformationMode)
- QT_Q_FLAG(ImageConversionFlags)
- QT_Q_ENUM(Key)
- QT_Q_ENUM(ShortcutContext)
- QT_Q_ENUM(TextInteractionFlag)
- QT_Q_FLAG(TextInteractionFlags)
- QT_Q_ENUM(ItemSelectionMode)
- QT_Q_ENUM(ItemSelectionOperation)
- QT_Q_FLAG(ItemFlags)
- QT_Q_ENUM(CheckState)
- QT_Q_ENUM(ItemDataRole)
- QT_Q_ENUM(SortOrder)
- QT_Q_ENUM(CaseSensitivity)
- QT_Q_FLAG(MatchFlags)
- QT_Q_FLAG(KeyboardModifiers)
- QT_Q_FLAG(MouseButtons)
- QT_Q_ENUM(WindowType)
- QT_Q_ENUM(WindowState)
- QT_Q_ENUM(WindowModality)
- QT_Q_ENUM(WidgetAttribute)
- QT_Q_ENUM(ApplicationAttribute)
- QT_Q_FLAG(WindowFlags)
- QT_Q_FLAG(WindowStates)
- QT_Q_ENUM(FocusReason)
- QT_Q_ENUM(InputMethodHint)
- QT_Q_ENUM(InputMethodQuery)
- QT_Q_FLAG(InputMethodHints)
- QT_Q_ENUM(EnterKeyType)
- QT_Q_FLAG(InputMethodQueries)
- QT_Q_FLAG(TouchPointStates)
- QT_Q_ENUM(ScreenOrientation)
- QT_Q_FLAG(ScreenOrientations)
- QT_Q_ENUM(ConnectionType)
- QT_Q_ENUM(ApplicationState)
+ // NOTE: Generally, do not add Q_ENUM_NS if a corresponding Q_FLAG_NS exists.
+ Q_ENUM_NS(ScrollBarPolicy)
+ Q_ENUM_NS(FocusPolicy)
+ Q_ENUM_NS(ContextMenuPolicy)
+ Q_ENUM_NS(ArrowType)
+ Q_ENUM_NS(ToolButtonStyle)
+ Q_ENUM_NS(PenStyle)
+ Q_ENUM_NS(PenCapStyle)
+ Q_ENUM_NS(PenJoinStyle)
+ Q_ENUM_NS(BrushStyle)
+ Q_ENUM_NS(FillRule)
+ Q_ENUM_NS(MaskMode)
+ Q_ENUM_NS(BGMode)
+ Q_ENUM_NS(ClipOperation)
+ Q_ENUM_NS(SizeMode)
+ Q_ENUM_NS(Axis)
+ Q_ENUM_NS(Corner)
+ Q_ENUM_NS(Edge)
+ Q_ENUM_NS(LayoutDirection)
+ Q_ENUM_NS(SizeHint)
+ Q_ENUM_NS(Orientation)
+ Q_ENUM_NS(DropAction)
+ Q_FLAG_NS(Alignment)
+ Q_ENUM_NS(TextFlag)
+ Q_FLAG_NS(Orientations)
+ Q_FLAG_NS(SplitBehavior)
+ Q_FLAG_NS(DropActions)
+ Q_FLAG_NS(Edges)
+ Q_FLAG_NS(DockWidgetAreas)
+ Q_FLAG_NS(ToolBarAreas)
+ Q_ENUM_NS(DockWidgetArea)
+ Q_ENUM_NS(ToolBarArea)
+ Q_ENUM_NS(TextFormat)
+ Q_ENUM_NS(TextElideMode)
+ Q_ENUM_NS(DateFormat)
+ Q_ENUM_NS(TimeSpec)
+ Q_ENUM_NS(DayOfWeek)
+ Q_ENUM_NS(CursorShape)
+ Q_ENUM_NS(GlobalColor)
+ Q_ENUM_NS(AspectRatioMode)
+ Q_ENUM_NS(TransformationMode)
+ Q_FLAG_NS(ImageConversionFlags)
+ Q_ENUM_NS(Key)
+ Q_ENUM_NS(ShortcutContext)
+ Q_ENUM_NS(TextInteractionFlag)
+ Q_FLAG_NS(TextInteractionFlags)
+ Q_ENUM_NS(ItemSelectionMode)
+ Q_ENUM_NS(ItemSelectionOperation)
+ Q_FLAG_NS(ItemFlags)
+ Q_ENUM_NS(CheckState)
+ Q_ENUM_NS(ItemDataRole)
+ Q_ENUM_NS(SortOrder)
+ Q_ENUM_NS(CaseSensitivity)
+ Q_FLAG_NS(MatchFlags)
+ Q_FLAG_NS(KeyboardModifiers)
+ Q_FLAG_NS(MouseButtons)
+ Q_ENUM_NS(WindowType)
+ Q_ENUM_NS(WindowState)
+ Q_ENUM_NS(WindowModality)
+ Q_ENUM_NS(WidgetAttribute)
+ Q_ENUM_NS(ApplicationAttribute)
+ Q_FLAG_NS(WindowFlags)
+ Q_FLAG_NS(WindowStates)
+ Q_ENUM_NS(FocusReason)
+ Q_ENUM_NS(InputMethodHint)
+ Q_ENUM_NS(InputMethodQuery)
+ Q_FLAG_NS(InputMethodHints)
+ Q_ENUM_NS(EnterKeyType)
+ Q_FLAG_NS(InputMethodQueries)
+ Q_FLAG_NS(TouchPointStates)
+ Q_ENUM_NS(ScreenOrientation)
+ Q_FLAG_NS(ScreenOrientations)
+ Q_ENUM_NS(ConnectionType)
+ Q_ENUM_NS(ApplicationState)
#ifndef QT_NO_GESTURES
- QT_Q_ENUM(GestureState)
- QT_Q_ENUM(GestureType)
- QT_Q_ENUM(NativeGestureType)
+ Q_ENUM_NS(GestureState)
+ Q_ENUM_NS(GestureType)
+ Q_ENUM_NS(NativeGestureType)
#endif
- QT_Q_ENUM(CursorMoveStyle)
- QT_Q_ENUM(TimerType)
- QT_Q_ENUM(ScrollPhase)
- QT_Q_ENUM(MouseEventSource)
- QT_Q_FLAG(MouseEventFlag)
- QT_Q_ENUM(ChecksumType)
- QT_Q_ENUM(HighDpiScaleFactorRoundingPolicy)
- QT_Q_ENUM(TabFocusBehavior)
+ Q_ENUM_NS(CursorMoveStyle)
+ Q_ENUM_NS(TimerType)
+ Q_ENUM_NS(ScrollPhase)
+ Q_ENUM_NS(MouseEventSource)
+ Q_FLAG_NS(MouseEventFlag)
+ Q_ENUM_NS(ChecksumType)
+ Q_ENUM_NS(HighDpiScaleFactorRoundingPolicy)
+ Q_ENUM_NS(TabFocusBehavior)
#endif // Q_DOC
}
-#ifdef Q_MOC_RUN
- ;
-#endif
-
-#undef QT_Q_ENUM
-#undef QT_Q_FLAG
typedef bool (*qInternalCallback)(void **);
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index 7418579fe0..7a03e32699 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -202,7 +202,7 @@ namespace {
This function works for v containing infinities, but not NaN. It's the
caller's responsibility to exclude that possibility before calling it.
*/
-template <typename T> static inline bool convertDoubleTo(double v, T *value)
+template <typename T> static inline bool convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
{
Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
@@ -227,6 +227,10 @@ template <typename T> static inline bool convertDoubleTo(double v, T *value)
supremum = -2.0 * std::numeric_limits<ST>::min(); // -2 * (-2^63) = 2^64, exact (for T = quint64)
v = fabs(v);
}
+ if (std::is_integral<T>::value && sizeof(T) > 4 && !allow_precision_upgrade) {
+ if (v > double(Q_INT64_C(1)<<53) || v < double(-((Q_INT64_C(1)<<53) + 1)))
+ return false;
+ }
*value = std::numeric_limits<T>::max();
if (v >= supremum)
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index 10672c1f92..3dc024e301 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -355,7 +355,7 @@ struct QRandomGenerator::SystemAndGlobalGenerators
// the state in case another thread tries to lock the mutex. It's not
// a common scenario, but since sizeof(QRandomGenerator) >= 2560, the
// overhead is actually acceptable.
- // 2) We use both Q_DECL_ALIGN and std::aligned_storage<..., 64> because
+ // 2) We use both alignas and std::aligned_storage<..., 64> because
// some implementations of std::aligned_storage can't align to more
// than a primitive type's alignment.
// 3) We don't store the entire system QRandomGenerator, only the space
@@ -364,7 +364,7 @@ struct QRandomGenerator::SystemAndGlobalGenerators
QBasicMutex globalPRNGMutex;
struct ShortenedSystem { uint type; } system_;
SystemGenerator sys;
- Q_DECL_ALIGN(64) std::aligned_storage<sizeof(QRandomGenerator64), 64>::type global_;
+ alignas(64) std::aligned_storage<sizeof(QRandomGenerator64), 64>::type global_;
#ifdef Q_COMPILER_CONSTEXPR
constexpr SystemAndGlobalGenerators()
diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h
index 445b520c76..e1494ab523 100644
--- a/src/corelib/global/qrandom.h
+++ b/src/corelib/global/qrandom.h
@@ -196,7 +196,7 @@ private:
RandomEngine &engine() { return twister; }
const RandomEngine &engine() const { return twister; }
#else
- std::aligned_storage<sizeof(RandomEngine), Q_ALIGNOF(RandomEngine)>::type buffer;
+ std::aligned_storage<sizeof(RandomEngine), alignof(RandomEngine)>::type buffer;
RandomEngine &engine() { return reinterpret_cast<RandomEngine &>(buffer); }
const RandomEngine &engine() const { return reinterpret_cast<const RandomEngine &>(buffer); }
#endif
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 30be47296e..34cf1de4f5 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -209,7 +209,6 @@ public: \
}; \
}
-Q_DECLARE_MOVABLE_CONTAINER(QList);
Q_DECLARE_MOVABLE_CONTAINER(QVector);
Q_DECLARE_MOVABLE_CONTAINER(QQueue);
Q_DECLARE_MOVABLE_CONTAINER(QStack);
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 421c5d933b..2314b36bda 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -234,12 +234,6 @@ inline QDebug printSequentialContainer(QDebug debug, const char *which, const Se
} // namespace QtPrivate
-template <class T>
-inline QDebug operator<<(QDebug debug, const QList<T> &list)
-{
- return QtPrivate::printSequentialContainer(debug, "" /*for historical reasons*/, list);
-}
-
template <typename T>
inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
{
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index 31c490de66..7adaafea18 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -342,7 +342,6 @@ void QFileSelectorPrivate::updateSelectors()
QStringList QFileSelectorPrivate::platformSelectors()
{
// similar, but not identical to QSysInfo::osType
- // ### Qt6: remove macOS fallbacks to "mac" and the future compatibility
QStringList ret;
#if defined(Q_OS_WIN)
ret << QStringLiteral("windows");
@@ -355,16 +354,10 @@ QStringList QFileSelectorPrivate::platformSelectors()
# if !defined(Q_OS_ANDROID) && !defined(Q_OS_QNX)
// we don't want "linux" for Android or two instances of "qnx" for QNX
ret << QSysInfo::kernelType();
-# ifdef Q_OS_MAC
- ret << QStringLiteral("mac"); // compatibility, since kernelType() is "darwin"
-# endif
# endif
QString productName = QSysInfo::productType();
if (productName != QLatin1String("unknown"))
ret << productName; // "opensuse", "fedora", "osx", "ios", "android"
-# if defined(Q_OS_MACOS)
- ret << QStringLiteral("macos"); // future compatibility
-# endif
#endif
return ret;
}
diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp
index 74b7e820d9..ad6dbaba11 100644
--- a/src/corelib/io/qfilesystemiterator_unix.cpp
+++ b/src/corelib/io/qfilesystemiterator_unix.cpp
@@ -86,6 +86,8 @@ static bool checkNameDecodable(const char *d_name, qsizetype len)
return cs.invalidChars == 0 && cs.remainingChars == 0;
#else
// if we have no text codecs, then QString::fromLocal8Bit is fromLatin1
+ Q_UNUSED(d_name)
+ Q_UNUSED(len)
return true;
#endif
}
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp
index 3b67dd61c7..f955e3b53a 100644
--- a/src/corelib/io/qfilesystemwatcher_win.cpp
+++ b/src/corelib/io/qfilesystemwatcher_win.cpp
@@ -81,7 +81,7 @@ static Qt::HANDLE createChangeNotification(const QString &path, uint flags)
nativePath.append(QLatin1Char('\\'));
const HANDLE result = FindFirstChangeNotification(reinterpret_cast<const wchar_t *>(nativePath.utf16()),
FALSE, flags);
- DEBUG() << __FUNCTION__ << nativePath << Qt::hex <<showbase << flags << "returns" << result;
+ DEBUG() << __FUNCTION__ << nativePath << Qt::hex << Qt::showbase << flags << "returns" << result;
return result;
}
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 225ee0a769..e636712e57 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -1241,14 +1241,8 @@ bool QDynamicFileResourceRoot::registerSelf(const QString &f)
uchar *data = nullptr;
qsizetype data_len = 0;
-#ifdef QT_USE_MMAP
- int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY,
-#if defined(Q_OS_WIN)
- _S_IREAD | _S_IWRITE
-#else
- 0666
-#endif
- );
+#if defined(QT_USE_MMAP)
+ int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY, 0666);
if (fd >= 0) {
QT_STATBUF st;
if (!QT_FSTAT(fd, &st) && st.st_size <= std::numeric_limits<qsizetype>::max()) {
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index b191397e7e..6c66d1097d 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -409,14 +409,16 @@ QString QSettingsPrivate::variantToString(const QVariant &v)
break;
}
+#if QT_CONFIG(shortcut)
+ case QMetaType::QKeySequence:
+#endif
case QMetaType::QString:
case QMetaType::LongLong:
case QMetaType::ULongLong:
case QMetaType::Int:
case QMetaType::UInt:
case QMetaType::Bool:
- case QMetaType::Double:
- case QMetaType::QKeySequence: {
+ case QMetaType::Double: {
result = v.toString();
if (result.contains(QChar::Null))
result = QLatin1String("@String(") + result + QLatin1Char(')');
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index bca454fc7a..a5128a868b 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -345,6 +345,8 @@ QT_BEGIN_NAMESPACE
\note On Android, applications with open files on the external storage (<USER> locations),
will be killed if the external storage is unmounted.
+ \note On Android, reading/writing to GenericDataLocation needs the READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE permission granted.
+
\note On iOS, if you do pass \c {QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last()}
as argument to \l{QFileDialog::setDirectory()},
a native image picker dialog will be used for accessing the user's photo album.
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 659552b72f..0a5f9256eb 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -979,7 +979,7 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
// validate it:
int needsLowercasing = -1;
- const ushort *p = reinterpret_cast<const ushort *>(value.constData());
+ const ushort *p = value.utf16();
for (int i = 0; i < len; ++i) {
if (p[i] >= 'a' && p[i] <= 'z')
continue;
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 608407c136..f0eb8e5c8b 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -63,7 +63,7 @@ QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex &
Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list
QPersistentModelIndexData *d = nullptr;
QAbstractItemModel *model = const_cast<QAbstractItemModel *>(index.model());
- QHash<QModelIndex, QPersistentModelIndexData *> &indexes = model->d_func()->persistent.indexes;
+ QMultiHash<QModelIndex, QPersistentModelIndexData *> &indexes = model->d_func()->persistent.indexes;
const auto it = indexes.constFind(index);
if (it != indexes.cend()) {
d = (*it);
@@ -662,8 +662,7 @@ void QAbstractItemModelPrivate::rowsAboutToBeInserted(const QModelIndex &parent,
Q_UNUSED(last);
QVector<QPersistentModelIndexData *> persistent_moved;
if (first < q->rowCount(parent)) {
- for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
- it != persistent.indexes.constEnd(); ++it) {
+ for (auto it = persistent.indexes.constBegin(); it != persistent.indexes.constEnd(); ++it) {
QPersistentModelIndexData *data = *it;
const QModelIndex &index = data->index;
if (index.row() >= first && index.isValid() && index.parent() == parent) {
@@ -699,14 +698,13 @@ void QAbstractItemModelPrivate::itemsAboutToBeMoved(const QModelIndex &srcParent
QVector<QPersistentModelIndexData *> persistent_moved_in_source;
QVector<QPersistentModelIndexData *> persistent_moved_in_destination;
- QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it;
- const QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator begin = persistent.indexes.constBegin();
- const QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator end = persistent.indexes.constEnd();
+ const auto begin = persistent.indexes.constBegin();
+ const auto end = persistent.indexes.constEnd();
const bool sameParent = (srcParent == destinationParent);
const bool movingUp = (srcFirst > destinationChild);
- for ( it = begin; it != end; ++it) {
+ for (auto it = begin; it != end; ++it) {
QPersistentModelIndexData *data = *it;
const QModelIndex &index = data->index;
const QModelIndex &parent = index.parent();
@@ -811,8 +809,7 @@ void QAbstractItemModelPrivate::rowsAboutToBeRemoved(const QModelIndex &parent,
QVector<QPersistentModelIndexData *> persistent_invalidated;
// find the persistent indexes that are affected by the change, either by being in the removed subtree
// or by being on the same level and below the removed rows
- for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
- it != persistent.indexes.constEnd(); ++it) {
+ for (auto it = persistent.indexes.constBegin(); it != persistent.indexes.constEnd(); ++it) {
QPersistentModelIndexData *data = *it;
bool level_changed = false;
QModelIndex current = data->index;
@@ -867,8 +864,7 @@ void QAbstractItemModelPrivate::columnsAboutToBeInserted(const QModelIndex &pare
Q_UNUSED(last);
QVector<QPersistentModelIndexData *> persistent_moved;
if (first < q->columnCount(parent)) {
- for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
- it != persistent.indexes.constEnd(); ++it) {
+ for (auto it = persistent.indexes.constBegin(); it != persistent.indexes.constEnd(); ++it) {
QPersistentModelIndexData *data = *it;
const QModelIndex &index = data->index;
if (index.column() >= first && index.isValid() && index.parent() == parent)
@@ -904,8 +900,7 @@ void QAbstractItemModelPrivate::columnsAboutToBeRemoved(const QModelIndex &paren
QVector<QPersistentModelIndexData *> persistent_invalidated;
// find the persistent indexes that are affected by the change, either by being in the removed subtree
// or by being on the same level and to the right of the removed columns
- for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
- it != persistent.indexes.constEnd(); ++it) {
+ for (auto it = persistent.indexes.constBegin(); it != persistent.indexes.constEnd(); ++it) {
QPersistentModelIndexData *data = *it;
bool level_changed = false;
QModelIndex current = data->index;
@@ -3294,7 +3289,11 @@ void QAbstractItemModel::endResetModel()
{
Q_D(QAbstractItemModel);
d->invalidatePersistentIndexes();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ resetInternalData();
+#else
QMetaObject::invokeMethod(this, "resetInternalData");
+#endif
emit modelReset(QPrivateSignal());
}
@@ -3372,8 +3371,7 @@ QModelIndexList QAbstractItemModel::persistentIndexList() const
Q_D(const QAbstractItemModel);
QModelIndexList result;
result.reserve(d->persistent.indexes.count());
- for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = d->persistent.indexes.constBegin();
- it != d->persistent.indexes.constEnd(); ++it) {
+ for (auto it = d->persistent.indexes.constBegin(); it != d->persistent.indexes.constEnd(); ++it) {
QPersistentModelIndexData *data = *it;
result.append(data->index);
}
@@ -3991,8 +3989,8 @@ bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
*/
void QAbstractItemModelPrivate::Persistent::insertMultiAtEnd(const QModelIndex& key, QPersistentModelIndexData *data)
{
- QHash<QModelIndex,QPersistentModelIndexData *>::iterator newIt = indexes.insert(key, data);
- QHash<QModelIndex,QPersistentModelIndexData *>::iterator it = newIt;
+ auto newIt = indexes.insert(key, data);
+ auto it = newIt;
++it;
while (it != indexes.end() && it.key() == key) {
qSwap(*newIt,*it);
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index 43649cf79b..2cc1bd8ce6 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -156,7 +156,6 @@ inline uint qHash(const QPersistentModelIndex &index, uint seed) noexcept
Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &);
#endif
-template<typename T> class QList;
typedef QList<QModelIndex> QModelIndexList;
class QMimeData;
diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h
index c9a73b6a31..f6f6e45c1a 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.h
+++ b/src/corelib/itemmodels/qabstractproxymodel.h
@@ -103,7 +103,11 @@ Q_SIGNALS:
void sourceModelChanged(QPrivateSignal);
protected Q_SLOTS:
- void resetInternalData();
+ void resetInternalData()
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ override
+#endif
+ ;
protected:
QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent);
diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h
index 5820695592..5421eb2afa 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.h
+++ b/src/corelib/itemmodels/qitemselectionmodel.h
@@ -241,7 +241,7 @@ inline uint qHash(const QItemSelectionRange &) { return 0; }
# define Q_TEMPLATE_EXTERN extern
# endif
# endif
-Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QList<QItemSelectionRange>;
+Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QItemSelectionRange>;
#endif // Q_CC_MSVC
class Q_CORE_EXPORT QItemSelection : public QList<QItemSelectionRange>
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 34f54d8f94..dc46695f80 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -138,10 +138,10 @@ QT_BEGIN_NAMESPACE
extern QString qAppFileName();
#endif
-#if QT_VERSION >= 0x060000
-# error "Bump QCoreApplicatoinPrivate::app_compile_version to 0x060000"
+#if QT_VERSION >= 0x070000
+# error "Bump QCoreApplicatoinPrivate::app_compile_version to 0x070000"
#endif
-int QCoreApplicationPrivate::app_compile_version = 0x050000; //we don't know exactly, but it's at least 5.0.0
+int QCoreApplicationPrivate::app_compile_version = 0x060000; //we don't know exactly, but it's at least 6.0.0
bool QCoreApplicationPrivate::setuidAllowed = false;
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 765f129758..824c0535ed 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -772,7 +772,7 @@ QString decodeMSG(const MSG& msg)
auto rect = reinterpret_cast<const RECT *>(lParam);
QTextStream(&parameters) << "DPI: " << HIWORD(wParam) << ','
<< LOWORD(wParam) << ' ' << (rect->right - rect->left) << 'x'
- << (rect->bottom - rect->top) << forcesign << rect->left << rect->top;
+ << (rect->bottom - rect->top) << Qt::forcesign << rect->left << rect->top;
}
break;
case WM_IME_NOTIFY:
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 1661520b78..f4d0a88529 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -154,20 +154,29 @@ QT_BEGIN_NAMESPACE
static inline const QMetaObjectPrivate *priv(const uint* data)
{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+static inline const char *rawStringData(const QMetaObject *mo, int index)
+{
+ Q_ASSERT(priv(mo->d.data)->revision >= 7);
+ uint offset = mo->d.stringdata[2*index];
+ return reinterpret_cast<const char *>(mo->d.stringdata) + offset;
+}
+
static inline const QByteArray stringData(const QMetaObject *mo, int index)
{
Q_ASSERT(priv(mo->d.data)->revision >= 7);
- const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo->d.stringdata[index]) };
- Q_ASSERT(data.ptr->ref.isStatic());
- Q_ASSERT(data.ptr->alloc == 0);
- Q_ASSERT(data.ptr->capacityReserved == 0);
- Q_ASSERT(data.ptr->size >= 0);
- return data;
+ uint offset = mo->d.stringdata[2*index];
+ uint length = mo->d.stringdata[2*index + 1];
+ const char *string = reinterpret_cast<const char *>(mo->d.stringdata) + offset;
+ return QByteArray::fromRawData(string, length);
}
-static inline const char *rawStringData(const QMetaObject *mo, int index)
+static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
{
- return stringData(mo, index).data();
+ if (typeInfo & IsUnresolvedType) {
+ return rawStringData(mo, typeInfo & TypeNameIndexMask);
+ } else {
+ return QMetaType::typeName(typeInfo);
+ }
}
static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
@@ -181,16 +190,11 @@ static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeIn
}
}
-static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
-{
- return typeNameFromTypeInfo(mo, typeInfo).constData();
-}
-
static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo)
{
if (!(typeInfo & IsUnresolvedType))
return typeInfo;
- return QMetaType::type(stringData(mo, typeInfo & TypeNameIndexMask));
+ return QMetaType::type(rawStringData(mo, typeInfo & TypeNameIndexMask));
}
class QMetaMethodPrivate : public QMetaMethod
@@ -577,7 +581,7 @@ static bool methodMatch(const QMetaObject *m, int handle,
if (int(m->d.data[handle + 1]) != argc)
return false;
- if (stringData(m, m->d.data[handle]) != name)
+ if (rawStringData(m, m->d.data[handle]) != name)
return false;
int paramsIndex = m->d.data[handle + 2] + 1;
@@ -682,7 +686,9 @@ static void argumentTypesFromString(const char *str, const char *end,
--level;
++str;
}
- types += QArgumentType(QByteArray(begin, str - begin));
+ QByteArray argType(begin, str - begin);
+ argType.replace("QList<", "QVector<");
+ types += QArgumentType(std::move(argType));
}
}
@@ -1161,7 +1167,7 @@ QMetaProperty QMetaObject::property(int index) const
const QMetaObject *scope = nullptr;
if (qstrcmp(scope_name, "Qt") == 0)
- scope = &QObject::staticQtMetaObject;
+ scope = &Qt::staticMetaObject;
else
scope = QMetaObject_findMetaObject(this, scope_name);
if (scope)
@@ -3670,6 +3676,21 @@ const char* QMetaClassInfo::value() const
}
/*!
+ \class QMethodRawArguments
+ \internal
+
+ A wrapper class for the void ** arguments array used by the meta
+ object system. If a slot uses a single argument of this type,
+ the meta object system will pass the raw arguments array directly
+ to the slot and set the arguments count in the slot description to
+ zero, so that any signal can connect to it.
+
+ This is used internally to implement signal relay functionality in
+ our state machine and dbus.
+*/
+
+
+/*!
\macro QGenericArgument Q_ARG(Type, const Type &value)
\relates QMetaObject
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index beb85becae..d0c4b489a6 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -46,9 +46,6 @@
QT_BEGIN_NAMESPACE
-
-template <typename T> class QList;
-
#define Q_METAMETHOD_INVOKE_MAX_ARGS 10
class Q_CORE_EXPORT QMetaMethod
diff --git a/src/corelib/kernel/qmetaobject_moc_p.h b/src/corelib/kernel/qmetaobject_moc_p.h
index 8c7900767b..471e43f85b 100644
--- a/src/corelib/kernel/qmetaobject_moc_p.h
+++ b/src/corelib/kernel/qmetaobject_moc_p.h
@@ -213,6 +213,9 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc
}
}
+ // Qt 5 compatibility, make sure we use the correct type name for QList
+ result.replace("QList<", "QVector<");
+
return result;
}
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index 4ecc340787..d02708540a 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -1103,13 +1103,13 @@ int QMetaStringTable::enter(const QByteArray &value)
int QMetaStringTable::preferredAlignment()
{
- return Q_ALIGNOF(QByteArrayData);
+ return alignof(uint);
}
// Returns the size (in bytes) required for serializing this string table.
int QMetaStringTable::blobSize() const
{
- int size = m_entries.size() * sizeof(QByteArrayData);
+ int size = m_entries.size() * 2*sizeof(uint);
Entries::const_iterator it;
for (it = m_entries.constBegin(); it != m_entries.constEnd(); ++it)
size += it.key().size() + 1;
@@ -1120,14 +1120,12 @@ static void writeString(char *out, int i, const QByteArray &str,
const int offsetOfStringdataMember, int &stringdataOffset)
{
int size = str.size();
- qptrdiff offset = offsetOfStringdataMember + stringdataOffset
- - i * sizeof(QByteArrayData);
- const QByteArrayData data =
- Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset);
+ int offset = offsetOfStringdataMember + stringdataOffset;
+ uint offsetLen[2] = { uint(offset), uint(size) };
- memcpy(out + i * sizeof(QByteArrayData), &data, sizeof(QByteArrayData));
+ memcpy(out + 2 * i * sizeof(uint), &offsetLen, 2*sizeof(uint));
- memcpy(out + offsetOfStringdataMember + stringdataOffset, str.constData(), size);
+ memcpy(out + offset, str.constData(), size);
out[offsetOfStringdataMember + stringdataOffset + size] = '\0';
stringdataOffset += size + 1;
@@ -1141,7 +1139,7 @@ void QMetaStringTable::writeBlob(char *out) const
{
Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (preferredAlignment()-1)));
- int offsetOfStringdataMember = m_entries.size() * sizeof(QByteArrayData);
+ int offsetOfStringdataMember = m_entries.size() * 2*sizeof(uint);
int stringdataOffset = 0;
// qt_metacast expects the first string in the string table to be the class name.
@@ -1282,10 +1280,10 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
char *str = reinterpret_cast<char *>(buf + size);
if (buf) {
if (relocatable) {
- meta->d.stringdata = reinterpret_cast<const QByteArrayData *>((quintptr)size);
+ meta->d.stringdata = reinterpret_cast<const uint *>((quintptr)size);
meta->d.data = reinterpret_cast<uint *>((quintptr)pmetaSize);
} else {
- meta->d.stringdata = reinterpret_cast<const QByteArrayData *>(str);
+ meta->d.stringdata = reinterpret_cast<const uint *>(str);
meta->d.data = reinterpret_cast<uint *>(data);
}
}
@@ -1553,7 +1551,7 @@ void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output,
quintptr dataOffset = (quintptr)dataMo->d.data;
output->d.superdata = superclass;
- output->d.stringdata = reinterpret_cast<const QByteArrayData *>(buf + stringdataOffset);
+ output->d.stringdata = reinterpret_cast<const uint *>(buf + stringdataOffset);
output->d.data = reinterpret_cast<const uint *>(buf + dataOffset);
output->d.extradata = nullptr;
output->d.relatedMetaObjects = nullptr;
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index a2b7fec5cd..e498772e32 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -37,6 +37,8 @@
**
****************************************************************************/
+#include <bitset>
+
#include "qmetatype.h"
#include "qmetatype_p.h"
#include "qobjectdefs.h"
@@ -538,13 +540,12 @@ struct DefinedTypesFilter {
#define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \
{ RealNameStr, sizeof(RealNameStr) - 1, QMetaType::MetaTypeName },
-#define QT_ADD_STATIC_METATYPE_HACKS_ITER(MetaTypeName, TypeId, Name) \
- QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeName, Name)
+
static const struct { const char * typeName; int typeNameLength; int type; } types[] = {
QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
- QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER)
+ QT_ADD_STATIC_METATYPE(_, QMetaTypeId2<qreal>::MetaType, qreal)
{nullptr, 0, QMetaType::UnknownType}
};
@@ -2458,6 +2459,50 @@ const QMetaObject *metaObjectForQWidget()
return nullptr;
return qMetaObjectWidgetsHelper;
}
+
+void qt5CompatibilityHookPostRegister(int id, const QByteArray &normalizedTypeName)
+{
+ // In Qt6 QList got typedef'ed to QVector. To keep runtime behavior compatibility
+ // with Qt5 we install corresponding aliases. For example if one register
+ // QVector<QVector<int>>
+ // we need to register the type plus all possible aliases:
+ // QVector<QList<int>>
+ // QList<QVector<int>>
+ // QList<QList<int>>
+ // ### Qt6 TODO This is slow, as it allocates couple of strings we would need to
+ // if def this call with something like QT_NO_QLIST
+ const char *vectorName = "QVector<";
+ const char *listName = "QList<";
+
+ auto isSubstringOfAType = [](char c) { return c != ' ' && c != ',' && c != '<'; };
+ QVarLengthArray<int> indexes;
+
+ for (auto containerName: {vectorName, listName}) {
+ for (int i = normalizedTypeName.indexOf(containerName, 0); i != -1; i = normalizedTypeName.indexOf(containerName, i + 1)) {
+ if (!i || (i > 0 && !isSubstringOfAType(normalizedTypeName[i - 1])))
+ indexes.append(i);
+ }
+ }
+ // To avoid problems with the constantly changing size we start replacements
+ // from the end of normalizedTypeName
+ std::sort(indexes.rbegin(), indexes.rend());
+
+ for (quint64 combination = 1; ; ++combination) {
+ std::bitset<64> bits(combination);
+ QByteArray name = normalizedTypeName;
+ for (auto j = 0; j < indexes.size(); ++j) {
+ if (bits.test(j)) {
+ auto i = indexes[j];
+ auto replaceFrom = normalizedTypeName[i + 1] == 'V' ? vectorName : listName;
+ auto replaceTo = normalizedTypeName[i + 1] == 'V' ? listName : vectorName;
+ name.replace(i, sizeof(replaceFrom), replaceTo);
+ }
+ }
+ QMetaType::registerNormalizedTypedef(name, id);
+ if (bits.count() >= size_t(indexes.size()))
+ break;
+ }
+}
}
namespace QtMetaTypePrivate {
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 4f70eb4c6d..927bfb7667 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -151,6 +151,13 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QVariantHash, 28, QVariantHash) \
F(QByteArrayList, 49, QByteArrayList) \
+#if QT_CONFIG(shortcut)
+#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)\
+ F(QKeySequence, 75, QKeySequence)
+#else
+#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
+#endif
+
#define QT_FOR_EACH_STATIC_GUI_CLASS(F)\
F(QFont, 64, QFont) \
F(QPixmap, 65, QPixmap) \
@@ -163,7 +170,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QRegion, 72, QRegion) \
F(QBitmap, 73, QBitmap) \
F(QCursor, 74, QCursor) \
- F(QKeySequence, 75, QKeySequence) \
+ QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) \
F(QPen, 76, QPen) \
F(QTextLength, 77, QTextLength) \
F(QTextFormat, 78, QTextFormat) \
@@ -181,10 +188,6 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
#define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
F(QSizePolicy, 121, QSizePolicy) \
-// ### FIXME kill that set
-#define QT_FOR_EACH_STATIC_HACKS_TYPE(F)\
- F(QMetaTypeId2<qreal>::MetaType, -1, qreal)
-
// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType")
#define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)\
F(ULong, -1, ulong, "unsigned long") \
@@ -201,10 +204,11 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(UInt, -1, uint, "quint32") \
F(LongLong, -1, qlonglong, "qint64") \
F(ULongLong, -1, qulonglong, "quint64") \
+ F(QVariantList, -1, QVariantList, "QVector<QVariant>") \
F(QVariantList, -1, QVariantList, "QList<QVariant>") \
F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \
F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \
- F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \
+ F(QByteArrayList, -1, QByteArrayList, "QVector<QByteArray>") \
#define QT_FOR_EACH_STATIC_TYPE(F)\
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
@@ -219,7 +223,6 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
TypeName = Id,
#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \
- F(QList) \
F(QVector) \
F(QQueue) \
F(QStack) \
@@ -501,7 +504,7 @@ public:
typedef void (*Deleter)(void *);
typedef void *(*Creator)(const void *);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+#if 1 || QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt6: fix this
typedef void (*Destructor)(void *);
typedef void *(*Constructor)(void *, const void *); // TODO Qt6: remove me
#endif
@@ -749,8 +752,6 @@ private:
static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
#endif
-// ### Qt6: FIXME: Remove the special Q_CC_MSVC handling, it was introduced to maintain BC.
-#if !defined(Q_NO_TEMPLATE_FRIENDS) && !defined(Q_CC_MSVC)
#ifndef Q_CLANG_QDOC
template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
template<typename, typename> friend struct QtPrivate::ConverterMemberFunction;
@@ -760,9 +761,6 @@ private:
template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
#endif
-#else
-public:
-#endif
static bool registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to);
static void unregisterConverterFunction(int from, int to);
private:
@@ -1010,10 +1008,6 @@ struct ContainerAPI : CapabilitiesImpl<T>
};
template<typename T>
-struct ContainerAPI<QList<T> > : CapabilitiesImpl<QList<T> >
-{ static int size(const QList<T> *t) { return t->size(); } };
-
-template<typename T>
struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
{ static int size(const QVector<T> *t) { return t->size(); } };
@@ -1659,6 +1653,23 @@ namespace QtPrivate
static bool registerConverter(int) { return false; }
};
+ template<class T>
+ struct Qt5CompatibilityHook
+ {
+ static inline void postRegister(int, const QByteArray &) {};
+ };
+
+ Q_CORE_EXPORT void qt5CompatibilityHookPostRegister(int id, const QByteArray &normalizedTypeName);
+
+ template<class T>
+ struct Qt5CompatibilityHook<QVector<T>>
+ {
+ static inline void postRegister(int id, const QByteArray &normalizedTypeName)
+ {
+ qt5CompatibilityHookPostRegister(id, normalizedTypeName);
+ }
+ };
+
Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
} // namespace QtPrivate
@@ -1785,6 +1796,7 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz
QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
+ QtPrivate::Qt5CompatibilityHook<T>::postRegister(id, normalizedTypeName);
}
return id;
@@ -2008,7 +2020,7 @@ typedef QHash<QString, QVariant> QVariantHash;
#ifdef Q_CLANG_QDOC
class QByteArrayList;
#else
-typedef QList<QByteArray> QByteArrayList;
+typedef QVector<QByteArray> QByteArrayList;
#endif
#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index d743d5a5c7..f2057e25b4 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -232,9 +232,6 @@ template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = fals
#if !QT_CONFIG(regularexpression)
template<> struct TypeDefinition<QRegularExpression> { static const bool IsAvailable = false; };
#endif
-#ifdef QT_NO_SHORTCUT
-template<> struct TypeDefinition<QKeySequence> { static const bool IsAvailable = false; };
-#endif
#ifdef QT_NO_CURSOR
template<> struct TypeDefinition<QCursor> { static const bool IsAvailable = false; };
#endif
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index a51b794604..c72383ff4a 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -161,7 +161,6 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
#endif
void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = nullptr;
-void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = nullptr;
void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = nullptr;
void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = nullptr;
int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = nullptr;
@@ -234,10 +233,6 @@ QObjectPrivate::~QObjectPrivate()
if (metaObject) metaObject->objectDestroyed(q_ptr);
-#ifndef QT_NO_USERDATA
- if (extraData)
- qDeleteAll(extraData->userData);
-#endif
delete extraData;
}
@@ -997,15 +992,8 @@ QObject::~QObject()
emit destroyed(this);
}
- if (d->declarativeData) {
- if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
- if (QAbstractDeclarativeData::destroyed_qml1)
- QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
- } else {
- if (QAbstractDeclarativeData::destroyed)
- QAbstractDeclarativeData::destroyed(d->declarativeData, this);
- }
- }
+ if (d->declarativeData && QAbstractDeclarativeData::destroyed)
+ QAbstractDeclarativeData::destroyed(d->declarativeData, this);
QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
if (cd) {
@@ -4249,58 +4237,6 @@ void QObject::dumpObjectInfo() const
}
}
-#ifndef QT_NO_USERDATA
-static QBasicAtomicInteger<uint> user_data_registration = Q_BASIC_ATOMIC_INITIALIZER(0);
-
-/*!
- \internal
- */
-uint QObject::registerUserData()
-{
- return user_data_registration.fetchAndAddRelaxed(1);
-}
-
-/*!
- \fn QObjectUserData::QObjectUserData()
- \internal
- */
-
-/*!
- \internal
- */
-QObjectUserData::~QObjectUserData()
-{
-}
-
-/*!
- \internal
- */
-void QObject::setUserData(uint id, QObjectUserData* data)
-{
- Q_D(QObject);
- if (!d->extraData)
- d->extraData = new QObjectPrivate::ExtraData;
-
- if (d->extraData->userData.size() <= (int) id)
- d->extraData->userData.resize((int) id + 1);
- d->extraData->userData[id] = data;
-}
-
-/*!
- \internal
- */
-QObjectUserData* QObject::userData(uint id) const
-{
- Q_D(const QObject);
- if (!d->extraData)
- return nullptr;
- if ((int)id < d->extraData->userData.size())
- return d->extraData->userData.at(id);
- return nullptr;
-}
-
-#endif // QT_NO_USERDATA
-
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QObject *o)
@@ -4607,6 +4543,23 @@ QDebug operator<<(QDebug dbg, const QObject *o)
*/
/*!
+ \macro Q_MOC_INCLUDE
+ \relates QObject
+ \since 6.0
+
+ The Q_MOC_INCLUDE macro can be used within or outside a class, and tell the
+ \l{moc}{Meta Object Compiler} to add an include.
+
+ \code
+ // Put this in your code and the generated code will include this header.
+ Q_MOC_INCLUDE("myheader.h")
+ \endcode
+
+ This is useful if the types you use as properties or signal/slots arguments
+ are forward declared.
+*/
+
+/*!
\macro Q_SIGNALS
\relates QObject
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index f5d7c22e3a..8d9cc3ab83 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -78,12 +78,6 @@ class QRegExp;
#if QT_CONFIG(regularexpression)
class QRegularExpression;
#endif
-#if !QT_DEPRECATED_SINCE(5, 14) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-# define QT_NO_USERDATA
-#endif
-#ifndef QT_NO_USERDATA
-class QObjectUserData;
-#endif
struct QDynamicMetaObjectData;
typedef QList<QObject*> QObjectList;
@@ -408,15 +402,6 @@ public:
QList<QByteArray> dynamicPropertyNames() const;
#endif // QT_NO_PROPERTIES
-#ifndef QT_NO_USERDATA
- QT_DEPRECATED_VERSION_5_14
- static uint registerUserData();
- QT_DEPRECATED_VERSION_X_5_14("Use setProperty()")
- void setUserData(uint id, QObjectUserData* data);
- QT_DEPRECATED_VERSION_X_5_14("Use property()")
- QObjectUserData* userData(uint id) const;
-#endif // QT_NO_USERDATA
-
Q_SIGNALS:
void destroyed(QObject * = nullptr);
void objectNameChanged(const QString &objectName, QPrivateSignal);
@@ -449,9 +434,6 @@ protected:
protected:
QScopedPointer<QObjectData> d_ptr;
- static const QMetaObject staticQtMetaObject;
- friend inline const QMetaObject *qt_getQtMetaObject() noexcept;
-
friend struct QMetaObject;
friend struct QMetaObjectPrivate;
friend class QMetaCallEvent;
@@ -482,18 +464,6 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch
const char *amember, Qt::ConnectionType atype) const
{ return connect(asender, asignal, this, amember, atype); }
-inline const QMetaObject *qt_getQtMetaObject() noexcept
-{ return &QObject::staticQtMetaObject; }
-
-#ifndef QT_NO_USERDATA
-class Q_CORE_EXPORT QObjectUserData {
- Q_DISABLE_COPY(QObjectUserData)
-public:
- QObjectUserData() = default;
- virtual ~QObjectUserData();
-};
-#endif
-
#if QT_DEPRECATED_SINCE(5, 0)
template<typename T>
inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString())
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 838a9aa8c5..d6e73fbefc 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -89,7 +89,6 @@ class Q_CORE_EXPORT QAbstractDeclarativeData
{
public:
static void (*destroyed)(QAbstractDeclarativeData *, QObject *);
- static void (*destroyed_qml1)(QAbstractDeclarativeData *, QObject *);
static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *);
static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **);
static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int);
@@ -97,14 +96,6 @@ public:
static void (*setWidgetParent)(QObject *, QObject *); // Used by the QML engine to specify parents for widgets. Set by QtWidgets.
};
-// This is an implementation of QAbstractDeclarativeData that is identical with
-// the implementation in QtDeclarative and QtQml for the first bit
-struct QAbstractDeclarativeDataImpl : public QAbstractDeclarativeData
-{
- quint32 ownedByQml1:1;
- quint32 unused: 31;
-};
-
class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
Q_DECLARE_PUBLIC(QObject)
@@ -113,9 +104,6 @@ public:
struct ExtraData
{
ExtraData() {}
- #ifndef QT_NO_USERDATA
- QVector<QObjectUserData *> userData;
- #endif
QList<QByteArray> propertyNames;
QVector<QVariant> propertyValues;
QVector<int> runningTimers;
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index dc2d832fe5..657cb9940b 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -46,199 +46,15 @@
#endif
#include <QtCore/qnamespace.h>
-
#include <QtCore/qobjectdefs_impl.h>
+#include <QtCore/qtmetamacros.h>
QT_BEGIN_NAMESPACE
-
class QByteArray;
struct QArrayData;
-typedef QArrayData QByteArrayData;
class QString;
-#ifndef Q_MOC_OUTPUT_REVISION
-#define Q_MOC_OUTPUT_REVISION 67
-#endif
-
-// The following macros can be defined by tools that understand Qt
-// to have the information from the macro.
-#ifndef QT_ANNOTATE_CLASS
-# define QT_ANNOTATE_CLASS(type, ...)
-#endif
-#ifndef QT_ANNOTATE_CLASS2
-# define QT_ANNOTATE_CLASS2(type, a1, a2)
-#endif
-#ifndef QT_ANNOTATE_FUNCTION
-# define QT_ANNOTATE_FUNCTION(x)
-#endif
-#ifndef QT_ANNOTATE_ACCESS_SPECIFIER
-# define QT_ANNOTATE_ACCESS_SPECIFIER(x)
-#endif
-
-// The following macros are our "extensions" to C++
-// They are used, strictly speaking, only by the moc.
-
-#ifndef Q_MOC_RUN
-#ifndef QT_NO_META_MACROS
-# if defined(QT_NO_KEYWORDS)
-# define QT_NO_EMIT
-# else
-# ifndef QT_NO_SIGNALS_SLOTS_KEYWORDS
-# define slots Q_SLOTS
-# define signals Q_SIGNALS
-# endif
-# endif
-# define Q_SLOTS QT_ANNOTATE_ACCESS_SPECIFIER(qt_slot)
-# define Q_SIGNALS public QT_ANNOTATE_ACCESS_SPECIFIER(qt_signal)
-# define Q_PRIVATE_SLOT(d, signature) QT_ANNOTATE_CLASS2(qt_private_slot, d, signature)
-# define Q_EMIT
-#ifndef QT_NO_EMIT
-# define emit
-#endif
-#ifndef Q_CLASSINFO
-# define Q_CLASSINFO(name, value)
-#endif
-#define Q_PLUGIN_METADATA(x) QT_ANNOTATE_CLASS(qt_plugin_metadata, x)
-#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x)
-#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)
-#define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text)
-#ifndef Q_REVISION
-# define Q_REVISION(v)
-#endif
-#define Q_OVERRIDE(text) QT_ANNOTATE_CLASS(qt_override, text)
-#define QDOC_PROPERTY(text) QT_ANNOTATE_CLASS(qt_qdoc_property, text)
-#define Q_ENUMS(x) QT_ANNOTATE_CLASS(qt_enums, x)
-#define Q_FLAGS(x) QT_ANNOTATE_CLASS(qt_enums, x)
-#define Q_ENUM_IMPL(ENUM) \
- friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
- friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
-#define Q_ENUM(x) Q_ENUMS(x) Q_ENUM_IMPL(x)
-#define Q_FLAG(x) Q_FLAGS(x) Q_ENUM_IMPL(x)
-#define Q_ENUM_NS_IMPL(ENUM) \
- inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
- inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
-#define Q_ENUM_NS(x) Q_ENUMS(x) Q_ENUM_NS_IMPL(x)
-#define Q_FLAG_NS(x) Q_FLAGS(x) Q_ENUM_NS_IMPL(x)
-#define Q_SCRIPTABLE QT_ANNOTATE_FUNCTION(qt_scriptable)
-#define Q_INVOKABLE QT_ANNOTATE_FUNCTION(qt_invokable)
-#define Q_SIGNAL QT_ANNOTATE_FUNCTION(qt_signal)
-#define Q_SLOT QT_ANNOTATE_FUNCTION(qt_slot)
-#endif // QT_NO_META_MACROS
-
-#ifndef QT_NO_TRANSLATION
-// full set of tr functions
-# define QT_TR_FUNCTIONS \
- static inline QString tr(const char *s, const char *c = nullptr, int n = -1) \
- { return staticMetaObject.tr(s, c, n); } \
- QT_DEPRECATED static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) \
- { return staticMetaObject.tr(s, c, n); }
-#else
-// inherit the ones from QObject
-# define QT_TR_FUNCTIONS
-#endif
-
-#ifdef Q_CLANG_QDOC
-#define QT_TR_FUNCTIONS
-#endif
-
-// ### Qt6: remove
-#define Q_OBJECT_CHECK /* empty, unused since Qt 5.2 */
-
-#if defined(Q_CC_INTEL)
-// Cannot redefine the visibility of a method in an exported class
-# define Q_DECL_HIDDEN_STATIC_METACALL
-#else
-# define Q_DECL_HIDDEN_STATIC_METACALL Q_DECL_HIDDEN
-#endif
-
-#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306
-# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override")
-#elif defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 501
-# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_GCC("-Wsuggest-override")
-#else
-# define Q_OBJECT_NO_OVERRIDE_WARNING
-#endif
-
-#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 600
-# define Q_OBJECT_NO_ATTRIBUTES_WARNING QT_WARNING_DISABLE_GCC("-Wattributes")
-#else
-# define Q_OBJECT_NO_ATTRIBUTES_WARNING
-#endif
-
-/* qmake ignore Q_OBJECT */
-#define Q_OBJECT \
-public: \
- QT_WARNING_PUSH \
- Q_OBJECT_NO_OVERRIDE_WARNING \
- static const QMetaObject staticMetaObject; \
- virtual const QMetaObject *metaObject() const; \
- virtual void *qt_metacast(const char *); \
- virtual int qt_metacall(QMetaObject::Call, int, void **); \
- QT_TR_FUNCTIONS \
-private: \
- Q_OBJECT_NO_ATTRIBUTES_WARNING \
- Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
- QT_WARNING_POP \
- struct QPrivateSignal {}; \
- QT_ANNOTATE_CLASS(qt_qobject, "")
-
-/* qmake ignore Q_OBJECT */
-#define Q_OBJECT_FAKE Q_OBJECT QT_ANNOTATE_CLASS(qt_fake, "")
-
-#ifndef QT_NO_META_MACROS
-/* qmake ignore Q_GADGET */
-#define Q_GADGET \
-public: \
- static const QMetaObject staticMetaObject; \
- void qt_check_for_QGADGET_macro(); \
- typedef void QtGadgetHelper; \
-private: \
- QT_WARNING_PUSH \
- Q_OBJECT_NO_ATTRIBUTES_WARNING \
- Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
- QT_WARNING_POP \
- QT_ANNOTATE_CLASS(qt_qgadget, "") \
- /*end*/
-
-/* qmake ignore Q_NAMESPACE_EXPORT */
-#define Q_NAMESPACE_EXPORT(...) \
- extern __VA_ARGS__ const QMetaObject staticMetaObject; \
- QT_ANNOTATE_CLASS(qt_qnamespace, "") \
- /*end*/
-
-/* qmake ignore Q_NAMESPACE */
-#define Q_NAMESPACE Q_NAMESPACE_EXPORT() \
- /*end*/
-
-#endif // QT_NO_META_MACROS
-
-#else // Q_MOC_RUN
-#define slots slots
-#define signals signals
-#define Q_SLOTS Q_SLOTS
-#define Q_SIGNALS Q_SIGNALS
-#define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value)
-#define Q_INTERFACES(x) Q_INTERFACES(x)
-#define Q_PROPERTY(text) Q_PROPERTY(text)
-#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text)
-#define Q_REVISION(v) Q_REVISION(v)
-#define Q_OVERRIDE(text) Q_OVERRIDE(text)
-#define Q_ENUMS(x) Q_ENUMS(x)
-#define Q_FLAGS(x) Q_FLAGS(x)
-#define Q_ENUM(x) Q_ENUM(x)
-#define Q_FLAGS(x) Q_FLAGS(x)
- /* qmake ignore Q_OBJECT */
-#define Q_OBJECT Q_OBJECT
- /* qmake ignore Q_OBJECT */
-#define Q_OBJECT_FAKE Q_OBJECT_FAKE
- /* qmake ignore Q_GADGET */
-#define Q_GADGET Q_GADGET
-#define Q_SCRIPTABLE Q_SCRIPTABLE
-#define Q_INVOKABLE Q_INVOKABLE
-#define Q_SIGNAL Q_SIGNAL
-#define Q_SLOT Q_SLOT
-#endif //Q_MOC_RUN
#ifndef QT_NO_META_MACROS
// macro for onaming members
@@ -285,6 +101,10 @@ class QMetaEnum;
class QMetaProperty;
class QMetaClassInfo;
+struct QMethodRawArguments
+{
+ void **arguments;
+};
class Q_CORE_EXPORT QGenericArgument
{
@@ -603,7 +423,7 @@ struct Q_CORE_EXPORT QMetaObject
struct { // private data
SuperData superdata;
- const QByteArrayData *stringdata;
+ const uint *stringdata;
const uint *data;
typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);
StaticMetacallFunction static_metacall;
diff --git a/src/corelib/kernel/qtmetamacros.h b/src/corelib/kernel/qtmetamacros.h
new file mode 100644
index 0000000000..1d095c0d7c
--- /dev/null
+++ b/src/corelib/kernel/qtmetamacros.h
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
+** Contact: https://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 QTMETAMACROS_H
+#define QTMETAMACROS_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef Q_MOC_OUTPUT_REVISION
+#define Q_MOC_OUTPUT_REVISION 67
+#endif
+
+// The following macros can be defined by tools that understand Qt
+// to have the information from the macro.
+#ifndef QT_ANNOTATE_CLASS
+# define QT_ANNOTATE_CLASS(type, ...)
+#endif
+#ifndef QT_ANNOTATE_CLASS2
+# define QT_ANNOTATE_CLASS2(type, a1, a2)
+#endif
+#ifndef QT_ANNOTATE_FUNCTION
+# define QT_ANNOTATE_FUNCTION(x)
+#endif
+#ifndef QT_ANNOTATE_ACCESS_SPECIFIER
+# define QT_ANNOTATE_ACCESS_SPECIFIER(x)
+#endif
+
+// The following macros are our "extensions" to C++
+// They are used, strictly speaking, only by the moc.
+
+#ifndef Q_MOC_RUN
+#ifndef QT_NO_META_MACROS
+# if defined(QT_NO_KEYWORDS)
+# define QT_NO_EMIT
+# else
+# ifndef QT_NO_SIGNALS_SLOTS_KEYWORDS
+# define slots Q_SLOTS
+# define signals Q_SIGNALS
+# endif
+# endif
+# define Q_SLOTS QT_ANNOTATE_ACCESS_SPECIFIER(qt_slot)
+# define Q_SIGNALS public QT_ANNOTATE_ACCESS_SPECIFIER(qt_signal)
+# define Q_PRIVATE_SLOT(d, signature) QT_ANNOTATE_CLASS2(qt_private_slot, d, signature)
+# define Q_EMIT
+#ifndef QT_NO_EMIT
+# define emit
+#endif
+#ifndef Q_CLASSINFO
+# define Q_CLASSINFO(name, value)
+#endif
+#define Q_PLUGIN_METADATA(x) QT_ANNOTATE_CLASS(qt_plugin_metadata, x)
+#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x)
+#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)
+#define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text)
+#ifndef Q_REVISION
+# define Q_REVISION(v)
+#endif
+#define Q_OVERRIDE(text) QT_ANNOTATE_CLASS(qt_override, text)
+#define QDOC_PROPERTY(text) QT_ANNOTATE_CLASS(qt_qdoc_property, text)
+#define Q_ENUMS(x) QT_ANNOTATE_CLASS(qt_enums, x)
+#define Q_FLAGS(x) QT_ANNOTATE_CLASS(qt_enums, x)
+#define Q_ENUM_IMPL(ENUM) \
+ friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
+ friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
+#define Q_ENUM(x) Q_ENUMS(x) Q_ENUM_IMPL(x)
+#define Q_FLAG(x) Q_FLAGS(x) Q_ENUM_IMPL(x)
+#define Q_ENUM_NS_IMPL(ENUM) \
+ inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
+ inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
+#define Q_ENUM_NS(x) Q_ENUMS(x) Q_ENUM_NS_IMPL(x)
+#define Q_FLAG_NS(x) Q_FLAGS(x) Q_ENUM_NS_IMPL(x)
+#define Q_SCRIPTABLE QT_ANNOTATE_FUNCTION(qt_scriptable)
+#define Q_INVOKABLE QT_ANNOTATE_FUNCTION(qt_invokable)
+#define Q_SIGNAL QT_ANNOTATE_FUNCTION(qt_signal)
+#define Q_SLOT QT_ANNOTATE_FUNCTION(qt_slot)
+#define Q_MOC_INCLUDE(...) QT_ANNOTATE_CLASS(qt_moc_include, __VA_ARGS__)
+#endif // QT_NO_META_MACROS
+
+#ifndef QT_NO_TRANSLATION
+// full set of tr functions
+# define QT_TR_FUNCTIONS \
+ static inline QString tr(const char *s, const char *c = nullptr, int n = -1) \
+ { return staticMetaObject.tr(s, c, n); } \
+ QT_DEPRECATED static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) \
+ { return staticMetaObject.tr(s, c, n); }
+#else
+// inherit the ones from QObject
+# define QT_TR_FUNCTIONS
+#endif
+
+#ifdef Q_CLANG_QDOC
+#define QT_TR_FUNCTIONS
+#endif
+
+// ### Qt6: remove
+#define Q_OBJECT_CHECK /* empty, unused since Qt 5.2 */
+
+#if defined(Q_CC_INTEL)
+// Cannot redefine the visibility of a method in an exported class
+# define Q_DECL_HIDDEN_STATIC_METACALL
+#else
+# define Q_DECL_HIDDEN_STATIC_METACALL Q_DECL_HIDDEN
+#endif
+
+#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306
+# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override")
+#elif defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 501
+# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_GCC("-Wsuggest-override")
+#else
+# define Q_OBJECT_NO_OVERRIDE_WARNING
+#endif
+
+#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 600
+# define Q_OBJECT_NO_ATTRIBUTES_WARNING QT_WARNING_DISABLE_GCC("-Wattributes")
+#else
+# define Q_OBJECT_NO_ATTRIBUTES_WARNING
+#endif
+
+/* qmake ignore Q_OBJECT */
+#define Q_OBJECT \
+public: \
+ QT_WARNING_PUSH \
+ Q_OBJECT_NO_OVERRIDE_WARNING \
+ static const QMetaObject staticMetaObject; \
+ virtual const QMetaObject *metaObject() const; \
+ virtual void *qt_metacast(const char *); \
+ virtual int qt_metacall(QMetaObject::Call, int, void **); \
+ QT_TR_FUNCTIONS \
+private: \
+ Q_OBJECT_NO_ATTRIBUTES_WARNING \
+ Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
+ QT_WARNING_POP \
+ struct QPrivateSignal {}; \
+ QT_ANNOTATE_CLASS(qt_qobject, "")
+
+/* qmake ignore Q_OBJECT */
+#define Q_OBJECT_FAKE Q_OBJECT QT_ANNOTATE_CLASS(qt_fake, "")
+
+#ifndef QT_NO_META_MACROS
+/* qmake ignore Q_GADGET */
+#define Q_GADGET \
+public: \
+ static const QMetaObject staticMetaObject; \
+ void qt_check_for_QGADGET_macro(); \
+ typedef void QtGadgetHelper; \
+private: \
+ QT_WARNING_PUSH \
+ Q_OBJECT_NO_ATTRIBUTES_WARNING \
+ Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
+ QT_WARNING_POP \
+ QT_ANNOTATE_CLASS(qt_qgadget, "") \
+ /*end*/
+
+/* qmake ignore Q_NAMESPACE_EXPORT */
+#define Q_NAMESPACE_EXPORT(...) \
+ extern __VA_ARGS__ const QMetaObject staticMetaObject; \
+ QT_ANNOTATE_CLASS(qt_qnamespace, "") \
+ /*end*/
+
+/* qmake ignore Q_NAMESPACE */
+#define Q_NAMESPACE Q_NAMESPACE_EXPORT() \
+ /*end*/
+
+#endif // QT_NO_META_MACROS
+
+#else // Q_MOC_RUN
+#define slots slots
+#define signals signals
+#define Q_SLOTS Q_SLOTS
+#define Q_SIGNALS Q_SIGNALS
+#define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value)
+#define Q_INTERFACES(x) Q_INTERFACES(x)
+#define Q_PROPERTY(text) Q_PROPERTY(text)
+#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text)
+#define Q_REVISION(v) Q_REVISION(v)
+#define Q_OVERRIDE(text) Q_OVERRIDE(text)
+#define Q_ENUMS(x) Q_ENUMS(x)
+#define Q_FLAGS(x) Q_FLAGS(x)
+#define Q_ENUM(x) Q_ENUM(x)
+#define Q_FLAGS(x) Q_FLAGS(x)
+ /* qmake ignore Q_OBJECT */
+#define Q_OBJECT Q_OBJECT
+ /* qmake ignore Q_OBJECT */
+#define Q_OBJECT_FAKE Q_OBJECT_FAKE
+ /* qmake ignore Q_GADGET */
+#define Q_GADGET Q_GADGET
+#define Q_SCRIPTABLE Q_SCRIPTABLE
+#define Q_INVOKABLE Q_INVOKABLE
+#define Q_SIGNAL Q_SIGNAL
+#define Q_SLOT Q_SLOT
+#endif //Q_MOC_RUN
+
+QT_END_NAMESPACE
+
+#endif // QTMETAMACROS_H
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index 93d75feafa..4bd8874630 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -58,11 +58,11 @@
#include "qendian.h"
#include "qresource.h"
-#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
-#define QT_USE_MMAP
-#include "private/qcore_unix_p.h"
+#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
+# define QT_USE_MMAP
+# include "private/qcore_unix_p.h"
// for mmap
-#include <sys/mman.h>
+# include <sys/mman.h>
#endif
#include <stdlib.h>
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index b417683d2a..815eefc617 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2018 Intel Corporation.
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
@@ -1470,7 +1470,7 @@ static void customConstruct(QVariant::Private *d, const void *copy)
} else {
// Private::Data contains long long, and long double is the biggest standard type.
const size_t maxAlignment =
- qMax(Q_ALIGNOF(QVariant::Private::Data), Q_ALIGNOF(long double));
+ qMax(alignof(QVariant::Private::Data), alignof(long double));
const size_t s = sizeof(QVariant::PrivateShared);
const size_t offset = s + ((s * maxAlignment - s) % maxAlignment);
void *data = operator new(offset + size);
@@ -2469,7 +2469,9 @@ static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
QMetaType::QDateTime,
QMetaType::QByteArray,
QMetaType::QBitArray,
+#if QT_CONFIG(shortcut)
QMetaType::QKeySequence,
+#endif
QMetaType::QPen,
QMetaType::LongLong,
QMetaType::ULongLong,
@@ -2574,7 +2576,11 @@ void QVariant::save(QDataStream &s) const
typeId += 97;
} else if (typeId == QMetaType::QSizePolicy) {
typeId = 75;
+#if QT_CONFIG(shortcut)
} else if (typeId >= QMetaType::QKeySequence && typeId <= QMetaType::QQuaternion) {
+#else
+ } else if (typeId >= QMetaType::QPen && typeId <= QMetaType::QQuaternion) {
+#endif
// and as a result these types received lower ids too
typeId +=1;
} else if (typeId == QMetaType::QPolygonF || typeId == QMetaType::QUuid) {
@@ -3647,9 +3653,11 @@ bool QVariant::canConvert(int targetTypeId) const
if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) {
switch (uint(targetTypeId)) {
case QVariant::Int:
+#if QT_CONFIG(shortcut)
if (currentType == QVariant::KeySequence)
return true;
Q_FALLTHROUGH();
+#endif
case QVariant::UInt:
case QVariant::LongLong:
case QVariant::ULongLong:
@@ -3672,11 +3680,16 @@ bool QVariant::canConvert(int targetTypeId) const
return currentType == QVariant::Color || currentType == QMetaType::Nullptr
|| ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
case QVariant::String:
- return currentType == QVariant::KeySequence || currentType == QVariant::Font
- || currentType == QVariant::Color || currentType == QMetaType::Nullptr
- || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
+ return currentType == QVariant::Font
+ || currentType == QVariant::Color || currentType == QMetaType::Nullptr
+#if QT_CONFIG(shortcut)
+ || currentType == QVariant::KeySequence
+#endif
+ || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
+#if QT_CONFIG(shortcut)
case QVariant::KeySequence:
return currentType == QVariant::String || currentType == QVariant::Int;
+#endif
case QVariant::Font:
return currentType == QVariant::String;
case QVariant::Color:
@@ -3827,72 +3840,6 @@ bool QVariant::convert(const int type, void *ptr) const
QMetaType::registerComparators().
*/
-/*!
- \fn bool QVariant::operator<(const QVariant &v) const
- \obsolete
-
- Compares this QVariant with \a v and returns \c true if this is less than \a v.
-
- \note Comparability might not be availabe for the type stored in this QVariant
- or in \a v.
-
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
-
- This operator is deprecated as it cannot establish a total order required
- for most use of this operator, which is the reason you cannot use QVariant
- as the key of a QMap.
-*/
-
-/*!
- \fn bool QVariant::operator<=(const QVariant &v) const
- \obsolete
-
- Compares this QVariant with \a v and returns \c true if this is less or equal than \a v.
-
- \note Comparability might not be available for the type stored in this QVariant
- or in \a v.
-
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
-
- This operator is deprecated as it cannot establish a total order.
-*/
-
-/*!
- \fn bool QVariant::operator>(const QVariant &v) const
- \obsolete
-
- Compares this QVariant with \a v and returns \c true if this is larger than \a v.
-
- \note Comparability might not be available for the type stored in this QVariant
- or in \a v.
-
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
-
- This operator is deprecated as it cannot establish a total order.
-*/
-
-/*!
- \fn bool QVariant::operator>=(const QVariant &v) const
- \obsolete
-
- Compares this QVariant with \a v and returns \c true if this is larger or equal than \a v.
-
- \note Comparability might not be available for the type stored in this QVariant
- or in \a v.
-
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
-
- This operator is deprecated as it cannot establish a total order.
-*/
-
static bool qIsNumericType(uint tp)
{
static const qulonglong numericTypeBits =
@@ -4073,73 +4020,6 @@ bool QVariant::cmp(const QVariant &v) const
/*!
\internal
*/
-int QVariant::compare(const QVariant &v) const
-{
- // try numerics first, with C++ type promotion rules (no conversion)
- if (qIsNumericType(d.type) && qIsNumericType(v.d.type))
- return numericCompare(&d, &v.d);
-
- // check for equality next, as more types implement operator== than operator<
- if (cmp(v))
- return 0;
-
- const QVariant *v1 = this;
- const QVariant *v2 = &v;
- QVariant converted1;
- QVariant converted2;
-
- if (d.type != v.d.type) {
- // if both types differ, try to convert
- if (v2->canConvert(v1->d.type)) {
- converted2 = *v2;
- if (converted2.convert(v1->d.type))
- v2 = &converted2;
- }
- if (v1->d.type != v2->d.type && v1->canConvert(v2->d.type)) {
- converted1 = *v1;
- if (converted1.convert(v2->d.type))
- v1 = &converted1;
- }
- if (v1->d.type != v2->d.type) {
- // if conversion fails, default to toString
- int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive);
- if (r == 0) {
- // cmp(v) returned false, so we should try to agree with it.
- return (v1->d.type < v2->d.type) ? -1 : 1;
- }
- return r;
- }
-
- // did we end up with two numerics? If so, restart
- if (qIsNumericType(v1->d.type) && qIsNumericType(v2->d.type))
- return v1->compare(*v2);
- }
- if (v1->d.type >= QMetaType::User) {
- int result;
- if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2->d)), d.type, &result))
- return result;
- }
- switch (v1->d.type) {
- case QVariant::Date:
- return v1->toDate() < v2->toDate() ? -1 : 1;
- case QVariant::Time:
- return v1->toTime() < v2->toTime() ? -1 : 1;
- case QVariant::DateTime:
- return v1->toDateTime() < v2->toDateTime() ? -1 : 1;
- case QVariant::StringList:
- return v1->toStringList() < v2->toStringList() ? -1 : 1;
- }
- int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive);
- if (r == 0) {
- // cmp(v) returned false, so we should try to agree with it.
- return (d.type < v.d.type) ? -1 : 1;
- }
- return r;
-}
-
-/*!
- \internal
- */
const void *QVariant::constData() const
{
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 24657818c5..353bfa7ce7 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -184,7 +184,9 @@ class Q_CORE_EXPORT QVariant
Region = QMetaType::QRegion,
Bitmap = QMetaType::QBitmap,
Cursor = QMetaType::QCursor,
+#if QT_CONFIG(shortcut)
KeySequence = QMetaType::QKeySequence,
+#endif
Pen = QMetaType::QPen,
TextLength = QMetaType::QTextLength,
TextFormat = QMetaType::QTextFormat,
@@ -394,7 +396,7 @@ class Q_CORE_EXPORT QVariant
struct Private
{
inline Private() noexcept : type(Invalid), is_shared(false), is_null(true)
- { data.ptr = nullptr; }
+ {}
// Internal constructor for initialized variants.
explicit inline Private(uint variantType) noexcept
@@ -410,6 +412,7 @@ class Q_CORE_EXPORT QVariant
#endif
union Data
{
+ void *threeptr[3] = { nullptr, nullptr, nullptr };
char c;
uchar uc;
short s;
@@ -463,16 +466,6 @@ class Q_CORE_EXPORT QVariant
{ return cmp(v); }
inline bool operator!=(const QVariant &v) const
{ return !cmp(v); }
-#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED inline bool operator<(const QVariant &v) const
- { return compare(v) < 0; }
- QT_DEPRECATED inline bool operator<=(const QVariant &v) const
- { return compare(v) <= 0; }
- QT_DEPRECATED inline bool operator>(const QVariant &v) const
- { return compare(v) > 0; }
- QT_DEPRECATED inline bool operator>=(const QVariant &v) const
- { return compare(v) >= 0; }
-#endif
protected:
friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
@@ -491,7 +484,6 @@ public:
Private d;
void create(int type, const void *copy);
bool cmp(const QVariant &other) const;
- int compare(const QVariant &other) const;
bool convert(const int t, void *ptr) const; // ### Qt6: drop const
private:
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index 10b2190966..f1d0dc859e 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -91,8 +91,8 @@ bool QMimeDatabasePrivate::shouldCheck()
return true;
}
-#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
-#define QT_USE_MMAP
+#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
+# define QT_USE_MMAP
#endif
void QMimeDatabasePrivate::loadProviders()
diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h
index d9cf446d44..831390de1f 100644
--- a/src/corelib/mimetypes/qmimedatabase_p.h
+++ b/src/corelib/mimetypes/qmimedatabase_p.h
@@ -63,6 +63,7 @@ QT_REQUIRE_CONFIG(mimetype);
#include <QtCore/qmutex.h>
#include <QtCore/qvector.h>
+#include <vector>
#include <memory>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index b3a95d4f26..406a83c7dd 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -692,7 +692,7 @@ static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
};
#else
auto getMetaData = [](QFunctionPointer fptr) {
- auto f = reinterpret_cast<QPair<const char *, size_t> (*)()>(fptr);
+ auto f = reinterpret_cast<QPluginMetaData (*)()>(fptr);
return f();
};
#endif
@@ -702,7 +702,7 @@ static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
return false;
auto metaData = getMetaData(pfn);
- QJsonDocument doc = qJsonFromRawLibraryMetaData(metaData.first, metaData.second, errMsg);
+ QJsonDocument doc = qJsonFromRawLibraryMetaData(reinterpret_cast<const char *>(metaData.data), metaData.size, errMsg);
if (doc.isNull())
return false;
priv->metaData = doc.object();
diff --git a/src/corelib/serialization/qbinaryjsonvalue.cpp b/src/corelib/serialization/qbinaryjsonvalue.cpp
index 5e3a01ad38..7d0bc3d366 100644
--- a/src/corelib/serialization/qbinaryjsonvalue.cpp
+++ b/src/corelib/serialization/qbinaryjsonvalue.cpp
@@ -63,12 +63,9 @@ QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data,
case QJsonValue::Double:
dbl = v.toDouble(parent);
break;
- case QJsonValue::String: {
- QString s = v.toString(parent);
- stringData = s.data_ptr();
- stringData->ref.ref();
+ case QJsonValue::String:
+ stringData = v.toString(parent);
break;
- }
case QJsonValue::Array:
case QJsonValue::Object:
d = data;
@@ -80,9 +77,9 @@ QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data,
}
QBinaryJsonValue::QBinaryJsonValue(QString string)
- : stringData(*reinterpret_cast<QStringData **>(&string)), t(QJsonValue::String)
+ : d(nullptr), t(QJsonValue::String)
{
- stringData->ref.ref();
+ stringData = std::move(string);
}
QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonArray &a)
@@ -101,9 +98,6 @@ QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonObject &o)
QBinaryJsonValue::~QBinaryJsonValue()
{
- if (t == QJsonValue::String && stringData && !stringData->ref.deref())
- free(stringData);
-
if (d && !d->ref.deref())
delete d;
}
@@ -134,9 +128,7 @@ QString QBinaryJsonValue::toString() const
{
if (t != QJsonValue::String)
return QString();
- stringData->ref.ref(); // the constructor below doesn't add a ref.
- QStringDataPtr holder = { stringData };
- return QString(holder);
+ return stringData;
}
void QBinaryJsonValue::detach()
diff --git a/src/corelib/serialization/qbinaryjsonvalue_p.h b/src/corelib/serialization/qbinaryjsonvalue_p.h
index 498fc62ecd..c3b943250c 100644
--- a/src/corelib/serialization/qbinaryjsonvalue_p.h
+++ b/src/corelib/serialization/qbinaryjsonvalue_p.h
@@ -86,6 +86,7 @@ public:
QBinaryJsonValue(QBinaryJsonValue &&other) noexcept
: ui(other.ui),
+ stringData(std::move(other.stringData)),
d(other.d),
t(other.t)
{
@@ -96,6 +97,7 @@ public:
QBinaryJsonValue &operator =(QBinaryJsonValue &&other) noexcept
{
+ qSwap(stringData, other.stringData);
qSwap(ui, other.ui);
qSwap(d, other.d);
qSwap(t, other.t);
@@ -122,9 +124,9 @@ private:
quint64 ui;
bool b;
double dbl;
- QStringData *stringData;
const QBinaryJsonPrivate::Base *base;
};
+ QString stringData;
QBinaryJsonPrivate::MutableData *d = nullptr; // needed for Objects and Arrays
QJsonValue::Type t = QJsonValue::Null;
};
diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h
index 48818e4c63..53ba81fa18 100644
--- a/src/corelib/serialization/qcborvalue_p.h
+++ b/src/corelib/serialization/qcborvalue_p.h
@@ -147,8 +147,8 @@ public:
qptrdiff offset = data.size();
// align offset
- offset += Q_ALIGNOF(QtCbor::ByteData) - 1;
- offset &= ~(Q_ALIGNOF(QtCbor::ByteData) - 1);
+ offset += alignof(QtCbor::ByteData) - 1;
+ offset &= ~(alignof(QtCbor::ByteData) - 1);
qptrdiff increment = qptrdiff(sizeof(QtCbor::ByteData)) + len;
@@ -170,7 +170,7 @@ public:
return nullptr;
size_t offset = size_t(e.value);
- Q_ASSERT((offset % Q_ALIGNOF(QtCbor::ByteData)) == 0);
+ Q_ASSERT((offset % alignof(QtCbor::ByteData)) == 0);
Q_ASSERT(offset + sizeof(QtCbor::ByteData) <= size_t(data.size()));
auto b = reinterpret_cast<const QtCbor::ByteData *>(data.constData() + offset);
@@ -214,7 +214,7 @@ public:
}
void insertAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp = CopyContainer)
{
- replaceAt_internal(*elements.insert(elements.begin() + idx, {}), value, disp);
+ replaceAt_internal(*elements.insert(elements.begin() + int(idx), {}), value, disp);
}
void append(QtCbor::Undefined)
@@ -235,6 +235,15 @@ public:
elements.append(QtCbor::Element(addByteData(data, len), type,
QtCbor::Element::HasByteData | extraFlags));
}
+ void appendAsciiString(const QString &s);
+ void appendAsciiString(const char *str, qsizetype len)
+ {
+ appendByteData(str, len, QCborValue::String, QtCbor::Element::StringIsAscii);
+ }
+ void appendUtf8String(const char *str, qsizetype len)
+ {
+ appendByteData(str, len, QCborValue::String);
+ }
void append(QLatin1String s)
{
if (!QtPrivate::isAscii(s))
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index 4d827772c8..b7c16018d5 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -43,6 +43,7 @@
#include <QtCore/qscopedpointer.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qpair.h>
+#include <QtCore/qcontainerfwd.h>
#ifdef Status
#error qdatastream.h must be included before any header file that defines Status
@@ -54,12 +55,6 @@ class qfloat16;
class QByteArray;
class QIODevice;
-template <typename T> class QList;
-template <typename T> class QVector;
-template <typename T> class QSet;
-template <class Key, class T> class QHash;
-template <class Key, class T> class QMap;
-
#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
class QDataStreamPrivate;
namespace QtPrivate {
@@ -414,18 +409,6 @@ typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
operator>>(QDataStream &s, T &t)
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
-template <typename T>
-inline QDataStream &operator>>(QDataStream &s, QList<T> &l)
-{
- return QtPrivate::readArrayBasedContainer(s, l);
-}
-
-template <typename T>
-inline QDataStream &operator<<(QDataStream &s, const QList<T> &l)
-{
- return QtPrivate::writeSequentialContainer(s, l);
-}
-
template<typename T>
inline QDataStream &operator>>(QDataStream &s, QVector<T> &v)
{
diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h
index 22aa996a3e..9b7e10766f 100644
--- a/src/corelib/serialization/qjsonarray.h
+++ b/src/corelib/serialization/qjsonarray.h
@@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE
class QDebug;
class QStringList;
-template <typename T> class QList;
typedef QList<QVariant> QVariantList;
class Q_CORE_EXPORT QJsonArray
diff --git a/src/corelib/serialization/qjsoncbor.cpp b/src/corelib/serialization/qjsoncbor.cpp
index ee4dd90416..000008db50 100644
--- a/src/corelib/serialization/qjsoncbor.cpp
+++ b/src/corelib/serialization/qjsoncbor.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 Intel Corporation.
+** Copyright (C) 2020 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -262,8 +262,7 @@ QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
const auto &e = d->elements.at(idx);
switch (e.type) {
case QCborValue::Integer:
- return QJsonPrivate::Value::fromTrustedCbor(e.value);
-
+ return QJsonValue(e.value);
case QCborValue::ByteArray:
case QCborValue::String:
case QCborValue::SimpleType:
@@ -370,7 +369,7 @@ QJsonValue QCborValue::toJsonValue() const
return false;
case Integer:
- return QJsonPrivate::Value::fromTrustedCbor(n);
+ return QJsonPrivate::Value::fromTrustedCbor(*this);
case True:
return true;
@@ -615,11 +614,9 @@ QCborValue QCborValue::fromJsonValue(const QJsonValue &v)
case QJsonValue::Bool:
return v.toBool();
case QJsonValue::Double: {
- qint64 i;
- const double dbl = v.toDouble();
- if (convertDoubleTo(dbl, &i))
- return i;
- return dbl;
+ if (v.t == Integer)
+ return v.toInteger();
+ return v.toDouble();
}
case QJsonValue::String:
return v.toString();
@@ -667,9 +664,7 @@ static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
\row \li \c bool \li Bool
\row \li \c std::nullptr_t \li Null
\row \li \c short, \c ushort, \c int, \c uint, \l qint64 \li Integer
- \row \li \l quint64 \li Integer, but they are cast to \c qint64 first so
- values higher than 2\sup{63}-1 (\c INT64_MAX) will
- be wrapped to negative
+ \row \li \l quint64 \li Integer, or Double if outside the range of qint64
\row \li \c float, \c double \li Double
\row \li \l QByteArray \li ByteArray
\row \li \l QDateTime \li DateTime
@@ -713,9 +708,12 @@ QCborValue QCborValue::fromVariant(const QVariant &variant)
case QMetaType::UShort:
case QMetaType::Int:
case QMetaType::LongLong:
- case QMetaType::ULongLong:
case QMetaType::UInt:
return variant.toLongLong();
+ case QMetaType::ULongLong:
+ if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max()))
+ return variant.toLongLong();
+ Q_FALLTHROUGH();
case QMetaType::Float:
case QMetaType::Double:
return variant.toDouble();
diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp
index 6d0a92e094..d7ce702ff7 100644
--- a/src/corelib/serialization/qjsonparser.cpp
+++ b/src/corelib/serialization/qjsonparser.cpp
@@ -709,10 +709,11 @@ bool Parser::parseNumber()
// frac = decimal-point 1*DIGIT
if (json < end && *json == '.') {
- isInt = false;
++json;
- while (json < end && *json >= '0' && *json <= '9')
+ while (json < end && *json >= '0' && *json <= '9') {
+ isInt = isInt && *json == '0';
++json;
+ }
}
// exp = e [ minus / plus ] 1*DIGIT
@@ -893,9 +894,10 @@ bool Parser::parseString()
// no escape sequences, we are done
if (isUtf8) {
- container->appendByteData(start, json - start - 1, QCborValue::String,
- isAscii ? QtCbor::Element::StringIsAscii
- : QtCbor::Element::ValueFlags {});
+ if (isAscii)
+ container->appendAsciiString(start, json - start - 1);
+ else
+ container->appendUtf8String(start, json - start - 1);
END;
return true;
}
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index caf81c79ef..e9ba176d7f 100644
--- a/src/corelib/serialization/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -154,7 +154,9 @@ QJsonValue::QJsonValue(bool b)
QJsonValue::QJsonValue(double v)
: d(nullptr)
{
- if (convertDoubleTo(v, &n)) {
+ // Convert to integer if the number is an integer and changing wouldn't
+ // introduce additional digit precision not present in the double.
+ if (convertDoubleTo<qint64>(v, &n, false /* allow_precision_upgrade */)) {
t = QCborValue::Integer;
} else {
memcpy(&n, &v, sizeof(n));
@@ -449,12 +451,18 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
return QJsonValue(Null);
case QMetaType::Bool:
return QJsonValue(variant.toBool());
+ case QMetaType::Short:
+ case QMetaType::UShort:
case QMetaType::Int:
- case QMetaType::Float:
- case QMetaType::Double:
+ case QMetaType::UInt:
case QMetaType::LongLong:
+ return QJsonValue(variant.toLongLong());
case QMetaType::ULongLong:
- case QMetaType::UInt:
+ if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max()))
+ return QJsonValue(variant.toLongLong());
+ Q_FALLTHROUGH();
+ case QMetaType::Float:
+ case QMetaType::Double:
return QJsonValue(variant.toDouble());
case QMetaType::QString:
return QJsonValue(variant.toString());
@@ -504,7 +512,7 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
\value Null QMetaType::Nullptr
\value Bool QMetaType::Bool
- \value Double QMetaType::Double
+ \value Double QMetaType::Double or QMetaType::LongLong
\value String QString
\value Array QVariantList
\value Object QVariantMap
@@ -520,6 +528,7 @@ QVariant QJsonValue::toVariant() const
case QCborValue::False:
return false;
case QCborValue::Integer:
+ return toInteger();
case QCborValue::Double:
return toDouble();
case QCborValue::String:
@@ -548,7 +557,8 @@ QVariant QJsonValue::toVariant() const
\value Null A Null value
\value Bool A boolean value. Use toBool() to convert to a bool.
- \value Double A double. Use toDouble() to convert to a double.
+ \value Double A number value. Use toDouble() to convert to a double,
+ or toInteger() to convert to a qint64.
\value String A string. Use toString() to convert to a QString.
\value Array An array. Use toArray() to convert to a QJsonArray.
\value Object An object. Use toObject() to convert to a QJsonObject.
@@ -613,18 +623,43 @@ int QJsonValue::toInt(int defaultValue) const
{
switch (t) {
case QCborValue::Double: {
- const double dbl = toDouble();
int dblInt;
- convertDoubleTo<int>(dbl, &dblInt);
- return dbl == dblInt ? dblInt : defaultValue;
+ if (convertDoubleTo<int>(toDouble(), &dblInt))
+ return dblInt;
+ break;
}
case QCborValue::Integer:
- return (n <= qint64(std::numeric_limits<int>::max())
- && n >= qint64(std::numeric_limits<int>::min()))
- ? n : defaultValue;
+ if (qint64(int(n)) == n)
+ return int(n);
+ break;
default:
- return defaultValue;
+ break;
}
+ return defaultValue;
+}
+
+/*!
+ \since 6.0
+ Converts the value to an integer and returns it.
+
+ If type() is not Double or the value is not a whole number
+ representable as qint64, the \a defaultValue will be returned.
+ */
+qint64 QJsonValue::toInteger(qint64 defaultValue) const
+{
+ switch (t) {
+ case QCborValue::Integer:
+ return n;
+ case QCborValue::Double: {
+ qint64 dblInt;
+ if (convertDoubleTo<qint64>(toDouble(), &dblInt))
+ return dblInt;
+ break;
+ }
+ default:
+ break;
+ }
+ return defaultValue;
}
/*!
@@ -641,7 +676,7 @@ double QJsonValue::toDouble(double defaultValue) const
return d;
}
case QCborValue::Integer:
- return n;
+ return double(n);
default:
return defaultValue;
}
@@ -787,8 +822,13 @@ const QJsonValue QJsonValue::operator[](int i) const
*/
bool QJsonValue::operator==(const QJsonValue &other) const
{
- if (t != other.t)
+ if (t != other.t) {
+ if (isDouble() && other.isDouble()) {
+ // One value Cbor integer, one Cbor double, should interact as doubles.
+ return toDouble() == other.toDouble();
+ }
return false;
+ }
switch (t) {
case QCborValue::Undefined:
@@ -929,32 +969,38 @@ uint qHash(const QJsonValue &value, uint seed)
QDebug operator<<(QDebug dbg, const QJsonValue &o)
{
QDebugStateSaver saver(dbg);
- switch (o.type()) {
- case QJsonValue::Undefined:
+ switch (o.t) {
+ case QCborValue::Undefined:
dbg << "QJsonValue(undefined)";
break;
- case QJsonValue::Null:
+ case QCborValue::Null:
dbg << "QJsonValue(null)";
break;
- case QJsonValue::Bool:
+ case QCborValue::True:
+ case QCborValue::False:
dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ')';
break;
- case QJsonValue::Double:
+ case QCborValue::Integer:
+ dbg.nospace() << "QJsonValue(double, " << o.toInteger() << ')';
+ break;
+ case QCborValue::Double:
dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ')';
break;
- case QJsonValue::String:
+ case QCborValue::String:
dbg.nospace() << "QJsonValue(string, " << o.toString() << ')';
break;
- case QJsonValue::Array:
+ case QCborValue::Array:
dbg.nospace() << "QJsonValue(array, ";
dbg << o.toArray();
dbg << ')';
break;
- case QJsonValue::Object:
+ case QCborValue::Map:
dbg.nospace() << "QJsonValue(object, ";
dbg << o.toObject();
dbg << ')';
break;
+ default:
+ Q_UNREACHABLE();
}
return dbg;
}
diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h
index 5adcd64176..bd8bf14baf 100644
--- a/src/corelib/serialization/qjsonvalue.h
+++ b/src/corelib/serialization/qjsonvalue.h
@@ -112,6 +112,7 @@ public:
bool toBool(bool defaultValue = false) const;
int toInt(int defaultValue = 0) const;
+ qint64 toInteger(qint64 defaultValue = 0) const;
double toDouble(double defaultValue = 0) const;
QString toString() const;
QString toString(const QString &defaultValue) const;
diff --git a/src/corelib/serialization/qjsonwriter.cpp b/src/corelib/serialization/qjsonwriter.cpp
index 627d1bbd62..590b59f09c 100644
--- a/src/corelib/serialization/qjsonwriter.cpp
+++ b/src/corelib/serialization/qjsonwriter.cpp
@@ -60,7 +60,8 @@ static inline uchar hexdig(uint u)
static QByteArray escapedString(const QString &s)
{
- QByteArray ba(s.length(), Qt::Uninitialized);
+ // give it a minimum size to ensure the resize() below always adds enough space
+ QByteArray ba(qMax(s.length(), 16), Qt::Uninitialized);
uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData()));
const uchar *ba_end = cursor + ba.length();
@@ -138,15 +139,14 @@ static void valueToJson(const QCborValue &v, QByteArray &json, int indent, bool
json += "false";
break;
case QCborValue::Integer:
+ json += QByteArray::number(v.toInteger());
+ break;
case QCborValue::Double: {
const double d = v.toDouble();
- if (qIsFinite(d)) {
- quint64 absInt;
- json += QByteArray::number(d, convertDoubleTo(std::abs(d), &absInt) ? 'f' : 'g',
- QLocale::FloatingPointShortest);
- } else {
+ if (qIsFinite(d))
+ json += QByteArray::number(d, 'g', QLocale::FloatingPointShortest);
+ else
json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
- }
break;
}
case QCborValue::String:
diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h
index 72592b8731..a9d5b96920 100644
--- a/src/corelib/statemachine/qsignaleventgenerator_p.h
+++ b/src/corelib/statemachine/qsignaleventgenerator_p.h
@@ -62,13 +62,12 @@ class QStateMachine;
class QSignalEventGenerator : public QObject
{
- Q_OBJECT_FAKE
+ Q_OBJECT
public:
QSignalEventGenerator(QStateMachine *parent);
-private:
-// slots
- void execute(void **_a);
+private Q_SLOTS:
+ void execute(QMethodRawArguments a);
private:
Q_DISABLE_COPY_MOVE(QSignalEventGenerator)
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 9d2505ba2e..fb551d5197 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -3045,102 +3045,14 @@ void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation)
#endif // animation
-
-// Begin moc-generated code -- modify carefully (check "HAND EDIT" parts)!
-struct qt_meta_stringdata_QSignalEventGenerator_t {
- QByteArrayData data[3];
- char stringdata[32];
-};
-#define QT_MOC_LITERAL(idx, ofs, len) \
- Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
- offsetof(qt_meta_stringdata_QSignalEventGenerator_t, stringdata) + ofs \
- - idx * sizeof(QByteArrayData) \
- )
-static const qt_meta_stringdata_QSignalEventGenerator_t qt_meta_stringdata_QSignalEventGenerator = {
- {
-QT_MOC_LITERAL(0, 0, 21),
-QT_MOC_LITERAL(1, 22, 7),
-QT_MOC_LITERAL(2, 30, 0)
- },
- "QSignalEventGenerator\0execute\0\0"
-};
-#undef QT_MOC_LITERAL
-
-static const uint qt_meta_data_QSignalEventGenerator[] = {
-
- // content:
- 7, // revision
- 0, // classname
- 0, 0, // classinfo
- 1, 14, // methods
- 0, 0, // properties
- 0, 0, // enums/sets
- 0, 0, // constructors
- 0, // flags
- 0, // signalCount
-
- // slots: name, argc, parameters, tag, flags
- 1, 0, 19, 2, 0x0a,
-
- // slots: parameters
- QMetaType::Void,
-
- 0 // eod
-};
-
-void QSignalEventGenerator::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
-{
- if (_c == QMetaObject::InvokeMetaMethod) {
- Q_ASSERT(staticMetaObject.cast(_o));
- QSignalEventGenerator *_t = static_cast<QSignalEventGenerator *>(_o);
- switch (_id) {
- case 0: _t->execute(_a); break; // HAND EDIT: add the _a parameter
- default: ;
- }
- }
- Q_UNUSED(_a);
-}
-
-const QMetaObject QSignalEventGenerator::staticMetaObject = {
- { &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator.data,
- qt_meta_data_QSignalEventGenerator, qt_static_metacall, nullptr, nullptr }
-};
-
-const QMetaObject *QSignalEventGenerator::metaObject() const
-{
- return &staticMetaObject;
-}
-
-void *QSignalEventGenerator::qt_metacast(const char *_clname)
-{
- if (!_clname) return nullptr;
- if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator.stringdata))
- return static_cast<void*>(const_cast< QSignalEventGenerator*>(this));
- return QObject::qt_metacast(_clname);
-}
-
-int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
- _id = QObject::qt_metacall(_c, _id, _a);
- if (_id < 0)
- return _id;
- if (_c == QMetaObject::InvokeMetaMethod) {
- if (_id < 1)
- qt_static_metacall(this, _c, _id, _a);
- _id -= 1;
- }
- return _id;
-}
-// End moc-generated code
-
-void QSignalEventGenerator::execute(void **_a)
+void QSignalEventGenerator::execute(QMethodRawArguments a)
{
auto machinePrivate = QStateMachinePrivate::get(qobject_cast<QStateMachine*>(parent()));
if (machinePrivate->state != QStateMachinePrivate::Running)
return;
int signalIndex = senderSignalIndex();
Q_ASSERT(signalIndex != -1);
- machinePrivate->handleTransitionSignal(sender(), signalIndex, _a);
+ machinePrivate->handleTransitionSignal(sender(), signalIndex, a.arguments);
}
QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent)
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 27e0d56225..ac5f2afb57 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -65,7 +65,7 @@
#include <string.h>
#include <stdlib.h>
-#define IS_RAW_DATA(d) ((d)->offset != sizeof(QByteArrayData))
+#define IS_RAW_DATA(d) ((d)->flags() & QArrayData::RawDataType)
QT_BEGIN_NAMESPACE
@@ -558,28 +558,13 @@ static const quint16 crc_tbl[16] = {
/*!
\relates QByteArray
-
- Returns the CRC-16 checksum of the first \a len bytes of \a data.
-
- The checksum is independent of the byte order (endianness) and will be
- calculated accorded to the algorithm published in ISO 3309 (Qt::ChecksumIso3309).
-
- \note This function is a 16-bit cache conserving (16 entry table)
- implementation of the CRC-16-CCITT algorithm.
-*/
-quint16 qChecksum(const char *data, uint len)
-{
- return qChecksum(data, len, Qt::ChecksumIso3309);
-}
-
-/*!
- \relates QByteArray
\since 5.9
Returns the CRC-16 checksum of the first \a len bytes of \a data.
The checksum is independent of the byte order (endianness) and will
be calculated accorded to the algorithm published in \a standard.
+ By default the algorithm published in ISO 3309 (Qt::ChecksumIso3309) is used.
\note This function is a 16-bit cache conserving (16 entry table)
implementation of the CRC-16-CCITT algorithm.
@@ -748,27 +733,25 @@ QByteArray qUncompress(const uchar* data, int nbytes)
return invalidCompressedData();
}
- QScopedPointer<QByteArray::Data, QByteArrayDataDeleter> d(QByteArray::Data::allocate(expectedSize + 1));
+ QPair<QByteArray::Data *, char *> pair = QByteArray::Data::allocate(expectedSize + 1);
+ QScopedPointer<QByteArray::Data, QByteArrayDataDeleter> d(pair.first);
if (Q_UNLIKELY(d.data() == nullptr))
return invalidCompressedData();
- d->size = expectedSize;
forever {
ulong alloc = len;
- int res = ::uncompress((uchar*)d->data(), &len,
+ int res = ::uncompress((uchar*)pair.second, &len,
data+4, nbytes-4);
switch (res) {
- case Z_OK:
+ case Z_OK: {
Q_ASSERT(len <= alloc);
Q_UNUSED(alloc);
- d->size = len;
- d->data()[len] = 0;
- {
- QByteArrayDataPtr dataPtr = { d.take() };
- return QByteArray(dataPtr);
- }
+ QByteArray::DataPointer dataPtr = { d.take(), pair.second, uint(len) };
+ pair.second[len] = '\0';
+ return QByteArray(dataPtr);
+ }
case Z_MEM_ERROR:
qWarning("qUncompress: Z_MEM_ERROR: Not enough memory");
@@ -781,11 +764,12 @@ QByteArray qUncompress(const uchar* data, int nbytes)
return invalidCompressedData();
} else {
// grow the block
- QByteArray::Data *p = QByteArray::Data::reallocateUnaligned(d.data(), len + 1);
- if (Q_UNLIKELY(p == nullptr))
+ pair = QByteArray::Data::reallocateUnaligned(d.data(), pair.second, len + 1);
+ Q_CHECK_PTR(pair.first);
+ if (Q_UNLIKELY(pair.first == nullptr))
return invalidCompressedData();
d.take(); // don't free
- d.reset(p);
+ d.reset(pair.first);
}
continue;
@@ -1211,9 +1195,6 @@ QByteArray qUncompress(const uchar* data, int nbytes)
*/
QByteArray &QByteArray::operator=(const QByteArray & other) noexcept
{
- other.d->ref.ref();
- if (!d->ref.deref())
- Data::deallocate(d);
d = other.d;
return *this;
}
@@ -1227,25 +1208,23 @@ QByteArray &QByteArray::operator=(const QByteArray & other) noexcept
QByteArray &QByteArray::operator=(const char *str)
{
- Data *x;
- if (!str) {
- x = Data::sharedNull();
- } else if (!*str) {
- x = Data::allocate(0);
+ if (!str || !*str) {
+ QPair<Data *, char *> pair;
+ if (!str) {
+ pair = qMakePair(Data::sharedNull(), Data::sharedNullData());
+ } else {
+ pair = Data::allocate(0);
+ }
+ d = QByteArrayData(pair.first, pair.second, 0);
} else {
const int len = int(strlen(str));
- const uint fullLen = len + 1;
- if (d->ref.isShared() || fullLen > d->alloc
- || (len < d->size && fullLen < uint(d->alloc >> 1)))
+ const uint fullLen = uint(len) + 1;
+ if (d->needsDetach() || fullLen > d->allocatedCapacity()
+ || (len < size() && fullLen < (d->allocatedCapacity() >> 1)))
reallocData(fullLen, d->detachFlags());
- x = d;
- memcpy(x->data(), str, fullLen); // include null terminator
- x->size = len;
+ memcpy(d.data(), str, fullLen); // include null terminator
+ d.size = len;
}
- x->ref.ref();
- if (!d->ref.deref())
- Data::deallocate(d);
- d = x;
return *this;
}
@@ -1448,7 +1427,7 @@ QByteArray &QByteArray::operator=(const char *str)
\sa operator[]()
*/
-/*! \fn QByteRef QByteArray::operator[](int i)
+/*! \fn char &QByteArray::operator[](int i)
Returns the byte at index position \a i as a modifiable reference.
@@ -1459,21 +1438,6 @@ QByteArray &QByteArray::operator=(const char *str)
Example:
\snippet code/src_corelib_tools_qbytearray.cpp 9
- The return value is of type QByteRef, a helper class for
- QByteArray. When you get an object of type QByteRef, you can use
- it as if it were a char &. If you assign to it, the assignment
- will apply to the character in the QByteArray from which you got
- the reference.
-
- \note Before Qt 5.14 it was possible to use this operator to access
- a character at an out-of-bounds position in the byte array, and
- then assign to such a position, causing the byte array to be
- automatically resized. Furthermore, assigning a value to the
- returned QByteRef would cause a detach of the byte array, even if the
- byte array has been copied in the meanwhile (and the QByteRef kept
- alive while the copy was taken). These behaviors are deprecated,
- and will be changed in a future version of Qt.
-
\sa at()
*/
@@ -1484,16 +1448,6 @@ QByteArray &QByteArray::operator=(const char *str)
Same as at(\a i).
*/
-/*! \fn QByteRef QByteArray::operator[](uint i)
-
- \overload
-*/
-
-/*! \fn char QByteArray::operator[](uint i) const
-
- \overload
-*/
-
/*!
\fn char QByteArray::front() const
\since 5.10
@@ -1525,7 +1479,7 @@ QByteArray &QByteArray::operator=(const char *str)
*/
/*!
- \fn QByteRef QByteArray::front()
+ \fn char &QByteArray::front()
\since 5.10
Returns a reference to the first character in the byte array.
@@ -1540,7 +1494,7 @@ QByteArray &QByteArray::operator=(const char *str)
*/
/*!
- \fn QByteRef QByteArray::back()
+ \fn char &QByteArray::back()
\since 5.10
Returns a reference to the last character in the byte array.
@@ -1591,7 +1545,7 @@ QByteArray &QByteArray::operator=(const char *str)
*/
void QByteArray::truncate(int pos)
{
- if (pos < d->size)
+ if (pos < size())
resize(pos);
}
@@ -1611,7 +1565,7 @@ void QByteArray::truncate(int pos)
void QByteArray::chop(int n)
{
if (n > 0)
- resize(d->size - n);
+ resize(size() - n);
}
@@ -1715,19 +1669,13 @@ void QByteArray::chop(int n)
QByteArray::QByteArray(const char *data, int size)
{
if (!data) {
- d = Data::sharedNull();
+ d = DataPointer();
} else {
if (size < 0)
size = int(strlen(data));
- if (!size) {
- d = Data::allocate(0);
- } else {
- d = Data::allocate(uint(size) + 1u);
- Q_CHECK_PTR(d);
- d->size = size;
- memcpy(d->data(), data, size);
- d->data()[size] = '\0';
- }
+ d = DataPointer(Data::allocate(uint(size) + 1u), size);
+ memcpy(d.data(), data, size);
+ d.data()[size] = '\0';
}
}
@@ -1741,13 +1689,11 @@ QByteArray::QByteArray(const char *data, int size)
QByteArray::QByteArray(int size, char ch)
{
if (size <= 0) {
- d = Data::allocate(0);
+ d = DataPointer(Data::allocate(0), 0);
} else {
- d = Data::allocate(uint(size) + 1u);
- Q_CHECK_PTR(d);
- d->size = size;
- memset(d->data(), ch, size);
- d->data()[size] = '\0';
+ d = DataPointer(Data::allocate(uint(size) + 1u), size);
+ memset(d.data(), ch, size);
+ d.data()[size] = '\0';
}
}
@@ -1759,10 +1705,8 @@ QByteArray::QByteArray(int size, char ch)
QByteArray::QByteArray(int size, Qt::Initialization)
{
- d = Data::allocate(uint(size) + 1u);
- Q_CHECK_PTR(d);
- d->size = size;
- d->data()[size] = '\0';
+ d = DataPointer(Data::allocate(uint(size) + 1u), size);
+ d.data()[size] = '\0';
}
/*!
@@ -1782,31 +1726,21 @@ void QByteArray::resize(int size)
if (size < 0)
size = 0;
- if (IS_RAW_DATA(d) && !d->ref.isShared() && size < d->size) {
- d->size = size;
+ if (!d->isShared() && !d->isMutable() && size < int(d.size)) {
+ d.size = size;
return;
}
- if (d->size == 0 && d->ref.isStatic()) {
- //
- // Optimize the idiom:
- // QByteArray a;
- // a.resize(sz);
- // ...
- // which is used in place of the Qt 3 idiom:
- // QByteArray a(sz);
- //
- Data *x = Data::allocate(uint(size) + 1u);
- Q_CHECK_PTR(x);
- x->size = size;
- x->data()[size] = '\0';
- d = x;
+ if (size == 0 && !(d->flags() & Data::CapacityReserved)) {
+ d = DataPointer(Data::allocate(0), 0);
} else {
- if (d->ref.isShared() || uint(size) + 1u > d->alloc)
- reallocData(uint(size) + 1u, d->detachFlags() | Data::Grow);
- if (d->alloc) {
- d->size = size;
- d->data()[size] = '\0';
+ if (d->needsDetach() || size > capacity()
+ || (!(d->flags() & Data::CapacityReserved) && size < int(d.size)
+ && size < (capacity() >> 1)))
+ reallocData(uint(size) + 1u, d->detachFlags() | Data::GrowsForward);
+ d.size = size;
+ if (d->isMutable()) {
+ d.data()[size] = '\0';
}
}
}
@@ -1824,33 +1758,27 @@ void QByteArray::resize(int size)
QByteArray &QByteArray::fill(char ch, int size)
{
- resize(size < 0 ? d->size : size);
- if (d->size)
- memset(d->data(), ch, d->size);
+ resize(size < 0 ? this->size() : size);
+ if (this->size())
+ memset(d.data(), ch, this->size());
return *this;
}
-void QByteArray::reallocData(uint alloc, Data::AllocationOptions options)
+void QByteArray::reallocData(uint alloc, Data::ArrayOptions options)
{
- if (d->ref.isShared() || IS_RAW_DATA(d)) {
- Data *x = Data::allocate(alloc, options);
- Q_CHECK_PTR(x);
- x->size = qMin(int(alloc) - 1, d->size);
- ::memcpy(x->data(), d->data(), x->size);
- x->data()[x->size] = '\0';
- if (!d->ref.deref())
- Data::deallocate(d);
- d = x;
+ if (d->needsDetach()) {
+ DataPointer dd(Data::allocate(alloc, options), qMin(int(alloc) - 1, d.size));
+ ::memcpy(dd.data(), d.data(), dd.size);
+ dd.data()[dd.size] = 0;
+ d = dd;
} else {
- Data *x = Data::reallocateUnaligned(d, alloc, options);
- Q_CHECK_PTR(x);
- d = x;
+ d.reallocate(alloc, options);
}
}
void QByteArray::expand(int i)
{
- resize(qMax(i + 1, d->size));
+ resize(qMax(i + 1, size()));
}
/*!
@@ -1896,9 +1824,9 @@ QByteArray QByteArray::nulTerminated() const
QByteArray &QByteArray::prepend(const QByteArray &ba)
{
- if (d->size == 0 && d->ref.isStatic() && !IS_RAW_DATA(ba.d)) {
+ if (size() == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) {
*this = ba;
- } else if (ba.d->size != 0) {
+ } else if (ba.size() != 0) {
QByteArray tmp = *this;
*this = ba;
append(tmp);
@@ -1927,12 +1855,12 @@ QByteArray &QByteArray::prepend(const char *str)
QByteArray &QByteArray::prepend(const char *str, int len)
{
if (str) {
- if (d->ref.isShared() || uint(d->size + len) + 1u > d->alloc)
- reallocData(uint(d->size + len) + 1u, d->detachFlags() | Data::Grow);
- memmove(d->data()+len, d->data(), d->size);
- memcpy(d->data(), str, len);
- d->size += len;
- d->data()[d->size] = '\0';
+ if (d->needsDetach() || size() + len > capacity())
+ reallocData(uint(size() + len) + 1u, d->detachFlags() | Data::GrowsForward);
+ memmove(d.data()+len, d.data(), d.size);
+ memcpy(d.data(), str, len);
+ d.size += len;
+ d.data()[d.size] = '\0';
}
return *this;
}
@@ -1953,12 +1881,12 @@ QByteArray &QByteArray::prepend(const char *str, int len)
QByteArray &QByteArray::prepend(char ch)
{
- if (d->ref.isShared() || uint(d->size) + 2u > d->alloc)
- reallocData(uint(d->size) + 2u, d->detachFlags() | Data::Grow);
- memmove(d->data()+1, d->data(), d->size);
- d->data()[0] = ch;
- ++d->size;
- d->data()[d->size] = '\0';
+ if (d->needsDetach() || size() + 1 > capacity())
+ reallocData(uint(size()) + 2u, d->detachFlags() | Data::GrowsForward);
+ memmove(d.data()+1, d.data(), d.size);
+ d.data()[0] = ch;
+ ++d.size;
+ d.data()[d.size] = '\0';
return *this;
}
@@ -1988,14 +1916,14 @@ QByteArray &QByteArray::prepend(char ch)
QByteArray &QByteArray::append(const QByteArray &ba)
{
- if (d->size == 0 && d->ref.isStatic() && !IS_RAW_DATA(ba.d)) {
+ if (size() == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) {
*this = ba;
- } else if (ba.d->size != 0) {
- if (d->ref.isShared() || uint(d->size + ba.d->size) + 1u > d->alloc)
- reallocData(uint(d->size + ba.d->size) + 1u, d->detachFlags() | Data::Grow);
- memcpy(d->data() + d->size, ba.d->data(), ba.d->size);
- d->size += ba.d->size;
- d->data()[d->size] = '\0';
+ } else if (ba.size() != 0) {
+ if (d->needsDetach() || size() + ba.size() > capacity())
+ reallocData(uint(size() + ba.size()) + 1u, d->detachFlags() | Data::GrowsForward);
+ memcpy(d.data() + d.size, ba.data(), ba.size());
+ d.size += ba.size();
+ d.data()[d.size] = '\0';
}
return *this;
}
@@ -2023,10 +1951,10 @@ QByteArray& QByteArray::append(const char *str)
{
if (str) {
const int len = int(strlen(str));
- if (d->ref.isShared() || uint(d->size + len) + 1u > d->alloc)
- reallocData(uint(d->size + len) + 1u, d->detachFlags() | Data::Grow);
- memcpy(d->data() + d->size, str, len + 1); // include null terminator
- d->size += len;
+ if (d->needsDetach() || size() + len > capacity())
+ reallocData(uint(size() + len) + 1u, d->detachFlags() | Data::GrowsForward);
+ memcpy(d.data() + d.size, str, len + 1); // include null terminator
+ d.size += len;
}
return *this;
}
@@ -2048,11 +1976,11 @@ QByteArray &QByteArray::append(const char *str, int len)
if (len < 0)
len = qstrlen(str);
if (str && len) {
- if (d->ref.isShared() || uint(d->size + len) + 1u > d->alloc)
- reallocData(uint(d->size + len) + 1u, d->detachFlags() | Data::Grow);
- memcpy(d->data() + d->size, str, len); // include null terminator
- d->size += len;
- d->data()[d->size] = '\0';
+ if (d->needsDetach() || size() + len > capacity())
+ reallocData(uint(size() + len) + 1u, d->detachFlags() | Data::GrowsForward);
+ memcpy(d.data() + d.size, str, len);
+ d.size += len;
+ d.data()[d.size] = '\0';
}
return *this;
}
@@ -2076,10 +2004,10 @@ QByteArray &QByteArray::append(const char *str, int len)
QByteArray& QByteArray::append(char ch)
{
- if (d->ref.isShared() || uint(d->size) + 2u > d->alloc)
- reallocData(uint(d->size) + 2u, d->detachFlags() | Data::Grow);
- d->data()[d->size++] = ch;
- d->data()[d->size] = '\0';
+ if (d->needsDetach() || size() + 1 > capacity())
+ reallocData(uint(size()) + 2u, d->detachFlags() | Data::GrowsForward);
+ d.data()[d.size++] = ch;
+ d.data()[d.size] = '\0';
return *this;
}
@@ -2120,7 +2048,7 @@ static inline QByteArray &qbytearray_insert(QByteArray *ba,
QByteArray &QByteArray::insert(int i, const QByteArray &ba)
{
QByteArray copy(ba);
- return qbytearray_insert(this, i, copy.d->data(), copy.d->size);
+ return qbytearray_insert(this, i, copy.constData(), copy.size());
}
/*!
@@ -2202,7 +2130,7 @@ QByteArray &QByteArray::insert(int i, int count, char ch)
int oldsize = size();
resize(qMax(i, oldsize) + count);
- char *dst = d->data();
+ char *dst = d.data();
if (i > oldsize)
::memset(dst + oldsize, 0x20, i - oldsize);
else if (i < oldsize)
@@ -2227,14 +2155,14 @@ QByteArray &QByteArray::insert(int i, int count, char ch)
QByteArray &QByteArray::remove(int pos, int len)
{
- if (len <= 0 || uint(pos) >= uint(d->size))
+ if (len <= 0 || uint(pos) >= uint(size()))
return *this;
detach();
- if (len >= d->size - pos) {
+ if (len >= size() - pos) {
resize(pos);
} else {
- memmove(d->data() + pos, d->data() + pos + len, d->size - pos - len);
- resize(d->size - len);
+ memmove(d.data() + pos, d.data() + pos + len, size() - pos - len);
+ resize(size() - len);
}
return *this;
}
@@ -2251,9 +2179,9 @@ QByteArray &QByteArray::remove(int pos, int len)
QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after)
{
- if (len == after.d->size && (pos + len <= d->size)) {
+ if (len == after.size() && (pos + len <= size())) {
detach();
- memmove(d->data() + pos, after.d->data(), len*sizeof(char));
+ memmove(d.data() + pos, after.data(), len*sizeof(char));
return *this;
} else {
QByteArray copy(after);
@@ -2288,9 +2216,9 @@ QByteArray &QByteArray::replace(int pos, int len, const char *after)
*/
QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen)
{
- if (len == alen && (pos + len <= d->size)) {
+ if (len == alen && (pos + len <= size())) {
detach();
- memcpy(d->data() + pos, after, len*sizeof(char));
+ memcpy(d.data() + pos, after, len*sizeof(char));
return *this;
} else {
remove(pos, len);
@@ -2313,14 +2241,7 @@ QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen)
QByteArray &QByteArray::replace(const QByteArray &before, const QByteArray &after)
{
- if (isNull() || before.d == after.d)
- return *this;
-
- QByteArray aft = after;
- if (after.d == d)
- aft.detach();
-
- return replace(before.constData(), before.size(), aft.constData(), aft.size());
+ return replace(before.constData(), before.size(), after.constData(), after.size());
}
/*!
@@ -2333,11 +2254,7 @@ QByteArray &QByteArray::replace(const QByteArray &before, const QByteArray &afte
QByteArray &QByteArray::replace(const char *c, const QByteArray &after)
{
- QByteArray aft = after;
- if (after.d == d)
- aft.detach();
-
- return replace(c, qstrlen(c), aft.constData(), aft.size());
+ return replace(c, qstrlen(c), after.constData(), after.size());
}
/*!
@@ -2357,13 +2274,13 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
// protect against before or after being part of this
const char *a = after;
const char *b = before;
- if (after >= d->data() && after < d->data() + d->size) {
+ if (after >= constBegin() && after < constEnd()) {
char *copy = (char *)malloc(asize);
Q_CHECK_PTR(copy);
memcpy(copy, after, asize);
a = copy;
}
- if (before >= d->data() && before < d->data() + d->size) {
+ if (before >= constBegin() && before < constEnd()) {
char *copy = (char *)malloc(bsize);
Q_CHECK_PTR(copy);
memcpy(copy, before, bsize);
@@ -2372,13 +2289,13 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
QByteArrayMatcher matcher(before, bsize);
int index = 0;
- int len = d->size;
- char *d = data();
+ int len = size();
+ char *d = data(); // detaches
if (bsize == asize) {
if (bsize) {
while ((index = matcher.indexIn(*this, index)) != -1) {
- memcpy(d + index, after, asize);
+ memcpy(d + index, a, asize);
index += bsize;
}
}
@@ -2397,7 +2314,7 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
to = index;
}
if (asize) {
- memcpy(d + to, after, asize);
+ memcpy(d + to, a, asize);
to += asize;
}
index += bsize;
@@ -2440,7 +2357,7 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
resize(newlen);
len = newlen;
}
- d = this->d->data();
+ d = this->d.data(); // data(), without the detach() check
while(pos) {
pos--;
@@ -2449,7 +2366,7 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
int moveto = insertstart + asize;
memmove(d + moveto, d + movestart, (moveend - movestart));
if (asize)
- memcpy(d + insertstart, after, asize);
+ memcpy(d + insertstart, a, asize);
moveend = movestart - bsize;
}
}
@@ -2512,8 +2429,7 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
QByteArray &QByteArray::replace(char before, const QByteArray &after)
{
char b[2] = { before, '\0' };
- QByteArray cb = fromRawData(b, 1);
- return replace(cb, after);
+ return replace(b, 1, after.constData(), after.size());
}
/*! \fn QByteArray &QByteArray::replace(char before, const QString &after)
@@ -2547,9 +2463,9 @@ QByteArray &QByteArray::replace(char before, const QByteArray &after)
QByteArray &QByteArray::replace(char before, char after)
{
- if (d->size) {
+ if (!isEmpty()) {
char *i = data();
- char *e = i + d->size;
+ char *e = i + size();
for (; i != e; ++i)
if (*i == before)
* i = after;
@@ -2590,7 +2506,7 @@ QList<QByteArray> QByteArray::split(char sep) const
*/
QByteArray QByteArray::repeated(int times) const
{
- if (d->size == 0)
+ if (isEmpty())
return *this;
if (times <= 1) {
@@ -2599,27 +2515,27 @@ QByteArray QByteArray::repeated(int times) const
return QByteArray();
}
- const int resultSize = times * d->size;
+ const int resultSize = times * size();
QByteArray result;
result.reserve(resultSize);
- if (result.d->alloc != uint(resultSize) + 1u)
+ if (result.capacity() != resultSize)
return QByteArray(); // not enough memory
- memcpy(result.d->data(), d->data(), d->size);
+ memcpy(result.d.data(), data(), size());
- int sizeSoFar = d->size;
- char *end = result.d->data() + sizeSoFar;
+ int sizeSoFar = size();
+ char *end = result.d.data() + sizeSoFar;
const int halfResultSize = resultSize >> 1;
while (sizeSoFar <= halfResultSize) {
- memcpy(end, result.d->data(), sizeSoFar);
+ memcpy(end, result.d.data(), sizeSoFar);
end += sizeSoFar;
sizeSoFar <<= 1;
}
- memcpy(end, result.d->data(), resultSize - sizeSoFar);
- result.d->data()[resultSize] = '\0';
- result.d->size = resultSize;
+ memcpy(end, result.d.data(), resultSize - sizeSoFar);
+ result.d.data()[resultSize] = '\0';
+ result.d.size = resultSize;
return result;
}
@@ -2641,17 +2557,17 @@ QByteArray QByteArray::repeated(int times) const
int QByteArray::indexOf(const QByteArray &ba, int from) const
{
- const int ol = ba.d->size;
+ const int ol = ba.size();
if (ol == 0)
return from;
if (ol == 1)
- return indexOf(*ba.d->data(), from);
+ return indexOf(ba[0], from);
- const int l = d->size;
- if (from > d->size || ol + from > l)
+ const int l = size();
+ if (from > l || ol + from > l)
return -1;
- return qFindByteArray(d->data(), d->size, from, ba.d->data(), ol);
+ return qFindByteArray(data(), size(), from, ba.data(), ol);
}
/*! \fn int QByteArray::indexOf(const QString &str, int from) const
@@ -2685,13 +2601,13 @@ int QByteArray::indexOf(const char *c, int from) const
if (ol == 1)
return indexOf(*c, from);
- const int l = d->size;
- if (from > d->size || ol + from > l)
+ const int l = size();
+ if (from > l || ol + from > l)
return -1;
if (ol == 0)
return from;
- return qFindByteArray(d->data(), d->size, from, c, ol);
+ return qFindByteArray(data(), size(), from, c, ol);
}
/*!
@@ -2710,13 +2626,13 @@ int QByteArray::indexOf(const char *c, int from) const
int QByteArray::indexOf(char ch, int from) const
{
if (from < 0)
- from = qMax(from + d->size, 0);
- if (from < d->size) {
- const char *n = d->data() + from - 1;
- const char *e = d->data() + d->size;
+ from = qMax(from + size(), 0);
+ if (from < size()) {
+ const char *n = data() + from - 1;
+ const char *e = end();
while (++n != e)
if (*n == ch)
- return n - d->data();
+ return n - data();
}
return -1;
}
@@ -2771,11 +2687,11 @@ static int lastIndexOfHelper(const char *haystack, int l, const char *needle, in
int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
{
- const int ol = ba.d->size;
+ const int ol = ba.size();
if (ol == 1)
- return lastIndexOf(*ba.d->data(), from);
+ return lastIndexOf(ba[0], from);
- return lastIndexOfHelper(d->data(), d->size, ba.d->data(), ol, from);
+ return lastIndexOfHelper(data(), size(), ba.data(), ol, from);
}
/*! \fn int QByteArray::lastIndexOf(const QString &str, int from) const
@@ -2810,7 +2726,7 @@ int QByteArray::lastIndexOf(const char *str, int from) const
if (ol == 1)
return lastIndexOf(*str, from);
- return lastIndexOfHelper(d->data(), d->size, str, ol, from);
+ return lastIndexOfHelper(data(), size(), str, ol, from);
}
/*!
@@ -2830,12 +2746,12 @@ int QByteArray::lastIndexOf(const char *str, int from) const
int QByteArray::lastIndexOf(char ch, int from) const
{
if (from < 0)
- from += d->size;
- else if (from > d->size)
- from = d->size-1;
+ from += size();
+ else if (from > size())
+ from = size()-1;
if (from >= 0) {
- const char *b = d->data();
- const char *n = d->data() + from + 1;
+ const char *b = data();
+ const char *n = b + from + 1;
while (n-- != b)
if (*n == ch)
return n - b;
@@ -2854,7 +2770,7 @@ int QByteArray::count(const QByteArray &ba) const
{
int num = 0;
int i = -1;
- if (d->size > 500 && ba.d->size > 5) {
+ if (size() > 500 && ba.size() > 5) {
QByteArrayMatcher matcher(ba);
while ((i = matcher.indexIn(*this, i + 1)) != -1)
++num;
@@ -2889,8 +2805,8 @@ int QByteArray::count(const char *str) const
int QByteArray::count(char ch) const
{
int num = 0;
- const char *i = d->data() + d->size;
- const char *b = d->data();
+ const char *i = end();
+ const char *b = begin();
while (i != b)
if (*--i == ch)
++num;
@@ -2940,11 +2856,11 @@ int QByteArray::count(char ch) const
*/
bool QByteArray::startsWith(const QByteArray &ba) const
{
- if (d == ba.d || ba.d->size == 0)
- return true;
- if (d->size < ba.d->size)
+ if (size() < ba.size())
return false;
- return memcmp(d->data(), ba.d->data(), ba.d->size) == 0;
+ if (data() == ba.data() || ba.size() == 0)
+ return true;
+ return memcmp(data(), ba.data(), ba.size()) == 0;
}
/*! \overload
@@ -2957,9 +2873,9 @@ bool QByteArray::startsWith(const char *str) const
if (!str || !*str)
return true;
const int len = int(strlen(str));
- if (d->size < len)
+ if (size() < len)
return false;
- return qstrncmp(d->data(), str, len) == 0;
+ return qstrncmp(data(), str, len) == 0;
}
/*! \overload
@@ -2969,9 +2885,9 @@ bool QByteArray::startsWith(const char *str) const
*/
bool QByteArray::startsWith(char ch) const
{
- if (d->size == 0)
+ if (size() == 0)
return false;
- return d->data()[0] == ch;
+ return data()[0] == ch;
}
/*!
@@ -2985,11 +2901,11 @@ bool QByteArray::startsWith(char ch) const
*/
bool QByteArray::endsWith(const QByteArray &ba) const
{
- if (d == ba.d || ba.d->size == 0)
- return true;
- if (d->size < ba.d->size)
+ if (size() < ba.size())
return false;
- return memcmp(d->data() + d->size - ba.d->size, ba.d->data(), ba.d->size) == 0;
+ if (end() == ba.end() || ba.size() == 0)
+ return true;
+ return memcmp(end() - ba.size(), ba.data(), ba.size()) == 0;
}
/*! \overload
@@ -3002,9 +2918,9 @@ bool QByteArray::endsWith(const char *str) const
if (!str || !*str)
return true;
const int len = int(strlen(str));
- if (d->size < len)
+ if (size() < len)
return false;
- return qstrncmp(d->data() + d->size - len, str, len) == 0;
+ return qstrncmp(end() - len, str, len) == 0;
}
/*
@@ -3086,9 +3002,9 @@ bool QByteArray::isLower() const
*/
bool QByteArray::endsWith(char ch) const
{
- if (d->size == 0)
+ if (size() == 0)
return false;
- return d->data()[d->size - 1] == ch;
+ return data()[size() - 1] == ch;
}
/*!
@@ -3106,11 +3022,11 @@ bool QByteArray::endsWith(char ch) const
QByteArray QByteArray::left(int len) const
{
- if (len >= d->size)
+ if (len >= size())
return *this;
if (len < 0)
len = 0;
- return QByteArray(d->data(), len);
+ return QByteArray(data(), len);
}
/*!
@@ -3128,11 +3044,11 @@ QByteArray QByteArray::left(int len) const
QByteArray QByteArray::right(int len) const
{
- if (len >= d->size)
+ if (len >= size())
return *this;
if (len < 0)
len = 0;
- return QByteArray(d->data() + d->size - len, len);
+ return QByteArray(end() - len, len);
}
/*!
@@ -3157,13 +3073,14 @@ QByteArray QByteArray::mid(int pos, int len) const
return QByteArray();
case QContainerImplHelper::Empty:
{
- QByteArrayDataPtr empty = { Data::allocate(0) };
+ auto alloc = Data::allocate(0);
+ QByteArray::DataPointer empty = { alloc.first, alloc.second, 0 };
return QByteArray(empty);
}
case QContainerImplHelper::Full:
return *this;
case QContainerImplHelper::Subset:
- return QByteArray(d->data() + pos, len);
+ return QByteArray(d.data() + pos, len);
}
Q_UNREACHABLE();
return QByteArray();
@@ -3266,9 +3183,7 @@ QByteArray QByteArray::toUpper_helper(QByteArray &a)
void QByteArray::clear()
{
- if (!d->ref.deref())
- Data::deallocate(d);
- d = Data::sharedNull();
+ d.clear();
}
#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
@@ -3745,13 +3660,13 @@ QByteArray QByteArray::trimmed_helper(QByteArray &a)
QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const
{
QByteArray result;
- int len = d->size;
+ int len = size();
int padlen = width - len;
if (padlen > 0) {
result.resize(len+padlen);
if (len)
- memcpy(result.d->data(), d->data(), len);
- memset(result.d->data()+len, fill, padlen);
+ memcpy(result.d.data(), data(), len);
+ memset(result.d.data()+len, fill, padlen);
} else {
if (truncate)
result = left(width);
@@ -3782,13 +3697,13 @@ QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const
QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const
{
QByteArray result;
- int len = d->size;
+ int len = size();
int padlen = width - len;
if (padlen > 0) {
result.resize(len+padlen);
if (len)
- memcpy(result.d->data()+padlen, data(), len);
- memset(result.d->data(), fill, padlen);
+ memcpy(result.d.data()+padlen, data(), len);
+ memset(result.d.data(), fill, padlen);
} else {
if (truncate)
result = left(width);
@@ -3798,7 +3713,10 @@ QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const
return result;
}
-bool QByteArray::isNull() const { return d == QArrayData::sharedNull(); }
+bool QByteArray::isNull() const
+{
+ return d->isNull();
+}
static qlonglong toIntegral_helper(const char *data, bool *ok, int base, qlonglong)
{
@@ -4105,26 +4023,11 @@ float QByteArray::toFloat(bool *ok) const
}
/*!
- Returns a copy of the byte array, encoded as Base64.
-
- \snippet code/src_corelib_tools_qbytearray.cpp 39
-
- The algorithm used to encode Base64-encoded data is defined in \l{RFC 4648}.
-
- \sa fromBase64()
-*/
-QByteArray QByteArray::toBase64() const
-{
- return toBase64(Base64Encoding);
-}
-
-/*!
\since 5.2
- \overload
Returns a copy of the byte array, encoded using the options \a options.
- \snippet code/src_corelib_tools_qbytearray.cpp 39bis
+ \snippet code/src_corelib_tools_qbytearray.cpp 39
The algorithm used to encode Base64-encoded data is defined in \l{RFC 4648}.
@@ -4140,19 +4043,19 @@ QByteArray QByteArray::toBase64(Base64Options options) const
const char padchar = '=';
int padlen = 0;
- QByteArray tmp((d->size + 2) / 3 * 4, Qt::Uninitialized);
+ QByteArray tmp((size() + 2) / 3 * 4, Qt::Uninitialized);
int i = 0;
char *out = tmp.data();
- while (i < d->size) {
+ while (i < size()) {
// encode 3 bytes at a time
int chunk = 0;
- chunk |= int(uchar(d->data()[i++])) << 16;
- if (i == d->size) {
+ chunk |= int(uchar(data()[i++])) << 16;
+ if (i == size()) {
padlen = 2;
} else {
- chunk |= int(uchar(d->data()[i++])) << 8;
- if (i == d->size)
+ chunk |= int(uchar(data()[i++])) << 8;
+ if (i == size())
padlen = 1;
else
chunk |= int(uchar(data()[i++]));
@@ -4482,17 +4385,14 @@ QByteArray QByteArray::number(double n, char f, int prec)
QByteArray QByteArray::fromRawData(const char *data, int size)
{
- Data *x;
+ QByteArray::DataPointer x;
if (!data) {
- x = Data::sharedNull();
} else if (!size) {
- x = Data::allocate(0);
+ x = DataPointer(Data::allocate(0), 0);
} else {
x = Data::fromRawData(data, size);
- Q_CHECK_PTR(x);
}
- QByteArrayDataPtr dataPtr = { x };
- return QByteArray(dataPtr);
+ return QByteArray(x);
}
/*!
@@ -4511,17 +4411,15 @@ QByteArray QByteArray::fromRawData(const char *data, int size)
*/
QByteArray &QByteArray::setRawData(const char *data, uint size)
{
- if (d->ref.isShared() || d->alloc) {
- *this = fromRawData(data, size);
- } else {
- if (data) {
- d->size = size;
- d->offset = data - reinterpret_cast<char *>(d);
- } else {
- d->offset = sizeof(QByteArrayData);
- d->size = 0;
- }
+ if (!data || !size) {
+ clear();
}
+// else if (d->isShared() || (d->flags() & Data::RawDataType) == 0) {
+ *this = fromRawData(data, size);
+// } else {
+// d.size = size;
+// d.data() = const_cast<char *>(data);
+// }
return *this;
}
@@ -4657,32 +4555,7 @@ QByteArray::FromBase64Result QByteArray::fromBase64Encoding(const QByteArray &ba
}
/*!
- \overload
-
- Returns a decoded copy of the Base64 array \a base64. Input is not checked
- for validity; invalid characters in the input are skipped, enabling the
- decoding process to continue with subsequent characters.
-
- For example:
-
- \snippet code/src_corelib_tools_qbytearray.cpp 44
-
- The algorithm used to decode Base64-encoded data is defined in \l{RFC 4648}.
-
- \note The fromBase64Encoding() function is recommended in new code.
-
- \sa toBase64(), fromBase64Encoding()
-*/
-QByteArray QByteArray::fromBase64(const QByteArray &base64)
-{
- if (auto result = fromBase64Encoding(base64, Base64Encoding))
- return std::move(result.decoded);
- return QByteArray();
-}
-
-/*!
\since 5.2
- \overload
Returns a decoded copy of the Base64 array \a base64, using the options
defined by \a options. If \a options contains \c{IgnoreBase64DecodingErrors}
@@ -4694,7 +4567,7 @@ QByteArray QByteArray::fromBase64(const QByteArray &base64)
For example:
- \snippet code/src_corelib_tools_qbytearray.cpp 44bis
+ \snippet code/src_corelib_tools_qbytearray.cpp 44
The algorithm used to decode Base64-encoded data is defined in \l{RFC 4648}.
@@ -4748,21 +4621,7 @@ QByteArray QByteArray::fromHex(const QByteArray &hexEncoded)
return res;
}
-/*!
- Returns a hex encoded copy of the byte array. The hex encoding uses the numbers 0-9 and
- the letters a-f.
-
- \sa fromHex()
-*/
-QByteArray QByteArray::toHex() const
-{
- return toHex('\0');
-}
-
-/*! \overload
- \since 5.9
-
- Returns a hex encoded copy of the byte array. The hex encoding uses the numbers 0-9 and
+/*! Returns a hex encoded copy of the byte array. The hex encoding uses the numbers 0-9 and
the letters a-f.
If \a separator is not '\0', the separator character is inserted between the hex bytes.
@@ -4770,18 +4629,19 @@ QByteArray QByteArray::toHex() const
Example:
\snippet code/src_corelib_tools_qbytearray.cpp 50
+ \since 5.9
\sa fromHex()
*/
QByteArray QByteArray::toHex(char separator) const
{
- if (!d->size)
+ if (isEmpty())
return QByteArray();
- const int length = separator ? (d->size * 3 - 1) : (d->size * 2);
+ const int length = separator ? (size() * 3 - 1) : (size() * 2);
QByteArray hex(length, Qt::Uninitialized);
char *hexData = hex.data();
- const uchar *data = (const uchar *)d->data();
- for (int i = 0, o = 0; i < d->size; ++i) {
+ const uchar *data = (const uchar *)this->data();
+ for (int i = 0, o = 0; i < size(); ++i) {
hexData[o++] = QtMiscUtils::toHexLower(data[i] >> 4);
hexData[o++] = QtMiscUtils::toHexLower(data[i] & 0xf);
@@ -5093,42 +4953,6 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA
\sa QStringLiteral
*/
-namespace QtPrivate {
-namespace DeprecatedRefClassBehavior {
-void warn(WarningType w, EmittingClass c)
-{
- static const char deprecatedBehaviorString[] =
- "The corresponding behavior is deprecated, and will be changed"
- " in a future version of Qt.";
-
- const char *emittingClassName = nullptr;
- const char *containerClassName = nullptr;
-
- switch (c) {
- case EmittingClass::QByteRef:
- emittingClassName = "QByteRef";
- containerClassName = "QByteArray";
- break;
- case EmittingClass::QCharRef:
- emittingClassName = "QCharRef";
- containerClassName = "QString";
- break;
- }
-
- switch (w) {
- case WarningType::OutOfRange:
- qWarning("Using %s with an index pointing outside the valid range of a %s. %s",
- emittingClassName, containerClassName, deprecatedBehaviorString);
- break;
- case WarningType::DelayedDetach:
- qWarning("Using %s with on a %s that is not already detached. %s",
- emittingClassName, containerClassName, deprecatedBehaviorString);
- break;
- }
-}
-} // namespace DeprecatedRefClassBehavior
-} // namespace QtPrivate
-
/*!
\class QByteArray::FromBase64Result
\inmodule QtCore
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index 36cf580cd9..e3fec1e62c 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -44,6 +44,8 @@
#include <QtCore/qrefcount.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qarraydata.h>
+#include <QtCore/qarraydatapointer.h>
+#include <QtCore/qcontainerfwd.h>
#include <stdlib.h>
#include <string.h>
@@ -106,48 +108,23 @@ Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap);
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...);
// qChecksum: Internet checksum
-Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len); // ### Qt 6: Remove
-Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len, Qt::ChecksumType standard); // ### Qt 6: Use Qt::ChecksumType standard = Qt::ChecksumIso3309
+Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len,
+ Qt::ChecksumType standard = Qt::ChecksumIso3309);
-class QByteRef;
class QString;
class QDataStream;
-template <typename T> class QList;
-typedef QArrayData QByteArrayData;
-
-template<int N> struct QStaticByteArrayData
-{
- QByteArrayData ba;
- char data[N + 1];
-
- QByteArrayData *data_ptr() const
- {
- Q_ASSERT(ba.ref.isStatic());
- return const_cast<QByteArrayData *>(&ba);
- }
-};
-
-struct QByteArrayDataPtr
-{
- QByteArrayData *ptr;
-};
-
-#define Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
- Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset)
- /**/
-
-#define Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER(size) \
- Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, sizeof(QByteArrayData)) \
- /**/
+using QByteArrayData = QArrayDataPointer<char>;
# define QByteArrayLiteral(str) \
([]() -> QByteArray { \
enum { Size = sizeof(str) - 1 }; \
- static const QStaticByteArrayData<Size> qbytearray_literal = { \
- Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER(Size), \
- str }; \
- QByteArrayDataPtr holder = { qbytearray_literal.data_ptr() }; \
+ static const QArrayData qbytearray_literal = { \
+ Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }; \
+ QByteArrayData holder = { \
+ static_cast<QTypedArrayData<char> *>(const_cast<QArrayData *>(&qbytearray_literal)), \
+ const_cast<char *>(str), \
+ Size }; \
const QByteArray ba(holder); \
return ba; \
}()) \
@@ -155,10 +132,14 @@ struct QByteArrayDataPtr
class Q_CORE_EXPORT QByteArray
{
+public:
+ using DataPointer = QByteArrayData;
private:
typedef QTypedArrayData<char> Data;
+ DataPointer d;
public:
+
enum Base64Option {
Base64Encoding = 0,
Base64UrlEncoding = 1,
@@ -187,14 +168,13 @@ public:
QByteArray &operator=(const QByteArray &) noexcept;
QByteArray &operator=(const char *str);
- inline QByteArray(QByteArray && other) noexcept : d(other.d) { other.d = Data::sharedNull(); }
+ inline QByteArray(QByteArray && other) noexcept
+ { qSwap(d, other.d); }
inline QByteArray &operator=(QByteArray &&other) noexcept
{ qSwap(d, other.d); return *this; }
-
inline void swap(QByteArray &other) noexcept
{ qSwap(d, other.d); }
- inline int size() const;
inline bool isEmpty() const;
void resize(int size);
@@ -213,18 +193,17 @@ public:
inline const char *constData() const;
inline void detach();
inline bool isDetached() const;
- inline bool isSharedWith(const QByteArray &other) const { return d == other.d; }
+ inline bool isSharedWith(const QByteArray &other) const
+ { return data() == other.data() && size() == other.size(); }
void clear();
inline char at(int i) const;
inline char operator[](int i) const;
- inline char operator[](uint i) const;
- Q_REQUIRED_RESULT inline QByteRef operator[](int i);
- Q_REQUIRED_RESULT inline QByteRef operator[](uint i);
+ Q_REQUIRED_RESULT inline char &operator[](int i);
Q_REQUIRED_RESULT char front() const { return at(0); }
- Q_REQUIRED_RESULT inline QByteRef front();
+ Q_REQUIRED_RESULT inline char &front();
Q_REQUIRED_RESULT char back() const { return at(size() - 1); }
- Q_REQUIRED_RESULT inline QByteRef back();
+ Q_REQUIRED_RESULT inline char &back();
int indexOf(char c, int from = 0) const;
int indexOf(const char *c, int from = 0) const;
@@ -365,10 +344,8 @@ public:
qulonglong toULongLong(bool *ok = nullptr, int base = 10) const;
float toFloat(bool *ok = nullptr) const;
double toDouble(bool *ok = nullptr) const;
- QByteArray toBase64(Base64Options options) const;
- QByteArray toBase64() const; // ### Qt6 merge with previous
- QByteArray toHex() const;
- QByteArray toHex(char separator) const; // ### Qt6 merge with previous
+ QByteArray toBase64(Base64Options options = Base64Encoding) const;
+ QByteArray toHex(char separator = '\0') const;
QByteArray toPercentEncoding(const QByteArray &exclude = QByteArray(),
const QByteArray &include = QByteArray(),
char percent = '%') const;
@@ -393,8 +370,7 @@ public:
class FromBase64Result;
Q_REQUIRED_RESULT static FromBase64Result fromBase64Encoding(QByteArray &&base64, Base64Options options = Base64Encoding);
Q_REQUIRED_RESULT static FromBase64Result fromBase64Encoding(const QByteArray &base64, Base64Options options = Base64Encoding);
- Q_REQUIRED_RESULT static QByteArray fromBase64(const QByteArray &base64, Base64Options options);
- Q_REQUIRED_RESULT static QByteArray fromBase64(const QByteArray &base64); // ### Qt6 merge with previous
+ Q_REQUIRED_RESULT static QByteArray fromBase64(const QByteArray &base64, Base64Options options = Base64Encoding);
Q_REQUIRED_RESULT static QByteArray fromHex(const QByteArray &hexEncoded);
Q_REQUIRED_RESULT static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%');
@@ -449,19 +425,20 @@ public:
static inline QByteArray fromStdString(const std::string &s);
inline std::string toStdString() const;
- inline int count() const { return d->size; }
- int length() const { return d->size; }
+ inline int size() const { return d->size; }
+ inline int count() const { return size(); }
+ inline int length() const { return size(); }
bool isNull() const;
- inline QByteArray(QByteArrayDataPtr dd)
- : d(static_cast<Data *>(dd.ptr))
+ inline DataPointer &data_ptr() { return d; }
+ explicit inline QByteArray(const DataPointer &dd)
+ : d(dd)
{
}
private:
operator QNoImplicitBoolCast() const;
- Data *d;
- void reallocData(uint alloc, Data::AllocationOptions options);
+ void reallocData(uint alloc, Data::ArrayOptions options);
void expand(int i);
QByteArray nulTerminated() const;
@@ -474,171 +451,86 @@ private:
static QByteArray simplified_helper(const QByteArray &a);
static QByteArray simplified_helper(QByteArray &a);
- friend class QByteRef;
friend class QString;
friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, int nbytes);
-public:
- typedef Data * DataPtr;
- inline DataPtr &data_ptr() { return d; }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QByteArray::Base64Options)
-inline QByteArray::QByteArray() noexcept : d(Data::sharedNull()) { }
-inline QByteArray::~QByteArray() { if (!d->ref.deref()) Data::deallocate(d); }
-inline int QByteArray::size() const
-{ return d->size; }
+inline QByteArray::QByteArray() noexcept {}
+inline QByteArray::~QByteArray() {}
inline char QByteArray::at(int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d.data()[i]; }
inline char QByteArray::operator[](int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; }
-inline char QByteArray::operator[](uint i) const
-{ Q_ASSERT(i < uint(size())); return d->data()[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d.data()[i]; }
inline bool QByteArray::isEmpty() const
-{ return d->size == 0; }
+{ return size() == 0; }
#ifndef QT_NO_CAST_FROM_BYTEARRAY
inline QByteArray::operator const char *() const
-{ return d->data(); }
+{ return data(); }
inline QByteArray::operator const void *() const
-{ return d->data(); }
+{ return data(); }
#endif
inline char *QByteArray::data()
-{ detach(); return d->data(); }
+{ detach(); return d.data(); }
inline const char *QByteArray::data() const
-{ return d->data(); }
+{ return d.data(); }
inline const char *QByteArray::constData() const
-{ return d->data(); }
+{ return d.data(); }
inline void QByteArray::detach()
-{ if (d->ref.isShared() || (d->offset != sizeof(QByteArrayData))) reallocData(uint(d->size) + 1u, d->detachFlags()); }
+{ if (d->needsDetach()) reallocData(uint(size()) + 1u, d->detachFlags()); }
inline bool QByteArray::isDetached() const
-{ return !d->ref.isShared(); }
+{ return !d->isShared(); }
inline QByteArray::QByteArray(const QByteArray &a) noexcept : d(a.d)
-{ d->ref.ref(); }
+{}
inline int QByteArray::capacity() const
-{ return d->alloc ? d->alloc - 1 : 0; }
+{ const auto realCapacity = d->constAllocatedCapacity(); return realCapacity ? int(realCapacity) - 1 : 0; }
inline void QByteArray::reserve(int asize)
{
- if (d->ref.isShared() || uint(asize) + 1u > d->alloc) {
+ if (d->needsDetach() || asize > capacity()) {
reallocData(qMax(uint(size()), uint(asize)) + 1u, d->detachFlags() | Data::CapacityReserved);
} else {
- // cannot set unconditionally, since d could be the shared_null or
- // otherwise static
- d->capacityReserved = true;
+ d->flags() |= Data::CapacityReserved;
}
}
inline void QByteArray::squeeze()
{
- if (d->ref.isShared() || uint(d->size) + 1u < d->alloc) {
- reallocData(uint(d->size) + 1u, d->detachFlags() & ~Data::CapacityReserved);
+ if ((d->flags() & Data::CapacityReserved) == 0)
+ return;
+ if (d->needsDetach() || size() < capacity()) {
+ reallocData(uint(size()) + 1u, d->detachFlags() & ~Data::CapacityReserved);
} else {
- // cannot set unconditionally, since d could be shared_null or
- // otherwise static.
- d->capacityReserved = false;
+ d->flags() &= uint(~Data::CapacityReserved);
}
}
-namespace QtPrivate {
-namespace DeprecatedRefClassBehavior {
- enum class EmittingClass {
- QByteRef,
- QCharRef,
- };
-
- enum class WarningType {
- OutOfRange,
- DelayedDetach,
- };
-
- Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void warn(WarningType w, EmittingClass c);
-} // namespace DeprecatedAssignmentOperatorBehavior
-} // namespace QtPrivate
-
-class
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-Q_CORE_EXPORT
-#endif
-QByteRef { // ### Qt 7: remove
- QByteArray &a;
- int i;
- inline QByteRef(QByteArray &array, int idx)
- : a(array),i(idx) {}
- friend class QByteArray;
-public:
- inline operator char() const
- {
- using namespace QtPrivate::DeprecatedRefClassBehavior;
- if (Q_LIKELY(i < a.d->size))
- return a.d->data()[i];
-#ifdef QT_DEBUG
- warn(WarningType::OutOfRange, EmittingClass::QByteRef);
-#endif
- return char(0);
- }
- inline QByteRef &operator=(char c)
- {
- using namespace QtPrivate::DeprecatedRefClassBehavior;
- if (Q_UNLIKELY(i >= a.d->size)) {
-#ifdef QT_DEBUG
- warn(WarningType::OutOfRange, EmittingClass::QByteRef);
-#endif
- a.expand(i);
- } else {
-#ifdef QT_DEBUG
- if (Q_UNLIKELY(!a.isDetached()))
- warn(WarningType::DelayedDetach, EmittingClass::QByteRef);
-#endif
- a.detach();
- }
- a.d->data()[i] = c;
- return *this;
- }
- inline QByteRef &operator=(const QByteRef &c)
- {
- return operator=(char(c));
- }
- inline bool operator==(char c) const
- { return a.d->data()[i] == c; }
- inline bool operator!=(char c) const
- { return a.d->data()[i] != c; }
- inline bool operator>(char c) const
- { return a.d->data()[i] > c; }
- inline bool operator>=(char c) const
- { return a.d->data()[i] >= c; }
- inline bool operator<(char c) const
- { return a.d->data()[i] < c; }
- inline bool operator<=(char c) const
- { return a.d->data()[i] <= c; }
-};
-
-inline QByteRef QByteArray::operator[](int i)
-{ Q_ASSERT(i >= 0); detach(); return QByteRef(*this, i); }
-inline QByteRef QByteArray::operator[](uint i)
-{ detach(); return QByteRef(*this, i); }
-inline QByteRef QByteArray::front() { return operator[](0); }
-inline QByteRef QByteArray::back() { return operator[](size() - 1); }
+inline char &QByteArray::operator[](int i)
+{ Q_ASSERT(i >= 0 && i < size()); return data()[i]; }
+inline char &QByteArray::front() { return operator[](0); }
+inline char &QByteArray::back() { return operator[](size() - 1); }
inline QByteArray::iterator QByteArray::begin()
-{ detach(); return d->data(); }
+{ return data(); }
inline QByteArray::const_iterator QByteArray::begin() const
-{ return d->data(); }
+{ return data(); }
inline QByteArray::const_iterator QByteArray::cbegin() const
-{ return d->data(); }
+{ return data(); }
inline QByteArray::const_iterator QByteArray::constBegin() const
-{ return d->data(); }
+{ return data(); }
inline QByteArray::iterator QByteArray::end()
-{ detach(); return d->data() + d->size; }
+{ return data() + size(); }
inline QByteArray::const_iterator QByteArray::end() const
-{ return d->data() + d->size; }
+{ return data() + size(); }
inline QByteArray::const_iterator QByteArray::cend() const
-{ return d->data() + d->size; }
+{ return data() + size(); }
inline QByteArray::const_iterator QByteArray::constEnd() const
-{ return d->data() + d->size; }
+{ return data() + size(); }
inline QByteArray &QByteArray::append(int n, char ch)
-{ return insert(d->size, n, ch); }
+{ return insert(size(), n, ch); }
inline QByteArray &QByteArray::prepend(int n, char ch)
{ return insert(0, n, ch); }
inline QByteArray &QByteArray::operator+=(char c)
diff --git a/src/corelib/text/qbytearray_p.h b/src/corelib/text/qbytearray_p.h
index 3c6257f786..d6a5e277b3 100644
--- a/src/corelib/text/qbytearray_p.h
+++ b/src/corelib/text/qbytearray_p.h
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
enum {
// Define as enum to force inlining. Don't expose MaxAllocSize in a public header.
- MaxByteArraySize = MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPtr>::type)
+ MaxByteArraySize = MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPointer>::type)
};
QT_END_NAMESPACE
diff --git a/src/corelib/text/qbytearraylist.h b/src/corelib/text/qbytearraylist.h
index 0250b649b8..d02fa6d20f 100644
--- a/src/corelib/text/qbytearraylist.h
+++ b/src/corelib/text/qbytearraylist.h
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include <QtCore/qlist.h>
+#include <QtCore/qvector.h>
#ifndef QBYTEARRAYLIST_H
#define QBYTEARRAYLIST_H
@@ -49,12 +49,12 @@
QT_BEGIN_NAMESPACE
#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
-typedef QListIterator<QByteArray> QByteArrayListIterator;
-typedef QMutableListIterator<QByteArray> QMutableByteArrayListIterator;
+typedef QVectorIterator<QByteArray> QByteArrayListIterator;
+typedef QMutableVectorIterator<QByteArray> QMutableByteArrayListIterator;
#endif
#ifndef Q_CLANG_QDOC
-typedef QList<QByteArray> QByteArrayList;
+typedef QVector<QByteArray> QByteArrayList;
namespace QtPrivate {
QByteArray Q_CORE_EXPORT QByteArrayList_join(const QByteArrayList *that, const char *separator, int separatorLength);
@@ -63,14 +63,14 @@ namespace QtPrivate {
#endif
#ifdef Q_CLANG_QDOC
-class QByteArrayList : public QList<QByteArray>
+class QByteArrayList : public QVector<QByteArray>
#else
-template <> struct QListSpecialMethods<QByteArray>
+template <> struct QVectorSpecialMethods<QByteArray>
#endif
{
#ifndef Q_CLANG_QDOC
protected:
- ~QListSpecialMethods() = default;
+ ~QVectorSpecialMethods() = default;
#endif
public:
inline QByteArray join() const
@@ -80,11 +80,8 @@ public:
inline QByteArray join(char sep) const
{ return QtPrivate::QByteArrayList_join(self(), &sep, 1); }
- inline int indexOf(const char *needle, int from = 0) const
- { return QtPrivate::QByteArrayList_indexOf(self(), needle, from); }
-
private:
- typedef QList<QByteArray> Self;
+ typedef QVector<QByteArray> Self;
Self *self() { return static_cast<Self *>(this); }
const Self *self() const { return static_cast<const Self *>(this); }
};
diff --git a/src/corelib/text/qbytearraymatcher.h b/src/corelib/text/qbytearraymatcher.h
index 0eedfc1d20..7cc5037095 100644
--- a/src/corelib/text/qbytearraymatcher.h
+++ b/src/corelib/text/qbytearraymatcher.h
@@ -85,7 +85,7 @@ private:
class QStaticByteArrayMatcherBase
{
- Q_DECL_ALIGN(16)
+ alignas(16)
struct Skiptable {
uchar data[256];
} m_skiptable;
diff --git a/src/corelib/text/qchar.h b/src/corelib/text/qchar.h
index a3d5d7a65e..9d0741af8b 100644
--- a/src/corelib/text/qchar.h
+++ b/src/corelib/text/qchar.h
@@ -439,7 +439,6 @@ public:
Unicode_12_0,
Unicode_12_1
};
- // ****** WHEN ADDING FUNCTIONS, CONSIDER ADDING TO QCharRef TOO
inline Category category() const noexcept { return QChar::category(ucs); }
inline Direction direction() const noexcept { return QChar::direction(ucs); }
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 720c3e98c7..877f5df462 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -100,7 +100,7 @@
#define ULLONG_MAX quint64_C(18446744073709551615)
#endif
-#define IS_RAW_DATA(d) ((d)->offset != sizeof(QStringData))
+#define IS_RAW_DATA(d) ((d.d)->flags & QArrayData::RawDataType)
QT_BEGIN_NAMESPACE
@@ -163,7 +163,7 @@ qsizetype QtPrivate::qustrlen(const ushort *str) noexcept
{
qsizetype result = 0;
-#ifdef __SSE2__
+#if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || QT_HAS_FEATURE(address_sanitizer))
// find the 16-byte alignment immediately prior or equal to str
quintptr misalignment = quintptr(str) & 0xf;
Q_ASSERT((misalignment & 1) == 0);
@@ -1377,28 +1377,6 @@ const QString::Null QString::null = { };
*/
/*!
- \class QCharRef
- \inmodule QtCore
- \reentrant
- \brief The QCharRef class is a helper class for QString.
-
- \internal
-
- \ingroup string-processing
-
- When you get an object of type QCharRef, if you can assign to it,
- the assignment will apply to the character in the string from
- which you got the reference. That is its whole purpose in life.
- The QCharRef becomes invalid once modifications are made to the
- string: if you want to keep the character, copy it into a QChar.
-
- Most of the QChar member functions also exist in QCharRef.
- However, they are not explicitly documented here.
-
- \sa QString::operator[](), QString::at(), QChar
-*/
-
-/*!
\class QString
\inmodule QtCore
\reentrant
@@ -2117,8 +2095,8 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
*/
QString::QString(const QChar *unicode, int size)
{
- if (!unicode) {
- d = Data::sharedNull();
+ if (!unicode) {
+ d.clear();
} else {
if (size < 0) {
size = 0;
@@ -2126,13 +2104,11 @@ QString::QString(const QChar *unicode, int size)
++size;
}
if (!size) {
- d = Data::allocate(0);
+ d = DataPointer(Data::allocate(0), 0);
} else {
- d = Data::allocate(size + 1);
- Q_CHECK_PTR(d);
- d->size = size;
- memcpy(d->data(), unicode, size * sizeof(QChar));
- d->data()[size] = '\0';
+ d = DataPointer(Data::allocate(size + 1), size);
+ memcpy(d.data(), unicode, size * sizeof(QChar));
+ d.data()[size] = '\0';
}
}
}
@@ -2145,15 +2121,13 @@ QString::QString(const QChar *unicode, int size)
*/
QString::QString(int size, QChar ch)
{
- if (size <= 0) {
- d = Data::allocate(0);
+ if (size <= 0) {
+ d = DataPointer(Data::allocate(0), 0);
} else {
- d = Data::allocate(size + 1);
- Q_CHECK_PTR(d);
- d->size = size;
- d->data()[size] = '\0';
- ushort *i = d->data() + size;
- ushort *b = d->data();
+ d = DataPointer(Data::allocate(size + 1), size);
+ d.data()[size] = '\0';
+ ushort *i = d.data() + size;
+ ushort *b = d.data();
const ushort value = ch.unicode();
while (i != b)
*--i = value;
@@ -2168,10 +2142,8 @@ QString::QString(int size, QChar ch)
*/
QString::QString(int size, Qt::Initialization)
{
- d = Data::allocate(size + 1);
- Q_CHECK_PTR(d);
- d->size = size;
- d->data()[size] = '\0';
+ d = DataPointer(Data::allocate(size + 1), size);
+ d.data()[size] = '\0';
}
/*! \fn QString::QString(QLatin1String str)
@@ -2186,11 +2158,9 @@ QString::QString(int size, Qt::Initialization)
*/
QString::QString(QChar ch)
{
- d = Data::allocate(2);
- Q_CHECK_PTR(d);
- d->size = 1;
- d->data()[0] = ch.unicode();
- d->data()[1] = '\0';
+ d = DataPointer(Data::allocate(2), 1);
+ d.data()[0] = ch.unicode();
+ d.data()[1] = '\0';
}
/*! \fn QString::QString(const QByteArray &ba)
@@ -2212,7 +2182,7 @@ QString::QString(QChar ch)
\internal
*/
-/*! \fn QString::QString(QStringDataPtr)
+/*! \fn QString::QString(QStringPrivate)
\internal
*/
@@ -2282,16 +2252,16 @@ void QString::resize(int size)
if (size < 0)
size = 0;
- if (IS_RAW_DATA(d) && !d->ref.isShared() && size < d->size) {
- d->size = size;
+ if (!d->isShared() && !d->isMutable() && size < int(d.size)) {
+ d.size = size;
return;
}
- if (d->ref.isShared() || uint(size) + 1u > d->alloc)
+ if (d->needsDetach() || size > capacity())
reallocData(uint(size) + 1u, true);
- if (d->alloc) {
- d->size = size;
- d->data()[size] = '\0';
+ d.size = size;
+ if (d->isMutable()) {
+ d.data()[size] = '\0';
}
}
@@ -2311,7 +2281,7 @@ void QString::resize(int size, QChar fillChar)
resize(size);
const int difference = length() - oldSize;
if (difference > 0)
- std::fill_n(d->begin() + oldSize, difference, fillChar.unicode());
+ std::fill_n(d.data() + oldSize, difference, fillChar.unicode());
}
/*! \fn int QString::capacity() const
@@ -2368,28 +2338,22 @@ void QString::reallocData(uint alloc, bool grow)
{
auto allocOptions = d->detachFlags();
if (grow)
- allocOptions |= QArrayData::Grow;
-
- if (d->ref.isShared() || IS_RAW_DATA(d)) {
- Data *x = Data::allocate(alloc, allocOptions);
- Q_CHECK_PTR(x);
- x->size = qMin(int(alloc) - 1, d->size);
- ::memcpy(x->data(), d->data(), x->size * sizeof(QChar));
- x->data()[x->size] = 0;
- if (!d->ref.deref())
- Data::deallocate(d);
- d = x;
+ allocOptions |= QArrayData::GrowsForward;
+
+ if (d->needsDetach()) {
+ DataPointer dd(Data::allocate(alloc, allocOptions), qMin(int(alloc) - 1, d.size));
+ ::memcpy(dd.data(), d.data(), dd.size * sizeof(QChar));
+ dd.data()[dd.size] = 0;
+ d = dd;
} else {
- Data *p = Data::reallocateUnaligned(d, alloc, allocOptions);
- Q_CHECK_PTR(p);
- d = p;
+ d.reallocate(alloc, allocOptions);
}
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void QString::expand(int i)
{
- resize(qMax(i + 1, d->size), QLatin1Char(' '));
+ resize(qMax(i + 1, size()), QLatin1Char(' '));
}
#endif
@@ -2408,9 +2372,6 @@ void QString::expand(int i)
QString &QString::operator=(const QString &other) noexcept
{
- other.d->ref.ref();
- if (!d->ref.deref())
- Data::deallocate(d);
d = other.d;
return *this;
}
@@ -2432,9 +2393,9 @@ QString &QString::operator=(const QString &other) noexcept
QString &QString::operator=(QLatin1String other)
{
if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 -> !isDetached() (sharedNull)
- d->size = other.size();
- d->data()[other.size()] = 0;
- qt_from_latin1(d->data(), other.latin1(), other.size());
+ d.size = other.size();
+ d.data()[other.size()] = 0;
+ qt_from_latin1(d.data(), other.latin1(), other.size());
} else {
*this = fromLatin1(other.latin1(), other.size());
}
@@ -2497,10 +2458,9 @@ QString &QString::operator=(QChar ch)
{
if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 -> !isDetached() (sharedNull)
// re-use existing capacity:
- ushort *dat = d->data();
- dat[0] = ch.unicode();
- dat[1] = 0;
- d->size = 1;
+ d.data()[0] = ch.unicode();
+ d.data()[1] = 0;
+ d.size = 1;
} else {
operator=(QString(ch));
}
@@ -2586,13 +2546,13 @@ QString &QString::insert(int i, QLatin1String str)
return *this;
int len = str.size();
- if (Q_UNLIKELY(i > d->size))
+ if (Q_UNLIKELY(i > size()))
resize(i + len, QLatin1Char(' '));
else
- resize(d->size + len);
+ resize(size() + len);
- ::memmove(d->data() + i + len, d->data() + i, (d->size - i - len) * sizeof(QChar));
- qt_from_latin1(d->data() + i, s, uint(len));
+ ::memmove(d.data() + i + len, d.data() + i, (d.size - i - len) * sizeof(QChar));
+ qt_from_latin1(d.data() + i, s, uint(len));
return *this;
}
@@ -2609,7 +2569,7 @@ QString& QString::insert(int i, const QChar *unicode, int size)
return *this;
const ushort *s = (const ushort *)unicode;
- if (s >= d->data() && s < d->data() + d->alloc) {
+ if (s >= d.data() && s < d.data() + d.size) {
// Part of me - take a copy
ushort *tmp = static_cast<ushort *>(::malloc(size * sizeof(QChar)));
Q_CHECK_PTR(tmp);
@@ -2619,13 +2579,13 @@ QString& QString::insert(int i, const QChar *unicode, int size)
return *this;
}
- if (Q_UNLIKELY(i > d->size))
+ if (Q_UNLIKELY(i > int(d.size)))
resize(i + size, QLatin1Char(' '));
else
- resize(d->size + size);
+ resize(d.size + size);
- ::memmove(d->data() + i + size, d->data() + i, (d->size - i - size) * sizeof(QChar));
- memcpy(d->data() + i, s, size * sizeof(QChar));
+ ::memmove(d.data() + i + size, d.data() + i, (d.size - i - size) * sizeof(QChar));
+ memcpy(d.data() + i, s, size * sizeof(QChar));
return *this;
}
@@ -2639,15 +2599,15 @@ QString& QString::insert(int i, const QChar *unicode, int size)
QString& QString::insert(int i, QChar ch)
{
if (i < 0)
- i += d->size;
+ i += d.size;
if (i < 0)
return *this;
- if (Q_UNLIKELY(i > d->size))
+ if (Q_UNLIKELY(i > size()))
resize(i + 1, QLatin1Char(' '));
else
- resize(d->size + 1);
- ::memmove(d->data() + i + 1, d->data() + i, (d->size - i - 1) * sizeof(QChar));
- d->data()[i] = ch.unicode();
+ resize(d.size + 1);
+ ::memmove(d.data() + i + 1, d.data() + i, (d.size - i - 1) * sizeof(QChar));
+ d.data()[i] = ch.unicode();
return *this;
}
@@ -2671,15 +2631,15 @@ QString& QString::insert(int i, QChar ch)
*/
QString &QString::append(const QString &str)
{
- if (str.d != Data::sharedNull()) {
- if (d == Data::sharedNull()) {
+ if (!str.isNull()) {
+ if (isNull()) {
operator=(str);
} else {
- if (d->ref.isShared() || uint(d->size + str.d->size) + 1u > d->alloc)
- reallocData(uint(d->size + str.d->size) + 1u, true);
- memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar));
- d->size += str.d->size;
- d->data()[d->size] = '\0';
+ if (d->needsDetach() || size() + str.size() > capacity())
+ reallocData(uint(size() + str.size()) + 1u, true);
+ memcpy(d.data() + d.size, str.d.data(), str.d.size * sizeof(QChar));
+ d.size += str.d.size;
+ d.data()[d.size] = '\0';
}
}
return *this;
@@ -2694,11 +2654,11 @@ QString &QString::append(const QString &str)
QString &QString::append(const QChar *str, int len)
{
if (str && len > 0) {
- if (d->ref.isShared() || uint(d->size + len) + 1u > d->alloc)
- reallocData(uint(d->size + len) + 1u, true);
- memcpy(d->data() + d->size, str, len * sizeof(QChar));
- d->size += len;
- d->data()[d->size] = '\0';
+ if (d->needsDetach() || size() + len > capacity())
+ reallocData(uint(size() + len) + 1u, true);
+ memcpy(d.data() + d.size, str, len * sizeof(QChar));
+ d.size += len;
+ d.data()[d.size] = '\0';
}
return *this;
}
@@ -2713,12 +2673,12 @@ QString &QString::append(QLatin1String str)
const char *s = str.latin1();
if (s) {
int len = str.size();
- if (d->ref.isShared() || uint(d->size + len) + 1u > d->alloc)
- reallocData(uint(d->size + len) + 1u, true);
- ushort *i = d->data() + d->size;
+ if (d->needsDetach() || size() + len > capacity())
+ reallocData(uint(size() + len) + 1u, true);
+ ushort *i = d.data() + d.size;
qt_from_latin1(i, s, uint(len));
i[len] = '\0';
- d->size += len;
+ d.size += len;
}
return *this;
}
@@ -2760,10 +2720,10 @@ QString &QString::append(QLatin1String str)
*/
QString &QString::append(QChar ch)
{
- if (d->ref.isShared() || uint(d->size) + 2u > d->alloc)
- reallocData(uint(d->size) + 2u, true);
- d->data()[d->size++] = ch.unicode();
- d->data()[d->size] = '\0';
+ if (d->needsDetach() || size() + 1 > capacity())
+ reallocData(uint(d.size) + 2u, true);
+ d.data()[d.size++] = ch.unicode();
+ d.data()[d.size] = '\0';
return *this;
}
@@ -2856,16 +2816,16 @@ QString &QString::append(QChar ch)
QString &QString::remove(int pos, int len)
{
if (pos < 0) // count from end of string
- pos += d->size;
- if (uint(pos) >= uint(d->size)) {
+ pos += size();
+ if (uint(pos) >= uint(size())) {
// range problems
- } else if (len >= d->size - pos) {
+ } else if (len >= size() - pos) {
resize(pos); // truncate
} else if (len > 0) {
detach();
- memmove(d->data() + pos, d->data() + pos + len,
- (d->size - pos - len + 1) * sizeof(ushort));
- d->size -= len;
+ memmove(d.data() + pos, d.data() + pos + len,
+ (d.size - pos - len + 1) * sizeof(ushort));
+ d.size -= len;
}
return *this;
}
@@ -3010,10 +2970,10 @@ QString &QString::replace(int pos, int len, const QString &after)
*/
QString &QString::replace(int pos, int len, const QChar *unicode, int size)
{
- if (uint(pos) > uint(d->size))
+ if (uint(pos) > uint(this->size()))
return *this;
- if (len > d->size - pos)
- len = d->size - pos;
+ if (len > this->size() - pos)
+ len = this->size() - pos;
uint index = pos;
replace_helper(&index, 1, len, unicode, size);
@@ -3077,10 +3037,10 @@ bool pointsIntoRange(const QChar *ptr, const ushort *base, int len)
*/
void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen)
{
- // Copy after if it lies inside our own d->data() area (which we could
+ // Copy after if it lies inside our own d.b area (which we could
// possibly invalidate via a realloc or modify by replacement).
QChar *afterBuffer = nullptr;
- if (pointsIntoRange(after, d->data(), d->size)) // Use copy in place of vulnerable original:
+ if (pointsIntoRange(after, d.data(), d.size)) // Use copy in place of vulnerable original:
after = afterBuffer = textCopy(after, alen);
QT_TRY {
@@ -3088,36 +3048,36 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar
// replace in place
detach();
for (int i = 0; i < nIndices; ++i)
- memcpy(d->data() + indices[i], after, alen * sizeof(QChar));
+ memcpy(d.data() + indices[i], after, alen * sizeof(QChar));
} else if (alen < blen) {
// replace from front
detach();
uint to = indices[0];
if (alen)
- memcpy(d->data()+to, after, alen*sizeof(QChar));
+ memcpy(d.data()+to, after, alen*sizeof(QChar));
to += alen;
uint movestart = indices[0] + blen;
for (int i = 1; i < nIndices; ++i) {
int msize = indices[i] - movestart;
if (msize > 0) {
- memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar));
+ memmove(d.data() + to, d.data() + movestart, msize * sizeof(QChar));
to += msize;
}
if (alen) {
- memcpy(d->data() + to, after, alen * sizeof(QChar));
+ memcpy(d.data() + to, after, alen * sizeof(QChar));
to += alen;
}
movestart = indices[i] + blen;
}
- int msize = d->size - movestart;
+ int msize = d.size - movestart;
if (msize > 0)
- memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar));
- resize(d->size - nIndices*(blen-alen));
+ memmove(d.data() + to, d.data() + movestart, msize * sizeof(QChar));
+ resize(d.size - nIndices*(blen-alen));
} else {
// replace from back
int adjust = nIndices*(alen-blen);
- int newLen = d->size + adjust;
- int moveend = d->size;
+ int newLen = d.size + adjust;
+ int moveend = d.size;
resize(newLen);
while (nIndices) {
@@ -3125,9 +3085,9 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar
int movestart = indices[nIndices] + blen;
int insertstart = indices[nIndices] + nIndices*(alen-blen);
int moveto = insertstart + alen;
- memmove(d->data() + moveto, d->data() + movestart,
+ memmove(d.data() + moveto, d.data() + movestart,
(moveend - movestart)*sizeof(QChar));
- memcpy(d->data() + insertstart, after, alen * sizeof(QChar));
+ memcpy(d.data() + insertstart, after, alen * sizeof(QChar));
moveend = movestart-blen;
}
}
@@ -3153,7 +3113,7 @@ QString &QString::replace(const QChar *before, int blen,
const QChar *after, int alen,
Qt::CaseSensitivity cs)
{
- if (d->size == 0) {
+ if (d.size == 0) {
if (blen)
return *this;
} else {
@@ -3188,10 +3148,10 @@ QString &QString::replace(const QChar *before, int blen,
We're about to change data, that before and after might point
into, and we'll need that data for our next batch of indices.
*/
- if (!afterBuffer && pointsIntoRange(after, d->data(), d->size))
+ if (!afterBuffer && pointsIntoRange(after, d.data(), d.size))
after = afterBuffer = textCopy(after, alen);
- if (!beforeBuffer && pointsIntoRange(before, d->data(), d->size)) {
+ if (!beforeBuffer && pointsIntoRange(before, d.data(), d.size)) {
beforeBuffer = textCopy(before, blen);
matcher = QStringMatcher(beforeBuffer, blen, cs);
}
@@ -3220,13 +3180,13 @@ QString &QString::replace(const QChar *before, int blen,
*/
QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs)
{
- if (after.d->size == 0)
+ if (after.size() == 0)
return remove(ch, cs);
- if (after.d->size == 1)
+ if (after.size() == 1)
return replace(ch, after.front(), cs);
- if (d->size == 0)
+ if (size() == 0)
return *this;
ushort cc = (cs == Qt::CaseSensitive ? ch.unicode() : ch.toCaseFolded().unicode());
@@ -3236,14 +3196,14 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
uint indices[1024];
uint pos = 0;
if (cs == Qt::CaseSensitive) {
- while (pos < 1024 && index < d->size) {
- if (d->data()[index] == cc)
+ while (pos < 1024 && index < size()) {
+ if (d.data()[index] == cc)
indices[pos++] = index;
index++;
}
} else {
- while (pos < 1024 && index < d->size) {
- if (QChar::toCaseFolded(d->data()[index]) == cc)
+ while (pos < 1024 && index < size()) {
+ if (QChar::toCaseFolded(d.data()[index]) == cc)
indices[pos++] = index;
index++;
}
@@ -3251,12 +3211,12 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
if (!pos) // Nothing to replace
break;
- replace_helper(indices, pos, 1, after.constData(), after.d->size);
+ replace_helper(indices, pos, 1, after.constData(), after.size());
if (Q_LIKELY(index == -1)) // Nothing left to replace
break;
// The call to replace_helper just moved what index points at:
- index += pos*(after.d->size - 1);
+ index += pos*(after.size() - 1);
}
return *this;
}
@@ -3271,13 +3231,13 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
*/
QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs)
{
- if (d->size) {
+ if (d.size) {
const int idx = indexOf(before, 0, cs);
if (idx != -1) {
detach();
const ushort a = after.unicode();
- ushort *i = d->data();
- const ushort *e = i + d->size;
+ ushort *i = d.data();
+ ushort *const e = i + d.size;
i += idx;
*i = a;
if (cs == Qt::CaseSensitive) {
@@ -3338,7 +3298,7 @@ QString &QString::replace(QLatin1String before, const QString &after, Qt::CaseSe
int blen = before.size();
QVarLengthArray<ushort> b(blen);
qt_from_latin1(b.data(), before.latin1(), blen);
- return replace((const QChar *)b.data(), blen, after.constData(), after.d->size, cs);
+ return replace((const QChar *)b.data(), blen, after.constData(), after.d.size, cs);
}
/*!
@@ -3358,7 +3318,7 @@ QString &QString::replace(const QString &before, QLatin1String after, Qt::CaseSe
int alen = after.size();
QVarLengthArray<ushort> a(alen);
qt_from_latin1(a.data(), after.latin1(), alen);
- return replace(before.constData(), before.d->size, (const QChar *)a.data(), alen, cs);
+ return replace(before.constData(), before.d.size, (const QChar *)a.data(), alen, cs);
}
/*!
@@ -3394,7 +3354,7 @@ QString &QString::replace(QChar c, QLatin1String after, Qt::CaseSensitivity cs)
*/
bool operator==(const QString &s1, const QString &s2) noexcept
{
- if (s1.d->size != s2.d->size)
+ if (s1.d.size != s2.d.size)
return false;
return qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0;
@@ -3407,7 +3367,7 @@ bool operator==(const QString &s1, const QString &s2) noexcept
*/
bool QString::operator==(QLatin1String other) const noexcept
{
- if (d->size != other.size())
+ if (size() != other.size())
return false;
return qt_compare_strings(*this, other, Qt::CaseSensitive) == 0;
@@ -3953,7 +3913,7 @@ QString& QString::replace(const QRegExp &rx, const QString &after)
if (isEmpty() && rx2.indexIn(*this) == -1)
return *this;
- reallocData(uint(d->size) + 1u);
+ reallocData(uint(d.size) + 1u);
int index = 0;
int numCaptures = rx2.captureCount();
@@ -4052,8 +4012,8 @@ QString& QString::replace(const QRegExp &rx, const QString &after)
}
if (!pos)
break;
- replacements[pos].pos = d->size;
- int newlen = d->size + adjust;
+ replacements[pos].pos = d.size;
+ int newlen = d.size + adjust;
// to continue searching at the right position after we did
// the first round of replacements
@@ -4068,14 +4028,14 @@ QString& QString::replace(const QRegExp &rx, const QString &after)
while (i < pos) {
int copyend = replacements[i].pos;
int size = copyend - copystart;
- memcpy(static_cast<void*>(uc), static_cast<const void *>(d->data() + copystart), size * sizeof(QChar));
+ memcpy(static_cast<void*>(uc), static_cast<const void *>(d.data() + copystart), size * sizeof(QChar));
uc += size;
- memcpy(static_cast<void *>(uc), static_cast<const void *>(after.d->data()), al * sizeof(QChar));
+ memcpy(static_cast<void *>(uc), static_cast<const void *>(after.d.data()), al * sizeof(QChar));
uc += al;
copystart = copyend + replacements[i].length;
i++;
}
- memcpy(static_cast<void *>(uc), static_cast<const void *>(d->data() + copystart), (d->size - copystart) * sizeof(QChar));
+ memcpy(static_cast<void *>(uc), static_cast<const void *>(d.data() + copystart), (d.size - copystart) * sizeof(QChar));
newstring.resize(newlen);
*this = newstring;
caretMode = QRegExp::CaretWontMatch;
@@ -4115,7 +4075,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
if (!iterator.hasNext()) // no matches at all
return *this;
- reallocData(uint(d->size) + 1u);
+ reallocData(uint(d.size) + 1u);
int numCaptures = re.captureCount();
@@ -4448,24 +4408,6 @@ int QString::count(const QRegExp& rx) const
#if QT_CONFIG(regularexpression)
/*!
- \overload indexOf()
- \since 5.0
-
- Returns the index position of the first match of the regular
- expression \a re in the string, searching forward from index
- position \a from. Returns -1 if \a re didn't match anywhere.
-
- Example:
-
- \snippet qstring/main.cpp 93
-*/
-int QString::indexOf(const QRegularExpression& re, int from) const
-{
- return indexOf(re, from, nullptr);
-}
-
-/*!
- \overload
\since 5.5
Returns the index position of the first match of the regular
@@ -4478,7 +4420,7 @@ int QString::indexOf(const QRegularExpression& re, int from) const
Example:
- \snippet qstring/main.cpp 99
+ \snippet qstring/main.cpp 93
*/
int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const
{
@@ -4499,24 +4441,6 @@ int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionM
}
/*!
- \overload lastIndexOf()
- \since 5.0
-
- Returns the index position of the last match of the regular
- expression \a re in the string, which starts before the index
- position \a from. Returns -1 if \a re didn't match anywhere.
-
- Example:
-
- \snippet qstring/main.cpp 94
-*/
-int QString::lastIndexOf(const QRegularExpression &re, int from) const
-{
- return lastIndexOf(re, from, nullptr);
-}
-
-/*!
- \overload
\since 5.5
Returns the index position of the last match of the regular
@@ -4529,7 +4453,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from) const
Example:
- \snippet qstring/main.cpp 100
+ \snippet qstring/main.cpp 94
*/
int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const
{
@@ -4556,19 +4480,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpress
return lastIndex;
}
-/*! \overload contains()
- \since 5.0
-
- Returns \c true if the regular expression \a re matches somewhere in
- this string; otherwise returns \c false.
-*/
-bool QString::contains(const QRegularExpression &re) const
-{
- return contains(re, nullptr);
-}
-
/*!
- \overload contains()
\since 5.1
Returns \c true if the regular expression \a re matches somewhere in this
@@ -4915,9 +4827,9 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti
*/
QString QString::left(int n) const
{
- if (uint(n) >= uint(d->size))
+ if (uint(n) >= uint(size()))
return *this;
- return QString((const QChar*) d->data(), n);
+ return QString((const QChar*) d.data(), n);
}
/*!
@@ -4933,9 +4845,9 @@ QString QString::left(int n) const
*/
QString QString::right(int n) const
{
- if (uint(n) >= uint(d->size))
+ if (uint(n) >= uint(size()))
return *this;
- return QString((const QChar*) d->data() + d->size - n, n);
+ return QString(constData() + size() - n, n);
}
/*!
@@ -4958,18 +4870,19 @@ QString QString::right(int n) const
QString QString::mid(int position, int n) const
{
using namespace QtPrivate;
- switch (QContainerImplHelper::mid(d->size, &position, &n)) {
+ switch (QContainerImplHelper::mid(size(), &position, &n)) {
case QContainerImplHelper::Null:
return QString();
case QContainerImplHelper::Empty:
{
- QStringDataPtr empty = { Data::allocate(0) };
+ QPair<Data *, ushort *> pair = Data::allocate(0);
+ DataPointer empty = { pair.first, pair.second, 0 };
return QString(empty);
}
case QContainerImplHelper::Full:
return *this;
case QContainerImplHelper::Subset:
- return QString((const QChar*)d->data() + position, n);
+ return QString(constData() + position, n);
}
Q_UNREACHABLE();
return QString();
@@ -5219,29 +5132,29 @@ QByteArray QString::toLatin1_helper_inplace(QString &s)
// We can return our own buffer to the caller.
// Conversion to Latin-1 always shrinks the buffer by half.
- const ushort *data = reinterpret_cast<const ushort *>(s.constData());
- uint length = s.size();
+ const ushort *data = s.d.data();
+ int length = s.d.size;
- // Swap the d pointers.
+ // Move the d pointer over to the bytearray.
// Kids, avert your eyes. Don't try this at home.
- QArrayData *ba_d = s.d;
- // multiply the allocated capacity by sizeof(ushort)
- ba_d->alloc *= sizeof(ushort);
+ // this relies on the fact that we use QArrayData for everything behind the scenes which has the same layout
+ static_assert(sizeof(QByteArray::DataPointer) == sizeof(QString::DataPointer), "sizes have to be equal");
+ QByteArray::DataPointer ba_d(reinterpret_cast<QByteArray::Data *>(s.d.d_ptr()), reinterpret_cast<char *>(s.d.data()), length);
+ ba_d.ref();
+ s.clear();
- // reset ourselves to QString()
- s.d = QString().d;
+ char *ddata = ba_d.data();
- // do the in-place conversion
- uchar *dst = reinterpret_cast<uchar *>(ba_d->data());
- qt_to_latin1(dst, data, length);
- dst[length] = '\0';
+ // multiply the allocated capacity by sizeof(ushort)
+ ba_d.d_ptr()->alloc *= sizeof(ushort);
- QByteArrayDataPtr badptr = { ba_d };
- return QByteArray(badptr);
+ // do the in-place conversion
+ qt_to_latin1(reinterpret_cast<uchar *>(ddata), data, length);
+ ddata[length] = '\0';
+ return QByteArray(ba_d);
}
-
/*!
\fn QByteArray QString::toLatin1() const
@@ -5421,34 +5334,25 @@ QVector<uint> QtPrivate::convertToUcs4(QStringView string)
return qt_convert_to_ucs4(string);
}
-QString::Data *QString::fromLatin1_helper(const char *str, int size)
+QString::DataPointer QString::fromLatin1_helper(const char *str, int size)
{
- Data *d;
+ DataPointer d;
if (!str) {
- d = Data::sharedNull();
+ // nothing to do
} else if (size == 0 || (!*str && size < 0)) {
- d = Data::allocate(0);
+ d = DataPointer(Data::allocate(0), 0);
} else {
if (size < 0)
size = qstrlen(str);
- d = Data::allocate(size + 1);
- Q_CHECK_PTR(d);
- d->size = size;
- d->data()[size] = '\0';
- ushort *dst = d->data();
+ d = DataPointer(Data::allocate(size + 1), size);
+ d.data()[size] = '\0';
+ ushort *dst = d.data();
qt_from_latin1(dst, str, uint(size));
}
return d;
}
-QString::Data *QString::fromAscii_helper(const char *str, int size)
-{
- QString s = fromUtf8(str, size);
- s.d->ref.ref();
- return s.d;
-}
-
/*! \fn QString QString::fromLatin1(const char *str, int size)
Returns a QString initialized with the first \a size characters
of the Latin-1 string \a str.
@@ -5491,7 +5395,8 @@ QString QString::fromLocal8Bit_helper(const char *str, int size)
if (!str)
return QString();
if (size == 0 || (!*str && size < 0)) {
- QStringDataPtr empty = { Data::allocate(0) };
+ QPair<Data *, ushort *> pair = Data::allocate(0);
+ QString::DataPointer empty = { pair.first, pair.second, 0 };
return QString(empty);
}
#if QT_CONFIG(textcodec)
@@ -5661,7 +5566,7 @@ QString& QString::setUnicode(const QChar *unicode, int size)
{
resize(size);
if (unicode && size)
- memcpy(d->data(), unicode, size * sizeof(QChar));
+ memcpy(d.data(), unicode, size * sizeof(QChar));
return *this;
}
@@ -5783,7 +5688,7 @@ QString QString::trimmed_helper(QString &str)
*/
/*!
- \fn QCharRef QString::operator[](int position)
+ \fn QChar &QString::operator[](int position)
Returns the character at the specified \a position in the string as a
modifiable reference.
@@ -5792,20 +5697,6 @@ QString QString::trimmed_helper(QString &str)
\snippet qstring/main.cpp 85
- The return value is of type QCharRef, a helper class for QString.
- When you get an object of type QCharRef, you can use it as if it
- were a reference to a QChar. If you assign to it, the assignment will apply to
- the character in the QString from which you got the reference.
-
- \note Before Qt 5.14 it was possible to use this operator to access
- a character at an out-of-bounds position in the string, and
- then assign to such a position, causing the string to be
- automatically resized. Furthermore, assigning a value to the
- returned QCharRef would cause a detach of the string, even if the
- string has been copied in the meanwhile (and the QCharRef kept
- alive while the copy was taken). These behaviors are deprecated,
- and will be changed in a future version of Qt.
-
\sa at()
*/
@@ -5815,19 +5706,6 @@ QString QString::trimmed_helper(QString &str)
\overload operator[]()
*/
-/*! \fn QCharRef QString::operator[](uint position)
-
-\overload operator[]()
-
-Returns the character at the specified \a position in the string as a
-modifiable reference.
-*/
-
-/*! \fn const QChar QString::operator[](uint position) const
- Equivalent to \c at(position).
-\overload operator[]()
-*/
-
/*!
\fn QChar QString::front() const
\since 5.10
@@ -5859,7 +5737,7 @@ modifiable reference.
*/
/*!
- \fn QCharRef QString::front()
+ \fn QChar &QString::front()
\since 5.10
Returns a reference to the first character in the string.
@@ -5874,7 +5752,7 @@ modifiable reference.
*/
/*!
- \fn QCharRef QString::back()
+ \fn QChar &QString::back()
\since 5.10
Returns a reference to the last character in the string.
@@ -5907,7 +5785,7 @@ modifiable reference.
void QString::truncate(int pos)
{
- if (pos < d->size)
+ if (pos < size())
resize(pos);
}
@@ -5929,7 +5807,7 @@ void QString::truncate(int pos)
void QString::chop(int n)
{
if (n > 0)
- resize(d->size - n);
+ resize(d.size - n);
}
/*!
@@ -5946,10 +5824,10 @@ void QString::chop(int n)
QString& QString::fill(QChar ch, int size)
{
- resize(size < 0 ? d->size : size);
- if (d->size) {
- QChar *i = (QChar*)d->data() + d->size;
- QChar *b = (QChar*)d->data();
+ resize(size < 0 ? d.size : size);
+ if (d.size) {
+ QChar *i = (QChar*)d.data() + d.size;
+ QChar *b = (QChar*)d.data();
while (i != b)
*--i = ch;
}
@@ -6530,11 +6408,11 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
const ushort *QString::utf16() const
{
- if (IS_RAW_DATA(d)) {
+ if (!d->isMutable()) {
// ensure '\0'-termination for ::fromRawData strings
- const_cast<QString*>(this)->reallocData(uint(d->size) + 1u);
+ const_cast<QString*>(this)->reallocData(uint(d.size) + 1u);
}
- return d->data();
+ return d.data();
}
/*!
@@ -6563,8 +6441,8 @@ QString QString::leftJustified(int width, QChar fill, bool truncate) const
if (padlen > 0) {
result.resize(len+padlen);
if (len)
- memcpy(result.d->data(), d->data(), sizeof(QChar)*len);
- QChar *uc = (QChar*)result.d->data() + len;
+ memcpy(result.d.data(), d.data(), sizeof(QChar)*len);
+ QChar *uc = (QChar*)result.d.data() + len;
while (padlen--)
* uc++ = fill;
} else {
@@ -6601,11 +6479,11 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
int padlen = width - len;
if (padlen > 0) {
result.resize(len+padlen);
- QChar *uc = (QChar*)result.d->data();
+ QChar *uc = (QChar*)result.d.data();
while (padlen--)
* uc++ = fill;
if (len)
- memcpy(static_cast<void *>(uc), static_cast<const void *>(d->data()), sizeof(QChar)*len);
+ memcpy(static_cast<void *>(uc), static_cast<const void *>(d.data()), sizeof(QChar)*len);
} else {
if (truncate)
result = left(width);
@@ -8014,7 +7892,7 @@ QVector<QStringRef> QString::splitRef(const QRegularExpression &re, SplitBehavio
*/
QString QString::repeated(int times) const
{
- if (d->size == 0)
+ if (d.size == 0)
return *this;
if (times <= 1) {
@@ -8023,27 +7901,27 @@ QString QString::repeated(int times) const
return QString();
}
- const int resultSize = times * d->size;
+ const int resultSize = times * d.size;
QString result;
result.reserve(resultSize);
- if (result.d->alloc != uint(resultSize) + 1u)
+ if (result.capacity() != resultSize)
return QString(); // not enough memory
- memcpy(result.d->data(), d->data(), d->size * sizeof(ushort));
+ memcpy(result.d.data(), d.data(), d.size * sizeof(ushort));
- int sizeSoFar = d->size;
- ushort *end = result.d->data() + sizeSoFar;
+ int sizeSoFar = d.size;
+ ushort *end = result.d.data() + sizeSoFar;
const int halfResultSize = resultSize >> 1;
while (sizeSoFar <= halfResultSize) {
- memcpy(end, result.d->data(), sizeSoFar * sizeof(ushort));
+ memcpy(end, result.d.data(), sizeSoFar * sizeof(ushort));
end += sizeSoFar;
sizeSoFar <<= 1;
}
- memcpy(end, result.d->data(), (resultSize - sizeSoFar) * sizeof(ushort));
- result.d->data()[resultSize] = '\0';
- result.d->size = resultSize;
+ memcpy(end, result.d.data(), (resultSize - sizeSoFar) * sizeof(ushort));
+ result.d.data()[resultSize] = '\0';
+ result.d.size = resultSize;
return result;
}
@@ -9043,8 +8921,8 @@ QString QtPrivate::argToQString(QLatin1String pattern, size_t n, const ArgBase *
*/
bool QString::isSimpleText() const
{
- const ushort *p = d->data();
- const ushort * const end = p + d->size;
+ const ushort *p = d.data();
+ const ushort * const end = p + d.size;
while (p < end) {
ushort uc = *p;
// sort out regions of complex text formatting
@@ -9208,17 +9086,14 @@ bool QString::isRightToLeft() const
*/
QString QString::fromRawData(const QChar *unicode, int size)
{
- Data *x;
+ QString::DataPointer x;
if (!unicode) {
- x = Data::sharedNull();
} else if (!size) {
- x = Data::allocate(0);
+ x = DataPointer(Data::allocate(0), 0);
} else {
x = Data::fromRawData(reinterpret_cast<const ushort *>(unicode), size);
- Q_CHECK_PTR(x);
}
- QStringDataPtr dataPtr = { x };
- return QString(dataPtr);
+ return QString(x);
}
/*!
@@ -9237,17 +9112,10 @@ QString QString::fromRawData(const QChar *unicode, int size)
*/
QString &QString::setRawData(const QChar *unicode, int size)
{
- if (d->ref.isShared() || d->alloc) {
- *this = fromRawData(unicode, size);
- } else {
- if (unicode) {
- d->size = size;
- d->offset = reinterpret_cast<const char *>(unicode) - reinterpret_cast<char *>(d);
- } else {
- d->offset = sizeof(QStringData);
- d->size = 0;
- }
+ if (!unicode || !size) {
+ clear();
}
+ *this = fromRawData(unicode, size);
return *this;
}
@@ -10546,7 +10414,7 @@ ownership of it, no memory is freed when instances are destroyed.
*/
QString QStringRef::toString() const {
- if (!m_string)
+ if (isNull())
return QString();
if (m_size && m_position == 0 && m_size == m_string->size())
return *m_string;
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 1f4e856660..65d702ff1c 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2019 Intel Corporation.
** Copyright (C) 2019 Mail.ru Group.
** Contact: https://www.qt.io/licensing/
**
@@ -48,7 +48,7 @@
#include <QtCore/qchar.h>
#include <QtCore/qbytearray.h>
-#include <QtCore/qrefcount.h>
+#include <QtCore/qarraydata.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qstringliteral.h>
#include <QtCore/qstringalgorithms.h>
@@ -70,7 +70,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
QT_BEGIN_NAMESPACE
-class QCharRef;
class QRegExp;
class QRegularExpression;
class QRegularExpressionMatch;
@@ -246,8 +245,9 @@ qsizetype QStringView::lastIndexOf(QLatin1String s, qsizetype from, Qt::CaseSens
class Q_CORE_EXPORT QString
{
+ typedef QTypedArrayData<ushort> Data;
public:
- typedef QStringData Data;
+ typedef QStringPrivate DataPointer;
inline QString() noexcept;
explicit QString(const QChar *unicode, int size = -1);
@@ -259,12 +259,13 @@ public:
QString &operator=(QChar c);
QString &operator=(const QString &) noexcept;
QString &operator=(QLatin1String latin1);
- inline QString(QString && other) noexcept : d(other.d) { other.d = Data::sharedNull(); }
+ inline QString(QString &&other) noexcept
+ { qSwap(d, other.d); }
inline QString &operator=(QString &&other) noexcept
{ qSwap(d, other.d); return *this; }
inline void swap(QString &other) noexcept { qSwap(d, other.d); }
- inline int size() const { return d->size; }
- inline int count() const { return d->size; }
+ inline int size() const { return int(d.size); }
+ inline int count() const { return int(d.size); }
inline int length() const;
inline bool isEmpty() const;
void resize(int size);
@@ -274,7 +275,7 @@ public:
void truncate(int pos);
void chop(int n);
- int capacity() const;
+ inline int capacity() const;
inline void reserve(int size);
inline void squeeze();
@@ -285,19 +286,17 @@ public:
inline void detach();
inline bool isDetached() const;
- inline bool isSharedWith(const QString &other) const { return d == other.d; }
+ inline bool isSharedWith(const QString &other) const { return d.isSharedWith(other.d); }
void clear();
inline const QChar at(int i) const;
const QChar operator[](int i) const;
- Q_REQUIRED_RESULT QCharRef operator[](int i);
- const QChar operator[](uint i) const;
- Q_REQUIRED_RESULT QCharRef operator[](uint i);
+ Q_REQUIRED_RESULT QChar &operator[](int i);
Q_REQUIRED_RESULT inline QChar front() const { return at(0); }
- Q_REQUIRED_RESULT inline QCharRef front();
+ Q_REQUIRED_RESULT inline QChar &front();
Q_REQUIRED_RESULT inline QChar back() const { return at(size() - 1); }
- Q_REQUIRED_RESULT inline QCharRef back();
+ Q_REQUIRED_RESULT inline QChar &back();
Q_REQUIRED_RESULT QString arg(qlonglong a, int fieldwidth=0, int base=10,
QChar fillChar = QLatin1Char(' ')) const;
@@ -425,12 +424,11 @@ public:
#endif
#if QT_CONFIG(regularexpression)
- int indexOf(const QRegularExpression &re, int from = 0) const;
- int indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads
- int lastIndexOf(const QRegularExpression &re, int from = -1) const;
- int lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads
- bool contains(const QRegularExpression &re) const;
- bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads
+ int indexOf(const QRegularExpression &re, int from = 0,
+ QRegularExpressionMatch *rmatch = nullptr) const;
+ int lastIndexOf(const QRegularExpression &re, int from = -1,
+ QRegularExpressionMatch *rmatch = nullptr) const;
+ bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
int count(const QRegularExpression &re) const;
#endif
@@ -543,10 +541,10 @@ public:
inline QString &prepend(QLatin1String s) { return insert(0, s); }
inline QString &operator+=(QChar c) {
- if (d->ref.isShared() || uint(d->size) + 2u > d->alloc)
- reallocData(uint(d->size) + 2u, true);
- d->data()[d->size++] = c.unicode();
- d->data()[d->size] = '\0';
+ if (d->needsDetach() || int(d.size + 1) > capacity())
+ reallocData(uint(d.size) + 2u, true);
+ d->data()[d.size++] = c.unicode();
+ d->data()[d.size] = '\0';
return *this;
}
@@ -659,8 +657,7 @@ public:
// note - this are all inline so we can benefit from strlen() compile time optimizations
static inline QString fromLatin1(const char *str, int size = -1)
{
- QStringDataPtr dataPtr = { fromLatin1_helper(str, (str && size == -1) ? int(strlen(str)) : size) };
- return QString(dataPtr);
+ return QString(fromLatin1_helper(str, (str && size == -1) ? int(strlen(str)) : size));
}
static inline QString fromUtf8(const char *str, int size = -1)
{
@@ -792,10 +789,10 @@ public:
#endif
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
inline QT_ASCII_CAST_WARN QString(const char *ch)
- : d(fromAscii_helper(ch, ch ? int(strlen(ch)) : -1))
+ : QString(fromUtf8(ch))
{}
inline QT_ASCII_CAST_WARN QString(const QByteArray &a)
- : d(fromAscii_helper(a.constData(), qstrnlen(a.constData(), a.size())))
+ : QString(fromUtf8(a))
{}
inline QT_ASCII_CAST_WARN QString &operator=(const char *ch)
{ return (*this = fromUtf8(ch)); }
@@ -911,10 +908,10 @@ public:
struct Null { };
QT_DEPRECATED_X("use QString()")
static const Null null;
- inline QString(const Null &): d(Data::sharedNull()) {}
+ inline QString(const Null &) {}
inline QString &operator=(const Null &) { *this = QString(); return *this; }
#endif
- inline bool isNull() const { return d == Data::sharedNull(); }
+ inline bool isNull() const { return d->isNull(); }
bool isSimpleText() const;
@@ -923,7 +920,7 @@ public:
{ return QStringView(*this).isValidUtf16(); }
QString(int size, Qt::Initialization);
- Q_DECL_CONSTEXPR inline QString(QStringDataPtr dd) : d(dd.ptr) {}
+ explicit QString(DataPointer dd) : d(dd) {}
private:
#if defined(QT_NO_CAST_FROM_ASCII)
@@ -935,7 +932,7 @@ private:
QString &operator=(const QByteArray &a);
#endif
- Data *d;
+ DataPointer d;
friend inline bool operator==(QChar, const QString &) noexcept;
friend inline bool operator< (QChar, const QString &) noexcept;
@@ -973,8 +970,7 @@ private:
static QString trimmed_helper(QString &str);
static QString simplified_helper(const QString &str);
static QString simplified_helper(QString &str);
- static Data *fromLatin1_helper(const char *str, int size = -1);
- static Data *fromAscii_helper(const char *str, int size = -1);
+ static DataPointer fromLatin1_helper(const char *str, int size = -1);
static QString fromUtf8_helper(const char *str, int size);
static QString fromLocal8Bit_helper(const char *, int size);
static QByteArray toLatin1_helper(const QString &);
@@ -985,7 +981,6 @@ private:
static qlonglong toIntegral_helper(const QChar *data, int len, bool *ok, int base);
static qulonglong toIntegral_helper(const QChar *data, uint len, bool *ok, int base);
void replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen);
- friend class QCharRef;
friend class QTextCodec;
friend class QStringRef;
friend class QStringView;
@@ -1010,8 +1005,7 @@ private:
}
public:
- typedef Data * DataPtr;
- inline DataPtr &data_ptr() { return d; }
+ inline DataPointer &data_ptr() { return d; }
};
//
@@ -1026,33 +1020,31 @@ QString QStringView::toString() const
inline QString::QString(QLatin1String aLatin1) : d(fromLatin1_helper(aLatin1.latin1(), aLatin1.size()))
{ }
inline int QString::length() const
-{ return d->size; }
+{ return int(d.size); }
inline const QChar QString::at(int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return QChar(d->data()[i]); }
+{ Q_ASSERT(uint(i) < uint(size())); return QChar(d.data()[i]); }
inline const QChar QString::operator[](int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return QChar(d->data()[i]); }
-inline const QChar QString::operator[](uint i) const
-{ Q_ASSERT(i < uint(size())); return QChar(d->data()[i]); }
+{ Q_ASSERT(uint(i) < uint(size())); return QChar(d.data()[i]); }
inline bool QString::isEmpty() const
-{ return d->size == 0; }
+{ return d.size == 0; }
inline const QChar *QString::unicode() const
-{ return reinterpret_cast<const QChar*>(d->data()); }
+{ return reinterpret_cast<const QChar*>(d.data()); }
inline const QChar *QString::data() const
-{ return reinterpret_cast<const QChar*>(d->data()); }
+{ return reinterpret_cast<const QChar*>(d.data()); }
inline QChar *QString::data()
-{ detach(); return reinterpret_cast<QChar*>(d->data()); }
+{ detach(); return reinterpret_cast<QChar*>(d.data()); }
inline const QChar *QString::constData() const
-{ return reinterpret_cast<const QChar*>(d->data()); }
+{ return reinterpret_cast<const QChar*>(d.data()); }
inline void QString::detach()
-{ if (d->ref.isShared() || (d->offset != sizeof(QStringData))) reallocData(uint(d->size) + 1u); }
+{ if (d->needsDetach()) reallocData(d.size + 1u); }
inline bool QString::isDetached() const
-{ return !d->ref.isShared(); }
+{ return !d->isShared(); }
inline void QString::clear()
{ if (!isNull()) *this = QString(); }
inline QString::QString(const QString &other) noexcept : d(other.d)
-{ Q_ASSERT(&other != this); d->ref.ref(); }
+{ }
inline int QString::capacity() const
-{ return d->alloc ? d->alloc - 1 : 0; }
+{ const auto realCapacity = d->constAllocatedCapacity(); return realCapacity ? int(realCapacity) - 1 : 0; }
inline QString &QString::setNum(short n, int base)
{ return setNum(qlonglong(n), base); }
inline QString &QString::setNum(ushort n, int base)
@@ -1139,178 +1131,51 @@ inline QString QString::fromWCharArray(const wchar_t *string, int size)
: fromUcs4(reinterpret_cast<const uint *>(string), size);
}
-class
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-Q_CORE_EXPORT
-#endif
-QCharRef { // ### Qt 7: remove
- QString &s;
- int i;
- inline QCharRef(QString &str, int idx)
- : s(str),i(idx) {}
- friend class QString;
-public:
-
- // most QChar operations repeated here
-
- // all this is not documented: We just say "like QChar" and let it be.
- inline operator QChar() const
- {
- using namespace QtPrivate::DeprecatedRefClassBehavior;
- if (Q_LIKELY(i < s.d->size))
- return QChar(s.d->data()[i]);
-#ifdef QT_DEBUG
- warn(WarningType::OutOfRange, EmittingClass::QCharRef);
-#endif
- return QChar();
- }
- inline QCharRef &operator=(QChar c)
- {
- using namespace QtPrivate::DeprecatedRefClassBehavior;
- if (Q_UNLIKELY(i >= s.d->size)) {
-#ifdef QT_DEBUG
- warn(WarningType::OutOfRange, EmittingClass::QCharRef);
-#endif
- s.resize(i + 1, QLatin1Char(' '));
- } else {
-#ifdef QT_DEBUG
- if (Q_UNLIKELY(!s.isDetached()))
- warn(WarningType::DelayedDetach, EmittingClass::QCharRef);
-#endif
- s.detach();
- }
- s.d->data()[i] = c.unicode();
- return *this;
- }
-
- // An operator= for each QChar cast constructors
-#ifndef QT_NO_CAST_FROM_ASCII
- inline QT_ASCII_CAST_WARN QCharRef &operator=(char c)
- { return operator=(QChar::fromLatin1(c)); }
- inline QT_ASCII_CAST_WARN QCharRef &operator=(uchar c)
- { return operator=(QChar::fromLatin1(c)); }
-#endif
- inline QCharRef &operator=(const QCharRef &c) { return operator=(QChar(c)); }
- inline QCharRef &operator=(ushort rc) { return operator=(QChar(rc)); }
- inline QCharRef &operator=(short rc) { return operator=(QChar(rc)); }
- inline QCharRef &operator=(uint rc) { return operator=(QChar(rc)); }
- inline QCharRef &operator=(int rc) { return operator=(QChar(rc)); }
-
- // each function...
- inline bool isNull() const { return QChar(*this).isNull(); }
- inline bool isPrint() const { return QChar(*this).isPrint(); }
- inline bool isPunct() const { return QChar(*this).isPunct(); }
- inline bool isSpace() const { return QChar(*this).isSpace(); }
- inline bool isMark() const { return QChar(*this).isMark(); }
- inline bool isLetter() const { return QChar(*this).isLetter(); }
- inline bool isNumber() const { return QChar(*this).isNumber(); }
- inline bool isLetterOrNumber() { return QChar(*this).isLetterOrNumber(); }
- inline bool isDigit() const { return QChar(*this).isDigit(); }
- inline bool isLower() const { return QChar(*this).isLower(); }
- inline bool isUpper() const { return QChar(*this).isUpper(); }
- inline bool isTitleCase() const { return QChar(*this).isTitleCase(); }
-
- inline int digitValue() const { return QChar(*this).digitValue(); }
- QChar toLower() const { return QChar(*this).toLower(); }
- QChar toUpper() const { return QChar(*this).toUpper(); }
- QChar toTitleCase () const { return QChar(*this).toTitleCase(); }
-
- QChar::Category category() const { return QChar(*this).category(); }
- QChar::Direction direction() const { return QChar(*this).direction(); }
- QChar::JoiningType joiningType() const { return QChar(*this).joiningType(); }
-#if QT_DEPRECATED_SINCE(5, 3)
- QT_DEPRECATED QChar::Joining joining() const
- {
- switch (QChar(*this).joiningType()) {
- case QChar::Joining_Causing: return QChar::Center;
- case QChar::Joining_Dual: return QChar::Dual;
- case QChar::Joining_Right: return QChar::Right;
- case QChar::Joining_None:
- case QChar::Joining_Left:
- case QChar::Joining_Transparent:
- default: return QChar::OtherJoining;
- }
- }
-#endif
- bool hasMirrored() const { return QChar(*this).hasMirrored(); }
- QChar mirroredChar() const { return QChar(*this).mirroredChar(); }
- QString decomposition() const { return QChar(*this).decomposition(); }
- QChar::Decomposition decompositionTag() const { return QChar(*this).decompositionTag(); }
- uchar combiningClass() const { return QChar(*this).combiningClass(); }
-
- inline QChar::Script script() const { return QChar(*this).script(); }
-
- QChar::UnicodeVersion unicodeVersion() const { return QChar(*this).unicodeVersion(); }
-
- inline uchar cell() const { return QChar(*this).cell(); }
- inline uchar row() const { return QChar(*this).row(); }
- inline void setCell(uchar cell);
- inline void setRow(uchar row);
-
-#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED char toAscii() const { return QChar(*this).toLatin1(); }
-#endif
- char toLatin1() const { return QChar(*this).toLatin1(); }
- ushort unicode() const { return QChar(*this).unicode(); }
- ushort& unicode() { return s.data()[i].unicode(); }
-
-};
-Q_DECLARE_TYPEINFO(QCharRef, Q_MOVABLE_TYPE);
-
-inline void QCharRef::setRow(uchar arow) { QChar(*this).setRow(arow); }
-inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); }
-
-
-inline QString::QString() noexcept : d(Data::sharedNull()) {}
-inline QString::~QString() { if (!d->ref.deref()) Data::deallocate(d); }
+inline QString::QString() noexcept {}
+inline QString::~QString() {}
inline void QString::reserve(int asize)
{
- if (d->ref.isShared() || uint(asize) >= d->alloc)
- reallocData(qMax(asize, d->size) + 1u);
+ if (d->needsDetach() || asize >= capacity())
+ reallocData(uint(qMax(asize, size())) + 1u);
- if (!d->capacityReserved) {
- // cannot set unconditionally, since d could be the shared_null/shared_empty (which is const)
- d->capacityReserved = true;
- }
+ // we're not shared anymore, for sure
+ d->flags() |= Data::CapacityReserved;
}
inline void QString::squeeze()
{
- if (d->ref.isShared() || uint(d->size) + 1u < d->alloc)
- reallocData(uint(d->size) + 1u);
+ if ((d->flags() & Data::CapacityReserved) == 0)
+ return;
+ if (d->needsDetach() || int(d.size) < capacity())
+ reallocData(uint(d.size) + 1u);
- if (d->capacityReserved) {
- // cannot set unconditionally, since d could be shared_null or
- // otherwise static.
- d->capacityReserved = false;
- }
+ // we're not shared anymore, for sure
+ d->flags() &= uint(~Data::CapacityReserved);
}
inline QString &QString::setUtf16(const ushort *autf16, int asize)
{ return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); }
-inline QCharRef QString::operator[](int i)
-{ Q_ASSERT(i >= 0); detach(); return QCharRef(*this, i); }
-inline QCharRef QString::operator[](uint i)
-{ detach(); return QCharRef(*this, i); }
-inline QCharRef QString::front() { return operator[](0); }
-inline QCharRef QString::back() { return operator[](size() - 1); }
+inline QChar &QString::operator[](int i)
+{ Q_ASSERT(i >= 0 && i < size()); return data()[i]; }
+inline QChar &QString::front() { return operator[](0); }
+inline QChar &QString::back() { return operator[](size() - 1); }
inline QString::iterator QString::begin()
-{ detach(); return reinterpret_cast<QChar*>(d->data()); }
+{ detach(); return reinterpret_cast<QChar*>(d.data()); }
inline QString::const_iterator QString::begin() const
-{ return reinterpret_cast<const QChar*>(d->data()); }
+{ return reinterpret_cast<const QChar*>(d.data()); }
inline QString::const_iterator QString::cbegin() const
-{ return reinterpret_cast<const QChar*>(d->data()); }
+{ return reinterpret_cast<const QChar*>(d.data()); }
inline QString::const_iterator QString::constBegin() const
-{ return reinterpret_cast<const QChar*>(d->data()); }
+{ return reinterpret_cast<const QChar*>(d.data()); }
inline QString::iterator QString::end()
-{ detach(); return reinterpret_cast<QChar*>(d->data() + d->size); }
+{ detach(); return reinterpret_cast<QChar*>(d.data() + d.size); }
inline QString::const_iterator QString::end() const
-{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
+{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
inline QString::const_iterator QString::cend() const
-{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
+{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
inline QString::const_iterator QString::constEnd() const
-{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
+{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
#if QT_STRINGVIEW_LEVEL < 2
inline bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
{ return indexOf(s, 0, cs) != -1; }
@@ -1537,7 +1402,8 @@ inline QString QString::fromStdU32String(const std::u32string &s)
inline std::u32string QString::toStdU32String() const
{
std::u32string u32str(length(), char32_t(0));
- int len = toUcs4_helper(d->data(), length(), reinterpret_cast<uint*>(&u32str[0]));
+ int len = toUcs4_helper(reinterpret_cast<const ushort *>(constData()), length(),
+ reinterpret_cast<uint*>(&u32str[0]));
u32str.resize(len);
return u32str;
}
@@ -1669,7 +1535,7 @@ public:
inline const QChar *unicode() const
{
if (!m_string)
- return reinterpret_cast<const QChar *>(QString::Data::sharedNull()->data());
+ return reinterpret_cast<const QChar *>(QString::Data::sharedNullData());
return m_string->unicode() + m_position;
}
inline const QChar *data() const { return unicode(); }
diff --git a/src/corelib/text/qstringbuilder.cpp b/src/corelib/text/qstringbuilder.cpp
index cf443ec369..29bd216e80 100644
--- a/src/corelib/text/qstringbuilder.cpp
+++ b/src/corelib/text/qstringbuilder.cpp
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
\list
\li QString, QStringRef, (since 5.10:) QStringView
- \li QChar, QCharRef, QLatin1Char, (since 5.10:) \c char16_t,
+ \li QChar, QLatin1Char, (since 5.10:) \c char16_t,
\li QLatin1String,
\li (since 5.10:) \c{const char16_t[]} (\c{u"foo"}),
\li QByteArray, \c char, \c{const char[]}.
@@ -108,7 +108,7 @@ QT_BEGIN_NAMESPACE
This function is usable with arguments of type \c QString,
\c QLatin1String, \c QStringRef,
- \c QChar, \c QCharRef, \c QLatin1Char, and \c char.
+ \c QChar, \c QLatin1Char, and \c char.
*/
/* \fn template <typename A, typename B> QByteArray QStringBuilder<A, B>::toLatin1() const
diff --git a/src/corelib/text/qstringbuilder.h b/src/corelib/text/qstringbuilder.h
index 288d98d633..45fd270b66 100644
--- a/src/corelib/text/qstringbuilder.h
+++ b/src/corelib/text/qstringbuilder.h
@@ -231,16 +231,6 @@ template <> struct QConcatenable<QChar::SpecialCharacter> : private QAbstractCon
{ *out++ = c; }
};
-template <> struct QConcatenable<QCharRef> : private QAbstractConcatenable
-{
- typedef QCharRef type;
- typedef QString ConvertTo;
- enum { ExactSize = true };
- static int size(QCharRef) { return 1; }
- static inline void appendTo(QCharRef c, QChar *&out)
- { *out++ = QChar(c); }
-};
-
template <> struct QConcatenable<QLatin1String> : private QAbstractConcatenable
{
typedef QLatin1String type;
diff --git a/src/corelib/text/qstringlist.h b/src/corelib/text/qstringlist.h
index a464d443dc..6e0940c488 100644
--- a/src/corelib/text/qstringlist.h
+++ b/src/corelib/text/qstringlist.h
@@ -38,7 +38,7 @@
**
****************************************************************************/
-#include <QtCore/qlist.h>
+#include <QtCore/qvector.h>
#ifndef QSTRINGLIST_H
#define QSTRINGLIST_H
@@ -55,21 +55,21 @@ class QRegExp;
class QRegularExpression;
#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
-typedef QListIterator<QString> QStringListIterator;
-typedef QMutableListIterator<QString> QMutableStringListIterator;
+typedef QVectorIterator<QString> QStringListIterator;
+typedef QMutableVectorIterator<QString> QMutableStringListIterator;
#endif
class QStringList;
#ifdef Q_QDOC
-class QStringList : public QList<QString>
+class QStringList : public QVector<QString>
#else
-template <> struct QListSpecialMethods<QString>
+template <> struct QVectorSpecialMethods<QString>
#endif
{
#ifndef Q_QDOC
protected:
- ~QListSpecialMethods() = default;
+ ~QVectorSpecialMethods() = default;
#endif
public:
inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive);
@@ -108,23 +108,23 @@ private:
};
// ### Qt6: check if there's a better way
-class QStringList : public QList<QString>
+class QStringList : public QVector<QString>
{
#endif
public:
inline QStringList() noexcept { }
inline explicit QStringList(const QString &i) { append(i); }
- inline QStringList(const QList<QString> &l) : QList<QString>(l) { }
- inline QStringList(QList<QString> &&l) noexcept : QList<QString>(std::move(l)) { }
- inline QStringList(std::initializer_list<QString> args) : QList<QString>(args) { }
+ inline QStringList(const QVector<QString> &l) : QVector<QString>(l) { }
+ inline QStringList(QVector<QString> &&l) noexcept : QVector<QString>(std::move(l)) { }
+ inline QStringList(std::initializer_list<QString> args) : QVector<QString>(args) { }
template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
inline QStringList(InputIterator first, InputIterator last)
- : QList<QString>(first, last) { }
+ : QVector<QString>(first, last) { }
- QStringList &operator=(const QList<QString> &other)
- { QList<QString>::operator=(other); return *this; }
- QStringList &operator=(QList<QString> &&other) noexcept
- { QList<QString>::operator=(std::move(other)); return *this; }
+ QStringList &operator=(const QVector<QString> &other)
+ { QVector<QString>::operator=(other); return *this; }
+ QStringList &operator=(QVector<QString> &&other) noexcept
+ { QVector<QString>::operator=(std::move(other)); return *this; }
#if QT_STRINGVIEW_LEVEL < 2
inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -138,7 +138,7 @@ public:
{ append(str); return *this; }
inline QStringList &operator<<(const QStringList &l)
{ *this += l; return *this; }
- inline QStringList &operator<<(const QList<QString> &l)
+ inline QStringList &operator<<(const QVector<QString> &l)
{ *this += l; return *this; }
inline int indexOf(QStringView str, int from = 0) const;
@@ -159,16 +159,16 @@ public:
inline int lastIndexOf(const QRegularExpression &re, int from = -1) const;
#endif // QT_CONFIG(regularexpression)
- using QList<QString>::indexOf;
- using QList<QString>::lastIndexOf;
+ using QVector<QString>::indexOf;
+ using QVector<QString>::lastIndexOf;
};
Q_DECLARE_TYPEINFO(QStringList, Q_MOVABLE_TYPE);
#ifndef Q_QDOC
-inline QStringList *QListSpecialMethods<QString>::self()
+inline QStringList *QVectorSpecialMethods<QString>::self()
{ return static_cast<QStringList *>(this); }
-inline const QStringList *QListSpecialMethods<QString>::self() const
+inline const QStringList *QVectorSpecialMethods<QString>::self() const
{ return static_cast<const QStringList *>(this); }
namespace QtPrivate {
@@ -213,45 +213,45 @@ namespace QtPrivate {
#endif // QT_CONFIG(regularexpression)
}
-inline void QListSpecialMethods<QString>::sort(Qt::CaseSensitivity cs)
+inline void QVectorSpecialMethods<QString>::sort(Qt::CaseSensitivity cs)
{
QtPrivate::QStringList_sort(self(), cs);
}
-inline int QListSpecialMethods<QString>::removeDuplicates()
+inline int QVectorSpecialMethods<QString>::removeDuplicates()
{
return QtPrivate::QStringList_removeDuplicates(self());
}
#if QT_STRINGVIEW_LEVEL < 2
-inline QString QListSpecialMethods<QString>::join(const QString &sep) const
+inline QString QVectorSpecialMethods<QString>::join(const QString &sep) const
{
return QtPrivate::QStringList_join(self(), sep.constData(), sep.length());
}
#endif
-inline QString QListSpecialMethods<QString>::join(QStringView sep) const
+inline QString QVectorSpecialMethods<QString>::join(QStringView sep) const
{
return QtPrivate::QStringList_join(self(), sep);
}
-QString QListSpecialMethods<QString>::join(QLatin1String sep) const
+QString QVectorSpecialMethods<QString>::join(QLatin1String sep) const
{
return QtPrivate::QStringList_join(*self(), sep);
}
-inline QString QListSpecialMethods<QString>::join(QChar sep) const
+inline QString QVectorSpecialMethods<QString>::join(QChar sep) const
{
return QtPrivate::QStringList_join(self(), &sep, 1);
}
-inline QStringList QListSpecialMethods<QString>::filter(QStringView str, Qt::CaseSensitivity cs) const
+inline QStringList QVectorSpecialMethods<QString>::filter(QStringView str, Qt::CaseSensitivity cs) const
{
return QtPrivate::QStringList_filter(self(), str, cs);
}
#if QT_STRINGVIEW_LEVEL < 2
-inline QStringList QListSpecialMethods<QString>::filter(const QString &str, Qt::CaseSensitivity cs) const
+inline QStringList QVectorSpecialMethods<QString>::filter(const QString &str, Qt::CaseSensitivity cs) const
{
return QtPrivate::QStringList_filter(self(), str, cs);
}
@@ -274,33 +274,33 @@ inline bool QStringList::contains(QStringView str, Qt::CaseSensitivity cs) const
return QtPrivate::QStringList_contains(this, str, cs);
}
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs)
+inline QStringList &QVectorSpecialMethods<QString>::replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs)
{
QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
return *self();
}
#if QT_STRINGVIEW_LEVEL < 2
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
+inline QStringList &QVectorSpecialMethods<QString>::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
{
QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
return *self();
}
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs)
+inline QStringList &QVectorSpecialMethods<QString>::replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs)
{
QtPrivate::QStringList_replaceInStrings(self(), before, qToStringViewIgnoringNull(after), cs);
return *self();
}
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs)
+inline QStringList &QVectorSpecialMethods<QString>::replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs)
{
QtPrivate::QStringList_replaceInStrings(self(), QStringView(before), after, cs);
return *self();
}
#endif
-inline QStringList operator+(const QList<QString> &one, const QStringList &other)
+inline QStringList operator+(const QVector<QString> &one, const QStringList &other)
{
QStringList n = one;
n += other;
@@ -328,13 +328,13 @@ inline int QStringList::lastIndexOf(QLatin1String string, int from) const
}
#ifndef QT_NO_REGEXP
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QRegExp &rx, const QString &after)
+inline QStringList &QVectorSpecialMethods<QString>::replaceInStrings(const QRegExp &rx, const QString &after)
{
QtPrivate::QStringList_replaceInStrings(self(), rx, after);
return *self();
}
-inline QStringList QListSpecialMethods<QString>::filter(const QRegExp &rx) const
+inline QStringList QVectorSpecialMethods<QString>::filter(const QRegExp &rx) const
{
return QtPrivate::QStringList_filter(self(), rx);
}
@@ -361,13 +361,13 @@ inline int QStringList::lastIndexOf(QRegExp &rx, int from) const
#endif
#if QT_CONFIG(regularexpression)
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QRegularExpression &rx, const QString &after)
+inline QStringList &QVectorSpecialMethods<QString>::replaceInStrings(const QRegularExpression &rx, const QString &after)
{
QtPrivate::QStringList_replaceInStrings(self(), rx, after);
return *self();
}
-inline QStringList QListSpecialMethods<QString>::filter(const QRegularExpression &rx) const
+inline QStringList QVectorSpecialMethods<QString>::filter(const QRegularExpression &rx) const
{
return QtPrivate::QStringList_filter(self(), rx);
}
diff --git a/src/corelib/text/qstringliteral.h b/src/corelib/text/qstringliteral.h
index 2a7e607c63..742d38de7d 100644
--- a/src/corelib/text/qstringliteral.h
+++ b/src/corelib/text/qstringliteral.h
@@ -42,6 +42,7 @@
#define QSTRINGLITERAL_H
#include <QtCore/qarraydata.h>
+#include <QtCore/qarraydatapointer.h>
#if 0
#pragma qt_class(QStringLiteral)
@@ -49,8 +50,6 @@
QT_BEGIN_NAMESPACE
-typedef QTypedArrayData<ushort> QStringData;
-
// all our supported compilers support Unicode string literals,
// even if their Q_COMPILER_UNICODE_STRING has been revoked due
// to lacking stdlib support. But QStringLiteral only needs the
@@ -65,44 +64,23 @@ Q_STATIC_ASSERT_X(sizeof(qunicodechar) == 2,
#define QStringLiteral(str) \
([]() noexcept -> QString { \
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
- static const QStaticStringData<Size> qstring_literal = { \
- Q_STATIC_STRING_DATA_HEADER_INITIALIZER(Size), \
- QT_UNICODE_LITERAL(str) }; \
- QStringDataPtr holder = { qstring_literal.data_ptr() }; \
- const QString qstring_literal_temp(holder); \
- return qstring_literal_temp; \
+ static const QArrayData qstring_literal = { \
+ Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 \
+ }; \
+ QStringPrivate holder = { \
+ static_cast<QTypedArrayData<ushort> *>(const_cast<QArrayData *>(&qstring_literal)), \
+ reinterpret_cast<ushort *>(const_cast<qunicodechar *>(QT_UNICODE_LITERAL(str))), \
+ Size \
+ }; \
+ return QString(holder); \
}()) \
/**/
-#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
- { Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, offset } \
- /**/
-
-#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER(size) \
- Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, sizeof(QStringData)) \
- /**/
-
#if QT_DEPRECATED_SINCE(5, 14)
# define QStringViewLiteral(str) QStringView(QT_UNICODE_LITERAL(str), QtPrivate::Deprecated)
#endif
-template <int N>
-struct QStaticStringData
-{
- QArrayData str;
- qunicodechar data[N + 1];
-
- QStringData *data_ptr() const
- {
- Q_ASSERT(str.ref.isStatic());
- return const_cast<QStringData *>(static_cast<const QStringData*>(&str));
- }
-};
-
-struct QStringDataPtr
-{
- QStringData *ptr;
-};
+using QStringPrivate = QArrayDataPointer<ushort>;
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index f1fd40e7b6..e6380a8732 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -424,12 +424,7 @@ void QFutureInterfaceBase::setProgressValueAndText(int progressValue,
}
}
-QMutex *QFutureInterfaceBase::mutex() const
-{
- return &d->m_mutex;
-}
-
-QMutex &QFutureInterfaceBase::mutex(int) const
+QMutex &QFutureInterfaceBase::mutex() const
{
return d->m_mutex;
}
diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h
index bcdae24833..43dfd6bac4 100644
--- a/src/corelib/thread/qfutureinterface.h
+++ b/src/corelib/thread/qfutureinterface.h
@@ -119,8 +119,7 @@ public:
void waitForResult(int resultIndex);
void waitForResume();
- QMutex *mutex() const;
- QMutex &mutex(int) const;
+ QMutex &mutex() const;
QtPrivate::ExceptionStore &exceptionStore();
QtPrivate::ResultStoreBase &resultStoreBase();
const QtPrivate::ResultStoreBase &resultStoreBase() const;
@@ -191,7 +190,7 @@ public:
template <typename T>
inline void QFutureInterface<T>::reportResult(const T *result, int index)
{
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
if (this->queryState(Canceled) || this->queryState(Finished)) {
return;
}
@@ -217,7 +216,7 @@ inline void QFutureInterface<T>::reportResult(const T &result, int index)
template <typename T>
inline void QFutureInterface<T>::reportResults(const QVector<T> &_results, int beginIndex, int count)
{
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
if (this->queryState(Canceled) || this->queryState(Finished)) {
return;
}
@@ -245,14 +244,14 @@ inline void QFutureInterface<T>::reportFinished(const T *result)
template <typename T>
inline const T &QFutureInterface<T>::resultReference(int index) const
{
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
return resultStoreBase().resultAt(index).template value<T>();
}
template <typename T>
inline const T *QFutureInterface<T>::resultPointer(int index) const
{
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
return resultStoreBase().resultAt(index).template pointer<T>();
}
@@ -266,7 +265,7 @@ inline QList<T> QFutureInterface<T>::results()
QFutureInterfaceBase::waitForResult(-1);
QList<T> res;
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
while (it != resultStoreBase().end()) {
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index d18056063f..155bff1758 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -853,7 +853,7 @@ bool QThread::event(QEvent* event)
return QObject::event(event);
}
-Qt::HANDLE QThread::currentThreadId() noexcept
+Qt::HANDLE QThread::currentThreadIdImpl() noexcept
{
return Qt::HANDLE(currentThread());
}
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index 2072e22340..635dd94522 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -161,6 +161,7 @@ private:
#if QT_CONFIG(cxx11_future)
static QThread *createThreadImpl(std::future<void> &&future);
#endif
+ static Qt::HANDLE currentThreadIdImpl() noexcept Q_DECL_PURE_FUNCTION;
friend class QCoreApplication;
friend class QThreadData;
@@ -236,6 +237,38 @@ QThread *QThread::create(Function &&f)
#endif // QT_CONFIG(cxx11_future)
+/*
+ On architectures and platforms we know, interpret the thread control
+ block (TCB) as a unique identifier for a thread within a process. Otherwise,
+ fall back to a slower but safe implementation.
+
+ As per the documentation of currentThreadId, we return an opaque handle
+ as a thread identifier, and application code is not supposed to use that
+ value for anything. In Qt we use the handle to check if threads are identical,
+ for which the TCB is sufficient.
+
+ So we use the fastest possible way, rathern than spend time on returning
+ some pseudo-interoperable value.
+*/
+inline Qt::HANDLE QThread::currentThreadId() noexcept
+{
+ Qt::HANDLE tid; // typedef to void*
+ Q_STATIC_ASSERT(sizeof(tid) == sizeof(void*));
+ // See https://akkadia.org/drepper/tls.pdf for x86 ABI
+#if defined(Q_PROCESSOR_X86_32) && defined(Q_OS_LINUX) // x86 32-bit always uses GS
+ __asm__("movl %%gs:0, %0" : "=r" (tid) : : );
+#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN64)
+ // 64bit macOS uses GS, see https://github.com/apple/darwin-xnu/blob/master/libsyscall/os/tsd.h
+ __asm__("movq %%gs:0, %0" : "=r" (tid) : : );
+#elif defined(Q_PROCESSOR_X86_64) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD))
+ // x86_64 Linux, BSD uses FS
+ __asm__("movq %%fs:0, %0" : "=r" (tid) : : );
+#else
+ tid = currentThreadIdImpl();
+#endif
+ return tid;
+}
+
QT_END_NAMESPACE
#endif // QTHREAD_H
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 1da68b3130..727d72a334 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -415,16 +415,36 @@ void QThreadPrivate::finish(void *arg)
}
-
-
/**************************************************************************
** QThread
*************************************************************************/
-Qt::HANDLE QThread::currentThreadId() noexcept
+/*
+ Since each thread is guaranteed to have its own copy of
+ currenThreadData, the address is guaranteed to be unique for each
+ running thread (but likely to be reused for newly started threads).
+
+ CI tests fails on ARM architectures if we try to use the assembler,
+ or the address of the thread_local (even with a recent gcc version), so
+ stick to the pthread version there. The assembler would be
+
+ // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344k/Babeihid.html
+ asm volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (tid));
+
+ and
+
+ // see glibc/sysdeps/aarch64/nptl/tls.h
+ asm volatile ("mrs %0, tpidr_el0" : "=r" (tid));
+
+ for 32 and 64bit versions, respectively.
+*/
+Qt::HANDLE QThread::currentThreadIdImpl() noexcept
{
- // requires a C cast here otherwise we run into trouble on AIX
+#if defined(Q_PROCESSOR_ARM)
return to_HANDLE(pthread_self());
+#else
+ return &currentThreadData;
+#endif
}
#if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN)
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index bc70e3178a..00d67b3a00 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -449,7 +449,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) noexcept
** QThread
*************************************************************************/
-Qt::HANDLE QThread::currentThreadId() noexcept
+Qt::HANDLE QThread::currentThreadIdImpl() noexcept
{
return reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
}
diff --git a/src/corelib/time/qdatetimeparser_p.h b/src/corelib/time/qdatetimeparser_p.h
index 5c612ef6a4..bc390db223 100644
--- a/src/corelib/time/qdatetimeparser_p.h
+++ b/src/corelib/time/qdatetimeparser_p.h
@@ -77,7 +77,6 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QDateTimeParser
{
- Q_DECLARE_TR_FUNCTIONS(QDateTimeParser)
public:
enum Context {
FromString,
@@ -267,10 +266,11 @@ protected: // for the benefit of QDateTimeEditPrivate
return skipToNextSection(section, current, QStringRef(&sectionText));
}
QString stateName(State s) const;
+ QString getAmPmText(AmPm ap, Case cs) const;
+
virtual QDateTime getMinimum() const;
virtual QDateTime getMaximum() const;
virtual int cursorPosition() const { return -1; }
- virtual QString getAmPmText(AmPm ap, Case cs) const;
virtual QLocale locale() const { return defaultLocale; }
mutable int currentSectionIndex;
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 3879b48cbb..497eae1f7f 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -153,18 +153,16 @@ QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers")
const QArrayData QArrayData::shared_null[2] = {
- { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, sizeof(QArrayData) }, // shared null
+ { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }, // shared null
/* zero initialized terminator */};
-static const QArrayData qt_array[3] = {
- { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, sizeof(QArrayData) }, // shared empty
- { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, sizeof(QArrayData) }, // unsharable empty
+static const QArrayData emptyNotNullShared[2] = {
+ { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }, // shared empty
/* zero initialized terminator */};
QT_WARNING_POP
-static const QArrayData &qt_array_empty = qt_array[0];
-static const QArrayData &qt_array_unsharable_empty = qt_array[1];
+static const QArrayData &qt_array_empty = emptyNotNullShared[0];
static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, size_t headerSize,
uint options)
@@ -172,7 +170,7 @@ static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, siz
// Calculate the byte size
// allocSize = objectSize * capacity + headerSize, but checked for overflow
// plus padded to grow in size
- if (options & QArrayData::Grow) {
+ if (options & QArrayData::GrowsForward) {
auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
capacity = r.elementCount;
return r.size;
@@ -181,91 +179,104 @@ static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, siz
}
}
+static QArrayData *allocateData(size_t allocSize, uint options)
+{
+ QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
+ if (header) {
+ header->ref_.storeRelaxed(1);
+ header->flags = options;
+ header->alloc = 0;
+ }
+ return header;
+}
+
static QArrayData *reallocateData(QArrayData *header, size_t allocSize, uint options)
{
header = static_cast<QArrayData *>(::realloc(header, allocSize));
if (header)
- header->capacityReserved = bool(options & QArrayData::CapacityReserved);
+ header->flags = options;
return header;
}
-QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
- size_t capacity, AllocationOptions options) noexcept
+void *QArrayData::allocate(QArrayData **dptr, size_t objectSize, size_t alignment,
+ size_t capacity, ArrayOptions options) noexcept
{
+ Q_ASSERT(dptr);
// Alignment is a power of two
- Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
+ Q_ASSERT(alignment >= alignof(QArrayData)
&& !(alignment & (alignment - 1)));
- // Don't allocate empty headers
- if (!(options & RawData) && !capacity) {
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- if (options & Unsharable)
- return const_cast<QArrayData *>(&qt_array_unsharable_empty);
-#endif
- return const_cast<QArrayData *>(&qt_array_empty);
+ if (capacity == 0) {
+ // optimization for empty headers
+ *dptr = const_cast<QArrayData *>(&qt_array_empty);
+ return sharedNullData();
}
size_t headerSize = sizeof(QArrayData);
- // Allocate extra (alignment - Q_ALIGNOF(QArrayData)) padding bytes so we
- // can properly align the data array. This assumes malloc is able to
- // provide appropriate alignment for the header -- as it should!
- // Padding is skipped when allocating a header for RawData.
- if (!(options & RawData))
- headerSize += (alignment - Q_ALIGNOF(QArrayData));
+ if (alignment > alignof(QArrayData)) {
+ // Allocate extra (alignment - Q_ALIGNOF(QArrayData)) padding bytes so we
+ // can properly align the data array. This assumes malloc is able to
+ // provide appropriate alignment for the header -- as it should!
+ headerSize += alignment - alignof(QArrayData);
+ }
if (headerSize > size_t(MaxAllocSize))
return nullptr;
size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
- QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
+ options |= AllocatedDataType | MutableData;
+ options &= ~ImmutableHeader;
+ QArrayData *header = allocateData(allocSize, options);
+ quintptr data = 0;
if (header) {
- quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
+ // find where offset should point to so that data() is aligned to alignment bytes
+ data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
& ~(alignment - 1);
-
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- header->ref.atomic.storeRelaxed(bool(!(options & Unsharable)));
-#else
- header->ref.atomic.storeRelaxed(1);
-#endif
- header->size = 0;
- header->alloc = capacity;
- header->capacityReserved = bool(options & CapacityReserved);
- header->offset = data - quintptr(header);
+ header->alloc = uint(capacity);
}
+ *dptr = header;
+ return reinterpret_cast<void *>(data);
+}
+
+QArrayData *QArrayData::prepareRawData(ArrayOptions options) Q_DECL_NOTHROW
+{
+ QArrayData *header = allocateData(sizeof(QArrayData), (options & ~DataTypeBits) | RawDataType);
+ if (header)
+ header->alloc = 0;
return header;
}
-QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, size_t capacity,
- AllocationOptions options) noexcept
+QPair<QArrayData *, void *>
+QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer,
+ size_t objectSize, size_t capacity, ArrayOptions options) noexcept
{
Q_ASSERT(data);
Q_ASSERT(data->isMutable());
- Q_ASSERT(!data->ref.isShared());
+ Q_ASSERT(!data->isShared());
size_t headerSize = sizeof(QArrayData);
size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
- QArrayData *header = static_cast<QArrayData *>(reallocateData(data, allocSize, options));
- if (header)
- header->alloc = capacity;
- return header;
+ qptrdiff offset = reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data);
+ options |= AllocatedDataType | MutableData;
+ QArrayData *header = reallocateData(data, allocSize, options);
+ if (header) {
+ header->alloc = uint(capacity);
+ dataPointer = reinterpret_cast<char *>(header) + offset;
+ }
+ return qMakePair(static_cast<QArrayData *>(header), dataPointer);
}
void QArrayData::deallocate(QArrayData *data, size_t objectSize,
size_t alignment) noexcept
{
// Alignment is a power of two
- Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
+ Q_ASSERT(alignment >= alignof(QArrayData)
&& !(alignment & (alignment - 1)));
Q_UNUSED(objectSize) Q_UNUSED(alignment)
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- if (data == &qt_array_unsharable_empty)
- return;
-#endif
-
- Q_ASSERT_X(data == nullptr || !data->ref.isStatic(), "QArrayData::deallocate",
+ Q_ASSERT_X(data == nullptr || !data->isStatic(), "QArrayData::deallocate",
"Static data cannot be deleted");
::free(data);
}
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index dcd95924c1..483f6d5edb 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -40,32 +41,64 @@
#ifndef QARRAYDATA_H
#define QARRAYDATA_H
-#include <QtCore/qrefcount.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qatomic.h>
#include <string.h>
QT_BEGIN_NAMESPACE
+template <class T> struct QTypedArrayData;
+
struct Q_CORE_EXPORT QArrayData
{
- QtPrivate::RefCount ref;
- int size;
- uint alloc : 31;
- uint capacityReserved : 1;
+ enum ArrayOption {
+ RawDataType = 0x0001, //!< this class is really a QArrayData
+ AllocatedDataType = 0x0002, //!< this class is really a QArrayAllocatedData
+ DataTypeBits = 0x000f,
+
+ CapacityReserved = 0x0010, //!< the capacity was reserved by the user, try to keep it
+ GrowsForward = 0x0020, //!< allocate with eyes towards growing through append()
+ GrowsBackwards = 0x0040, //!< allocate with eyes towards growing through prepend()
+ MutableData = 0x0080, //!< the data can be changed; doesn't say anything about the header
+ ImmutableHeader = 0x0100, //!< the header is static, it can't be changed
+
+ /// this option is used by the Q_ARRAY_LITERAL and similar macros
+ StaticDataFlags = RawDataType | ImmutableHeader,
+ /// this option is used by the allocate() function
+ DefaultAllocationFlags = MutableData,
+ /// this option is used by the prepareRawData() function
+ DefaultRawFlags = 0
+ };
+ Q_DECLARE_FLAGS(ArrayOptions, ArrayOption)
- qptrdiff offset; // in bytes from beginning of header
+ QBasicAtomicInt ref_;
+ uint flags;
+ uint alloc;
+
+ inline size_t allocatedCapacity()
+ {
+ return alloc;
+ }
+
+ inline size_t constAllocatedCapacity() const
+ {
+ return alloc;
+ }
- void *data()
+ /// Returns true if sharing took place
+ bool ref()
{
- Q_ASSERT(size == 0
- || offset < 0 || size_t(offset) >= sizeof(QArrayData));
- return reinterpret_cast<char *>(this) + offset;
+ if (!isStatic())
+ ref_.ref();
+ return true;
}
- const void *data() const
+ /// Returns false if deallocation is necessary
+ bool deref()
{
- Q_ASSERT(size == 0
- || offset < 0 || size_t(offset) >= sizeof(QArrayData));
- return reinterpret_cast<const char *>(this) + offset;
+ if (isStatic())
+ return true;
+ return ref_.deref();
}
// This refers to array data mutability, not "header data" represented by
@@ -73,57 +106,93 @@ struct Q_CORE_EXPORT QArrayData
// follow COW principles.
bool isMutable() const
{
- return alloc != 0;
+ return flags & MutableData;
}
- enum AllocationOption {
- CapacityReserved = 0x1,
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- Unsharable = 0x2,
-#endif
- RawData = 0x4,
- Grow = 0x8,
+ bool isStatic() const
+ {
+ return flags & ImmutableHeader;
+ }
- Default = 0
- };
+ bool isShared() const
+ {
+ return ref_.loadRelaxed() != 1;
+ }
- Q_DECLARE_FLAGS(AllocationOptions, AllocationOption)
+ // Returns true if a detach is necessary before modifying the data
+ // This method is intentionally not const: if you want to know whether
+ // detaching is necessary, you should be in a non-const function already
+ bool needsDetach()
+ {
+ // requires two conditionals
+ return !isMutable() || isShared();
+ }
size_t detachCapacity(size_t newSize) const
{
- if (capacityReserved && newSize < alloc)
- return alloc;
+ if (flags & CapacityReserved && newSize < constAllocatedCapacity())
+ return constAllocatedCapacity();
return newSize;
}
- AllocationOptions detachFlags() const
+ ArrayOptions detachFlags() const
{
- AllocationOptions result;
- if (capacityReserved)
+ ArrayOptions result = DefaultAllocationFlags;
+ if (flags & CapacityReserved)
result |= CapacityReserved;
return result;
}
- AllocationOptions cloneFlags() const
+ ArrayOptions cloneFlags() const
{
- AllocationOptions result;
- if (capacityReserved)
+ ArrayOptions result = DefaultAllocationFlags;
+ if (flags & CapacityReserved)
result |= CapacityReserved;
return result;
}
- Q_REQUIRED_RESULT static QArrayData *allocate(size_t objectSize, size_t alignment,
- size_t capacity, AllocationOptions options = Default) noexcept;
+ Q_REQUIRED_RESULT
+#if defined(Q_CC_GNU)
+ __attribute__((__malloc__))
+#endif
+ static void *allocate(QArrayData **pdata, size_t objectSize, size_t alignment,
+ size_t capacity, ArrayOptions options = DefaultAllocationFlags) noexcept;
Q_REQUIRED_RESULT static QArrayData *reallocateUnaligned(QArrayData *data, size_t objectSize,
- size_t newCapacity, AllocationOptions newOptions = Default) noexcept;
+ size_t newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) noexcept;
+ Q_REQUIRED_RESULT static QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer,
+ size_t objectSize, size_t newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT static QArrayData *prepareRawData(ArrayOptions options = ArrayOptions(RawDataType))
+ Q_DECL_NOTHROW;
static void deallocate(QArrayData *data, size_t objectSize,
size_t alignment) noexcept;
static const QArrayData shared_null[2];
static QArrayData *sharedNull() noexcept { return const_cast<QArrayData*>(shared_null); }
+ static void *sharedNullData()
+ {
+ QArrayData *const null = const_cast<QArrayData *>(&shared_null[1]);
+ return null;
+ }
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions)
+
+template <class T, size_t N>
+struct QStaticArrayData
+{
+ // static arrays are of type RawDataType
+ QArrayData header;
+ T data[N];
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::AllocationOptions)
+// Support for returning QArrayDataPointer<T> from functions
+template <class T>
+struct QArrayDataPointerRef
+{
+ QTypedArrayData<T> *ptr;
+ T *data;
+ uint size;
+};
template <class T>
struct QTypedArrayData
@@ -205,51 +274,45 @@ struct QTypedArrayData
typedef const T* const_iterator;
#endif
- T *data() { return static_cast<T *>(QArrayData::data()); }
- const T *data() const { return static_cast<const T *>(QArrayData::data()); }
-
- iterator begin(iterator = iterator()) { return data(); }
- iterator end(iterator = iterator()) { return data() + size; }
- const_iterator begin(const_iterator = const_iterator()) const { return data(); }
- const_iterator end(const_iterator = const_iterator()) const { return data() + size; }
- const_iterator constBegin(const_iterator = const_iterator()) const { return data(); }
- const_iterator constEnd(const_iterator = const_iterator()) const { return data() + size; }
-
class AlignmentDummy { QArrayData header; T data; };
- Q_REQUIRED_RESULT static QTypedArrayData *allocate(size_t capacity,
- AllocationOptions options = Default)
+ Q_REQUIRED_RESULT static QPair<QTypedArrayData *, T *> allocate(size_t capacity,
+ ArrayOptions options = DefaultAllocationFlags)
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
- return static_cast<QTypedArrayData *>(QArrayData::allocate(sizeof(T),
- Q_ALIGNOF(AlignmentDummy), capacity, options));
+ QArrayData *d;
+ void *result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, options);
+#if (defined(Q_CC_GNU) && Q_CC_GNU >= 407) || QT_HAS_BUILTIN(__builtin_assume_aligned)
+ result = __builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy));
+#endif
+ return qMakePair(static_cast<QTypedArrayData *>(d), static_cast<T *>(result));
}
- static QTypedArrayData *reallocateUnaligned(QTypedArrayData *data, size_t capacity,
- AllocationOptions options = Default)
+ static QPair<QTypedArrayData *, T *>
+ reallocateUnaligned(QTypedArrayData *data, T *dataPointer, size_t capacity,
+ ArrayOptions options = DefaultAllocationFlags)
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
- return static_cast<QTypedArrayData *>(QArrayData::reallocateUnaligned(data, sizeof(T),
- capacity, options));
+ QPair<QArrayData *, void *> pair =
+ QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, options);
+ return qMakePair(static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second));
}
static void deallocate(QArrayData *data)
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
- QArrayData::deallocate(data, sizeof(T), Q_ALIGNOF(AlignmentDummy));
+ QArrayData::deallocate(data, sizeof(T), alignof(AlignmentDummy));
}
- static QTypedArrayData *fromRawData(const T *data, size_t n,
- AllocationOptions options = Default)
+ static QArrayDataPointerRef<T> fromRawData(const T *data, size_t n,
+ ArrayOptions options = DefaultRawFlags)
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
- QTypedArrayData *result = allocate(0, options | RawData);
- if (result) {
- Q_ASSERT(!result->ref.isShared()); // No shared empty, please!
-
- result->offset = reinterpret_cast<const char *>(data)
- - reinterpret_cast<const char *>(result);
- result->size = int(n);
+ QArrayDataPointerRef<T> result = {
+ static_cast<QTypedArrayData *>(prepareRawData(options)), const_cast<T *>(data), uint(n)
+ };
+ if (result.ptr) {
+ Q_ASSERT(!result.ptr->isShared()); // No shared empty, please!
}
return result;
}
@@ -266,38 +329,13 @@ struct QTypedArrayData
return allocate(/* capacity */ 0);
}
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- static QTypedArrayData *unsharableEmpty()
+ static T *sharedNullData()
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
- return allocate(/* capacity */ 0, Unsharable);
+ return static_cast<T *>(QArrayData::sharedNullData());
}
-#endif
-};
-
-template <class T, size_t N>
-struct QStaticArrayData
-{
- QArrayData header;
- T data[N];
-};
-
-// Support for returning QArrayDataPointer<T> from functions
-template <class T>
-struct QArrayDataPointerRef
-{
- QTypedArrayData<T> *ptr;
};
-#define Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
- { Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, offset } \
- /**/
-
-#define Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(type, size) \
- Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size,\
- ((sizeof(QArrayData) + (Q_ALIGNOF(type) - 1)) & ~(Q_ALIGNOF(type) - 1) )) \
- /**/
-
////////////////////////////////////////////////////////////////////////////////
// Q_ARRAY_LITERAL
@@ -333,15 +371,16 @@ struct QArrayDataPointerRef
Q_ARRAY_LITERAL_CHECK_LITERAL_TYPE(Type); \
\
/* Portable compile-time array size computation */ \
- Q_CONSTEXPR Type data[] = { __VA_ARGS__ }; Q_UNUSED(data); \
+ static Type const data[] = { __VA_ARGS__ }; \
enum { Size = sizeof(data) / sizeof(data[0]) }; \
\
- static const QStaticArrayData<Type, Size> literal = { \
- Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(Type, Size), { __VA_ARGS__ } }; \
+ static const QArrayData literal = { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }; \
\
QArrayDataPointerRef<Type> ref = \
{ static_cast<QTypedArrayData<Type> *>( \
- const_cast<QArrayData *>(&literal.header)) }; \
+ const_cast<QArrayData *>(&literal)), \
+ const_cast<Type *>(data), \
+ Size }; \
/**/
namespace QtPrivate {
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index 8e19525f07..0d2be5d51c 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -41,12 +42,15 @@
#define QARRAYDATAOPS_H
#include <QtCore/qarraydata.h>
+#include <QtCore/qcontainertools_impl.h>
#include <new>
#include <string.h>
QT_BEGIN_NAMESPACE
+template <class T> struct QArrayDataPointer;
+
namespace QtPrivate {
QT_WARNING_PUSH
@@ -56,48 +60,67 @@ QT_WARNING_DISABLE_GCC("-Wstringop-overflow")
template <class T>
struct QPodArrayOps
- : QTypedArrayData<T>
+ : public QArrayDataPointer<T>
{
+ typedef typename QArrayDataPointer<T>::parameter_type parameter_type;
+
void appendInitialize(size_t newSize)
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(!this->isShared());
Q_ASSERT(newSize > uint(this->size));
- Q_ASSERT(newSize <= this->alloc);
+ Q_ASSERT(newSize <= this->allocatedCapacity());
::memset(static_cast<void *>(this->end()), 0, (newSize - this->size) * sizeof(T));
this->size = int(newSize);
}
+ template<typename iterator>
+ void copyAppend(iterator b, iterator e, QtPrivate::IfIsForwardIterator<iterator> = true)
+ {
+ Q_ASSERT(this->isMutable() || b == e);
+ Q_ASSERT(!this->isShared() || b == e);
+ Q_ASSERT(std::distance(b, e) >= 0 && size_t(std::distance(b, e)) <= this->allocatedCapacity() - this->size);
+
+ T *iter = this->end();
+ for (; b != e; ++iter, ++b) {
+ new (iter) T(*b);
+ ++this->size;
+ }
+ }
+
void copyAppend(const T *b, const T *e)
{
- Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
- Q_ASSERT(b < e);
- Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+ Q_ASSERT(this->isMutable() || b == e);
+ Q_ASSERT(!this->isShared() || b == e);
+ Q_ASSERT(b <= e);
+ Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
::memcpy(static_cast<void *>(this->end()), static_cast<const void *>(b),
(e - b) * sizeof(T));
this->size += e - b;
}
- void copyAppend(size_t n, const T &t)
+ void moveAppend(T *b, T *e)
+ { copyAppend(b, e); }
+
+ void copyAppend(size_t n, parameter_type t)
{
- Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
- Q_ASSERT(n <= this->alloc - uint(this->size));
+ Q_ASSERT(this->isMutable() || n == 0);
+ Q_ASSERT(!this->isShared() || n == 0);
+ Q_ASSERT(n <= uint(this->allocatedCapacity() - this->size));
T *iter = this->end();
const T *const end = iter + n;
for (; iter != end; ++iter)
- ::memcpy(iter, &t, sizeof(T));
+ *iter = t;
this->size += int(n);
}
void truncate(size_t newSize)
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(!this->isShared());
Q_ASSERT(newSize < size_t(this->size));
this->size = int(newSize);
@@ -106,7 +129,7 @@ struct QPodArrayOps
void destroyAll() // Call from destructors, ONLY!
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(this->ref.atomic.loadRelaxed() == 0);
+ Q_ASSERT(this->d->ref_.loadRelaxed() == 0);
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
@@ -115,11 +138,11 @@ struct QPodArrayOps
void insert(T *where, const T *b, const T *e)
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(!this->isShared());
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
- Q_ASSERT(b < e);
+ Q_ASSERT(b <= e);
Q_ASSERT(e <= where || b > this->end()); // No overlap
- Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+ Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
::memmove(static_cast<void *>(where + (e - b)), static_cast<void *>(where),
(static_cast<const T*>(this->end()) - where) * sizeof(T));
@@ -127,43 +150,97 @@ struct QPodArrayOps
this->size += (e - b);
}
+ void insert(T *where, size_t n, parameter_type t)
+ {
+ Q_ASSERT(!this->isShared());
+ Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
+ Q_ASSERT(this->allocatedCapacity() - this->size >= n);
+
+ ::memmove(static_cast<void *>(where + n), static_cast<void *>(where),
+ (static_cast<const T*>(this->end()) - where) * sizeof(T));
+ this->size += int(n); // PODs can't throw on copy
+ while (n--)
+ *where++ = t;
+ }
+
+ void insert(T *where, T &&t)
+ {
+ Q_ASSERT(!this->isShared());
+ Q_ASSERT(where >= this->begin() && where <= this->end());
+ Q_ASSERT(this->allocatedCapacity() - this->size >= 1);
+
+ ::memmove(static_cast<void *>(where + 1), static_cast<void *>(where),
+ (static_cast<const T*>(this->end()) - where) * sizeof(T));
+ this->size += 1;
+ new (where) T(std::move(t));
+ }
+
+
void erase(T *b, T *e)
{
Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
- Q_ASSERT(e > this->begin() && e < this->end());
+ Q_ASSERT(e > this->begin() && e <= this->end());
::memmove(static_cast<void *>(b), static_cast<void *>(e),
(static_cast<T *>(this->end()) - e) * sizeof(T));
this->size -= (e - b);
}
+
+ void assign(T *b, T *e, parameter_type t)
+ {
+ Q_ASSERT(b <= e);
+ Q_ASSERT(b >= this->begin() && e <= this->end());
+
+ while (b != e)
+ ::memcpy(static_cast<void *>(b++), static_cast<const void *>(&t), sizeof(T));
+ }
+
+ bool compare(const T *begin1, const T *begin2, size_t n) const
+ {
+ // only use memcmp for fundamental types or pointers.
+ // Other types could have padding in the data structure or custom comparison
+ // operators that would break the comparison using memcmp
+ if (QArrayDataPointer<T>::pass_parameter_by_value)
+ return ::memcmp(begin1, begin2, n * sizeof(T)) == 0;
+ const T *end1 = begin1 + n;
+ while (begin1 != end1) {
+ if (*begin1 == *begin2)
+ ++begin1, ++begin2;
+ else
+ return false;
+ }
+ return true;
+ }
};
QT_WARNING_POP
template <class T>
struct QGenericArrayOps
- : QTypedArrayData<T>
+ : public QArrayDataPointer<T>
{
+ typedef typename QArrayDataPointer<T>::parameter_type parameter_type;
+
void appendInitialize(size_t newSize)
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(!this->isShared());
Q_ASSERT(newSize > uint(this->size));
- Q_ASSERT(newSize <= this->alloc);
+ Q_ASSERT(newSize <= this->allocatedCapacity());
- T *const begin = this->begin();
+ T *const b = this->begin();
do {
- new (begin + this->size) T;
+ new (b + this->size) T;
} while (uint(++this->size) != newSize);
}
- void copyAppend(const T *b, const T *e)
+ template<typename iterator>
+ void copyAppend(iterator b, iterator e, QtPrivate::IfIsForwardIterator<iterator> = true)
{
- Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
- Q_ASSERT(b < e);
- Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+ Q_ASSERT(this->isMutable() || b == e);
+ Q_ASSERT(!this->isShared() || b == e);
+ Q_ASSERT(std::distance(b, e) >= 0 && size_t(std::distance(b, e)) <= this->allocatedCapacity() - this->size);
T *iter = this->end();
for (; b != e; ++iter, ++b) {
@@ -172,11 +249,37 @@ struct QGenericArrayOps
}
}
- void copyAppend(size_t n, const T &t)
+ void copyAppend(const T *b, const T *e)
{
- Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
- Q_ASSERT(n <= this->alloc - uint(this->size));
+ Q_ASSERT(this->isMutable() || b == e);
+ Q_ASSERT(!this->isShared() || b == e);
+ Q_ASSERT(std::distance(b, e) >= 0 && size_t(std::distance(b, e)) <= this->allocatedCapacity() - this->size);
+
+ T *iter = this->end();
+ this->size += e - b;
+ for (; b != e; ++iter, ++b)
+ new (iter) T(*b);
+ }
+
+ void moveAppend(T *b, T *e)
+ {
+ Q_ASSERT(this->isMutable() || b == e);
+ Q_ASSERT(!this->isShared() || b == e);
+ Q_ASSERT(b <= e);
+ Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
+
+ T *iter = this->end();
+ for (; b != e; ++iter, ++b) {
+ new (iter) T(std::move(*b));
+ ++this->size;
+ }
+ }
+
+ void copyAppend(size_t n, parameter_type t)
+ {
+ Q_ASSERT(this->isMutable() || n == 0);
+ Q_ASSERT(!this->isShared() || n == 0);
+ Q_ASSERT(n <= size_t(this->allocatedCapacity() - this->size));
T *iter = this->end();
const T *const end = iter + n;
@@ -189,7 +292,7 @@ struct QGenericArrayOps
void truncate(size_t newSize)
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(!this->isShared());
Q_ASSERT(newSize < size_t(this->size));
const T *const b = this->begin();
@@ -204,7 +307,7 @@ struct QGenericArrayOps
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
- Q_ASSERT(this->ref.atomic.loadRelaxed() == 0);
+ Q_ASSERT(this->d->ref_.loadRelaxed() == 0);
const T *const b = this->begin();
const T *i = this->end();
@@ -216,11 +319,11 @@ struct QGenericArrayOps
void insert(T *where, const T *b, const T *e)
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(!this->isShared());
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
- Q_ASSERT(b < e);
+ Q_ASSERT(b <= e);
Q_ASSERT(e <= where || b > this->end()); // No overlap
- Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+ Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
// Array may be truncated at where in case of exceptions
@@ -279,25 +382,139 @@ struct QGenericArrayOps
}
}
+ void insert(T *where, size_t n, parameter_type t)
+ {
+ Q_ASSERT(!this->isShared());
+ Q_ASSERT(where >= this->begin() && where <= this->end());
+ Q_ASSERT(this->allocatedCapacity() - this->size >= n);
+
+ // Array may be truncated at where in case of exceptions
+ T *const end = this->end();
+ const T *readIter = end;
+ T *writeIter = end + n;
+
+ const T *const step1End = where + qMax<size_t>(n, end - where);
+
+ struct Destructor
+ {
+ Destructor(T *&it)
+ : iter(&it)
+ , end(it)
+ {
+ }
+
+ void commit()
+ {
+ iter = &end;
+ }
+
+ ~Destructor()
+ {
+ for (; *iter != end; --*iter)
+ (*iter)->~T();
+ }
+
+ T **iter;
+ T *end;
+ } destroyer(writeIter);
+
+ // Construct new elements in array
+ do {
+ --readIter, --writeIter;
+ new (writeIter) T(*readIter);
+ } while (writeIter != step1End);
+
+ while (writeIter != end) {
+ --n, --writeIter;
+ new (writeIter) T(t);
+ }
+
+ destroyer.commit();
+ this->size += destroyer.end - end;
+
+ // Copy assign over existing elements
+ while (readIter != where) {
+ --readIter, --writeIter;
+ *writeIter = *readIter;
+ }
+
+ while (writeIter != where) {
+ --n, --writeIter;
+ *writeIter = t;
+ }
+ }
+
+ void insert(T *where, T &&t)
+ {
+ Q_ASSERT(!this->isShared());
+ Q_ASSERT(where >= this->begin() && where <= this->end());
+ Q_ASSERT(this->allocatedCapacity() - this->size >= 1);
+
+ // Array may be truncated at where in case of exceptions
+ T *const end = this->end();
+
+ if (where != end) {
+ // Move elements in array
+ T *readIter = end - 1;
+ T *writeIter = end;
+ new (writeIter) T(std::move(*readIter));
+ while (readIter > where) {
+ --readIter;
+ --writeIter;
+ *writeIter = std::move(*readIter);
+ }
+ *where = std::move(t);
+ } else {
+ new (where) T(std::move(t));
+ }
+
+ ++this->size;
+ }
+
void erase(T *b, T *e)
{
Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
- Q_ASSERT(e > this->begin() && e < this->end());
+ Q_ASSERT(e > this->begin() && e <= this->end());
const T *const end = this->end();
- do {
+ // move (by assignment) the elements from e to end
+ // onto b to the new end
+ while (e != end) {
*b = *e;
++b, ++e;
- } while (e != end);
+ }
+ // destroy the final elements at the end
+ // here, b points to the new end and e to the actual end
do {
(--e)->~T();
--this->size;
} while (e != b);
}
+
+ void assign(T *b, T *e, parameter_type t)
+ {
+ Q_ASSERT(b <= e);
+ Q_ASSERT(b >= this->begin() && e <= this->end());
+
+ while (b != e)
+ *b++ = t;
+ }
+
+ bool compare(const T *begin1, const T *begin2, size_t n) const
+ {
+ const T *end1 = begin1 + n;
+ while (begin1 != end1) {
+ if (*begin1 == *begin2)
+ ++begin1, ++begin2;
+ else
+ return false;
+ }
+ return true;
+ }
};
template <class T>
@@ -308,15 +525,16 @@ struct QMovableArrayOps
// using QGenericArrayOps<T>::copyAppend;
// using QGenericArrayOps<T>::truncate;
// using QGenericArrayOps<T>::destroyAll;
+ typedef typename QGenericArrayOps<T>::parameter_type parameter_type;
void insert(T *where, const T *b, const T *e)
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(!this->isShared());
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
- Q_ASSERT(b < e);
+ Q_ASSERT(b <= e);
Q_ASSERT(e <= where || b > this->end()); // No overlap
- Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+ Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
// Provides strong exception safety guarantee,
// provided T::~T() nothrow
@@ -376,12 +594,79 @@ struct QMovableArrayOps
this->size += (e - b);
}
+ void insert(T *where, size_t n, parameter_type t)
+ {
+ Q_ASSERT(!this->isShared());
+ Q_ASSERT(where >= this->begin() && where <= this->end());
+ Q_ASSERT(this->allocatedCapacity() - this->size >= n);
+
+ // Provides strong exception safety guarantee,
+ // provided T::~T() nothrow
+
+ struct ReversibleDisplace
+ {
+ ReversibleDisplace(T *start, T *finish, size_t diff)
+ : begin(start)
+ , end(finish)
+ , displace(diff)
+ {
+ ::memmove(static_cast<void *>(begin + displace), static_cast<void *>(begin),
+ (end - begin) * sizeof(T));
+ }
+
+ void commit() { displace = 0; }
+
+ ~ReversibleDisplace()
+ {
+ if (displace)
+ ::memmove(static_cast<void *>(begin), static_cast<void *>(begin + displace),
+ (end - begin) * sizeof(T));
+ }
+
+ T *const begin;
+ T *const end;
+ size_t displace;
+
+ } displace(where, this->end(), n);
+
+ struct CopyConstructor
+ {
+ CopyConstructor(T *w) : where(w) {}
+
+ void copy(size_t count, parameter_type proto)
+ {
+ n = 0;
+ while (count--) {
+ new (where + n) T(proto);
+ ++n;
+ }
+ n = 0;
+ }
+
+ ~CopyConstructor()
+ {
+ while (n)
+ where[--n].~T();
+ }
+
+ T *const where;
+ size_t n;
+ } copier(where);
+
+ copier.copy(n, t);
+ displace.commit();
+ this->size += int(n);
+ }
+
+ // use moving insert
+ using QGenericArrayOps<T>::insert;
+
void erase(T *b, T *e)
{
Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
- Q_ASSERT(e > this->begin() && e < this->end());
+ Q_ASSERT(e > this->begin() && e <= this->end());
struct Mover
{
@@ -405,11 +690,51 @@ struct QMovableArrayOps
int &size;
} mover(e, this->end(), this->size);
+ // destroy the elements we're erasing
do {
// Exceptions or not, dtor called once per instance
(--e)->~T();
} while (e != b);
}
+
+ void moveAppend(T *b, T *e)
+ {
+ Q_ASSERT(this->isMutable());
+ Q_ASSERT(!this->isShared());
+ Q_ASSERT(b <= e);
+ Q_ASSERT(e <= this->begin() || b > this->end()); // No overlap
+ Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
+
+ // Provides strong exception safety guarantee,
+ // provided T::~T() nothrow
+
+ struct CopyConstructor
+ {
+ CopyConstructor(T *w) : where(w) {}
+
+ void copy(T *src, const T *const srcEnd)
+ {
+ n = 0;
+ for (; src != srcEnd; ++src) {
+ new (where + n) T(std::move(*src));
+ ++n;
+ }
+ n = 0;
+ }
+
+ ~CopyConstructor()
+ {
+ while (n)
+ where[--n].~T();
+ }
+
+ T *const where;
+ size_t n;
+ } copier(this->end());
+
+ copier.copy(b, e);
+ this->size += (e - b);
+ }
};
template <class T, class = void>
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index af5173c9ad..a17cf4a101 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -41,6 +41,7 @@
#define QARRAYDATAPOINTER_H
#include <QtCore/qarraydataops.h>
+#include <QtCore/qcontainertools_impl.h>
QT_BEGIN_NAMESPACE
@@ -52,30 +53,40 @@ private:
typedef QArrayDataOps<T> DataOps;
public:
+ typedef typename Data::iterator iterator;
+ typedef typename Data::const_iterator const_iterator;
+ enum { pass_parameter_by_value = std::is_fundamental<T>::value || std::is_pointer<T>::value };
+
+ typedef typename std::conditional<pass_parameter_by_value, T, const T &>::type parameter_type;
+
QArrayDataPointer() noexcept
- : d(Data::sharedNull())
+ : d(Data::sharedNull()), ptr(Data::sharedNullData()), size(0)
{
}
- QArrayDataPointer(const QArrayDataPointer &other)
- : d(other.d->ref.ref()
- ? other.d
- : other.clone(other.d->cloneFlags()))
+ QArrayDataPointer(const QArrayDataPointer &other) noexcept
+ : d(other.d), ptr(other.ptr), size(other.size)
{
+ other.d->ref();
}
- explicit QArrayDataPointer(QTypedArrayData<T> *ptr)
- : d(ptr)
+ QArrayDataPointer(Data *header, T *adata, size_t n = 0) noexcept
+ : d(header), ptr(adata), size(int(n))
{
- Q_CHECK_PTR(ptr);
}
- QArrayDataPointer(QArrayDataPointerRef<T> ref)
- : d(ref.ptr)
+ explicit QArrayDataPointer(QPair<QTypedArrayData<T> *, T *> adata, size_t n = 0)
+ : d(adata.first), ptr(adata.second), size(int(n))
{
+ Q_CHECK_PTR(d);
}
- QArrayDataPointer &operator=(const QArrayDataPointer &other)
+ QArrayDataPointer(QArrayDataPointerRef<T> dd) noexcept
+ : d(dd.ptr), ptr(dd.data), size(dd.size)
+ {
+ }
+
+ QArrayDataPointer &operator=(const QArrayDataPointer &other) noexcept
{
QArrayDataPointer tmp(other);
this->swap(tmp);
@@ -83,9 +94,11 @@ public:
}
QArrayDataPointer(QArrayDataPointer &&other) noexcept
- : d(other.d)
+ : d(other.d), ptr(other.ptr), size(other.size)
{
other.d = Data::sharedNull();
+ other.ptr = Data::sharedNullData();
+ other.size = 0;
}
QArrayDataPointer &operator=(QArrayDataPointer &&other) noexcept
@@ -95,114 +108,142 @@ public:
return *this;
}
- DataOps &operator*() const
+ DataOps &operator*() noexcept
{
Q_ASSERT(d);
- return *static_cast<DataOps *>(d);
+ return *static_cast<DataOps *>(this);
}
- DataOps *operator->() const
+ DataOps *operator->() noexcept
{
Q_ASSERT(d);
- return static_cast<DataOps *>(d);
+ return static_cast<DataOps *>(this);
}
- ~QArrayDataPointer()
+ const DataOps &operator*() const noexcept
{
- if (!d->ref.deref()) {
- if (d->isMutable())
- (*this)->destroyAll();
- Data::deallocate(d);
- }
+ Q_ASSERT(d);
+ return *static_cast<const DataOps *>(this);
}
- bool isNull() const
+ const DataOps *operator->() const noexcept
{
- return d == Data::sharedNull();
+ Q_ASSERT(d);
+ return static_cast<const DataOps *>(this);
}
- Data *data() const
+ ~QArrayDataPointer()
{
- return d;
+ if (!deref()) {
+ if (isMutable())
+ (*this)->destroyAll();
+ Data::deallocate(d);
+ }
}
- bool needsDetach() const
+ bool isNull() const noexcept
{
- return (!d->isMutable() || d->ref.isShared());
+ return d == Data::sharedNull();
}
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- void setSharable(bool sharable)
- {
- if (needsDetach()) {
- Data *detached = clone(sharable
- ? d->detachFlags() & ~QArrayData::Unsharable
- : d->detachFlags() | QArrayData::Unsharable);
- QArrayDataPointer old(d);
- d = detached;
- } else {
- d->ref.setSharable(sharable);
- }
- }
+ T *data() noexcept { return ptr; }
+ const T *data() const noexcept { return ptr; }
- bool isSharable() const { return d->isSharable(); }
-#endif
+ iterator begin(iterator = iterator()) noexcept { return data(); }
+ iterator end(iterator = iterator()) noexcept { return data() + size; }
+ const_iterator begin(const_iterator = const_iterator()) const noexcept { return data(); }
+ const_iterator end(const_iterator = const_iterator()) const noexcept { return data() + size; }
+ const_iterator constBegin(const_iterator = const_iterator()) const noexcept { return data(); }
+ const_iterator constEnd(const_iterator = const_iterator()) const noexcept { return data() + size; }
void swap(QArrayDataPointer &other) noexcept
{
qSwap(d, other.d);
+ qSwap(ptr, other.ptr);
+ qSwap(size, other.size);
}
- void clear()
+ void clear() Q_DECL_NOEXCEPT_EXPR(std::is_nothrow_destructible<T>::value)
{
- QArrayDataPointer tmp(d);
- d = Data::sharedNull();
+ QArrayDataPointer tmp;
+ swap(tmp);
}
bool detach()
{
- if (needsDetach()) {
- Data *copy = clone(d->detachFlags());
- QArrayDataPointer old(d);
- d = copy;
+ if (d->needsDetach()) {
+ QPair<Data *, T *> copy = clone(d->detachFlags());
+ QArrayDataPointer old(d, ptr, size);
+ d = copy.first;
+ ptr = copy.second;
return true;
}
return false;
}
-private:
- Q_REQUIRED_RESULT Data *clone(QArrayData::AllocationOptions options) const
+ // forwards from QArrayData
+ size_t allocatedCapacity() noexcept { return d->allocatedCapacity(); }
+ size_t constAllocatedCapacity() const noexcept { return d->constAllocatedCapacity(); }
+ int refCounterValue() const noexcept { return d->refCounterValue(); }
+ bool ref() noexcept { return d->ref(); }
+ bool deref() noexcept { return d->deref(); }
+ bool isMutable() const noexcept { return d->isMutable(); }
+ bool isStatic() const noexcept { return d->isStatic(); }
+ bool isShared() const noexcept { return d->isShared(); }
+ bool isSharedWith(const QArrayDataPointer &other) const noexcept { return d && d == other.d; }
+ bool needsDetach() const noexcept { return d->needsDetach(); }
+ size_t detachCapacity(size_t newSize) const noexcept { return d->detachCapacity(newSize); }
+ typename Data::ArrayOptions &flags() noexcept { return reinterpret_cast<typename Data::ArrayOptions &>(d->flags); }
+ typename Data::ArrayOptions flags() const noexcept { return typename Data::ArrayOption(d->flags); }
+ typename Data::ArrayOptions detachFlags() const noexcept { return d->detachFlags(); }
+ typename Data::ArrayOptions cloneFlags() const noexcept { return d->cloneFlags(); }
+
+ void reallocate(uint alloc, typename Data::ArrayOptions options)
{
- Data *x = Data::allocate(d->detachCapacity(d->size), options);
- Q_CHECK_PTR(x);
- QArrayDataPointer copy(x);
+ auto pair = Data::reallocateUnaligned(d, ptr, alloc, options);
+ d = pair.first;
+ ptr = pair.second;
+ }
+ Data *d_ptr() { return d; }
- if (d->size)
- copy->copyAppend(d->begin(), d->end());
+private:
+ Q_REQUIRED_RESULT QPair<Data *, T *> clone(QArrayData::ArrayOptions options) const
+ {
+ QPair<Data *, T *> pair = Data::allocate(d->detachCapacity(size),
+ options);
+ Q_CHECK_PTR(pair.first);
+ QArrayDataPointer copy(pair.first, pair.second, 0);
+ if (size)
+ copy->copyAppend(begin(), end());
- Data *result = copy.d;
+ pair.first = copy.d;
copy.d = Data::sharedNull();
- return result;
+ return pair;
}
+protected:
Data *d;
+ T *ptr;
+
+public:
+ int size;
};
template <class T>
-inline bool operator==(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
+inline bool operator==(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs) noexcept
{
- return lhs.data() == rhs.data();
+ return lhs.data() == rhs.data() && lhs.size == rhs.size;
}
template <class T>
-inline bool operator!=(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
+inline bool operator!=(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs) noexcept
{
- return lhs.data() != rhs.data();
+ return lhs.data() != rhs.data() || lhs.size != rhs.size;
}
template <class T>
-inline void swap(QArrayDataPointer<T> &p1, QArrayDataPointer<T> &p2)
+inline void qSwap(QArrayDataPointer<T> &p1, QArrayDataPointer<T> &p2) noexcept
{
p1.swap(p2);
}
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index f0b81cce66..a1dd537d4d 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -342,6 +342,38 @@ QBitArray QBitArray::fromBits(const char *data, qsizetype size)
return result;
}
+/*!
+ \since 6.0
+
+ Returns the array of bit converted to an int. The conversion is based on \a endianness.
+ Converts up to the first 32 bits of the array to \c quint32 and returns it,
+ obeying \a endianness. If \a ok is not a null pointer, and the array has more
+ than 32 bits, \a ok is set to false and this function returns zero; otherwise,
+ it's set to true.
+*/
+quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcept
+{
+ const qsizetype _size = size();
+ if (_size > 32) {
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+
+ if (ok)
+ *ok = true;
+
+ quint32 factor = 1;
+ quint32 total = 0;
+ for (qsizetype i = 0; i < _size; ++i, factor *= 2) {
+ const auto index = endianness == QSysInfo::Endian::LittleEndian ? i : (_size - i - 1);
+ if (testBit(index))
+ total += factor;
+ }
+
+ return total;
+}
+
/*! \fn bool QBitArray::isDetached() const
\internal
diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h
index 9b0e931aca..ac3a8771d9 100644
--- a/src/corelib/tools/qbitarray.h
+++ b/src/corelib/tools/qbitarray.h
@@ -105,8 +105,10 @@ public:
const char *bits() const { return isEmpty() ? nullptr : d.constData() + 1; }
static QBitArray fromBits(const char *data, qsizetype len);
+ quint32 toUInt32(QSysInfo::Endian endianness, bool *ok = nullptr) const noexcept;
+
public:
- typedef QByteArray::DataPtr DataPtr;
+ typedef QByteArray::DataPointer DataPtr;
inline DataPtr &data_ptr() { return d.data_ptr(); }
};
diff --git a/src/corelib/tools/qcontainerfwd.h b/src/corelib/tools/qcontainerfwd.h
index 532b4c95ce..f6efa99b6a 100644
--- a/src/corelib/tools/qcontainerfwd.h
+++ b/src/corelib/tools/qcontainerfwd.h
@@ -50,7 +50,6 @@ template <class Key, class T> class QHash;
#ifndef QT_NO_LINKED_LIST
template <class T> class QLinkedList;
#endif
-template <class T> class QList;
template <class Key, class T> class QMap;
template <class Key, class T> class QMultiHash;
template <class Key, class T> class QMultiMap;
@@ -60,6 +59,7 @@ template <class T> class QSet;
template <class T> class QStack;
template<class T, int Prealloc = 256> class QVarLengthArray;
template <class T> class QVector;
+template<typename T> using QList = QVector<T>;
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
index 7b74b4f526..8cae7d1651 100644
--- a/src/corelib/tools/qcontiguouscache.h
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -102,9 +102,6 @@ public:
inline void detach() { if (d->ref.loadRelaxed() != 1) detach_helper(); }
inline bool isDetached() const { return d->ref.loadRelaxed() == 1; }
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
-#endif
QContiguousCache<T> &operator=(const QContiguousCache<T> &other);
inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other) noexcept
@@ -166,7 +163,7 @@ private:
}
int alignOfTypedData() const
{
- return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
+ return qMax<int>(sizeof(void*), alignof(Data));
}
};
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index 84430ae49a..1207ce0659 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -1382,11 +1382,6 @@ void QEasingCurve::addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qre
}
/*!
- \fn QList<QPointF> QEasingCurve::cubicBezierSpline() const
- \obsolete Use toCubicSpline() instead.
- */
-
-/*!
\since 5.0
Returns the cubicBezierSpline that defines a custom easing curve.
diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h
index d3a468bb22..81833a758f 100644
--- a/src/corelib/tools/qeasingcurve.h
+++ b/src/corelib/tools/qeasingcurve.h
@@ -46,10 +46,6 @@ QT_REQUIRE_CONFIG(easingcurve);
#include <QtCore/qobjectdefs.h>
#include <QtCore/qvector.h>
-#if QT_DEPRECATED_SINCE(5, 0)
-# include <QtCore/qlist.h>
-# include <QtCore/qpoint.h>
-#endif
QT_BEGIN_NAMESPACE
@@ -105,9 +101,6 @@ public:
void addCubicBezierSegment(const QPointF & c1, const QPointF & c2, const QPointF & endPoint);
void addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qreal b);
QVector<QPointF> toCubicSpline() const;
-#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED QList<QPointF> cubicBezierSpline() const { return toCubicSpline().toList(); }
-#endif
Type type() const;
void setType(Type type);
diff --git a/src/corelib/tools/qflatmap_p.h b/src/corelib/tools/qflatmap_p.h
new file mode 100644
index 0000000000..590b0d942f
--- /dev/null
+++ b/src/corelib/tools/qflatmap_p.h
@@ -0,0 +1,982 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://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 QFLATMAP_P_H
+#define QFLATMAP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qvector.h"
+
+#include <algorithm>
+#include <functional>
+#include <initializer_list>
+#include <iterator>
+#include <numeric>
+#include <type_traits>
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ QFlatMap provides an associative container backed by sorted sequential
+ containers. By default, QVector is used.
+
+ Keys and values are stored in two separate containers. This provides improved
+ cache locality for key iteration and makes keys() and values() fast
+ operations.
+
+ One can customize the underlying container type by passing the KeyContainer
+ and MappedContainer template arguments:
+ QFlatMap<float, int, std::less<float>, std::vector<float>, std::vector<int>>
+*/
+
+namespace Qt {
+
+struct OrderedUniqueRange_t {};
+constexpr OrderedUniqueRange_t OrderedUniqueRange = {};
+
+} // namespace Qt
+
+template <class Key, class T, class Compare>
+class QFlatMapValueCompare : protected Compare
+{
+public:
+ QFlatMapValueCompare() = default;
+ QFlatMapValueCompare(const Compare &key_compare)
+ : Compare(key_compare)
+ {
+ }
+
+ using value_type = std::pair<const Key, T>;
+ static constexpr bool is_comparator_noexcept = noexcept(
+ std::declval<Compare>()(std::declval<Key>(), std::declval<Key>()));
+
+ bool operator()(const value_type &lhs, const value_type &rhs) const
+ noexcept(is_comparator_noexcept)
+ {
+ return Compare::operator()(lhs.first, rhs.first);
+ }
+};
+
+template <class Key, class T,
+ class Compare = std::less<Key>,
+ class KeyContainer = QVector<Key>,
+ class MappedContainer = QVector<T>>
+class QFlatMap : private QFlatMapValueCompare<Key, T, Compare>
+{
+ using full_map_t = QFlatMap<Key, T, Compare, KeyContainer, MappedContainer>;
+
+ template <class U>
+ class mock_pointer
+ {
+ U ref;
+ public:
+ mock_pointer(U r)
+ : ref(r)
+ {
+ }
+
+ U *operator->()
+ {
+ return &ref;
+ }
+ };
+
+public:
+ using key_type = Key;
+ using mapped_type = T;
+ using value_compare = QFlatMapValueCompare<Key, T, Compare>;
+ using value_type = typename value_compare::value_type;
+ using key_container_type = KeyContainer;
+ using mapped_container_type = MappedContainer;
+ using size_type = typename key_container_type::size_type;
+ using key_compare = Compare;
+
+ struct containers
+ {
+ key_container_type keys;
+ mapped_container_type values;
+ };
+
+ class iterator
+ {
+ public:
+ using difference_type = ptrdiff_t;
+ using value_type = std::pair<const Key, T>;
+ using reference = std::pair<const Key &, T &>;
+ using pointer = mock_pointer<reference>;
+ using iterator_category = std::random_access_iterator_tag;
+
+ iterator() = default;
+
+ iterator(containers *ac, size_type ai)
+ : c(ac), i(ai)
+ {
+ }
+
+ reference operator*()
+ {
+ return { c->keys[i], c->values[i] };
+ }
+
+ pointer operator->()
+ {
+ return { operator*() };
+ }
+
+ bool operator==(const iterator &o) const
+ {
+ return c == o.c && i == o.i;
+ }
+
+ bool operator!=(const iterator &o) const
+ {
+ return !operator==(o);
+ }
+
+ iterator &operator++()
+ {
+ ++i;
+ return *this;
+ }
+
+ iterator operator++(int)
+ {
+
+ iterator r = *this;
+ i++;
+ return r;
+ }
+
+ iterator &operator--()
+ {
+ --i;
+ return *this;
+ }
+
+ iterator operator--(int)
+ {
+ iterator r = *this;
+ i--;
+ return r;
+ }
+
+ iterator &operator+=(size_type n)
+ {
+ i += n;
+ return *this;
+ }
+
+ friend iterator operator+(size_type n, const iterator a)
+ {
+ iterator ret = a;
+ return ret += n;
+ }
+
+ friend iterator operator+(const iterator a, size_type n)
+ {
+ return n + a;
+ }
+
+ iterator &operator-=(size_type n)
+ {
+ i -= n;
+ return *this;
+ }
+
+ friend iterator operator-(const iterator a, size_type n)
+ {
+ iterator ret = a;
+ return ret -= n;
+ }
+
+ friend difference_type operator-(const iterator b, const iterator a)
+ {
+ return b.i - a.i;
+ }
+
+ reference operator[](size_type n)
+ {
+ size_type k = i + n;
+ return { c->keys[k], c->values[k] };
+ }
+
+ bool operator<(const iterator &other) const
+ {
+ return i < other.i;
+ }
+
+ bool operator>(const iterator &other) const
+ {
+ return i > other.i;
+ }
+
+ bool operator<=(const iterator &other) const
+ {
+ return i <= other.i;
+ }
+
+ bool operator>=(const iterator &other) const
+ {
+ return i >= other.i;
+ }
+
+ const Key &key() const { return c->keys[i]; }
+ T &value() { return c->values[i]; }
+
+ private:
+ containers *c = nullptr;
+ size_type i = 0;
+ friend full_map_t;
+ };
+
+ class const_iterator
+ {
+ public:
+ using difference_type = ptrdiff_t;
+ using value_type = std::pair<const Key, const T>;
+ using reference = std::pair<const Key &, const T &>;
+ using pointer = mock_pointer<reference>;
+ using iterator_category = std::random_access_iterator_tag;
+
+ const_iterator() = default;
+
+ const_iterator(const containers *ac, size_type ai)
+ : c(ac), i(ai)
+ {
+ }
+
+ const_iterator(iterator o)
+ : c(o.c), i(o.i)
+ {
+ }
+
+ reference operator*()
+ {
+ return { c->keys[i], c->values[i] };
+ }
+
+ pointer operator->()
+ {
+ return { operator*() };
+ }
+
+ bool operator==(const const_iterator &o) const
+ {
+ return c == o.c && i == o.i;
+ }
+
+ bool operator!=(const const_iterator &o) const
+ {
+ return !operator==(o);
+ }
+
+ const_iterator &operator++()
+ {
+ ++i;
+ return *this;
+ }
+
+ const_iterator operator++(int)
+ {
+
+ const_iterator r = *this;
+ i++;
+ return r;
+ }
+
+ const_iterator &operator--()
+ {
+ --i;
+ return *this;
+ }
+
+ const_iterator operator--(int)
+ {
+ const_iterator r = *this;
+ i--;
+ return r;
+ }
+
+ const_iterator &operator+=(size_type n)
+ {
+ i += n;
+ return *this;
+ }
+
+ friend const_iterator operator+(size_type n, const const_iterator a)
+ {
+ const_iterator ret = a;
+ return ret += n;
+ }
+
+ friend const_iterator operator+(const const_iterator a, size_type n)
+ {
+ return n + a;
+ }
+
+ const_iterator &operator-=(size_type n)
+ {
+ i -= n;
+ return *this;
+ }
+
+ friend const_iterator operator-(const const_iterator a, size_type n)
+ {
+ const_iterator ret = a;
+ return ret -= n;
+ }
+
+ friend difference_type operator-(const const_iterator b, const const_iterator a)
+ {
+ return b.i - a.i;
+ }
+
+ reference operator[](size_type n)
+ {
+ size_type k = i + n;
+ return { c->keys[k], c->values[k] };
+ }
+
+ bool operator<(const const_iterator &other) const
+ {
+ return i < other.i;
+ }
+
+ bool operator>(const const_iterator &other) const
+ {
+ return i > other.i;
+ }
+
+ bool operator<=(const const_iterator &other) const
+ {
+ return i <= other.i;
+ }
+
+ bool operator>=(const const_iterator &other) const
+ {
+ return i >= other.i;
+ }
+
+ const Key &key() const { return c->keys[i]; }
+ const T &value() { return c->values[i]; }
+
+ private:
+ const containers *c = nullptr;
+ size_type i = 0;
+ friend full_map_t;
+ };
+
+private:
+ template <class, class = void>
+ struct is_marked_transparent_type : std::false_type { };
+
+ template <class X>
+ struct is_marked_transparent_type<X, typename X::is_transparent> : std::true_type { };
+
+ template <class X>
+ using is_marked_transparent = typename std::enable_if<
+ is_marked_transparent_type<X>::value>::type *;
+
+ template <typename It>
+ using is_compatible_iterator = typename std::enable_if<
+ std::is_same<value_type, typename std::iterator_traits<It>::value_type>::value>::type *;
+
+public:
+ QFlatMap() = default;
+
+ explicit QFlatMap(const key_container_type &keys, const mapped_container_type &values)
+ : c{keys, values}
+ {
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(key_container_type &&keys, const mapped_container_type &values)
+ {
+ c.keys = std::move(keys);
+ c.values = values;
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(const key_container_type &keys, mapped_container_type &&values)
+ {
+ c.keys = keys;
+ c.values = std::move(values);
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(key_container_type &&keys, mapped_container_type &&values)
+ {
+ c.keys = std::move(keys);
+ c.values = std::move(values);
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(std::initializer_list<value_type> lst)
+ : QFlatMap(lst.begin(), lst.end())
+ {
+ }
+
+ template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
+ explicit QFlatMap(InputIt first, InputIt last)
+ {
+ initWithRange(first, last);
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys,
+ const mapped_container_type &values)
+ {
+ c.keys = keys;
+ c.values = values;
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys,
+ const mapped_container_type &values)
+ {
+ c.keys = std::move(keys);
+ c.values = values;
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys,
+ mapped_container_type &&values)
+ {
+ c.keys = keys;
+ c.values = std::move(values);
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys,
+ mapped_container_type &&values)
+ {
+ c.keys = std::move(keys);
+ c.values = std::move(values);
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list<value_type> lst)
+ : QFlatMap(lst.begin(), lst.end())
+ {
+ }
+
+ template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, InputIt first, InputIt last)
+ {
+ initWithRange(first, last);
+ }
+
+ explicit QFlatMap(const Compare &compare)
+ : value_compare(compare)
+ {
+ }
+
+ explicit QFlatMap(const key_container_type &keys, const mapped_container_type &values,
+ const Compare &compare)
+ : value_compare(compare), c{keys, values}
+ {
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(key_container_type &&keys, const mapped_container_type &values,
+ const Compare &compare)
+ : value_compare(compare), c{std::move(keys), values}
+ {
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(const key_container_type &keys, mapped_container_type &&values,
+ const Compare &compare)
+ : value_compare(compare), c{keys, std::move(values)}
+ {
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(key_container_type &&keys, mapped_container_type &&values,
+ const Compare &compare)
+ : value_compare(compare), c{std::move(keys), std::move(values)}
+ {
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(std::initializer_list<value_type> lst, const Compare &compare)
+ : QFlatMap(lst.begin(), lst.end(), compare)
+ {
+ }
+
+ template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
+ explicit QFlatMap(InputIt first, InputIt last, const Compare &compare)
+ : value_compare(compare)
+ {
+ initWithRange(first, last);
+ ensureOrderedUnique();
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys,
+ const mapped_container_type &values, const Compare &compare)
+ : value_compare(compare), c{keys, values}
+ {
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys,
+ const mapped_container_type &values, const Compare &compare)
+ : value_compare(compare), c{std::move(keys), values}
+ {
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys,
+ mapped_container_type &&values, const Compare &compare)
+ : value_compare(compare), c{keys, std::move(values)}
+ {
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys,
+ mapped_container_type &&values, const Compare &compare)
+ : value_compare(compare), c{std::move(keys), std::move(values)}
+ {
+ }
+
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list<value_type> lst,
+ const Compare &compare)
+ : QFlatMap(Qt::OrderedUniqueRange, lst.begin(), lst.end(), compare)
+ {
+ }
+
+ template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
+ explicit QFlatMap(Qt::OrderedUniqueRange_t, InputIt first, InputIt last, const Compare &compare)
+ : value_compare(compare)
+ {
+ initWithRange(first, last);
+ }
+
+ size_type count() const noexcept { return c.keys.size(); }
+ size_type size() const noexcept { return c.keys.size(); }
+ size_type capacity() const noexcept { return c.keys.capacity(); }
+ bool isEmpty() const noexcept { return c.keys.empty(); }
+ bool empty() const noexcept { return c.keys.empty(); }
+ containers extract() && { return std::move(c); }
+ const key_container_type &keys() const noexcept { return c.keys; }
+ const mapped_container_type &values() const noexcept { return c.values; }
+
+ void reserve(size_type s)
+ {
+ c.keys.reserve(s);
+ c.values.reserve(s);
+ }
+
+ void clear()
+ {
+ c.keys.clear();
+ c.values.clear();
+ }
+
+ bool remove(const Key &key)
+ {
+ auto it = binary_find(key);
+ if (it != end()) {
+ c.keys.erase(toKeysIterator(it));
+ c.values.erase(toValuesIterator(it));
+ return true;
+ }
+ return false;
+ }
+
+ iterator erase(iterator it)
+ {
+ c.values.erase(toValuesIterator(it));
+ return fromKeysIterator(c.keys.erase(toKeysIterator(it)));
+ }
+
+ T take(const Key &key)
+ {
+ auto it = binary_find(key);
+ if (it != end()) {
+ T result = std::move(it.value());
+ erase(it);
+ return result;
+ }
+ return {};
+ }
+
+ bool contains(const Key &key) const
+ {
+ return binary_find(key) != end();
+ }
+
+ T value(const Key &key, const T &defaultValue) const
+ {
+ auto it = binary_find(key);
+ return it == end() ? defaultValue : it.value();
+ }
+
+ T value(const Key &key) const
+ {
+ auto it = binary_find(key);
+ return it == end() ? T() : it.value();
+ }
+
+ T &operator[](const Key &key)
+ {
+ auto it = lower_bound(key);
+ if (it == end() || key_compare::operator()(key, it.key())) {
+ c.keys.insert(toKeysIterator(it), key);
+ return *c.values.insert(toValuesIterator(it), T());
+ }
+ return it.value();
+ }
+
+ T &operator[](Key &&key)
+ {
+ auto it = lower_bound(key);
+ if (it == end() || key_compare::operator()(key, it.key())) {
+ c.keys.insert(toKeysIterator(it), key);
+ return *c.values.insert(toValuesIterator(it), T());
+ }
+ return it.value();
+ }
+
+ T operator[](const Key &key) const
+ {
+ return value(key);
+ }
+
+ std::pair<iterator, bool> insert(const Key &key, const T &value)
+ {
+ auto it = lower_bound(key);
+ if (it == end() || key_compare::operator()(key, it.key())) {
+ c.values.insert(toValuesIterator(it), value);
+ auto k = c.keys.insert(toKeysIterator(it), key);
+ return { fromKeysIterator(k), true };
+ } else {
+ it.value() = value;
+ return {it, false};
+ }
+ }
+
+ std::pair<iterator, bool> insert(Key &&key, const T &value)
+ {
+ auto it = lower_bound(key);
+ if (it == end() || key_compare::operator()(key, it.key())) {
+ c.values.insert(toValuesIterator(it), value);
+ return { c.keys.insert(it, std::move(key)), true };
+ } else {
+ *toValuesIterator(it) = value;
+ return {it, false};
+ }
+ }
+
+ std::pair<iterator, bool> insert(const Key &key, T &&value)
+ {
+ auto it = lower_bound(key);
+ if (it == end() || key_compare::operator()(key, it.key())) {
+ c.values.insert(toValuesIterator(it), std::move(value));
+ return { c.keys.insert(it, key), true };
+ } else {
+ *toValuesIterator(it) = std::move(value);
+ return {it, false};
+ }
+ }
+
+ std::pair<iterator, bool> insert(Key &&key, T &&value)
+ {
+ auto it = lower_bound(key);
+ if (it == end() || key_compare::operator()(key, it.key())) {
+ c.values.insert(toValuesIterator(it), std::move(value));
+ return { fromKeysIterator(c.keys.insert(toKeysIterator(it), std::move(key))), true };
+ } else {
+ *toValuesIterator(it) = std::move(value);
+ return {it, false};
+ }
+ }
+
+ template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
+ void insert(InputIt first, InputIt last)
+ {
+ insertRange(first, last);
+ }
+
+ // ### Merge with the templated version above
+ // once we can use std::disjunction in is_compatible_iterator.
+ void insert(const value_type *first, const value_type *last)
+ {
+ insertRange(first, last);
+ }
+
+ template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
+ void insert(Qt::OrderedUniqueRange_t, InputIt first, InputIt last)
+ {
+ insertOrderedUniqueRange(first, last);
+ }
+
+ // ### Merge with the templated version above
+ // once we can use std::disjunction in is_compatible_iterator.
+ void insert(Qt::OrderedUniqueRange_t, const value_type *first, const value_type *last)
+ {
+ insertOrderedUniqueRange(first, last);
+ }
+
+ iterator begin() { return { &c, 0 }; }
+ const_iterator begin() const { return { &c, 0 }; }
+ const_iterator cbegin() const { return begin(); }
+ const_iterator constBegin() const { return cbegin(); }
+ iterator end() { return { &c, c.keys.size() }; }
+ const_iterator end() const { return { &c, c.keys.size() }; }
+ const_iterator cend() const { return end(); }
+ const_iterator constEnd() const { return cend(); }
+ std::reverse_iterator<iterator> rbegin() { return std::reverse_iterator<iterator>(end()); }
+ std::reverse_iterator<const_iterator> rbegin() const
+ {
+ return std::reverse_iterator<const_iterator>(end());
+ }
+ std::reverse_iterator<const_iterator> crbegin() const { return rbegin(); }
+ std::reverse_iterator<iterator> rend() {
+ return std::reverse_iterator<iterator>(begin());
+ }
+ std::reverse_iterator<const_iterator> rend() const
+ {
+ return std::reverse_iterator<const_iterator>(begin());
+ }
+ std::reverse_iterator<const_iterator> crend() const { return rend(); }
+
+ iterator lower_bound(const Key &key)
+ {
+ auto cit = const_cast<const full_map_t *>(this)->lower_bound(key);
+ return { &c, cit.i };
+ }
+
+ template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
+ iterator lower_bound(const X &key)
+ {
+ auto cit = const_cast<const full_map_t *>(this)->lower_bound(key);
+ return { &c, cit.i };
+ }
+
+ const_iterator lower_bound(const Key &key) const
+ {
+ return fromKeysIterator(std::lower_bound(c.keys.begin(), c.keys.end(), key, key_comp()));
+ }
+
+ template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
+ const_iterator lower_bound(const X &key) const
+ {
+ return fromKeysIterator(std::lower_bound(c.keys.begin(), c.keys.end(), key, key_comp()));
+ }
+
+ iterator find(const key_type &k)
+ {
+ return binary_find(k);
+ }
+
+ const_iterator find(const key_type &k) const
+ {
+ return binary_find(k);
+ }
+
+ key_compare key_comp() const noexcept
+ {
+ return static_cast<key_compare>(*this);
+ }
+
+ value_compare value_comp() const noexcept
+ {
+ return static_cast<value_compare>(*this);
+ }
+
+private:
+ template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
+ void initWithRange(InputIt first, InputIt last)
+ {
+ QtPrivate::reserveIfForwardIterator(this, first, last);
+ while (first != last) {
+ c.keys.push_back(first->first);
+ c.values.push_back(first->second);
+ ++first;
+ }
+ }
+
+ iterator fromKeysIterator(typename key_container_type::iterator kit)
+ {
+ return { &c, static_cast<size_type>(std::distance(c.keys.begin(), kit)) };
+ }
+
+ const_iterator fromKeysIterator(typename key_container_type::const_iterator kit) const
+ {
+ return { &c, static_cast<size_type>(std::distance(c.keys.begin(), kit)) };
+ }
+
+ typename key_container_type::iterator toKeysIterator(iterator it)
+ {
+ return c.keys.begin() + it.i;
+ }
+
+ typename mapped_container_type::iterator toValuesIterator(iterator it)
+ {
+ return c.values.begin() + it.i;
+ }
+
+ template <class InputIt>
+ void insertRange(InputIt first, InputIt last)
+ {
+ size_type i = c.keys.size();
+ c.keys.resize(i + std::distance(first, last));
+ c.values.resize(c.keys.size());
+ for (; first != last; ++first, ++i) {
+ c.keys[i] = first->first;
+ c.values[i] = first->second;
+ }
+ ensureOrderedUnique();
+ }
+
+ class IndexedKeyComparator
+ {
+ public:
+ IndexedKeyComparator(const full_map_t *am)
+ : m(am)
+ {
+ }
+
+ bool operator()(size_type i, size_type k) const
+ {
+ return m->key_comp()(m->c.keys[i], m->c.keys[k]);
+ }
+
+ private:
+ const full_map_t *m;
+ };
+
+ template <class InputIt>
+ void insertOrderedUniqueRange(InputIt first, InputIt last)
+ {
+ const size_type s = c.keys.size();
+ c.keys.resize(s + std::distance(first, last));
+ c.values.resize(c.keys.size());
+ for (size_type i = s; first != last; ++first, ++i) {
+ c.keys[i] = first->first;
+ c.values[i] = first->second;
+ }
+
+ std::vector<size_type> p(size_t(c.keys.size()));
+ std::iota(p.begin(), p.end(), 0);
+ std::inplace_merge(p.begin(), p.begin() + s, p.end(), IndexedKeyComparator(this));
+ applyPermutation(p);
+ makeUnique();
+ }
+
+ iterator binary_find(const Key &key)
+ {
+ return { &c, const_cast<const full_map_t *>(this)->binary_find(key).i };
+ }
+
+ const_iterator binary_find(const Key &key) const
+ {
+ auto it = lower_bound(key);
+ if (it != end()) {
+ if (!key_compare::operator()(key, it.key()))
+ return it;
+ it = end();
+ }
+ return it;
+ }
+
+ void ensureOrderedUnique()
+ {
+ std::vector<size_type> p(size_t(c.keys.size()));
+ std::iota(p.begin(), p.end(), 0);
+ std::stable_sort(p.begin(), p.end(), IndexedKeyComparator(this));
+ applyPermutation(p);
+ makeUnique();
+ }
+
+ void applyPermutation(const std::vector<size_type> &p)
+ {
+ const size_type s = c.keys.size();
+ std::vector<bool> done(s);
+ for (size_type i = 0; i < s; ++i) {
+ if (done[i])
+ continue;
+ done[i] = true;
+ size_type j = i;
+ size_type k = p[i];
+ while (i != k) {
+ qSwap(c.keys[j], c.keys[k]);
+ qSwap(c.values[j], c.values[k]);
+ done[k] = true;
+ j = k;
+ k = p[j];
+ }
+ }
+ }
+
+ void makeUnique()
+ {
+ if (c.keys.size() < 2)
+ return;
+ auto k = std::end(c.keys) - 1;
+ auto i = k - 1;
+ for (;;) {
+ if (key_compare::operator()(*i, *k) || key_compare::operator()(*k, *i)) {
+ if (i == std::begin(c.keys))
+ break;
+ --i;
+ --k;
+ } else {
+ c.values.erase(std::begin(c.values) + std::distance(std::begin(c.keys), i));
+ i = c.keys.erase(i);
+ if (i == std::begin(c.keys))
+ break;
+ k = i + 1;
+ }
+ }
+ c.keys.shrink_to_fit();
+ c.values.shrink_to_fit();
+ }
+
+ containers c;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFLATMAP_P_H
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 0b8a0b283d..c56324eef7 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -235,7 +235,7 @@ class QHash
return reinterpret_cast<Node *>(node);
}
- static inline int alignOfNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(Node)); }
+ static inline int alignOfNode() { return qMax<int>(sizeof(void*), alignof(Node)); }
public:
inline QHash() noexcept : d(const_cast<QHashData *>(&QHashData::shared_null)) { }
@@ -290,9 +290,6 @@ public:
inline void detach() { if (d->ref.isShared()) detach_helper(); }
inline bool isDetached() const { return !d->ref.isShared(); }
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QHashData::shared_null) d->sharable = sharable; }
-#endif
bool isSharedWith(const QHash &other) const { return d == other.d; }
void clear();
@@ -376,13 +373,8 @@ public:
friend inline QT_DEPRECATED iterator operator+(int j, iterator k) { return k + j; }
#endif
-#ifndef QT_STRICT_ITERATORS
- public:
- inline bool operator==(const const_iterator &o) const
- { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const
- { return i != o.i; }
-#endif
+ inline bool operator==(const const_iterator &o) const { return i == o.i; }
+ inline bool operator!=(const const_iterator &o) const { return i != o.i; }
};
friend class iterator;
@@ -408,11 +400,7 @@ public:
Q_DECL_CONSTEXPR inline const_iterator() : i(nullptr) { }
explicit inline const_iterator(void *node)
: i(reinterpret_cast<QHashData::Node *>(node)) { }
-#ifdef QT_STRICT_ITERATORS
- explicit inline const_iterator(const iterator &o)
-#else
inline const_iterator(const iterator &o)
-#endif
{ i = o.i; }
inline const Key &key() const { return concrete(i)->key; }
@@ -453,13 +441,6 @@ public:
return k + j;
}
#endif
-
- // ### Qt 5: not sure this is necessary anymore
-#ifdef QT_STRICT_ITERATORS
- private:
- inline bool operator==(const iterator &o) const { return operator==(const_iterator(o)); }
- inline bool operator!=(const iterator &o) const { return operator!=(const_iterator(o)); }
-#endif
};
friend class const_iterator;
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
index 8970d39be0..e3713d2c1c 100644
--- a/src/corelib/tools/qlinkedlist.h
+++ b/src/corelib/tools/qlinkedlist.h
@@ -107,9 +107,6 @@ public:
inline void detach()
{ if (d->ref.isShared()) detach_helper2(this->e); }
inline bool isDetached() const { return !d->ref.isShared(); }
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QLinkedListData::shared_null) d->sharable = sharable; }
-#endif
inline bool isSharedWith(const QLinkedList<T> &other) const { return d == other.d; }
inline bool isEmpty() const { return d->size == 0; }
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
index 5d5da20752..62201fd5d6 100644
--- a/src/corelib/tools/qlist.cpp
+++ b/src/corelib/tools/qlist.cpp
@@ -63,2029 +63,4 @@ template class Q_CORE_EXPORT QVector<QPointF>;
template class Q_CORE_EXPORT QVector<QPoint>;
#endif
-
-/*
- QList as an array-list combines the easy-of-use of a random
- access interface with fast list operations and the low memory
- management overhead of an array. Accessing elements by index,
- appending, prepending, and removing elements from both the front
- and the back all happen in constant time O(1). Inserting or
- removing elements at random index positions \ai happens in linear
- time, or more precisly in O(min{i,n-i}) <= O(n/2), with n being
- the number of elements in the list.
-*/
-
-const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { nullptr } };
-
-/*!
- * Detaches the QListData by allocating new memory for a list which will be bigger
- * than the copied one and is expected to grow further.
- * *idx is the desired insertion point and is clamped to the actual size of the list.
- * num is the number of new elements to insert at the insertion point.
- * Returns the old (shared) data, it is up to the caller to deref() and free().
- * For the new data node_copy needs to be called.
- *
- * \internal
- */
-QListData::Data *QListData::detach_grow(int *idx, int num)
-{
- Data *x = d;
- int l = x->end - x->begin;
- int nl = l + num;
- auto blockInfo = qCalculateGrowingBlockSize(nl, sizeof(void *), DataHeaderSize);
- Data* t = static_cast<Data *>(::malloc(blockInfo.size));
- Q_CHECK_PTR(t);
- t->alloc = int(uint(blockInfo.elementCount));
-
- t->ref.initializeOwned();
- // The space reservation algorithm's optimization is biased towards appending:
- // Something which looks like an append will put the data at the beginning,
- // while something which looks like a prepend will put it in the middle
- // instead of at the end. That's based on the assumption that prepending
- // is uncommon and even an initial prepend will eventually be followed by
- // at least some appends.
- int bg;
- if (*idx < 0) {
- *idx = 0;
- bg = (t->alloc - nl) >> 1;
- } else if (*idx > l) {
- *idx = l;
- bg = 0;
- } else if (*idx < (l >> 1)) {
- bg = (t->alloc - nl) >> 1;
- } else {
- bg = 0;
- }
- t->begin = bg;
- t->end = bg + nl;
- d = t;
-
- return x;
-}
-
-/*!
- * Detaches the QListData by allocating new memory for a list which possibly
- * has a different size than the copied one.
- * Returns the old (shared) data, it is up to the caller to deref() and free()
- * For the new data node_copy needs to be called.
- *
- * \internal
- */
-QListData::Data *QListData::detach(int alloc)
-{
- Data *x = d;
- Data* t = static_cast<Data *>(::malloc(qCalculateBlockSize(alloc, sizeof(void*), DataHeaderSize)));
- Q_CHECK_PTR(t);
-
- t->ref.initializeOwned();
- t->alloc = alloc;
- if (!alloc) {
- t->begin = 0;
- t->end = 0;
- } else {
- t->begin = x->begin;
- t->end = x->end;
- }
- d = t;
-
- return x;
-}
-
-void QListData::realloc(int alloc)
-{
- Q_ASSERT(!d->ref.isShared());
- Data *x = static_cast<Data *>(::realloc(d, qCalculateBlockSize(alloc, sizeof(void *), DataHeaderSize)));
- Q_CHECK_PTR(x);
-
- d = x;
- d->alloc = alloc;
- if (!alloc)
- d->begin = d->end = 0;
-}
-
-void QListData::realloc_grow(int growth)
-{
- Q_ASSERT(!d->ref.isShared());
- auto r = qCalculateGrowingBlockSize(d->alloc + growth, sizeof(void *), DataHeaderSize);
- Data *x = static_cast<Data *>(::realloc(d, r.size));
- Q_CHECK_PTR(x);
-
- d = x;
- d->alloc = int(uint(r.elementCount));
-}
-
-void QListData::dispose(Data *d)
-{
- Q_ASSERT(!d->ref.isShared());
- free(d);
-}
-
-// ensures that enough space is available to append n elements
-void **QListData::append(int n)
-{
- Q_ASSERT(!d->ref.isShared());
- int e = d->end;
- if (e + n > d->alloc) {
- int b = d->begin;
- if (b - n >= 2 * d->alloc / 3) {
- // we have enough space. Just not at the end -> move it.
- e -= b;
- ::memcpy(d->array, d->array + b, e * sizeof(void *));
- d->begin = 0;
- } else {
- realloc_grow(n);
- }
- }
- d->end = e + n;
- return d->array + e;
-}
-
-// ensures that enough space is available to append one element
-void **QListData::append()
-{
- return append(1);
-}
-
-// ensures that enough space is available to append the list
-void **QListData::append(const QListData& l)
-{
- return append(l.d->end - l.d->begin);
-}
-
-void **QListData::prepend()
-{
- Q_ASSERT(!d->ref.isShared());
- if (d->begin == 0) {
- if (d->end >= d->alloc / 3)
- realloc_grow(1);
-
- if (d->end < d->alloc / 3)
- d->begin = d->alloc - 2 * d->end;
- else
- d->begin = d->alloc - d->end;
-
- ::memmove(d->array + d->begin, d->array, d->end * sizeof(void *));
- d->end += d->begin;
- }
- return d->array + --d->begin;
-}
-
-void **QListData::insert(int i)
-{
- Q_ASSERT(!d->ref.isShared());
- if (i <= 0)
- return prepend();
- int size = d->end - d->begin;
- if (i >= size)
- return append();
-
- bool leftward = false;
-
- if (d->begin == 0) {
- if (d->end == d->alloc) {
- // If the array is full, we expand it and move some items rightward
- realloc_grow(1);
- } else {
- // If there is free space at the end of the array, we move some items rightward
- }
- } else {
- if (d->end == d->alloc) {
- // If there is free space at the beginning of the array, we move some items leftward
- leftward = true;
- } else {
- // If there is free space at both ends, we move as few items as possible
- leftward = (i < size - i);
- }
- }
-
- if (leftward) {
- --d->begin;
- ::memmove(d->array + d->begin, d->array + d->begin + 1, i * sizeof(void *));
- } else {
- ::memmove(d->array + d->begin + i + 1, d->array + d->begin + i,
- (size - i) * sizeof(void *));
- ++d->end;
- }
- return d->array + d->begin + i;
-}
-
-void QListData::remove(int i)
-{
- Q_ASSERT(!d->ref.isShared());
- i += d->begin;
- if (i - d->begin < d->end - i) {
- if (int offset = i - d->begin)
- ::memmove(d->array + d->begin + 1, d->array + d->begin, offset * sizeof(void *));
- d->begin++;
- } else {
- if (int offset = d->end - i - 1)
- ::memmove(d->array + i, d->array + i + 1, offset * sizeof(void *));
- d->end--;
- }
-}
-
-void QListData::remove(int i, int n)
-{
- Q_ASSERT(!d->ref.isShared());
- i += d->begin;
- int middle = i + n/2;
- if (middle - d->begin < d->end - middle) {
- ::memmove(d->array + d->begin + n, d->array + d->begin,
- (i - d->begin) * sizeof(void*));
- d->begin += n;
- } else {
- ::memmove(d->array + i, d->array + i + n,
- (d->end - i - n) * sizeof(void*));
- d->end -= n;
- }
-}
-
-void QListData::move(int from, int to)
-{
- Q_ASSERT(!d->ref.isShared());
- if (from == to)
- return;
-
- from += d->begin;
- to += d->begin;
- void *t = d->array[from];
-
- if (from < to) {
- if (d->end == d->alloc || 3 * (to - from) < 2 * (d->end - d->begin)) {
- ::memmove(d->array + from, d->array + from + 1, (to - from) * sizeof(void *));
- } else {
- // optimization
- if (int offset = from - d->begin)
- ::memmove(d->array + d->begin + 1, d->array + d->begin, offset * sizeof(void *));
- if (int offset = d->end - (to + 1))
- ::memmove(d->array + to + 2, d->array + to + 1, offset * sizeof(void *));
- ++d->begin;
- ++d->end;
- ++to;
- }
- } else {
- if (d->begin == 0 || 3 * (from - to) < 2 * (d->end - d->begin)) {
- ::memmove(d->array + to + 1, d->array + to, (from - to) * sizeof(void *));
- } else {
- // optimization
- if (int offset = to - d->begin)
- ::memmove(d->array + d->begin - 1, d->array + d->begin, offset * sizeof(void *));
- if (int offset = d->end - (from + 1))
- ::memmove(d->array + from, d->array + from + 1, offset * sizeof(void *));
- --d->begin;
- --d->end;
- --to;
- }
- }
- d->array[to] = t;
-}
-
-void **QListData::erase(void **xi)
-{
- Q_ASSERT(!d->ref.isShared());
- int i = xi - (d->array + d->begin);
- remove(i);
- return d->array + d->begin + i;
-}
-
-/*! \class QList
- \inmodule QtCore
- \brief The QList class is a template class that provides lists.
-
- \ingroup tools
- \ingroup shared
-
- \reentrant
-
- QList\<T\> is one of Qt's generic \l{container classes}. It
- stores items in a list that provides fast index-based access
- and index-based insertions and removals.
-
- QList\<T\>, QLinkedList\<T\>, and QVector\<T\> provide similar
- APIs and functionality. They are often interchangeable, but there
- are performance consequences. Here is an overview of use cases:
-
- \list
- \li QVector should be your default first choice.
- QVector\<T\> will usually give better performance than QList\<T\>,
- because QVector\<T\> always stores its items sequentially in memory,
- where QList\<T\> will allocate its items on the heap unless
- \c {sizeof(T) <= sizeof(void*)} and T has been declared to be
- either a \c{Q_MOVABLE_TYPE} or a \c{Q_PRIMITIVE_TYPE} using
- \l {Q_DECLARE_TYPEINFO}. See the \l {Pros and Cons of Using QList}
- for an explanation.
- \li However, QList is used throughout the Qt APIs for passing
- parameters and for returning values. Use QList to interface with
- those APIs.
- \li If you need a real linked list, which guarantees
- \l {Algorithmic Complexity}{constant time} insertions mid-list and
- uses iterators to items rather than indexes, use QLinkedList.
- \endlist
-
- \note QVector and QVarLengthArray both guarantee C-compatible
- array layout. QList does not. This might be important if your
- application must interface with a C API.
-
- \note Iterators into a QLinkedList and references into
- heap-allocating QLists remain valid as long as the referenced items
- remain in the container. This is not true for iterators and
- references into a QVector and non-heap-allocating QLists.
-
- Internally, QList\<T\> is represented as an array of T if
- \c{sizeof(T) <= sizeof(void*)} and T has been declared to be
- either a \c{Q_MOVABLE_TYPE} or a \c{Q_PRIMITIVE_TYPE} using
- \l {Q_DECLARE_TYPEINFO}. Otherwise, QList\<T\> is represented
- as an array of T* and the items are allocated on the heap.
-
- The array representation allows very fast insertions and
- index-based access. The prepend() and append() operations are
- also very fast because QList preallocates memory at both
- ends of its internal array. (See \l{Algorithmic Complexity} for
- details.
-
- Note, however, that when the conditions specified above are not met,
- each append or insert of a new item requires allocating the new item
- on the heap, and this per item allocation will make QVector a better
- choice for use cases that do a lot of appending or inserting, because
- QVector can allocate memory for many items in a single heap allocation.
-
- Note that the internal array only ever gets bigger over the life
- of the list. It never shrinks. The internal array is deallocated
- by the destructor and by the assignment operator, when one list
- is assigned to another.
-
- Here's an example of a QList that stores integers and
- a QList that stores QDate values:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 0
-
- Qt includes a QStringList class that inherits QList\<QString\>
- and adds a few convenience functions, such as QStringList::join()
- and QStringList::filter(). QString::split() creates QStringLists
- from strings.
-
- QList stores a list of items. The default constructor creates an
- empty list. You can use the initializer-list constructor to create
- a list with elements:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 1a
-
- QList provides these basic functions to add, move, and remove
- items: insert(), replace(), removeAt(), move(), and swap(). In
- addition, it provides the following convenience functions:
- append(), \l{operator<<()}, \l{operator+=()}, prepend(), removeFirst(),
- and removeLast().
-
- \l{operator<<()} allows to conveniently add multiple elements to a list:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 1b
-
- QList uses 0-based indexes, just like C++ arrays. To access the
- item at a particular index position, you can use operator[](). On
- non-const lists, operator[]() returns a reference to the item and
- can be used on the left side of an assignment:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 2
-
- Because QList is implemented as an array of pointers for types
- that are larger than a pointer or are not movable, this operation
- requires (\l{Algorithmic Complexity}{constant time}). For read-only
- access, an alternative syntax is to use at():
-
- \snippet code/src_corelib_tools_qlistdata.cpp 3
-
- at() can be faster than operator[](), because it never causes a
- \l{deep copy} to occur.
-
- A common requirement is to remove an item from a list and do
- something with it. For this, QList provides takeAt(), takeFirst(),
- and takeLast(). Here's a loop that removes the items from a list
- one at a time and calls \c delete on them:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 4
-
- Inserting and removing items at either end of the list is very
- fast (\l{Algorithmic Complexity}{constant time} in most cases),
- because QList preallocates extra space on both sides of its
- internal buffer to allow for fast growth at both ends of the list.
-
- If you want to find all occurrences of a particular value in a
- list, use indexOf() or lastIndexOf(). The former searches forward
- starting from a given index position, the latter searches
- backward. Both return the index of a matching item if they find
- it; otherwise, they return -1. For example:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 5
-
- If you simply want to check whether a list contains a particular
- value, use contains(). If you want to find out how many times a
- particular value occurs in the list, use count(). If you want to
- replace all occurrences of a particular value with another, use
- replace().
-
- QList's value type must be an \l{assignable data type}. This
- covers most data types that are commonly used, but the compiler
- won't let you, for example, store a QWidget as a value; instead,
- store a QWidget *. A few functions have additional requirements;
- for example, indexOf() and lastIndexOf() expect the value type to
- support \c operator==(). These requirements are documented on a
- per-function basis.
-
- Like the other container classes, QList provides \l{Java-style
- iterators} (QListIterator and QMutableListIterator) and
- \l{STL-style iterators} (QList::const_iterator and
- QList::iterator). In practice, these are rarely used, because you
- can use indexes into the QList. QList is implemented in such a way
- that direct index-based access is just as fast as using iterators.
-
- QList does \e not support inserting, prepending, appending or
- replacing with references to its own values. Doing so will cause
- your application to abort with an error message.
-
- To make QList as efficient as possible, its member functions don't
- validate their input before using it. Except for isEmpty(), member
- functions always assume the list is \e not empty. Member functions
- that take index values as parameters always assume their index
- value parameters are in the valid range. This means QList member
- functions can fail. If you define QT_NO_DEBUG when you compile,
- failures will not be detected. If you \e don't define QT_NO_DEBUG,
- failures will be detected using Q_ASSERT() or Q_ASSERT_X() with an
- appropriate message.
-
- To avoid failures when your list can be empty, call isEmpty()
- before calling other member functions. If you must pass an index
- value that might not be in the valid range, check that it is less
- than the value returned by size() but \e not less than 0.
-
- \section1 More Members
-
- If T is a QByteArray, this class has a couple more members that can be
- used. See the documentation for QByteArrayList for more information.
-
- If T is QString, this class has the following additional members:
- \l{QStringList::filter()}{filter},
- \l{QStringList::join()}{join},
- \l{QStringList::removeDuplicates()}{removeDuplicates},
- \l{QStringList::sort()}{sort}.
-
- \section1 More Information on Using Qt Containers
-
- For a detailed discussion comparing Qt containers with each other and
- with STL containers, see \l {Understand the Qt Containers}.
-
- \sa QListIterator, QMutableListIterator, QLinkedList, QVector
-*/
-
-/*!
- \fn template <class T> QList<T>::QList(QList<T> &&other)
-
- Move-constructs a QList instance, making it point at the same
- object that \a other was pointing to.
-
- \since 5.2
-*/
-
-/*! \fn template <class T> template<typename InputIterator> QList<T>::QList(InputIterator first, InputIterator last)
- \since 5.14
-
- Constructs a QList with the contents in the iterator range [\a first, \a last).
-
- The value type of \c InputIterator must be convertible to \c T.
-*/
-
-/*!
- \fn template <class T> QList<T> QList<T>::mid(int pos, int length) const
-
- Returns a sub-list which includes elements from this list,
- starting at position \a pos. If \a length is -1 (the default), all
- elements from \a pos are included; otherwise \a length elements (or
- all remaining elements if there are less than \a length elements)
- are included.
-*/
-
-/*! \fn template <class T> QList<T>::QList()
-
- Constructs an empty list.
-*/
-
-/*! \fn template <class T> QList<T>::QList(const QList<T> &other)
-
- Constructs a copy of \a other.
-
- This operation takes \l{Algorithmic Complexity}{constant time},
- because QList is \l{implicitly shared}. This makes returning a
- QList from a function very fast. If a shared instance is modified,
- it will be copied (copy-on-write), and that takes
- \l{Algorithmic Complexity}{linear time}.
-
- \sa operator=()
-*/
-
-/*! \fn template <class T> QList<T>::QList(std::initializer_list<T> args)
- \since 4.8
-
- Construct a list from the std::initializer_list specified by \a args.
-
- This constructor is only enabled if the compiler supports C++11 initializer
- lists.
-*/
-
-/*! \fn template <class T> QList<T>::~QList()
-
- Destroys the list. References to the values in the list and all
- iterators of this list become invalid.
-*/
-
-/*! \fn template <class T> QList<T> &QList<T>::operator=(const QList<T> &other)
-
- Assigns \a other to this list and returns a reference to this
- list.
-*/
-
-/*!
- \fn template <class T> QList &QList<T>::operator=(QList<T> &&other)
-
- Move-assigns \a other to this QList instance.
-
- \since 5.2
-*/
-
-/*! \fn template <class T> void QList<T>::swap(QList<T> &other)
- \since 4.8
-
- Swaps list \a other with this list. This operation is very
- fast and never fails.
-*/
-
-/*! \fn template <class T> bool QList<T>::operator==(const QList<T> &other) const
-
- Returns \c true if \a other is equal to this list; otherwise returns
- false.
-
- Two lists are considered equal if they contain the same values in
- the same order.
-
- This function requires the value type to have an implementation of
- \c operator==().
-
- \sa operator!=()
-*/
-
-/*! \fn template <class T> bool QList<T>::operator!=(const QList<T> &other) const
-
- Returns \c true if \a other is not equal to this list; otherwise
- returns \c false.
-
- Two lists are considered equal if they contain the same values in
- the same order.
-
- This function requires the value type to have an implementation of
- \c operator==().
-
- \sa operator==()
-*/
-
-/*! \fn template <class T> bool operator<(const QList<T> &lhs, const QList<T> &rhs)
- \since 5.6
- \relates QList
-
- Returns \c true if list \a lhs is
- \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically less than} \a rhs; otherwise returns \c false.
-
- This function requires the value type to have an implementation
- of \c operator<().
-*/
-
-/*! \fn template <class T> bool operator<=(const QList<T> &lhs, const QList<T> &rhs)
- \since 5.6
- \relates QList
-
- Returns \c true if list \a lhs is
- \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically less than or equal to} \a rhs; otherwise returns \c false.
-
- This function requires the value type to have an implementation
- of \c operator<().
-*/
-
-/*! \fn template <class T> bool operator>(const QList<T> &lhs, const QList<T> &rhs)
- \since 5.6
- \relates QList
-
- Returns \c true if list \a lhs is
- \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically greater than} \a rhs; otherwise returns \c false.
-
- This function requires the value type to have an implementation
- of \c operator<().
-*/
-
-/*! \fn template <class T> bool operator>=(const QList<T> &lhs, const QList<T> &rhs)
- \since 5.6
- \relates QList
-
- Returns \c true if list \a lhs is
- \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically greater than or equal to} \a rhs; otherwise returns \c false.
-
- This function requires the value type to have an implementation
- of \c operator<().
-*/
-
-/*!
- \fn template <class T> uint qHash(const QList<T> &key, uint seed = 0)
- \since 5.6
- \relates QList
-
- Returns the hash value for \a key,
- using \a seed to seed the calculation.
-
- This function requires qHash() to be overloaded for the value type \c T.
-*/
-
-/*!
- \fn template <class T> int QList<T>::size() const
-
- Returns the number of items in the list.
-
- \sa isEmpty(), count()
-*/
-
-/*! \fn template <class T> void QList<T>::detach()
-
- \internal
-*/
-
-/*! \fn template <class T> void QList<T>::detachShared()
-
- \internal
-
- like detach(), but does nothing if we're shared_null.
- This prevents needless mallocs, and makes QList more exception safe
- in case of cleanup work done in destructors on empty lists.
-*/
-
-/*! \fn template <class T> bool QList<T>::isDetached() const
-
- \internal
-*/
-
-/*! \fn template <class T> void QList<T>::setSharable(bool sharable)
-
- \internal
-*/
-
-/*! \fn template <class T> bool QList<T>::isSharedWith(const QList<T> &other) const
-
- \internal
-*/
-
-/*! \fn template <class T> bool QList<T>::isEmpty() const
-
- Returns \c true if the list contains no items; otherwise returns
- false.
-
- \sa size()
-*/
-
-/*! \fn template <class T> void QList<T>::clear()
-
- Removes all items from the list.
-
- \sa removeAll()
-*/
-
-/*! \fn template <class T> const T &QList<T>::at(int i) const
-
- Returns the item at index position \a i in the list. \a i must be
- a valid index position in the list (i.e., 0 <= \a i < size()).
-
- This function is very fast (\l{Algorithmic Complexity}{constant time}).
-
- \sa value(), operator[]()
-*/
-
-/*! \fn template <class T> T &QList<T>::operator[](int i)
-
- Returns the item at index position \a i as a modifiable reference.
- \a i must be a valid index position in the list (i.e., 0 <= \a i <
- size()).
-
- If this function is called on a list that is currently being shared, it
- will trigger a copy of all elements. Otherwise, this function runs in
- \l{Algorithmic Complexity}{constant time}. If you do not want to modify
- the list you should use QList::at().
-
- \sa at(), value()
-*/
-
-/*! \fn template <class T> const T &QList<T>::operator[](int i) const
-
- \overload
-
- Same as at(). This function runs in \l{Algorithmic Complexity}{constant time}.
-*/
-
-/*! \fn template <class T> void QList<T>::reserve(int alloc)
-
- Reserve space for \a alloc elements.
-
- If \a alloc is smaller than the current size of the list, nothing will happen.
-
- Use this function to avoid repetetive reallocation of QList's internal
- data if you can predict how many elements will be appended.
- Note that the reservation applies only to the internal pointer array.
-
- \since 4.7
-*/
-
-/*! \fn template <class T> void QList<T>::append(const T &value)
-
- Inserts \a value at the end of the list.
-
- Example:
- \snippet code/src_corelib_tools_qlistdata.cpp 6
-
- This is the same as list.insert(size(), \a value).
-
- If this list is not shared, this operation is typically
- very fast (amortized \l{Algorithmic Complexity}{constant time}),
- because QList preallocates extra space on both sides of its
- internal buffer to allow for fast growth at both ends of the list.
-
- \sa operator<<(), prepend(), insert()
-*/
-
-/*! \fn template <class T> void QList<T>::append(const QList<T> &value)
-
- \overload
-
- \since 4.5
-
- Appends the items of the \a value list to this list.
-
- \sa operator<<(), operator+=()
-*/
-
-/*! \fn template <class T> void QList<T>::prepend(const T &value)
-
- Inserts \a value at the beginning of the list.
-
- Example:
- \snippet code/src_corelib_tools_qlistdata.cpp 7
-
- This is the same as list.insert(0, \a value).
-
- If this list is not shared, this operation is typically
- very fast (amortized \l{Algorithmic Complexity}{constant time}),
- because QList preallocates extra space on both sides of its
- internal buffer to allow for fast growth at both ends of the list.
-
- \sa append(), insert()
-*/
-
-/*! \fn template <class T> void QList<T>::insert(int i, const T &value)
-
- Inserts \a value at index position \a i in the list.
-
- If \a i == 0, the value is prepended to the list. If \a i == size(),
- the value is appended to the list.
-
- Example:
- \snippet code/src_corelib_tools_qlistdata.cpp 8
-
- \sa append(), prepend(), replace(), removeAt()
-*/
-
-/*! \fn template <class T> QList<T>::iterator QList<T>::insert(iterator before, const T &value)
-
- \overload
-
- Inserts \a value in front of the item pointed to by the
- iterator \a before. Returns an iterator pointing at the inserted
- item. Note that the iterator passed to the function will be
- invalid after the call; the returned iterator should be used
- instead.
-*/
-
-/*! \fn template <class T> void QList<T>::replace(int i, const T &value)
-
- Replaces the item at index position \a i with \a value. \a i must
- be a valid index position in the list (i.e., 0 <= \a i < size()).
-
- \sa operator[](), removeAt()
-*/
-
-/*!
- \fn template <class T> int QList<T>::removeAll(const T &value)
-
- Removes all occurrences of \a value in the list and returns the
- number of entries removed.
-
- Example:
- \snippet code/src_corelib_tools_qlistdata.cpp 9
-
- This function requires the value type to have an implementation of
- \c operator==().
-
- \sa removeOne(), removeAt(), takeAt(), replace()
-*/
-
-/*!
- \fn template <class T> bool QList<T>::removeOne(const T &value)
- \since 4.4
-
- Removes the first occurrence of \a value in the list and returns
- true on success; otherwise returns \c false.
-
- Example:
- \snippet code/src_corelib_tools_qlistdata.cpp 10
-
- This function requires the value type to have an implementation of
- \c operator==().
-
- \sa removeAll(), removeAt(), takeAt(), replace()
-*/
-
-/*! \fn template <class T> void QList<T>::removeAt(int i)
-
- Removes the item at index position \a i. \a i must be a valid
- index position in the list (i.e., 0 <= \a i < size()).
-
- \sa takeAt(), removeFirst(), removeLast(), removeOne()
-*/
-
-/*! \fn template <class T> T QList<T>::takeAt(int i)
-
- Removes the item at index position \a i and returns it. \a i must
- be a valid index position in the list (i.e., 0 <= \a i < size()).
-
- If you don't use the return value, removeAt() is more efficient.
-
- \sa removeAt(), takeFirst(), takeLast()
-*/
-
-/*! \fn template <class T> T QList<T>::takeFirst()
-
- Removes the first item in the list and returns it. This is the
- same as takeAt(0). This function assumes the list is not empty. To
- avoid failure, call isEmpty() before calling this function.
-
- If this list is not shared, this operation takes
- \l {Algorithmic Complexity}{constant time}.
-
- If you don't use the return value, removeFirst() is more
- efficient.
-
- \sa takeLast(), takeAt(), removeFirst()
-*/
-
-/*! \fn template <class T> T QList<T>::takeLast()
-
- Removes the last item in the list and returns it. This is the
- same as takeAt(size() - 1). This function assumes the list is
- not empty. To avoid failure, call isEmpty() before calling this
- function.
-
- If this list is not shared, this operation takes
- \l {Algorithmic Complexity}{constant time}.
-
- If you don't use the return value, removeLast() is more
- efficient.
-
- \sa takeFirst(), takeAt(), removeLast()
-*/
-
-/*! \fn template <class T> void QList<T>::move(int from, int to)
-
- Moves the item at index position \a from to index position \a to.
-
- Example:
- \snippet code/src_corelib_tools_qlistdata.cpp 11
-
- This is the same as insert(\a{to}, takeAt(\a{from})).This function
- assumes that both \a from and \a to are at least 0 but less than
- size(). To avoid failure, test that both \a from and \a to are at
- least 0 and less than size().
-
- \sa swap(), insert(), takeAt()
-*/
-
-/*! \fn template <class T> void QList<T>::swap(int i, int j)
-
- \obsolete Use swapItemsAt()
-
- \sa move(), swapItemsAt()
-*/
-
-/*! \fn template <class T> void QList<T>::swapItemsAt(int i, int j)
- \since 5.13
-
- Exchange the item at index position \a i with the item at index
- position \a j. This function assumes that both \a i and \a j are
- at least 0 but less than size(). To avoid failure, test that both
- \a i and \a j are at least 0 and less than size().
-
- Example:
- \snippet code/src_corelib_tools_qlistdata.cpp 12
-
- \sa move()
-*/
-
-/*! \fn template <class T> int QList<T>::indexOf(const T &value, int from = 0) const
-
- Returns the index position of the first occurrence of \a value in
- the list, searching forward from index position \a from. Returns
- -1 if no item matched.
-
- Example:
- \snippet code/src_corelib_tools_qlistdata.cpp 13
-
- This function requires the value type to have an implementation of
- \c operator==().
-
- Note that QList uses 0-based indexes, just like C++ arrays. Negative
- indexes are not supported with the exception of the value mentioned
- above.
-
- \sa lastIndexOf(), contains()
-*/
-
-/*! \fn template <class T> int QList<T>::lastIndexOf(const T &value, int from = -1) const
-
- Returns the index position of the last occurrence of \a value in
- the list, searching backward from index position \a from. If \a
- from is -1 (the default), the search starts at the last item.
- Returns -1 if no item matched.
-
- Example:
- \snippet code/src_corelib_tools_qlistdata.cpp 14
-
- This function requires the value type to have an implementation of
- \c operator==().
-
- Note that QList uses 0-based indexes, just like C++ arrays. Negative
- indexes are not supported with the exception of the value mentioned
- above.
-
- \sa indexOf()
-*/
-
-/*! \fn template <class T> bool QList<T>::contains(const T &value) const
-
- Returns \c true if the list contains an occurrence of \a value;
- otherwise returns \c false.
-
- This function requires the value type to have an implementation of
- \c operator==().
-
- \sa indexOf(), count()
-*/
-
-/*! \fn template <class T> int QList<T>::count(const T &value) const
-
- Returns the number of occurrences of \a value in the list.
-
- This function requires the value type to have an implementation of
- \c operator==().
-
- \sa contains(), indexOf()
-*/
-
-/*! \fn template <class T> bool QList<T>::startsWith(const T &value) const
- \since 4.5
-
- Returns \c true if this list is not empty and its first
- item is equal to \a value; otherwise returns \c false.
-
- \sa isEmpty(), contains()
-*/
-
-/*! \fn template <class T> bool QList<T>::endsWith(const T &value) const
- \since 4.5
-
- Returns \c true if this list is not empty and its last
- item is equal to \a value; otherwise returns \c false.
-
- \sa isEmpty(), contains()
-*/
-
-/*! \fn template <class T> QList<T>::iterator QList<T>::begin()
-
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
- the list.
-
- \sa constBegin(), end()
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator QList<T>::begin() const
-
- \overload
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator QList<T>::cbegin() const
- \since 5.0
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
- in the list.
-
- \sa begin(), cend()
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator QList<T>::constBegin() const
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
- in the list.
-
- \sa begin(), constEnd()
-*/
-
-/*! \fn template <class T> QList<T>::iterator QList<T>::end()
-
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
- after the last item in the list.
-
- \sa begin(), constEnd()
-*/
-
-/*! \fn template <class T> const_iterator QList<T>::end() const
-
- \overload
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator QList<T>::cend() const
- \since 5.0
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- item after the last item in the list.
-
- \sa cbegin(), end()
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator QList<T>::constEnd() const
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- item after the last item in the list.
-
- \sa constBegin(), end()
-*/
-
-/*! \fn template <class T> QList<T>::reverse_iterator QList<T>::rbegin()
- \since 5.6
-
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the list, in reverse order.
-
- \sa begin(), crbegin(), rend()
-*/
-
-/*! \fn template <class T> QList<T>::const_reverse_iterator QList<T>::rbegin() const
- \since 5.6
- \overload
-*/
-
-/*! \fn template <class T> QList<T>::const_reverse_iterator QList<T>::crbegin() const
- \since 5.6
-
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the list, in reverse order.
-
- \sa begin(), rbegin(), rend()
-*/
-
-/*! \fn template <class T> QList<T>::reverse_iterator QList<T>::rend()
- \since 5.6
-
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last item in the list, in reverse order.
-
- \sa end(), crend(), rbegin()
-*/
-
-/*! \fn template <class T> QList<T>::const_reverse_iterator QList<T>::rend() const
- \since 5.6
- \overload
-*/
-
-/*! \fn template <class T> QList<T>::const_reverse_iterator QList<T>::crend() const
- \since 5.6
-
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one
- past the last item in the list, in reverse order.
-
- \sa end(), rend(), rbegin()
-*/
-
-/*! \fn template <class T> QList<T>::iterator QList<T>::erase(iterator pos)
-
- Removes the item associated with the iterator \a pos from the
- list, and returns an iterator to the next item in the list (which
- may be end()).
-
- \sa insert(), removeAt()
-*/
-
-/*! \fn template <class T> QList<T>::iterator QList<T>::erase(iterator begin, iterator end)
-
- \overload
-
- Removes all the items from \a begin up to (but not including) \a
- end. Returns an iterator to the same item that \a end referred to
- before the call.
-*/
-
-/*! \typedef QList::Iterator
-
- Qt-style synonym for QList::iterator.
-*/
-
-/*! \typedef QList::ConstIterator
-
- Qt-style synonym for QList::const_iterator.
-*/
-
-/*!
- \typedef QList::size_type
-
- Typedef for int. Provided for STL compatibility.
-*/
-
-/*!
- \typedef QList::value_type
-
- Typedef for T. Provided for STL compatibility.
-*/
-
-/*!
- \typedef QList::difference_type
-
- Typedef for ptrdiff_t. Provided for STL compatibility.
-*/
-
-/*!
- \typedef QList::pointer
-
- Typedef for T *. Provided for STL compatibility.
-*/
-
-/*!
- \typedef QList::const_pointer
-
- Typedef for const T *. Provided for STL compatibility.
-*/
-
-/*!
- \typedef QList::reference
-
- Typedef for T &. Provided for STL compatibility.
-*/
-
-/*!
- \typedef QList::const_reference
-
- Typedef for const T &. Provided for STL compatibility.
-*/
-
-/*! \typedef QList::reverse_iterator
- \since 5.6
-
- The QList::reverse_iterator typedef provides an STL-style non-const
- reverse iterator for QList.
-
- It is simply a typedef for \c{std::reverse_iterator<iterator>}.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QList::rbegin(), QList::rend(), QList::const_reverse_iterator, QList::iterator
-*/
-
-/*! \typedef QList::const_reverse_iterator
- \since 5.6
-
- The QList::const_reverse_iterator typedef provides an STL-style const
- reverse iterator for QList.
-
- It is simply a typedef for \c{std::reverse_iterator<const_iterator>}.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QList::rbegin(), QList::rend(), QList::reverse_iterator, QList::const_iterator
-*/
-
-/*! \fn template <class T> int QList<T>::count() const
-
- Returns the number of items in the list. This is effectively the
- same as size().
-*/
-
-/*! \fn template <class T> int QList<T>::length() const
- \since 4.5
-
- This function is identical to count().
-
- \sa count()
-*/
-
-/*! \fn template <class T> T& QList<T>::first()
-
- Returns a reference to the first item in the list. The list must
- not be empty. If the list can be empty, call isEmpty() before
- calling this function.
-
- \sa constFirst(), last(), isEmpty()
-*/
-
-/*! \fn template <class T> const T& QList<T>::first() const
-
- \overload
-*/
-
-/*! \fn template <class T> const T& QList<T>::constFirst() const
- \since 5.6
-
- Returns a const reference to the first item in the list. The list must
- not be empty. If the list can be empty, call isEmpty() before
- calling this function.
-
- \sa constLast(), isEmpty(), first()
-*/
-
-/*! \fn template <class T> T& QList<T>::last()
-
- Returns a reference to the last item in the list. The list must
- not be empty. If the list can be empty, call isEmpty() before
- calling this function.
-
- \sa constLast(), first(), isEmpty()
-*/
-
-/*! \fn template <class T> const T& QList<T>::last() const
-
- \overload
-*/
-
-/*! \fn template <class T> const T& QList<T>::constLast() const
- \since 5.6
-
- Returns a reference to the last item in the list. The list must
- not be empty. If the list can be empty, call isEmpty() before
- calling this function.
-
- \sa constFirst(), isEmpty(), last()
-*/
-
-/*! \fn template <class T> void QList<T>::removeFirst()
-
- Removes the first item in the list. Calling this function is
- equivalent to calling removeAt(0). The list must not be empty. If
- the list can be empty, call isEmpty() before calling this
- function.
-
- \sa removeAt(), takeFirst()
-*/
-
-/*! \fn template <class T> void QList<T>::removeLast()
-
- Removes the last item in the list. Calling this function is
- equivalent to calling removeAt(size() - 1). The list must not be
- empty. If the list can be empty, call isEmpty() before calling
- this function.
-
- \sa removeAt(), takeLast()
-*/
-
-/*! \fn template <class T> T QList<T>::value(int i) const
-
- Returns the value at index position \a i in the list.
-
- If the index \a i is out of bounds, the function returns a
- \l{default-constructed value}. If you are certain that the index
- is going to be within bounds, you can use at() instead, which is
- slightly faster.
-
- \sa at(), operator[]()
-*/
-
-/*! \fn template <class T> T QList<T>::value(int i, const T &defaultValue) const
-
- \overload
-
- If the index \a i is out of bounds, the function returns
- \a defaultValue.
-*/
-
-/*! \fn template <class T> void QList<T>::push_back(const T &value)
-
- This function is provided for STL compatibility. It is equivalent
- to \l{QList::append()}{append(\a value)}.
-*/
-
-/*! \fn template <class T> void QList<T>::push_front(const T &value)
-
- This function is provided for STL compatibility. It is equivalent
- to \l{QList::prepend()}{prepend(\a value)}.
-*/
-
-/*! \fn template <class T> T& QList<T>::front()
-
- This function is provided for STL compatibility. It is equivalent
- to first(). The list must not be empty. If the list can be empty,
- call isEmpty() before calling this function.
-*/
-
-/*! \fn template <class T> const T& QList<T>::front() const
-
- \overload
-*/
-
-/*! \fn template <class T> T& QList<T>::back()
-
- This function is provided for STL compatibility. It is equivalent
- to last(). The list must not be empty. If the list can be empty,
- call isEmpty() before calling this function.
-*/
-
-/*! \fn template <class T> const T& QList<T>::back() const
-
- \overload
-*/
-
-/*! \fn template <class T> void QList<T>::pop_front()
-
- This function is provided for STL compatibility. It is equivalent
- to removeFirst(). The list must not be empty. If the list can be
- empty, call isEmpty() before calling this function.
-*/
-
-/*! \fn template <class T> void QList<T>::pop_back()
-
- This function is provided for STL compatibility. It is equivalent
- to removeLast(). The list must not be empty. If the list can be
- empty, call isEmpty() before calling this function.
-*/
-
-/*! \fn template <class T> bool QList<T>::empty() const
-
- This function is provided for STL compatibility. It is equivalent
- to isEmpty() and returns \c true if the list is empty.
-*/
-
-/*! \fn template <class T> QList<T> &QList<T>::operator+=(const QList<T> &other)
-
- Appends the items of the \a other list to this list and returns a
- reference to this list.
-
- \sa operator+(), append()
-*/
-
-/*! \fn template <class T> void QList<T>::operator+=(const T &value)
-
- \overload
-
- Appends \a value to the list.
-
- \sa append(), operator<<()
-*/
-
-/*! \fn template <class T> QList<T> QList<T>::operator+(const QList<T> &other) const
-
- Returns a list that contains all the items in this list followed
- by all the items in the \a other list.
-
- \sa operator+=()
-*/
-
-/*! \fn template <class T> QList<T> &QList<T>::operator<<(const QList<T> &other)
-
- Appends the items of the \a other list to this list and returns a
- reference to this list.
-
- \sa operator+=(), append()
-*/
-
-/*! \fn template <class T> void QList<T>::operator<<(const T &value)
-
- \overload
-
- Appends \a value to the list.
-*/
-
-/*! \class QList::iterator
- \inmodule QtCore
- \brief The QList::iterator class provides an STL-style non-const iterator for QList and QQueue.
-
- QList features both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style iterators are more low-level and more
- cumbersome to use; on the other hand, they are slightly faster
- and, for developers who already know STL, have the advantage of
- familiarity.
-
- QList\<T\>::iterator allows you to iterate over a QList\<T\> (or
- QQueue\<T\>) and to modify the list item associated with the
- iterator. If you want to iterate over a const QList, use
- QList::const_iterator instead. It is generally good practice to
- use QList::const_iterator on a non-const QList as well, unless
- you need to change the QList through the iterator. Const
- iterators are slightly faster, and can improve code readability.
-
- The default QList::iterator constructor creates an uninitialized
- iterator. You must initialize it using a QList function like
- QList::begin(), QList::end(), or QList::insert() before you can
- start iterating. Here's a typical loop that prints all the items
- stored in a list:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 15
-
- Let's see a few examples of things we can do with a
- QList::iterator that we cannot do with a QList::const_iterator.
- Here's an example that increments every value stored in a
- QList\<int\> by 2:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 16
-
- Most QList functions accept an integer index rather than an
- iterator. For that reason, iterators are rarely useful in
- connection with QList. One place where STL-style iterators do
- make sense is as arguments to \l{generic algorithms}.
-
- For example, here's how to delete all the widgets stored in a
- QList\<QWidget *\>:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 17
-
- Multiple iterators can be used on the same list. However, be
- aware that any non-const function call performed on the QList
- will render all existing iterators undefined. If you need to keep
- iterators over a long period of time, we recommend that you use
- QLinkedList rather than QList.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QList::const_iterator, QMutableListIterator
-*/
-
-/*! \typedef QList::iterator::iterator_category
-
- A synonym for \e {std::random_access_iterator_tag} indicating
- this iterator is a random access iterator.
-*/
-
-/*! \typedef QList::iterator::difference_type
-
- \internal
-*/
-
-/*! \typedef QList::iterator::value_type
-
- \internal
-*/
-
-/*! \typedef QList::iterator::pointer
-
- \internal
-*/
-
-/*! \typedef QList::iterator::reference
-
- \internal
-*/
-
-/*! \fn template <class T> QList<T>::iterator::iterator()
-
- Constructs an uninitialized iterator.
-
- Functions like operator*() and operator++() should not be called
- on an uninitialized iterator. Use operator=() to assign a value
- to it before using it.
-
- \sa QList::begin(), QList::end()
-*/
-
-/*! \fn template <class T> QList<T>::iterator::iterator(Node *node)
-
- \internal
-*/
-
-/*! \fn template <class T> QList<T>::iterator::iterator(const iterator &other)
-
- Constructs a copy of \a other.
-*/
-
-/*! \fn template <class T> T &QList<T>::iterator::operator*() const
-
- Returns a modifiable reference to the current item.
-
- You can change the value of an item by using operator*() on the
- left side of an assignment, for example:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 18
-
- \sa operator->()
-*/
-
-/*! \fn template <class T> T *QList<T>::iterator::operator->() const
-
- Returns a pointer to the current item.
-
- \sa operator*()
-*/
-
-/*! \fn template <class T> T &QList<T>::iterator::operator[](difference_type j) const
-
- Returns a modifiable reference to the item at position *this +
- \a{j}.
-
- This function is provided to make QList iterators behave like C++
- pointers.
-
- \sa operator+()
-*/
-
-/*!
- \fn template <class T> bool QList<T>::iterator::operator==(const iterator &other) const
- \fn template <class T> bool QList<T>::iterator::operator==(const const_iterator &other) const
-
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-
-/*!
- \fn template <class T> bool QList<T>::iterator::operator!=(const iterator &other) const
- \fn template <class T> bool QList<T>::iterator::operator!=(const const_iterator &other) const
-
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-
-/*!
- \fn template <class T> bool QList<T>::iterator::operator<(const iterator& other) const
- \fn template <class T> bool QList<T>::iterator::operator<(const const_iterator& other) const
-
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
-*/
-
-/*!
- \fn template <class T> bool QList<T>::iterator::operator<=(const iterator& other) const
- \fn template <class T> bool QList<T>::iterator::operator<=(const const_iterator& other) const
-
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
-*/
-
-/*!
- \fn template <class T> bool QList<T>::iterator::operator>(const iterator& other) const
- \fn template <class T> bool QList<T>::iterator::operator>(const const_iterator& other) const
-
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
-*/
-
-/*!
- \fn template <class T> bool QList<T>::iterator::operator>=(const iterator& other) const
- \fn template <class T> bool QList<T>::iterator::operator>=(const const_iterator& other) const
-
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
-*/
-
-/*! \fn template <class T> QList<T>::iterator &QList<T>::iterator::operator++()
-
- The prefix ++ operator (\c{++it}) advances the iterator to the
- next item in the list and returns an iterator to the new current
- item.
-
- Calling this function on QList::end() leads to undefined results.
-
- \sa operator--()
-*/
-
-/*! \fn template <class T> QList<T>::iterator QList<T>::iterator::operator++(int)
-
- \overload
-
- The postfix ++ operator (\c{it++}) advances the iterator to the
- next item in the list and returns an iterator to the previously
- current item.
-*/
-
-/*! \fn template <class T> QList<T>::iterator &QList<T>::iterator::operator--()
-
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
-
- Calling this function on QList::begin() leads to undefined results.
-
- \sa operator++()
-*/
-
-/*! \fn template <class T> QList<T>::iterator QList<T>::iterator::operator--(int)
-
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
-*/
-
-/*! \fn template <class T> QList<T>::iterator &QList<T>::iterator::operator+=(difference_type j)
-
- Advances the iterator by \a j items. (If \a j is negative, the
- iterator goes backward.)
-
- \sa operator-=(), operator+()
-*/
-
-/*! \fn template <class T> QList<T>::iterator &QList<T>::iterator::operator-=(difference_type j)
-
- Makes the iterator go back by \a j items. (If \a j is negative,
- the iterator goes forward.)
-
- \sa operator+=(), operator-()
-*/
-
-/*! \fn template <class T> QList<T>::iterator QList<T>::iterator::operator+(difference_type j) const
-
- Returns an iterator to the item at \a j positions forward from
- this iterator. (If \a j is negative, the iterator goes backward.)
-
- \sa operator-(), operator+=()
-*/
-
-/*! \fn template <class T> QList<T>::iterator QList<T>::iterator::operator-(difference_type j) const
-
- Returns an iterator to the item at \a j positions backward from
- this iterator. (If \a j is negative, the iterator goes forward.)
-
- \sa operator+(), operator-=()
-*/
-
-/*! \fn template <class T> int QList<T>::iterator::operator-(iterator other) const
-
- Returns the number of items between the item pointed to by \a
- other and the item pointed to by this iterator.
-*/
-
-/*! \class QList::const_iterator
- \inmodule QtCore
- \brief The QList::const_iterator class provides an STL-style const iterator for QList and QQueue.
-
- QList provides both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style iterators are more low-level and more
- cumbersome to use; on the other hand, they are slightly faster
- and, for developers who already know STL, have the advantage of
- familiarity.
-
- QList\<T\>::const_iterator allows you to iterate over a
- QList\<T\> (or a QQueue\<T\>). If you want to modify the QList as
- you iterate over it, use QList::iterator instead. It is generally
- good practice to use QList::const_iterator on a non-const QList
- as well, unless you need to change the QList through the
- iterator. Const iterators are slightly faster, and can improve
- code readability.
-
- The default QList::const_iterator constructor creates an
- uninitialized iterator. You must initialize it using a QList
- function like QList::constBegin(), QList::constEnd(), or
- QList::insert() before you can start iterating. Here's a typical
- loop that prints all the items stored in a list:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 19
-
- Most QList functions accept an integer index rather than an
- iterator. For that reason, iterators are rarely useful in
- connection with QList. One place where STL-style iterators do
- make sense is as arguments to \l{generic algorithms}.
-
- For example, here's how to delete all the widgets stored in a
- QList\<QWidget *\>:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 20
-
- Multiple iterators can be used on the same list. However, be
- aware that any non-const function call performed on the QList
- will render all existing iterators undefined. If you need to keep
- iterators over a long period of time, we recommend that you use
- QLinkedList rather than QList.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QList::iterator, QListIterator
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator::const_iterator()
-
- Constructs an uninitialized iterator.
-
- Functions like operator*() and operator++() should not be called
- on an uninitialized iterator. Use operator=() to assign a value
- to it before using it.
-
- \sa QList::constBegin(), QList::constEnd()
-*/
-
-/*! \typedef QList::const_iterator::iterator_category
-
- A synonym for \e {std::random_access_iterator_tag} indicating
- this iterator is a random access iterator.
-*/
-
-/*! \typedef QList::const_iterator::difference_type
-
- \internal
-*/
-
-/*! \typedef QList::const_iterator::value_type
-
- \internal
-*/
-
-/*! \typedef QList::const_iterator::pointer
-
- \internal
-*/
-
-/*! \typedef QList::const_iterator::reference
-
- \internal
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator::const_iterator(Node *node)
-
- \internal
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator::const_iterator(const const_iterator &other)
-
- Constructs a copy of \a other.
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator::const_iterator(const iterator &other)
-
- Constructs a copy of \a other.
-*/
-
-/*! \fn template <class T> const T &QList<T>::const_iterator::operator*() const
-
- Returns the current item.
-
- \sa operator->()
-*/
-
-/*! \fn template <class T> const T *QList<T>::const_iterator::operator->() const
-
- Returns a pointer to the current item.
-
- \sa operator*()
-*/
-
-/*! \fn template <class T> const T &QList<T>::const_iterator::operator[](difference_type j) const
-
- Returns the item at position *this + \a{j}.
-
- This function is provided to make QList iterators behave like C++
- pointers.
-
- \sa operator+()
-*/
-
-/*! \fn template <class T> bool QList<T>::const_iterator::operator==(const const_iterator &other) const
-
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-
-/*! \fn template <class T> bool QList<T>::const_iterator::operator!=(const const_iterator &other) const
-
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-
-/*!
- \fn template <class T> bool QList<T>::const_iterator::operator<(const const_iterator& other) const
-
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
-*/
-
-/*!
- \fn template <class T> bool QList<T>::const_iterator::operator<=(const const_iterator& other) const
-
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
-*/
-
-/*!
- \fn template <class T> bool QList<T>::const_iterator::operator>(const const_iterator& other) const
-
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
-*/
-
-/*!
- \fn template <class T> bool QList<T>::const_iterator::operator>=(const const_iterator& other) const
-
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator &QList<T>::const_iterator::operator++()
-
- The prefix ++ operator (\c{++it}) advances the iterator to the
- next item in the list and returns an iterator to the new current
- item.
-
- Calling this function on QList::end() leads to undefined results.
-
- \sa operator--()
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator QList<T>::const_iterator::operator++(int)
-
- \overload
-
- The postfix ++ operator (\c{it++}) advances the iterator to the
- next item in the list and returns an iterator to the previously
- current item.
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator &QList<T>::const_iterator::operator--()
-
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
-
- Calling this function on QList::begin() leads to undefined results.
-
- \sa operator++()
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator QList<T>::const_iterator::operator--(int)
-
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator &QList<T>::const_iterator::operator+=(difference_type j)
-
- Advances the iterator by \a j items. (If \a j is negative, the
- iterator goes backward.)
-
- \sa operator-=(), operator+()
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator &QList<T>::const_iterator::operator-=(difference_type j)
-
- Makes the iterator go back by \a j items. (If \a j is negative,
- the iterator goes forward.)
-
- \sa operator+=(), operator-()
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator QList<T>::const_iterator::operator+(difference_type j) const
-
- Returns an iterator to the item at \a j positions forward from
- this iterator. (If \a j is negative, the iterator goes backward.)
-
- \sa operator-(), operator+=()
-*/
-
-/*! \fn template <class T> QList<T>::const_iterator QList<T>::const_iterator::operator-(difference_type j) const
-
- Returns an iterator to the item at \a j positions backward from
- this iterator. (If \a j is negative, the iterator goes forward.)
-
- \sa operator+(), operator-=()
-*/
-
-/*! \fn template <class T> int QList<T>::const_iterator::operator-(const_iterator other) const
-
- Returns the number of items between the item pointed to by \a
- other and the item pointed to by this iterator.
-*/
-
-/*! \fn template <class T> QDataStream &operator<<(QDataStream &out, const QList<T> &list)
- \relates QList
-
- Writes the list \a list to stream \a out.
-
- This function requires the value type to implement \c
- operator<<().
-
- \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
-*/
-
-/*! \fn template <class T> QDataStream &operator>>(QDataStream &in, QList<T> &list)
- \relates QList
-
- Reads a list from stream \a in into \a list.
-
- This function requires the value type to implement \c
- operator>>().
-
- \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
-*/
-
-/*! \fn template <class T> QList<T> QList<T>::fromVector(const QVector<T> &vector)
-
- Returns a QList object with the data contained in \a vector.
-
- Example:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 21
-
- \include containers-range-constructor.qdocinc
-
- \sa fromSet(), toVector(), QVector::toList()
-*/
-
-/*! \fn template <class T> QVector<T> QList<T>::toVector() const
-
- Returns a QVector object with the data contained in this QList.
-
- Example:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 22
-
- \include containers-range-constructor.qdocinc
-
- \sa toSet(), fromVector(), QVector::fromList()
-*/
-
-/*! \fn template <class T> QList<T> QList<T>::fromSet(const QSet<T> &set)
-
- Returns a QList object with the data contained in \a set. The
- order of the elements in the QList is undefined.
-
- Example:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 23
-
- \include containers-range-constructor.qdocinc
-
- \sa fromVector(), toSet(), QSet::toList()
-*/
-
-/*! \fn template <class T> QSet<T> QList<T>::toSet() const
-
- Returns a QSet object with the data contained in this QList.
- Since QSet doesn't allow duplicates, the resulting QSet might be
- smaller than the original list was.
-
- Example:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 24
-
- \include containers-range-constructor.qdocinc
-
- \sa toVector(), fromSet(), QSet::fromList()
-*/
-
-/*! \fn template <class T> QList<T> QList<T>::fromStdList(const std::list<T> &list)
-
- Returns a QList object with the data contained in \a list. The
- order of the elements in the QList is the same as in \a list.
-
- Example:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 25
-
- \include containers-range-constructor.qdocinc
-
- \sa toStdList(), QVector::fromStdVector()
-*/
-
-/*! \fn template <class T> std::list<T> QList<T>::toStdList() const
-
- Returns a std::list object with the data contained in this QList.
- Example:
-
- \snippet code/src_corelib_tools_qlistdata.cpp 26
-
- \include containers-range-constructor.qdocinc
-
- \sa fromStdList(), QVector::toStdVector()
-*/
-
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index ffd470efcd..515fba6530 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -40,1160 +40,19 @@
#ifndef QLIST_H
#define QLIST_H
-#include <QtCore/qalgorithms.h>
-#include <QtCore/qiterator.h>
-#include <QtCore/qrefcount.h>
-#include <QtCore/qarraydata.h>
-#include <QtCore/qhashfunctions.h>
#include <QtCore/qvector.h>
-#include <QtCore/qcontainertools_impl.h>
-
-#include <algorithm>
-#include <initializer_list>
-#include <iterator>
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
-#include <list>
-#endif
-
-#include <stdlib.h>
-#include <new>
-#include <limits.h>
-#include <string.h>
-
-#ifdef Q_CC_MSVC
-#pragma warning( push )
-#pragma warning( disable : 4127 ) // "conditional expression is constant"
-#endif
+#include <QtCore/qcontainerfwd.h>
+#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
QT_BEGIN_NAMESPACE
-
-
-template <typename T> class QVector;
-template <typename T> class QSet;
-
-template <typename T> struct QListSpecialMethods
-{
-protected:
- ~QListSpecialMethods() = default;
-};
-template <> struct QListSpecialMethods<QByteArray>;
-template <> struct QListSpecialMethods<QString>;
-
-struct Q_CORE_EXPORT QListData {
- // tags for tag-dispatching of QList implementations,
- // based on QList's three different memory layouts:
- struct NotArrayCompatibleLayout {};
- struct NotIndirectLayout {};
- struct ArrayCompatibleLayout : NotIndirectLayout {}; // data laid out like a C array
- struct InlineWithPaddingLayout : NotArrayCompatibleLayout, NotIndirectLayout {}; // data laid out like a C array with padding
- struct IndirectLayout : NotArrayCompatibleLayout {}; // data allocated on the heap
-
- struct Data {
- QtPrivate::RefCount ref;
- int alloc, begin, end;
- void *array[1];
- };
- enum { DataHeaderSize = sizeof(Data) - sizeof(void *) };
-
- Data *detach(int alloc);
- Data *detach_grow(int *i, int n);
- void realloc(int alloc);
- void realloc_grow(int growth);
- inline void dispose() { dispose(d); }
- static void dispose(Data *d);
- static const Data shared_null;
- Data *d;
- void **erase(void **xi);
- void **append(int n);
- void **append();
- void **append(const QListData &l);
- void **prepend();
- void **insert(int i);
- void remove(int i);
- void remove(int i, int n);
- void move(int from, int to);
- inline int size() const noexcept { return int(d->end - d->begin); } // q6sizetype
- inline bool isEmpty() const noexcept { return d->end == d->begin; }
- inline void **at(int i) const noexcept { return d->array + d->begin + i; }
- inline void **begin() const noexcept { return d->array + d->begin; }
- inline void **end() const noexcept { return d->array + d->end; }
-};
-
-namespace QtPrivate {
- template <typename V, typename U> int indexOf(const QList<V> &list, const U &u, int from);
- template <typename V, typename U> int lastIndexOf(const QList<V> &list, const U &u, int from);
-}
-
-template <typename T>
-class QList
-#ifndef Q_QDOC
- : public QListSpecialMethods<T>
-#endif
-{
-public:
- struct MemoryLayout
- : std::conditional<
- // must stay isStatic until ### Qt 6 for BC reasons (don't use !isRelocatable)!
- QTypeInfo<T>::isStatic || QTypeInfo<T>::isLarge,
- QListData::IndirectLayout,
- typename std::conditional<
- sizeof(T) == sizeof(void*),
- QListData::ArrayCompatibleLayout,
- QListData::InlineWithPaddingLayout
- >::type>::type {};
-private:
- template <typename V, typename U> friend int QtPrivate::indexOf(const QList<V> &list, const U &u, int from);
- template <typename V, typename U> friend int QtPrivate::lastIndexOf(const QList<V> &list, const U &u, int from);
- struct Node { void *v;
-#if defined(Q_CC_BOR)
- Q_INLINE_TEMPLATE T &t();
-#else
- Q_INLINE_TEMPLATE T &t()
- { return *reinterpret_cast<T*>(QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
- ? v : this); }
-#endif
- };
-
- union { QListData p; QListData::Data *d; };
-
-public:
- inline QList() noexcept : d(const_cast<QListData::Data *>(&QListData::shared_null)) { }
- QList(const QList<T> &l);
- ~QList();
- QList<T> &operator=(const QList<T> &l);
- inline QList(QList<T> &&other) noexcept
- : d(other.d) { other.d = const_cast<QListData::Data *>(&QListData::shared_null); }
- inline QList &operator=(QList<T> &&other) noexcept
- { QList moved(std::move(other)); swap(moved); return *this; }
- inline void swap(QList<T> &other) noexcept { qSwap(d, other.d); }
- inline QList(std::initializer_list<T> args)
- : QList(args.begin(), args.end()) {}
- template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
- QList(InputIterator first, InputIterator last);
- bool operator==(const QList<T> &l) const;
- inline bool operator!=(const QList<T> &l) const { return !(*this == l); }
-
- inline int size() const noexcept { return p.size(); }
-
- inline void detach() { if (d->ref.isShared()) detach_helper(); }
-
- inline void detachShared()
- {
- // The "this->" qualification is needed for GCCE.
- if (d->ref.isShared() && this->d != &QListData::shared_null)
- detach_helper();
- }
-
- inline bool isDetached() const { return !d->ref.isShared(); }
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- inline void setSharable(bool sharable)
- {
- if (sharable == d->ref.isSharable())
- return;
- if (!sharable)
- detach();
- if (d != &QListData::shared_null)
- d->ref.setSharable(sharable);
- }
-#endif
- inline bool isSharedWith(const QList<T> &other) const noexcept { return d == other.d; }
-
- inline bool isEmpty() const noexcept { return p.isEmpty(); }
-
- void clear();
-
- const T &at(int i) const;
- const T &operator[](int i) const;
- T &operator[](int i);
-
- void reserve(int size);
- void append(const T &t);
- void append(const QList<T> &t);
- void prepend(const T &t);
- void insert(int i, const T &t);
- void replace(int i, const T &t);
- void removeAt(int i);
- int removeAll(const T &t);
- bool removeOne(const T &t);
- T takeAt(int i);
- T takeFirst();
- T takeLast();
- void move(int from, int to);
- void swapItemsAt(int i, int j);
-#if QT_DEPRECATED_SINCE(5, 13) && QT_VERSION < QT_VERSION_CHECK(6,0,0)
- QT_DEPRECATED_X("Use QList<T>::swapItemsAt()")
- void swap(int i, int j) { swapItemsAt(i, j); }
-#endif
- int indexOf(const T &t, int from = 0) const;
- int lastIndexOf(const T &t, int from = -1) const;
- bool contains(const T &t) const;
- int count(const T &t) const;
-
- class const_iterator;
-
- class iterator {
- public:
- Node *i;
- typedef std::random_access_iterator_tag iterator_category;
- // ### Qt6: use int
- typedef qptrdiff difference_type;
- typedef T value_type;
- typedef T *pointer;
- typedef T &reference;
-
- inline iterator() noexcept : i(nullptr) {}
- inline iterator(Node *n) noexcept : i(n) {}
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- // can't remove it in Qt 5, since doing so would make the type trivial,
- // which changes the way it's passed to functions by value.
- inline iterator(const iterator &o) noexcept : i(o.i){}
- inline iterator &operator=(const iterator &o) noexcept
- { i = o.i; return *this; }
-#endif
- inline T &operator*() const { return i->t(); }
- inline T *operator->() const { return &i->t(); }
- inline T &operator[](difference_type j) const { return i[j].t(); }
- inline bool operator==(const iterator &o) const noexcept { return i == o.i; }
- inline bool operator!=(const iterator &o) const noexcept { return i != o.i; }
- inline bool operator<(const iterator& other) const noexcept { return i < other.i; }
- inline bool operator<=(const iterator& other) const noexcept { return i <= other.i; }
- inline bool operator>(const iterator& other) const noexcept { return i > other.i; }
- inline bool operator>=(const iterator& other) const noexcept { return i >= other.i; }
-#ifndef QT_STRICT_ITERATORS
- inline bool operator==(const const_iterator &o) const noexcept
- { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const noexcept
- { return i != o.i; }
- inline bool operator<(const const_iterator& other) const noexcept
- { return i < other.i; }
- inline bool operator<=(const const_iterator& other) const noexcept
- { return i <= other.i; }
- inline bool operator>(const const_iterator& other) const noexcept
- { return i > other.i; }
- inline bool operator>=(const const_iterator& other) const noexcept
- { return i >= other.i; }
-#endif
- inline iterator &operator++() { ++i; return *this; }
- inline iterator operator++(int) { Node *n = i; ++i; return n; }
- inline iterator &operator--() { i--; return *this; }
- inline iterator operator--(int) { Node *n = i; i--; return n; }
- inline iterator &operator+=(difference_type j) { i+=j; return *this; }
- inline iterator &operator-=(difference_type j) { i-=j; return *this; }
- inline iterator operator+(difference_type j) const { return iterator(i+j); }
- inline iterator operator-(difference_type j) const { return iterator(i-j); }
- friend inline iterator operator+(difference_type j, iterator k) { return k + j; }
- inline int operator-(iterator j) const { return int(i - j.i); }
- };
- friend class iterator;
-
- class const_iterator {
- public:
- Node *i;
- typedef std::random_access_iterator_tag iterator_category;
- // ### Qt6: use int
- typedef qptrdiff difference_type;
- typedef T value_type;
- typedef const T *pointer;
- typedef const T &reference;
-
- inline const_iterator() noexcept : i(nullptr) {}
- inline const_iterator(Node *n) noexcept : i(n) {}
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- // can't remove it in Qt 5, since doing so would make the type trivial,
- // which changes the way it's passed to functions by value.
- inline const_iterator(const const_iterator &o) noexcept : i(o.i) {}
- inline const_iterator &operator=(const const_iterator &o) noexcept
- { i = o.i; return *this; }
-#endif
-#ifdef QT_STRICT_ITERATORS
- inline explicit const_iterator(const iterator &o) noexcept : i(o.i) {}
-#else
- inline const_iterator(const iterator &o) noexcept : i(o.i) {}
-#endif
- inline const T &operator*() const { return i->t(); }
- inline const T *operator->() const { return &i->t(); }
- inline const T &operator[](difference_type j) const { return i[j].t(); }
- inline bool operator==(const const_iterator &o) const noexcept { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const noexcept { return i != o.i; }
- inline bool operator<(const const_iterator& other) const noexcept { return i < other.i; }
- inline bool operator<=(const const_iterator& other) const noexcept { return i <= other.i; }
- inline bool operator>(const const_iterator& other) const noexcept { return i > other.i; }
- inline bool operator>=(const const_iterator& other) const noexcept { return i >= other.i; }
- inline const_iterator &operator++() { ++i; return *this; }
- inline const_iterator operator++(int) { Node *n = i; ++i; return n; }
- inline const_iterator &operator--() { i--; return *this; }
- inline const_iterator operator--(int) { Node *n = i; i--; return n; }
- inline const_iterator &operator+=(difference_type j) { i+=j; return *this; }
- inline const_iterator &operator-=(difference_type j) { i-=j; return *this; }
- inline const_iterator operator+(difference_type j) const { return const_iterator(i+j); }
- inline const_iterator operator-(difference_type j) const { return const_iterator(i-j); }
- friend inline const_iterator operator+(difference_type j, const_iterator k) { return k + j; }
- inline int operator-(const_iterator j) const { return int(i - j.i); }
- };
- friend class const_iterator;
-
- // stl style
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- inline iterator begin() { detach(); return reinterpret_cast<Node *>(p.begin()); }
- inline const_iterator begin() const noexcept { return reinterpret_cast<Node *>(p.begin()); }
- inline const_iterator cbegin() const noexcept { return reinterpret_cast<Node *>(p.begin()); }
- inline const_iterator constBegin() const noexcept { return reinterpret_cast<Node *>(p.begin()); }
- inline iterator end() { detach(); return reinterpret_cast<Node *>(p.end()); }
- inline const_iterator end() const noexcept { return reinterpret_cast<Node *>(p.end()); }
- inline const_iterator cend() const noexcept { return reinterpret_cast<Node *>(p.end()); }
- inline const_iterator constEnd() const noexcept { return reinterpret_cast<Node *>(p.end()); }
- reverse_iterator rbegin() { return reverse_iterator(end()); }
- reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
- const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
- const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
- const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
- iterator insert(iterator before, const T &t);
- iterator erase(iterator pos);
- iterator erase(iterator first, iterator last);
-
- // more Qt
- typedef iterator Iterator;
- typedef const_iterator ConstIterator;
- inline int count() const { return p.size(); }
- inline int length() const { return p.size(); } // Same as count()
- inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
- inline const T& constFirst() const { return first(); }
- inline const T& first() const { Q_ASSERT(!isEmpty()); return at(0); }
- T& last() { Q_ASSERT(!isEmpty()); return *(--end()); }
- const T& last() const { Q_ASSERT(!isEmpty()); return at(count() - 1); }
- inline const T& constLast() const { return last(); }
- inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); }
- inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); }
- inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
- inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
- QList<T> mid(int pos, int length = -1) const;
-
- T value(int i) const;
- T value(int i, const T &defaultValue) const;
-
- // stl compatibility
- inline void push_back(const T &t) { append(t); }
- inline void push_front(const T &t) { prepend(t); }
- inline T& front() { return first(); }
- inline const T& front() const { return first(); }
- inline T& back() { return last(); }
- inline const T& back() const { return last(); }
- inline void pop_front() { removeFirst(); }
- inline void pop_back() { removeLast(); }
- inline bool empty() const { return isEmpty(); }
- typedef int size_type;
- typedef T value_type;
- typedef value_type *pointer;
- typedef const value_type *const_pointer;
- typedef value_type &reference;
- typedef const value_type &const_reference;
- // ### Qt6: use int
- typedef qptrdiff difference_type;
-
- // comfort
- QList<T> &operator+=(const QList<T> &l);
- inline QList<T> operator+(const QList<T> &l) const
- { QList n = *this; n += l; return n; }
- inline QList<T> &operator+=(const T &t)
- { append(t); return *this; }
- inline QList<T> &operator<< (const T &t)
- { append(t); return *this; }
- inline QList<T> &operator<<(const QList<T> &l)
- { *this += l; return *this; }
-
- static QList<T> fromVector(const QVector<T> &vector);
- QVector<T> toVector() const;
-
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- Q_DECL_DEPRECATED_X("Use QList<T>(set.begin(), set.end()) instead.")
- static QList<T> fromSet(const QSet<T> &set);
- Q_DECL_DEPRECATED_X("Use QSet<T>(list.begin(), list.end()) instead.")
- QSet<T> toSet() const;
-
- Q_DECL_DEPRECATED_X("Use QList<T>(list.begin(), list.end()) instead.")
- static inline QList<T> fromStdList(const std::list<T> &list)
- { return QList<T>(list.begin(), list.end()); }
- Q_DECL_DEPRECATED_X("Use std::list<T>(list.begin(), list.end()) instead.")
- inline std::list<T> toStdList() const
- { return std::list<T>(begin(), end()); }
-#endif
-
-private:
- Node *detach_helper_grow(int i, int n);
- void detach_helper(int alloc);
- void detach_helper();
- void dealloc(QListData::Data *d);
-
- void node_construct(Node *n, const T &t);
- void node_destruct(Node *n);
- void node_copy(Node *from, Node *to, Node *src);
- void node_destruct(Node *from, Node *to);
-
- bool isValidIterator(const iterator &i) const noexcept
- {
- const std::less<const Node *> less = {};
- return !less(i.i, cbegin().i) && !less(cend().i, i.i);
- }
-
-private:
- inline bool op_eq_impl(const QList &other, QListData::NotArrayCompatibleLayout) const;
- inline bool op_eq_impl(const QList &other, QListData::ArrayCompatibleLayout) const;
- inline bool contains_impl(const T &, QListData::NotArrayCompatibleLayout) const;
- inline bool contains_impl(const T &, QListData::ArrayCompatibleLayout) const;
- inline int count_impl(const T &, QListData::NotArrayCompatibleLayout) const;
- inline int count_impl(const T &, QListData::ArrayCompatibleLayout) const;
-};
-
-#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
-template <typename InputIterator,
- typename ValueType = typename std::iterator_traits<InputIterator>::value_type,
- QtPrivate::IfIsInputIterator<InputIterator> = true>
-QList(InputIterator, InputIterator) -> QList<ValueType>;
-#endif
-
-#if defined(Q_CC_BOR)
-template <typename T>
-Q_INLINE_TEMPLATE T &QList<T>::Node::t()
-{ return QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic ? *(T*)v:*(T*)this; }
-#endif
-
-template <typename T>
-Q_INLINE_TEMPLATE void QList<T>::node_construct(Node *n, const T &t)
-{
- if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);
- else if (QTypeInfo<T>::isComplex) new (n) T(t);
-#if (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__IBMCPP__)) && !defined(__OPTIMIZE__)
- // This violates pointer aliasing rules, but it is known to be safe (and silent)
- // in unoptimized GCC builds (-fno-strict-aliasing). The other compilers which
- // set the same define are assumed to be safe.
- else *reinterpret_cast<T*>(n) = t;
-#else
- // This is always safe, but penaltizes unoptimized builds a lot.
- else ::memcpy(n, static_cast<const void *>(&t), sizeof(T));
-#endif
-}
-
-template <typename T>
-Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *n)
-{
- if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) delete reinterpret_cast<T*>(n->v);
- else if (QTypeInfo<T>::isComplex) reinterpret_cast<T*>(n)->~T();
-}
-
-template <typename T>
-Q_INLINE_TEMPLATE void QList<T>::node_copy(Node *from, Node *to, Node *src)
-{
- Node *current = from;
- if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- QT_TRY {
- while(current != to) {
- current->v = new T(*reinterpret_cast<T*>(src->v));
- ++current;
- ++src;
- }
- } QT_CATCH(...) {
- while (current-- != from)
- delete reinterpret_cast<T*>(current->v);
- QT_RETHROW;
- }
-
- } else if (QTypeInfo<T>::isComplex) {
- QT_TRY {
- while(current != to) {
- new (current) T(*reinterpret_cast<T*>(src));
- ++current;
- ++src;
- }
- } QT_CATCH(...) {
- while (current-- != from)
- (reinterpret_cast<T*>(current))->~T();
- QT_RETHROW;
- }
- } else {
- if (src != from && to - from > 0)
- memcpy(from, src, (to - from) * sizeof(Node));
- }
-}
-
-template <typename T>
-Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *from, Node *to)
-{
- if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic)
- while(from != to) --to, delete reinterpret_cast<T*>(to->v);
- else if (QTypeInfo<T>::isComplex)
- while (from != to) --to, reinterpret_cast<T*>(to)->~T();
-}
-
-template <typename T>
-Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l)
-{
- if (d != l.d) {
- QList<T> tmp(l);
- tmp.swap(*this);
- }
- return *this;
-}
-template <typename T>
-inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t)
-{
- Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
-
- int iBefore = int(before.i - reinterpret_cast<Node *>(p.begin()));
- Node *n = nullptr;
- if (d->ref.isShared())
- n = detach_helper_grow(iBefore, 1);
- else
- n = reinterpret_cast<Node *>(p.insert(iBefore));
- QT_TRY {
- node_construct(n, t);
- } QT_CATCH(...) {
- p.remove(iBefore);
- QT_RETHROW;
- }
- return n;
-}
-template <typename T>
-inline typename QList<T>::iterator QList<T>::erase(iterator it)
-{
- Q_ASSERT_X(isValidIterator(it), "QList::erase", "The specified iterator argument 'it' is invalid");
- if (d->ref.isShared()) {
- int offset = int(it.i - reinterpret_cast<Node *>(p.begin()));
- it = begin(); // implies detach()
- it += offset;
- }
- node_destruct(it.i);
- return reinterpret_cast<Node *>(p.erase(reinterpret_cast<void**>(it.i)));
-}
-template <typename T>
-inline const T &QList<T>::at(int i) const
-{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::at", "index out of range");
- return reinterpret_cast<Node *>(p.at(i))->t(); }
-template <typename T>
-inline const T &QList<T>::operator[](int i) const
-{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::operator[]", "index out of range");
- return reinterpret_cast<Node *>(p.at(i))->t(); }
-template <typename T>
-inline T &QList<T>::operator[](int i)
-{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::operator[]", "index out of range");
- detach(); return reinterpret_cast<Node *>(p.at(i))->t(); }
-template <typename T>
-inline void QList<T>::removeAt(int i)
-{
-#if !QT_DEPRECATED_SINCE(5, 15)
- Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::removeAt", "index out of range");
-#elif !defined(QT_NO_DEBUG)
- if (i < 0 || i >= p.size())
- qWarning("QList::removeAt(): Index out of range.");
-#endif
- detach();
- node_destruct(reinterpret_cast<Node *>(p.at(i))); p.remove(i);
-}
-template <typename T>
-inline T QList<T>::takeAt(int i)
-{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::take", "index out of range");
- detach(); Node *n = reinterpret_cast<Node *>(p.at(i)); T t = std::move(n->t()); node_destruct(n);
- p.remove(i); return t; }
-template <typename T>
-inline T QList<T>::takeFirst()
-{ T t = std::move(first()); removeFirst(); return t; }
-template <typename T>
-inline T QList<T>::takeLast()
-{ T t = std::move(last()); removeLast(); return t; }
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc)
-{
- if (d->alloc < alloc) {
- if (d->ref.isShared())
- detach_helper(alloc);
- else
- p.realloc(alloc);
- }
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
-{
- if (d->ref.isShared()) {
- Node *n = detach_helper_grow(INT_MAX, 1);
- QT_TRY {
- node_construct(n, t);
- } QT_CATCH(...) {
- --d->end;
- QT_RETHROW;
- }
- } else {
- if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- Node *n = reinterpret_cast<Node *>(p.append());
- QT_TRY {
- node_construct(n, t);
- } QT_CATCH(...) {
- --d->end;
- QT_RETHROW;
- }
- } else {
- Node *n, copy;
- node_construct(&copy, t); // t might be a reference to an object in the array
- QT_TRY {
- n = reinterpret_cast<Node *>(p.append());;
- } QT_CATCH(...) {
- node_destruct(&copy);
- QT_RETHROW;
- }
- *n = copy;
- }
- }
-}
-
-template <typename T>
-inline void QList<T>::prepend(const T &t)
-{
- if (d->ref.isShared()) {
- Node *n = detach_helper_grow(0, 1);
- QT_TRY {
- node_construct(n, t);
- } QT_CATCH(...) {
- ++d->begin;
- QT_RETHROW;
- }
- } else {
- if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- Node *n = reinterpret_cast<Node *>(p.prepend());
- QT_TRY {
- node_construct(n, t);
- } QT_CATCH(...) {
- ++d->begin;
- QT_RETHROW;
- }
- } else {
- Node *n, copy;
- node_construct(&copy, t); // t might be a reference to an object in the array
- QT_TRY {
- n = reinterpret_cast<Node *>(p.prepend());;
- } QT_CATCH(...) {
- node_destruct(&copy);
- QT_RETHROW;
- }
- *n = copy;
- }
- }
-}
-
-template <typename T>
-inline void QList<T>::insert(int i, const T &t)
-{
-#if !QT_DEPRECATED_SINCE(5, 15)
- Q_ASSERT_X(i >= 0 && i <= p.size(), "QList<T>::insert", "index out of range");
-#elif !defined(QT_NO_DEBUG)
- if (i < 0 || i > p.size())
- qWarning("QList::insert(): Index out of range.");
-#endif
- if (d->ref.isShared()) {
- Node *n = detach_helper_grow(i, 1);
- QT_TRY {
- node_construct(n, t);
- } QT_CATCH(...) {
- p.remove(i);
- QT_RETHROW;
- }
- } else {
- if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- Node *n = reinterpret_cast<Node *>(p.insert(i));
- QT_TRY {
- node_construct(n, t);
- } QT_CATCH(...) {
- p.remove(i);
- QT_RETHROW;
- }
- } else {
- Node *n, copy;
- node_construct(&copy, t); // t might be a reference to an object in the array
- QT_TRY {
- n = reinterpret_cast<Node *>(p.insert(i));;
- } QT_CATCH(...) {
- node_destruct(&copy);
- QT_RETHROW;
- }
- *n = copy;
- }
- }
-}
-
-template <typename T>
-inline void QList<T>::replace(int i, const T &t)
-{
- Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::replace", "index out of range");
- detach();
- reinterpret_cast<Node *>(p.at(i))->t() = t;
-}
-
-template <typename T>
-inline void QList<T>::swapItemsAt(int i, int j)
-{
- Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(),
- "QList<T>::swap", "index out of range");
- detach();
- qSwap(d->array[d->begin + i], d->array[d->begin + j]);
-}
-
-template <typename T>
-inline void QList<T>::move(int from, int to)
-{
- Q_ASSERT_X(from >= 0 && from < p.size() && to >= 0 && to < p.size(),
- "QList<T>::move", "index out of range");
- detach();
- p.move(from, to);
-}
-
-template<typename T>
-Q_OUTOFLINE_TEMPLATE QList<T> QList<T>::mid(int pos, int alength) const
-{
- using namespace QtPrivate;
- switch (QContainerImplHelper::mid(size(), &pos, &alength)) {
- case QContainerImplHelper::Null:
- case QContainerImplHelper::Empty:
- return QList<T>();
- case QContainerImplHelper::Full:
- return *this;
- case QContainerImplHelper::Subset:
- break;
- }
-
- QList<T> cpy;
- if (alength <= 0)
- return cpy;
- cpy.reserve(alength);
- cpy.d->end = alength;
- QT_TRY {
- cpy.node_copy(reinterpret_cast<Node *>(cpy.p.begin()),
- reinterpret_cast<Node *>(cpy.p.end()),
- reinterpret_cast<Node *>(p.begin() + pos));
- } QT_CATCH(...) {
- // restore the old end
- cpy.d->end = 0;
- QT_RETHROW;
- }
- return cpy;
-}
-
template<typename T>
-Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i) const
-{
- if (i < 0 || i >= p.size()) {
- return T();
- }
- return reinterpret_cast<Node *>(p.at(i))->t();
-}
-
+using QMutableListIterator = QMutableVectorIterator<T>;
template<typename T>
-Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i, const T& defaultValue) const
-{
- return ((i < 0 || i >= p.size()) ? defaultValue : reinterpret_cast<Node *>(p.at(i))->t());
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE typename QList<T>::Node *QList<T>::detach_helper_grow(int i, int c)
-{
- Node *n = reinterpret_cast<Node *>(p.begin());
- QListData::Data *x = p.detach_grow(&i, c);
- QT_TRY {
- node_copy(reinterpret_cast<Node *>(p.begin()),
- reinterpret_cast<Node *>(p.begin() + i), n);
- } QT_CATCH(...) {
- p.dispose();
- d = x;
- QT_RETHROW;
- }
- QT_TRY {
- node_copy(reinterpret_cast<Node *>(p.begin() + i + c),
- reinterpret_cast<Node *>(p.end()), n + i);
- } QT_CATCH(...) {
- node_destruct(reinterpret_cast<Node *>(p.begin()),
- reinterpret_cast<Node *>(p.begin() + i));
- p.dispose();
- d = x;
- QT_RETHROW;
- }
-
- if (!x->ref.deref())
- dealloc(x);
-
- return reinterpret_cast<Node *>(p.begin() + i);
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper(int alloc)
-{
- Node *n = reinterpret_cast<Node *>(p.begin());
- QListData::Data *x = p.detach(alloc);
- QT_TRY {
- node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n);
- } QT_CATCH(...) {
- p.dispose();
- d = x;
- QT_RETHROW;
- }
-
- if (!x->ref.deref())
- dealloc(x);
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper()
-{
- detach_helper(d->alloc);
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE QList<T>::QList(const QList<T> &l)
- : QListSpecialMethods<T>(l), d(l.d)
-{
- if (!d->ref.ref()) {
- p.detach(d->alloc);
-
- QT_TRY {
- node_copy(reinterpret_cast<Node *>(p.begin()),
- reinterpret_cast<Node *>(p.end()),
- reinterpret_cast<Node *>(l.p.begin()));
- } QT_CATCH(...) {
- QListData::dispose(d);
- QT_RETHROW;
- }
- }
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE QList<T>::~QList()
-{
- if (!d->ref.deref())
- dealloc(d);
-}
-
-template <typename T>
-template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator>>
-QList<T>::QList(InputIterator first, InputIterator last)
- : QList()
-{
- QtPrivate::reserveIfForwardIterator(this, first, last);
- std::copy(first, last, std::back_inserter(*this));
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE bool QList<T>::operator==(const QList<T> &l) const
-{
- if (d == l.d)
- return true;
- if (p.size() != l.p.size())
- return false;
- return this->op_eq_impl(l, MemoryLayout());
-}
-
-template <typename T>
-inline bool QList<T>::op_eq_impl(const QList &l, QListData::NotArrayCompatibleLayout) const
-{
- Node *i = reinterpret_cast<Node *>(p.begin());
- Node *e = reinterpret_cast<Node *>(p.end());
- Node *li = reinterpret_cast<Node *>(l.p.begin());
- for (; i != e; ++i, ++li) {
- if (!(i->t() == li->t()))
- return false;
- }
- return true;
-}
-
-template <typename T>
-inline bool QList<T>::op_eq_impl(const QList &l, QListData::ArrayCompatibleLayout) const
-{
- const T *lb = reinterpret_cast<const T*>(l.p.begin());
- const T *b = reinterpret_cast<const T*>(p.begin());
- const T *e = reinterpret_cast<const T*>(p.end());
- return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(lb, l.p.size()));
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QList<T>::dealloc(QListData::Data *data)
-{
- node_destruct(reinterpret_cast<Node *>(data->array + data->begin),
- reinterpret_cast<Node *>(data->array + data->end));
- QListData::dispose(data);
-}
-
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QList<T>::clear()
-{
- *this = QList<T>();
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t)
-{
- int index = indexOf(_t);
- if (index == -1)
- return 0;
-
- const T t = _t;
- detach();
-
- Node *i = reinterpret_cast<Node *>(p.at(index));
- Node *e = reinterpret_cast<Node *>(p.end());
- Node *n = i;
- node_destruct(i);
- while (++i != e) {
- if (i->t() == t)
- node_destruct(i);
- else
- *n++ = *i;
- }
-
- int removedCount = int(e - n);
- d->end -= removedCount;
- return removedCount;
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE bool QList<T>::removeOne(const T &_t)
-{
- int index = indexOf(_t);
- if (index != -1) {
- removeAt(index);
- return true;
- }
- return false;
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE typename QList<T>::iterator QList<T>::erase(typename QList<T>::iterator afirst,
- typename QList<T>::iterator alast)
-{
- Q_ASSERT_X(isValidIterator(afirst), "QList::erase", "The specified iterator argument 'afirst' is invalid");
- Q_ASSERT_X(isValidIterator(alast), "QList::erase", "The specified iterator argument 'alast' is invalid");
-
- if (d->ref.isShared()) {
- // ### A block is erased and a detach is needed. We should shrink and only copy relevant items.
- int offsetfirst = int(afirst.i - reinterpret_cast<Node *>(p.begin()));
- int offsetlast = int(alast.i - reinterpret_cast<Node *>(p.begin()));
- afirst = begin(); // implies detach()
- alast = afirst;
- afirst += offsetfirst;
- alast += offsetlast;
- }
-
- for (Node *n = afirst.i; n < alast.i; ++n)
- node_destruct(n);
- int idx = afirst - begin();
- p.remove(idx, alast - afirst);
- return begin() + idx;
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l)
-{
- if (!l.isEmpty()) {
- if (d == &QListData::shared_null) {
- *this = l;
- } else {
- Node *n = (d->ref.isShared())
- ? detach_helper_grow(INT_MAX, l.size())
- : reinterpret_cast<Node *>(p.append(l.p));
- QT_TRY {
- node_copy(n, reinterpret_cast<Node *>(p.end()),
- reinterpret_cast<Node *>(l.p.begin()));
- } QT_CATCH(...) {
- // restore the old end
- d->end -= int(reinterpret_cast<Node *>(p.end()) - n);
- QT_RETHROW;
- }
- }
- }
- return *this;
-}
-
-template <typename T>
-inline void QList<T>::append(const QList<T> &t)
-{
- *this += t;
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE int QList<T>::indexOf(const T &t, int from) const
-{
- return QtPrivate::indexOf<T, T>(*this, t, from);
-}
-
-namespace QtPrivate
-{
-template <typename T, typename U>
-int indexOf(const QList<T> &list, const U &u, int from)
-{
- typedef typename QList<T>::Node Node;
-
- if (from < 0)
- from = qMax(from + list.p.size(), 0);
- if (from < list.p.size()) {
- Node *n = reinterpret_cast<Node *>(list.p.at(from -1));
- Node *e = reinterpret_cast<Node *>(list.p.end());
- while (++n != e)
- if (n->t() == u)
- return int(n - reinterpret_cast<Node *>(list.p.begin()));
- }
- return -1;
-}
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE int QList<T>::lastIndexOf(const T &t, int from) const
-{
- return QtPrivate::lastIndexOf<T, T>(*this, t, from);
-}
-
-namespace QtPrivate
-{
-template <typename T, typename U>
-int lastIndexOf(const QList<T> &list, const U &u, int from)
-{
- typedef typename QList<T>::Node Node;
-
- if (from < 0)
- from += list.p.size();
- else if (from >= list.p.size())
- from = list.p.size()-1;
- if (from >= 0) {
- Node *b = reinterpret_cast<Node *>(list.p.begin());
- Node *n = reinterpret_cast<Node *>(list.p.at(from + 1));
- while (n-- != b) {
- if (n->t() == u)
- return int(n - b);
- }
- }
- return -1;
-}
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE bool QList<T>::contains(const T &t) const
-{
- return contains_impl(t, MemoryLayout());
-}
-
-template <typename T>
-inline bool QList<T>::contains_impl(const T &t, QListData::NotArrayCompatibleLayout) const
-{
- Node *e = reinterpret_cast<Node *>(p.end());
- Node *i = reinterpret_cast<Node *>(p.begin());
- for (; i != e; ++i)
- if (i->t() == t)
- return true;
- return false;
-}
-
-template <typename T>
-inline bool QList<T>::contains_impl(const T &t, QListData::ArrayCompatibleLayout) const
-{
- const T *b = reinterpret_cast<const T*>(p.begin());
- const T *e = reinterpret_cast<const T*>(p.end());
- return std::find(b, e, t) != e;
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE int QList<T>::count(const T &t) const
-{
- return this->count_impl(t, MemoryLayout());
-}
-
-template <typename T>
-inline int QList<T>::count_impl(const T &t, QListData::NotArrayCompatibleLayout) const
-{
- int c = 0;
- Node *e = reinterpret_cast<Node *>(p.end());
- Node *i = reinterpret_cast<Node *>(p.begin());
- for (; i != e; ++i)
- if (i->t() == t)
- ++c;
- return c;
-}
-
-template <typename T>
-inline int QList<T>::count_impl(const T &t, QListData::ArrayCompatibleLayout) const
-{
- return int(std::count(reinterpret_cast<const T*>(p.begin()),
- reinterpret_cast<const T*>(p.end()),
- t));
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE QVector<T> QList<T>::toVector() const
-{
- return QVector<T>(begin(), end());
-}
-
-template <typename T>
-QList<T> QList<T>::fromVector(const QVector<T> &vector)
-{
- return vector.toList();
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE QList<T> QVector<T>::toList() const
-{
- return QList<T>(begin(), end());
-}
-
-template <typename T>
-QVector<T> QVector<T>::fromList(const QList<T> &list)
-{
- return list.toVector();
-}
-
-Q_DECLARE_SEQUENTIAL_ITERATOR(List)
-Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List)
-
-template <typename T>
-uint qHash(const QList<T> &key, uint seed = 0)
- noexcept(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
-{
- return qHashRange(key.cbegin(), key.cend(), seed);
-}
-
-template <typename T>
-bool operator<(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end())))
-{
- return std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end());
-}
-
-template <typename T>
-inline bool operator>(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(lhs < rhs))
-{
- return rhs < lhs;
-}
-
-template <typename T>
-inline bool operator<=(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(lhs < rhs))
-{
- return !(lhs > rhs);
-}
-
-template <typename T>
-inline bool operator>=(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(lhs < rhs))
-{
- return !(lhs < rhs);
-}
-
+using QListIterator = QVectorIterator<T>;
QT_END_NAMESPACE
+#endif
#include <QtCore/qbytearraylist.h>
#include <QtCore/qstringlist.h>
-#ifdef Q_CC_MSVC
-#pragma warning( pop )
-#endif
-
#endif // QLIST_H
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 281812b5e6..a70b355c67 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -219,7 +219,7 @@ struct QMapData : public QMapDataBase
Node *createNode(const Key &k, const T &v, Node *parent = nullptr, bool left = false)
{
- Node *n = static_cast<Node *>(QMapDataBase::createNode(sizeof(Node), Q_ALIGNOF(Node),
+ Node *n = static_cast<Node *>(QMapDataBase::createNode(sizeof(Node), alignof(Node),
parent, left));
QT_TRY {
new (&n->key) Key(k);
@@ -243,7 +243,7 @@ struct QMapData : public QMapDataBase
void destroy() {
if (root()) {
root()->destroySubTree();
- freeTree(header.left, Q_ALIGNOF(Node));
+ freeTree(header.left, alignof(Node));
}
freeData(this);
}
@@ -356,17 +356,6 @@ public:
inline void detach() { if (d->ref.isShared()) detach_helper(); }
inline bool isDetached() const { return !d->ref.isShared(); }
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- inline void setSharable(bool sharable)
- {
- if (sharable == d->ref.isSharable())
- return;
- if (!sharable)
- detach();
- // Don't call on shared_null
- d->ref.setSharable(sharable);
- }
-#endif
inline bool isSharedWith(const QMap<Key, T> &other) const { return d == other.d; }
void clear();
@@ -447,13 +436,8 @@ public:
inline iterator &operator-=(int j) { return *this = *this - j; }
friend inline iterator operator+(int j, iterator k) { return k + j; }
-#ifndef QT_STRICT_ITERATORS
- public:
- inline bool operator==(const const_iterator &o) const
- { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const
- { return i != o.i; }
-#endif
+ inline bool operator==(const const_iterator &o) const { return i == o.i; }
+ inline bool operator!=(const const_iterator &o) const { return i != o.i; }
friend class QMap<Key, T>;
friend class QMultiMap<Key, T>;
};
@@ -473,12 +457,7 @@ public:
Q_DECL_CONSTEXPR inline const_iterator() : i(nullptr) { }
inline const_iterator(const Node *node) : i(node) { }
-#ifdef QT_STRICT_ITERATORS
- explicit inline const_iterator(const iterator &o)
-#else
- inline const_iterator(const iterator &o)
-#endif
- { i = o.i; }
+ inline const_iterator(const iterator &o) { i = o.i; }
inline const Key &key() const { return i->key; }
inline const T &value() const { return i->value; }
@@ -512,11 +491,6 @@ public:
inline const_iterator &operator-=(int j) { return *this = *this - j; }
friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
-#ifdef QT_STRICT_ITERATORS
- private:
- inline bool operator==(const iterator &o) const { return operator==(const_iterator(o)); }
- inline bool operator!=(const iterator &o) const { return operator!=(const_iterator(o)); }
-#endif
friend class QMap<Key, T>;
friend class QMultiMap<Key, T>;
};
diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h
index 2e5388ad9a..982a9c2bbf 100644
--- a/src/corelib/tools/qrefcount.h
+++ b/src/corelib/tools/qrefcount.h
@@ -53,10 +53,6 @@ class RefCount
public:
inline bool ref() noexcept {
int count = atomic.loadRelaxed();
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- if (count == 0) // !isSharable
- return false;
-#endif
if (count != -1) // !isStatic
atomic.ref();
return true;
@@ -64,32 +60,11 @@ public:
inline bool deref() noexcept {
int count = atomic.loadRelaxed();
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- if (count == 0) // !isSharable
- return false;
-#endif
if (count == -1) // isStatic
return true;
return atomic.deref();
}
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- bool setSharable(bool sharable) noexcept
- {
- Q_ASSERT(!isShared());
- if (sharable)
- return atomic.testAndSetRelaxed(0, 1);
- else
- return atomic.testAndSetRelaxed(1, 0);
- }
-
- bool isSharable() const noexcept
- {
- // Sharable === Shared ownership.
- return atomic.loadRelaxed() != 0;
- }
-#endif
-
bool isStatic() const noexcept
{
// Persistent object, never deleted
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 879e2176f2..f98bb051ec 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -86,9 +86,6 @@ public:
inline void detach() { q_hash.detach(); }
inline bool isDetached() const { return q_hash.isDetached(); }
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- inline void setSharable(bool sharable) { q_hash.setSharable(sharable); }
-#endif
inline void clear() { q_hash.clear(); }
@@ -260,12 +257,6 @@ public:
{ QSet<T> result = *this; result -= other; return result; }
QList<T> values() const;
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- Q_DECL_DEPRECATED_X("Use values() instead.")
- QList<T> toList() const { return values(); }
- Q_DECL_DEPRECATED_X("Use QSet<T>(list.begin(), list.end()) instead.")
- static QSet<T> fromList(const QList<T> &list);
-#endif
private:
Hash q_hash;
@@ -397,30 +388,6 @@ Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::values() const
return result;
}
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
-template <typename T>
-Q_OUTOFLINE_TEMPLATE QSet<T> QList<T>::toSet() const
-{
- QSet<T> result;
- result.reserve(size());
- for (int i = 0; i < size(); ++i)
- result.insert(at(i));
- return result;
-}
-
-template <typename T>
-QSet<T> QSet<T>::fromList(const QList<T> &list)
-{
- return list.toSet();
-}
-
-template <typename T>
-QList<T> QList<T>::fromSet(const QSet<T> &set)
-{
- return set.toList();
-}
-#endif
-
Q_DECLARE_SEQUENTIAL_ITERATOR(Set)
#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 62fbdb4a2a..3e98de41f4 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Intel Corporation
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -40,127 +41,266 @@
#ifndef QVECTOR_H
#define QVECTOR_H
-#include <QtCore/qalgorithms.h>
-#include <QtCore/qiterator.h>
-#include <QtCore/qrefcount.h>
-#include <QtCore/qarraydata.h>
+#include <QtCore/qarraydatapointer.h>
+#include <QtCore/qnamespace.h>
#include <QtCore/qhashfunctions.h>
-#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/qiterator.h>
-#include <iterator>
+#include <functional>
+#include <limits>
#include <initializer_list>
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
-#include <vector>
-#endif
-#include <stdlib.h>
-#include <string.h>
-
-#include <algorithm>
+#include <type_traits>
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+ template <typename V, typename U> int indexOf(const QVector<V> &list, const U &u, int from);
+ template <typename V, typename U> int lastIndexOf(const QVector<V> &list, const U &u, int from);
+}
+
+template <typename T> struct QVectorSpecialMethods
+{
+protected:
+ ~QVectorSpecialMethods() = default;
+};
+template <> struct QVectorSpecialMethods<QByteArray>;
+template <> struct QVectorSpecialMethods<QString>;
+
template <typename T>
class QVector
+#ifndef Q_QDOC
+ : public QVectorSpecialMethods<T>
+#endif
{
typedef QTypedArrayData<T> Data;
- Data *d;
+ typedef QArrayDataOps<T> DataOps;
+ typedef QArrayDataPointer<T> DataPointer;
+ class DisableRValueRefs {};
+
+ DataPointer d;
+
+ template <typename V, typename U> friend int QtPrivate::indexOf(const QVector<V> &list, const U &u, int from);
+ template <typename V, typename U> friend int QtPrivate::lastIndexOf(const QVector<V> &list, const U &u, int from);
public:
- inline QVector() noexcept : d(Data::sharedNull()) { }
- explicit QVector(int size);
- QVector(int size, const T &t);
- inline QVector(const QVector<T> &v);
- inline ~QVector() { if (!d->ref.deref()) freeData(d); }
- QVector<T> &operator=(const QVector<T> &v);
- QVector(QVector<T> &&other) noexcept : d(other.d) { other.d = Data::sharedNull(); }
- QVector<T> &operator=(QVector<T> &&other) noexcept
- { QVector moved(std::move(other)); swap(moved); return *this; }
- void swap(QVector<T> &other) noexcept { qSwap(d, other.d); }
- inline QVector(std::initializer_list<T> args);
- QVector<T> &operator=(std::initializer_list<T> args);
- template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
- inline QVector(InputIterator first, InputIterator last);
- explicit QVector(QArrayDataPointerRef<T> ref) noexcept : d(ref.ptr) {}
+ typedef T Type;
+ typedef T value_type;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef int size_type;
+ typedef qptrdiff difference_type;
+ typedef typename Data::iterator iterator;
+ typedef typename Data::const_iterator const_iterator;
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef typename DataPointer::parameter_type parameter_type;
+ using rvalue_ref = typename std::conditional<DataPointer::pass_parameter_by_value, DisableRValueRefs, T &&>::type;
- bool operator==(const QVector<T> &v) const;
- inline bool operator!=(const QVector<T> &v) const { return !(*this == v); }
+private:
+ void resize_internal(int i, Qt::Initialization);
+ bool isValidIterator(const_iterator i) const
+ {
+ const std::less<const T*> less = {};
+ return !less(d->end(), i) && !less(i, d->begin());
+ }
+public:
+ QVector(DataPointer dd) noexcept
+ : d(dd)
+ {
+ }
- inline int size() const { return d->size; }
+public:
+ inline QVector() noexcept { }
+ explicit QVector(int size)
+ : d(Data::allocate(size))
+ {
+ if (size)
+ d->appendInitialize(size);
+ }
+ QVector(int size, const T &t)
+ : d(Data::allocate(size))
+ {
+ if (size)
+ d->copyAppend(size, t);
+ }
- inline bool isEmpty() const { return d->size == 0; }
+ inline QVector(const QVector<T> &other) noexcept : d(other.d) {}
+ QVector(QVector<T> &&other) noexcept : d(std::move(other.d)) {}
+ inline QVector(std::initializer_list<T> args)
+ : d(Data::allocate(args.size()))
+ {
+ if (args.size())
+ d->copyAppend(args.begin(), args.end());
+ }
- void resize(int size);
+ ~QVector() /*noexcept(std::is_nothrow_destructible<T>::value)*/ {}
+ QVector<T> &operator=(const QVector<T> &other) { d = other.d; return *this; }
+ QVector &operator=(QVector &&other) noexcept(std::is_nothrow_destructible<T>::value)
+ {
+ d = std::move(other.d);
+ return *this;
+ }
+ QVector<T> &operator=(std::initializer_list<T> args)
+ {
+ d = DataPointer(Data::allocate(args.size()));
+ if (args.size())
+ d->copyAppend(args.begin(), args.end());
+ return *this;
+ }
+ template <typename InputIterator, QtPrivate::IfIsForwardIterator<InputIterator> = true>
+ QVector(InputIterator i1, InputIterator i2)
+ : d(Data::allocate(std::distance(i1, i2)))
+ {
+ if (std::distance(i1, i2))
+ d->copyAppend(i1, i2);
+ }
- inline int capacity() const { return int(d->alloc); }
- void reserve(int size);
- inline void squeeze()
+ template <typename InputIterator, QtPrivate::IfIsNotForwardIterator<InputIterator> = true>
+ QVector(InputIterator i1, InputIterator i2)
+ : QVector()
{
- if (d->size < int(d->alloc)) {
- if (!d->size) {
- *this = QVector<T>();
- return;
- }
- realloc(d->size);
- }
- if (d->capacityReserved) {
- // capacity reserved in a read only memory would be useless
- // this checks avoid writing to such memory.
- d->capacityReserved = 0;
- }
+ QtPrivate::reserveIfForwardIterator(this, i1, i2);
+ std::copy(i1, i2, std::back_inserter(*this));
}
- inline void detach();
- inline bool isDetached() const { return !d->ref.isShared(); }
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- inline void setSharable(bool sharable)
+ void swap(QVector<T> &other) noexcept { qSwap(d, other.d); }
+
+ friend bool operator==(const QVector &l, const QVector &r)
{
- if (sharable == d->ref.isSharable())
- return;
- if (!sharable)
- detach();
+ if (l.size() != r.size())
+ return false;
+ if (l.begin() == r.begin())
+ return true;
- if (d == Data::unsharableEmpty()) {
- if (sharable)
- d = Data::sharedNull();
+ // do element-by-element comparison
+ return l.d->compare(l.begin(), r.begin(), l.size());
+ }
+ friend bool operator!=(const QVector &l, const QVector &r)
+ {
+ return !(l == r);
+ }
+
+ int size() const noexcept { return int(d->size); }
+ int count() const noexcept { return size(); }
+ int length() const noexcept { return size(); }
+
+ inline bool isEmpty() const noexcept { return d->size == 0; }
+
+ void resize(int size)
+ {
+ resize_internal(size, Qt::Uninitialized);
+ if (size > this->size())
+ d->appendInitialize(size);
+ }
+ void resize(int size, parameter_type c)
+ {
+ resize_internal(size, Qt::Uninitialized);
+ if (size > this->size())
+ d->copyAppend(size - this->size(), c);
+ }
+
+ inline int capacity() const { return int(d->constAllocatedCapacity()); }
+ void reserve(int size);
+ inline void squeeze();
+
+ void detach() { d.detach(); }
+ bool isDetached() const noexcept { return !d->isShared(); }
+
+ inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
+
+ pointer data() { detach(); return d->data(); }
+ const_pointer data() const noexcept { return d->data(); }
+ const_pointer constData() const noexcept { return d->data(); }
+ void clear() {
+ if (!size())
+ return;
+ if (d->needsDetach()) {
+ // must allocate memory
+ DataPointer detached(Data::allocate(d.allocatedCapacity(), d->detachFlags()));
+ d.swap(detached);
} else {
- d->ref.setSharable(sharable);
+ d->truncate(0);
}
- Q_ASSERT(d->ref.isSharable() == sharable);
}
+
+ const_reference at(int i) const noexcept
+ {
+ Q_ASSERT_X(size_t(i) < size_t(d->size), "QVector::at", "index out of range");
+ return data()[i];
+ }
+ reference operator[](int i)
+ {
+ Q_ASSERT_X(size_t(i) < size_t(d->size), "QVector::operator[]", "index out of range");
+ detach();
+ return data()[i];
+ }
+ const_reference operator[](int i) const noexcept { return at(i); }
+ void append(const_reference t)
+ { append(const_iterator(std::addressof(t)), const_iterator(std::addressof(t)) + 1); }
+ void append(const_iterator i1, const_iterator i2);
+ void append(value_type &&t);
+ void append(const QVector<T> &l) { append(l.constBegin(), l.constEnd()); }
+ void prepend(rvalue_ref t);
+ void prepend(const T &t);
+ iterator insert(int i, parameter_type t)
+ { return insert(i, 1, t); }
+ iterator insert(int i, int n, parameter_type t);
+ iterator insert(const_iterator before, parameter_type t)
+ {
+ Q_ASSERT_X(isValidIterator(before), "QVector::insert", "The specified iterator argument 'before' is invalid");
+ return insert(before, 1, t);
+ }
+ iterator insert(const_iterator before, int n, parameter_type t)
+ {
+ Q_ASSERT_X(isValidIterator(before), "QVector::insert", "The specified iterator argument 'before' is invalid");
+ return insert(std::distance(constBegin(), before), n, t);
+ }
+ iterator insert(const_iterator before, rvalue_ref t)
+ {
+ Q_ASSERT_X(isValidIterator(before), "QVector::insert", "The specified iterator argument 'before' is invalid");
+ return insert(std::distance(constBegin(), before), std::move(t));
+ }
+ iterator insert(int i, rvalue_ref t);
+#if 0
+ template< class InputIt >
+ iterator insert( const_iterator pos, InputIt first, InputIt last );
+ iterator insert( const_iterator pos, std::initializer_list<T> ilist );
#endif
+ void replace(int i, const T &t)
+ {
+ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range");
+ const T copy(t);
+ data()[i] = copy;
+ }
+ void replace(int i, rvalue_ref t)
+ {
+ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range");
+ const T copy(std::move(t));
+ data()[i] = std::move(copy);
+ }
- inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
+ void remove(int i, int n = 1);
+ void removeFirst() { Q_ASSERT(!isEmpty()); remove(0); }
+ void removeLast() { Q_ASSERT(!isEmpty()); remove(size() - 1); }
+ value_type takeFirst() { Q_ASSERT(!isEmpty()); value_type v = std::move(first()); remove(0); return v; }
+ value_type takeLast() { Q_ASSERT(!isEmpty()); value_type v = std::move(last()); remove(size() - 1); return v; }
- inline T *data() { detach(); return d->begin(); }
- inline const T *data() const { return d->begin(); }
- inline const T *constData() const { return d->begin(); }
- void clear();
-
- const T &at(int i) const;
- T &operator[](int i);
- const T &operator[](int i) const;
- void append(const T &t);
- void append(T &&t);
- inline void append(const QVector<T> &l) { *this += l; }
- void prepend(T &&t);
- void prepend(const T &t);
- void insert(int i, T &&t);
- void insert(int i, const T &t);
- void insert(int i, int n, const T &t);
- void replace(int i, const T &t);
- void remove(int i);
- void remove(int i, int n);
- inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(d->begin()); }
- inline void removeLast();
- T takeFirst() { Q_ASSERT(!isEmpty()); T r = std::move(first()); removeFirst(); return r; }
- T takeLast() { Q_ASSERT(!isEmpty()); T r = std::move(last()); removeLast(); return r; }
-
- QVector<T> &fill(const T &t, int size = -1);
-
- int indexOf(const T &t, int from = 0) const;
- int lastIndexOf(const T &t, int from = -1) const;
- bool contains(const T &t) const;
- int count(const T &t) const;
+ QVector<T> &fill(parameter_type t, int size = -1);
+
+ int indexOf(const T &t, int from = 0) const noexcept;
+ int lastIndexOf(const T &t, int from = -1) const noexcept;
+ bool contains(const T &t) const noexcept
+ {
+ return indexOf(t) != -1;
+ }
+ int count(const T &t) const noexcept
+ {
+ return int(std::count(&*cbegin(), &*cend(), t));
+ }
// QList compatibility
void removeAt(int i) { remove(i); }
@@ -169,10 +309,10 @@ public:
const const_iterator ce = this->cend(), cit = std::find(this->cbegin(), ce, t);
if (cit == ce)
return 0;
+ int index = cit - this->cbegin();
// next operation detaches, so ce, cit, t may become invalidated:
const T tCopy = t;
- const int firstFoundIdx = std::distance(this->cbegin(), cit);
- const iterator e = end(), it = std::remove(begin() + firstFoundIdx, e, tCopy);
+ const iterator e = end(), it = std::remove(begin() + index, e, tCopy);
const int result = std::distance(it, e);
erase(it, e);
return result;
@@ -185,7 +325,6 @@ public:
remove(i);
return true;
}
- int length() const { return size(); }
T takeAt(int i) { T t = std::move((*this)[i]); remove(i); return t; }
void move(int from, int to)
{
@@ -202,43 +341,26 @@ public:
}
// STL-style
- typedef typename Data::iterator iterator;
- typedef typename Data::const_iterator const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-#if !defined(QT_STRICT_ITERATORS) || defined(Q_CLANG_QDOC)
- inline iterator begin() { detach(); return d->begin(); }
- inline const_iterator begin() const noexcept { return d->constBegin(); }
- inline const_iterator cbegin() const noexcept { return d->constBegin(); }
- inline const_iterator constBegin() const noexcept { return d->constBegin(); }
- inline iterator end() { detach(); return d->end(); }
- inline const_iterator end() const noexcept { return d->constEnd(); }
- inline const_iterator cend() const noexcept { return d->constEnd(); }
- inline const_iterator constEnd() const noexcept { return d->constEnd(); }
-#else
- inline iterator begin(iterator = iterator()) { detach(); return d->begin(); }
- inline const_iterator begin(const_iterator = const_iterator()) const noexcept { return d->constBegin(); }
- inline const_iterator cbegin(const_iterator = const_iterator()) const noexcept { return d->constBegin(); }
- inline const_iterator constBegin(const_iterator = const_iterator()) const noexcept { return d->constBegin(); }
- inline iterator end(iterator = iterator()) { detach(); return d->end(); }
- inline const_iterator end(const_iterator = const_iterator()) const noexcept { return d->constEnd(); }
- inline const_iterator cend(const_iterator = const_iterator()) const noexcept { return d->constEnd(); }
- inline const_iterator constEnd(const_iterator = const_iterator()) const noexcept { return d->constEnd(); }
-#endif
+ iterator begin() { detach(); return d->begin(); }
+ iterator end() { detach(); return d->end(); }
+
+ const_iterator begin() const noexcept { return d->constBegin(); }
+ const_iterator end() const noexcept { return d->constEnd(); }
+ const_iterator cbegin() const noexcept { return d->constBegin(); }
+ const_iterator cend() const noexcept { return d->constEnd(); }
+ const_iterator constBegin() const noexcept { return d->constBegin(); }
+ const_iterator constEnd() const noexcept { return d->constEnd(); }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
- iterator insert(iterator before, int n, const T &x);
- inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
- inline iterator insert(iterator before, T &&x);
+
iterator erase(iterator begin, iterator end);
inline iterator erase(iterator pos) { return erase(pos, pos+1); }
// more Qt
- inline int count() const { return d->size; }
inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
inline const T &constFirst() const { Q_ASSERT(!isEmpty()); return *begin(); }
@@ -249,7 +371,7 @@ public:
inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
QVector<T> mid(int pos, int len = -1) const;
- T value(int i) const;
+ T value(int i) const { return value(i, T()); }
T value(int i, const T &defaultValue) const;
void swapItemsAt(int i, int j) {
@@ -260,31 +382,22 @@ public:
}
// STL compatibility
- typedef T value_type;
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef qptrdiff difference_type;
- typedef iterator Iterator;
- typedef const_iterator ConstIterator;
- typedef int size_type;
inline void push_back(const T &t) { append(t); }
- void push_back(T &&t) { append(std::move(t)); }
- void push_front(T &&t) { prepend(std::move(t)); }
+ void push_back(rvalue_ref t) { append(std::move(t)); }
+ void push_front(rvalue_ref t) { prepend(std::move(t)); }
inline void push_front(const T &t) { prepend(t); }
void pop_back() { removeLast(); }
void pop_front() { removeFirst(); }
inline bool empty() const
{ return d->size == 0; }
- inline T& front() { return first(); }
+ inline reference front() { return first(); }
inline const_reference front() const { return first(); }
inline reference back() { return last(); }
inline const_reference back() const { return last(); }
void shrink_to_fit() { squeeze(); }
// comfort
- QVector<T> &operator+=(const QVector<T> &l);
+ QVector<T> &operator+=(const QVector<T> &l) { append(l.cbegin(), l.cend()); return *this; }
inline QVector<T> operator+(const QVector<T> &l) const
{ QVector n = *this; n += l; return n; }
inline QVector<T> &operator+=(const T &t)
@@ -293,37 +406,17 @@ public:
{ append(t); return *this; }
inline QVector<T> &operator<<(const QVector<T> &l)
{ *this += l; return *this; }
- inline QVector<T> &operator+=(T &&t)
+ inline QVector<T> &operator+=(rvalue_ref t)
{ append(std::move(t)); return *this; }
- inline QVector<T> &operator<<(T &&t)
+ inline QVector<T> &operator<<(rvalue_ref t)
{ append(std::move(t)); return *this; }
- static QVector<T> fromList(const QList<T> &list);
- QList<T> toList() const;
+ // Consider deprecating in 6.4 or later
+ static QVector<T> fromList(const QVector<T> &list) { return list; }
+ QVector<T> toList() const { return *this; }
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- Q_DECL_DEPRECATED_X("Use QVector<T>(vector.begin(), vector.end()) instead.")
- static inline QVector<T> fromStdVector(const std::vector<T> &vector)
- { return QVector<T>(vector.begin(), vector.end()); }
- Q_DECL_DEPRECATED_X("Use std::vector<T>(vector.begin(), vector.end()) instead.")
- inline std::vector<T> toStdVector() const
- { return std::vector<T>(d->begin(), d->end()); }
-#endif
-private:
- // ### Qt6: remove methods, they are unused
- void reallocData(const int size, const int alloc, QArrayData::AllocationOptions options = QArrayData::Default);
- void reallocData(const int sz) { reallocData(sz, d->alloc); }
- void realloc(int alloc, QArrayData::AllocationOptions options = QArrayData::Default);
- void freeData(Data *d);
- void defaultConstruct(T *from, T *to);
- void copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom);
- void destruct(T *from, T *to);
- bool isValidIterator(const iterator &i) const
- {
- const std::less<const T*> less = {};
- return !less(d->end(), i) && !less(i, d->begin());
- }
- class AlignmentDummy { Data header; T array[1]; };
+ static inline QVector<T> fromVector(const QVector<T> &vector) { return vector; }
+ inline QVector<T> toVector() const { return *this; }
};
#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
@@ -333,747 +426,296 @@ template <typename InputIterator,
QVector(InputIterator, InputIterator) -> QVector<ValueType>;
#endif
-#ifdef Q_CC_MSVC
-// behavior change: an object of POD type constructed with an initializer of the form ()
-// will be default-initialized
-# pragma warning ( push )
-# pragma warning ( disable : 4345 )
-# pragma warning(disable : 4127) // conditional expression is constant
-#endif
-
template <typename T>
-void QVector<T>::defaultConstruct(T *from, T *to)
+inline void QVector<T>::resize_internal(int newSize, Qt::Initialization)
{
- if (QTypeInfo<T>::isComplex) {
- while (from != to) {
- new (from++) T();
+ Q_ASSERT(newSize >= 0);
+
+ if (d->needsDetach() || newSize > capacity()) {
+ // must allocate memory
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize),
+ d->detachFlags()));
+ if (size() && newSize) {
+ detached->copyAppend(constBegin(), constBegin() + qMin(newSize, size()));
}
- } else {
- ::memset(static_cast<void *>(from), 0, (to - from) * sizeof(T));
+ d.swap(detached);
}
-}
-template <typename T>
-void QVector<T>::copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom)
-{
- if (QTypeInfo<T>::isComplex) {
- while (srcFrom != srcTo)
- new (dstFrom++) T(*srcFrom++);
- } else {
- ::memcpy(static_cast<void *>(dstFrom), static_cast<const void *>(srcFrom), (srcTo - srcFrom) * sizeof(T));
- }
+ if (newSize < size())
+ d->truncate(newSize);
}
template <typename T>
-void QVector<T>::destruct(T *from, T *to)
+void QVector<T>::reserve(int asize)
{
- if (QTypeInfo<T>::isComplex) {
- while (from != to) {
- from++->~T();
+ // capacity() == 0 for immutable data, so this will force a detaching below
+ if (asize <= capacity()) {
+ if (d->flags() & Data::CapacityReserved)
+ return; // already reserved, don't shrink
+ if (!d->isShared()) {
+ // accept current allocation, don't shrink
+ d->flags() |= Data::CapacityReserved;
+ return;
}
}
+
+ DataPointer detached(Data::allocate(qMax(asize, size()),
+ d->detachFlags() | Data::CapacityReserved));
+ detached->copyAppend(constBegin(), constEnd());
+ d.swap(detached);
}
template <typename T>
-inline QVector<T>::QVector(const QVector<T> &v)
+inline void QVector<T>::squeeze()
{
- if (v.d->ref.ref()) {
- d = v.d;
- } else {
- if (v.d->capacityReserved) {
- d = Data::allocate(v.d->alloc);
- Q_CHECK_PTR(d);
- d->capacityReserved = true;
- } else {
- d = Data::allocate(v.d->size);
- Q_CHECK_PTR(d);
- }
- if (d->alloc) {
- copyConstruct(v.d->begin(), v.d->end(), d->begin());
- d->size = v.d->size;
+ if (d->needsDetach() || size() != capacity()) {
+ // must allocate memory
+ DataPointer detached(Data::allocate(size(), d->detachFlags() & ~Data::CapacityReserved));
+ if (size()) {
+ detached->copyAppend(constBegin(), constEnd());
}
+ d.swap(detached);
}
}
-#if defined(Q_CC_MSVC)
-#pragma warning( pop )
-#endif
-
template <typename T>
-void QVector<T>::detach()
+inline void QVector<T>::remove(int i, int n)
{
- if (!isDetached()) {
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- if (!d->alloc)
- d = Data::unsharableEmpty();
- else
-#endif
- realloc(int(d->alloc));
- }
- Q_ASSERT(isDetached());
-}
+ Q_ASSERT_X(size_t(i) + size_t(n) <= size_t(d->size), "QVector::remove", "index out of range");
+ Q_ASSERT_X(n >= 0, "QVector::remove", "invalid count");
-template <typename T>
-void QVector<T>::reserve(int asize)
-{
- if (asize > int(d->alloc))
- realloc(asize);
- if (isDetached()
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- && d != Data::unsharableEmpty()
-#endif
- )
- d->capacityReserved = 1;
- Q_ASSERT(capacity() >= asize);
-}
+ if (n == 0)
+ return;
-template <typename T>
-void QVector<T>::resize(int asize)
-{
- if (asize == d->size)
- return detach();
- if (asize > int(d->alloc) || !isDetached()) { // there is not enough space
- QArrayData::AllocationOptions opt = asize > int(d->alloc) ? QArrayData::Grow : QArrayData::Default;
- realloc(qMax(int(d->alloc), asize), opt);
+ const size_t newSize = size() - n;
+ if (d->needsDetach() ||
+ ((d->flags() & Data::CapacityReserved) == 0
+ && newSize < d->allocatedCapacity()/2)) {
+ // allocate memory
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize),
+ d->detachFlags() & ~(Data::GrowsBackwards | Data::GrowsForward)));
+ const_iterator where = constBegin() + i;
+ if (newSize) {
+ detached->copyAppend(constBegin(), where);
+ detached->copyAppend(where + n, constEnd());
+ }
+ d.swap(detached);
+ } else {
+ // we're detached and we can just move data around
+ d->erase(d->begin() + i, d->begin() + i + n);
}
- if (asize < d->size)
- destruct(begin() + asize, end());
- else
- defaultConstruct(end(), begin() + asize);
- d->size = asize;
-}
-template <typename T>
-inline void QVector<T>::clear()
-{
- if (!d->size)
- return;
- destruct(begin(), end());
- d->size = 0;
}
-template <typename T>
-inline const T &QVector<T>::at(int i) const
-{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
- return d->begin()[i]; }
-template <typename T>
-inline const T &QVector<T>::operator[](int i) const
-{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
- return d->begin()[i]; }
-template <typename T>
-inline T &QVector<T>::operator[](int i)
-{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
- return data()[i]; }
-template <typename T>
-inline void QVector<T>::insert(int i, const T &t)
-{ Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
- insert(begin() + i, 1, t); }
-template <typename T>
-inline void QVector<T>::insert(int i, int n, const T &t)
-{ Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
- insert(begin() + i, n, t); }
-template <typename T>
-inline void QVector<T>::insert(int i, T &&t)
-{ Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
- insert(begin() + i, std::move(t)); }
-template <typename T>
-inline void QVector<T>::remove(int i, int n)
-{ Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= d->size, "QVector<T>::remove", "index out of range");
- erase(d->begin() + i, d->begin() + i + n); }
-template <typename T>
-inline void QVector<T>::remove(int i)
-{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::remove", "index out of range");
- erase(d->begin() + i, d->begin() + i + 1); }
+
template <typename T>
inline void QVector<T>::prepend(const T &t)
-{ insert(begin(), 1, t); }
-template <typename T>
-inline void QVector<T>::prepend(T &&t)
-{ insert(begin(), std::move(t)); }
-
+{ insert(0, 1, t); }
template <typename T>
-inline void QVector<T>::replace(int i, const T &t)
-{
- Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range");
- const T copy(t);
- data()[i] = copy;
-}
+void QVector<T>::prepend(rvalue_ref t)
+{ insert(0, std::move(t)); }
-template <typename T>
-QVector<T> &QVector<T>::operator=(const QVector<T> &v)
+template<typename T>
+inline T QVector<T>::value(int i, const T &defaultValue) const
{
- if (v.d != d) {
- QVector<T> tmp(v);
- tmp.swap(*this);
- }
- return *this;
+ return size_t(i) < size_t(d->size) ? at(i) : defaultValue;
}
template <typename T>
-QVector<T>::QVector(int asize)
+inline void QVector<T>::append(const_iterator i1, const_iterator i2)
{
- Q_ASSERT_X(asize >= 0, "QVector::QVector", "Size must be greater than or equal to 0.");
- if (Q_LIKELY(asize > 0)) {
- d = Data::allocate(asize);
- Q_CHECK_PTR(d);
- d->size = asize;
- defaultConstruct(d->begin(), d->end());
+ if (i1 == i2)
+ return;
+ const size_t newSize = size() + std::distance(i1, i2);
+ if (d->needsDetach() || newSize > d->allocatedCapacity()) {
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize),
+ d->detachFlags() | Data::GrowsForward));
+ detached->copyAppend(constBegin(), constEnd());
+ detached->copyAppend(i1, i2);
+ d.swap(detached);
} else {
- d = Data::sharedNull();
+ // we're detached and we can just move data around
+ d->copyAppend(i1, i2);
}
}
template <typename T>
-QVector<T>::QVector(int asize, const T &t)
+inline void QVector<T>::append(value_type &&t)
{
- Q_ASSERT_X(asize >= 0, "QVector::QVector", "Size must be greater than or equal to 0.");
- if (asize > 0) {
- d = Data::allocate(asize);
- Q_CHECK_PTR(d);
- d->size = asize;
- T* i = d->end();
- while (i != d->begin())
- new (--i) T(t);
+ const size_t newSize = size() + 1;
+ const bool isTooSmall = newSize > d->allocatedCapacity();
+ const bool isOverlapping = std::addressof(*d->begin()) <= std::addressof(t)
+ && std::addressof(t) < std::addressof(*d->end());
+ if (isTooSmall || d->needsDetach() || Q_UNLIKELY(isOverlapping)) {
+ typename Data::ArrayOptions flags = d->detachFlags();
+ if (isTooSmall)
+ flags |= Data::GrowsForward;
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize), flags));
+ detached->copyAppend(constBegin(), constEnd());
+ detached->moveAppend(std::addressof(t), std::addressof(t) + 1);
+ d.swap(detached);
} else {
- d = Data::sharedNull();
+ // we're detached and we can just move data around
+ d->moveAppend(std::addressof(t), std::addressof(t) + 1);
}
}
-#if defined(Q_CC_MSVC)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_MSVC(4127) // conditional expression is constant
-#endif // Q_CC_MSVC
-
template <typename T>
-QVector<T>::QVector(std::initializer_list<T> args)
+inline typename QVector<T>::iterator
+QVector<T>::insert(int i, int n, parameter_type t)
{
- if (args.size() > 0) {
- d = Data::allocate(args.size());
- Q_CHECK_PTR(d);
- // std::initializer_list<T>::iterator is guaranteed to be
- // const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct
- copyConstruct(args.begin(), args.end(), d->begin());
- d->size = int(args.size());
- } else {
- d = Data::sharedNull();
- }
-}
+ Q_ASSERT_X(size_t(i) <= size_t(d->size), "QVector<T>::insert", "index out of range");
-template <typename T>
-QVector<T> &QVector<T>::operator=(std::initializer_list<T> args)
-{
- QVector<T> tmp(args);
- tmp.swap(*this);
- return *this;
-}
-
-#if defined(Q_CC_MSVC)
-QT_WARNING_POP
-#endif // Q_CC_MSVC
+ // we don't have a quick exit for n == 0
+ // it's not worth wasting CPU cycles for that
-template <typename T>
-template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator>>
-QVector<T>::QVector(InputIterator first, InputIterator last)
- : QVector()
-{
- QtPrivate::reserveIfForwardIterator(this, first, last);
- std::copy(first, last, std::back_inserter(*this));
-}
-
-template <typename T>
-void QVector<T>::freeData(Data *x)
-{
- destruct(x->begin(), x->end());
- Data::deallocate(x);
-}
+ const size_t newSize = size() + n;
+ if (d->needsDetach() || newSize > d->allocatedCapacity()) {
+ typename Data::ArrayOptions flags = d->detachFlags() | Data::GrowsForward;
+ if (size_t(i) <= newSize / 4)
+ flags |= Data::GrowsBackwards;
-#if defined(Q_CC_MSVC)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_MSVC(4127) // conditional expression is constant
-#endif
-
-template <typename T>
-void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::AllocationOptions options)
-{
- Q_ASSERT(asize >= 0 && asize <= aalloc);
- Data *x = d;
-
- const bool isShared = d->ref.isShared();
-
- if (aalloc != 0) {
- if (aalloc != int(d->alloc) || isShared) {
- QT_TRY {
- // allocate memory
- x = Data::allocate(aalloc, options);
- Q_CHECK_PTR(x);
- // aalloc is bigger then 0 so it is not [un]sharedEmpty
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- Q_ASSERT(x->ref.isSharable() || options.testFlag(QArrayData::Unsharable));
-#endif
- Q_ASSERT(!x->ref.isStatic());
- x->size = asize;
-
- T *srcBegin = d->begin();
- T *srcEnd = asize > d->size ? d->end() : d->begin() + asize;
- T *dst = x->begin();
-
- if (!QTypeInfoQuery<T>::isRelocatable || (isShared && QTypeInfo<T>::isComplex)) {
- QT_TRY {
- if (isShared || !std::is_nothrow_move_constructible<T>::value) {
- // we can not move the data, we need to copy construct it
- while (srcBegin != srcEnd)
- new (dst++) T(*srcBegin++);
- } else {
- while (srcBegin != srcEnd)
- new (dst++) T(std::move(*srcBegin++));
- }
- } QT_CATCH (...) {
- // destruct already copied objects
- destruct(x->begin(), dst);
- QT_RETHROW;
- }
- } else {
- ::memcpy(static_cast<void *>(dst), static_cast<void *>(srcBegin), (srcEnd - srcBegin) * sizeof(T));
- dst += srcEnd - srcBegin;
-
- // destruct unused / not moved data
- if (asize < d->size)
- destruct(d->begin() + asize, d->end());
- }
-
- if (asize > d->size) {
- // construct all new objects when growing
- if (!QTypeInfo<T>::isComplex) {
- ::memset(static_cast<void *>(dst), 0, (static_cast<T *>(x->end()) - dst) * sizeof(T));
- } else {
- QT_TRY {
- while (dst != x->end())
- new (dst++) T();
- } QT_CATCH (...) {
- // destruct already copied objects
- destruct(x->begin(), dst);
- QT_RETHROW;
- }
- }
- }
- } QT_CATCH (...) {
- Data::deallocate(x);
- QT_RETHROW;
- }
- x->capacityReserved = d->capacityReserved;
- } else {
- Q_ASSERT(int(d->alloc) == aalloc); // resize, without changing allocation size
- Q_ASSERT(isDetached()); // can be done only on detached d
- Q_ASSERT(x == d); // in this case we do not need to allocate anything
- if (asize <= d->size) {
- destruct(x->begin() + asize, x->end()); // from future end to current end
- } else {
- defaultConstruct(x->end(), x->begin() + asize); // from current end to future end
- }
- x->size = asize;
- }
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize), flags));
+ const_iterator where = constBegin() + i;
+ detached->copyAppend(constBegin(), where);
+ detached->copyAppend(n, t);
+ detached->copyAppend(where, constEnd());
+ d.swap(detached);
} else {
- x = Data::sharedNull();
- }
- if (d != x) {
- if (!d->ref.deref()) {
- if (!QTypeInfoQuery<T>::isRelocatable || !aalloc || (isShared && QTypeInfo<T>::isComplex)) {
- // data was copy constructed, we need to call destructors
- // or if !alloc we did nothing to the old 'd'.
- freeData(d);
- } else {
- Data::deallocate(d);
- }
- }
- d = x;
- }
-
- Q_ASSERT(d->data());
- Q_ASSERT(uint(d->size) <= d->alloc);
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- Q_ASSERT(d != Data::unsharableEmpty());
-#endif
- Q_ASSERT(aalloc ? d != Data::sharedNull() : d == Data::sharedNull());
- Q_ASSERT(d->alloc >= uint(aalloc));
- Q_ASSERT(d->size == asize);
-}
-
-template<typename T>
-void QVector<T>::realloc(int aalloc, QArrayData::AllocationOptions options)
-{
- Q_ASSERT(aalloc >= d->size);
- Data *x = d;
-
- const bool isShared = d->ref.isShared();
-
- QT_TRY {
- // allocate memory
- x = Data::allocate(aalloc, options);
- Q_CHECK_PTR(x);
- // aalloc is bigger then 0 so it is not [un]sharedEmpty
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- Q_ASSERT(x->ref.isSharable() || options.testFlag(QArrayData::Unsharable));
-#endif
- Q_ASSERT(!x->ref.isStatic());
- x->size = d->size;
-
- T *srcBegin = d->begin();
- T *srcEnd = d->end();
- T *dst = x->begin();
-
- if (!QTypeInfoQuery<T>::isRelocatable || (isShared && QTypeInfo<T>::isComplex)) {
- QT_TRY {
- if (isShared || !std::is_nothrow_move_constructible<T>::value) {
- // we can not move the data, we need to copy construct it
- while (srcBegin != srcEnd)
- new (dst++) T(*srcBegin++);
- } else {
- while (srcBegin != srcEnd)
- new (dst++) T(std::move(*srcBegin++));
- }
- } QT_CATCH (...) {
- // destruct already copied objects
- destruct(x->begin(), dst);
- QT_RETHROW;
- }
- } else {
- ::memcpy(static_cast<void *>(dst), static_cast<void *>(srcBegin), (srcEnd - srcBegin) * sizeof(T));
- dst += srcEnd - srcBegin;
- }
-
- } QT_CATCH (...) {
- Data::deallocate(x);
- QT_RETHROW;
- }
- x->capacityReserved = d->capacityReserved;
-
- Q_ASSERT(d != x);
- if (!d->ref.deref()) {
- if (!QTypeInfoQuery<T>::isRelocatable || !aalloc || (isShared && QTypeInfo<T>::isComplex)) {
- // data was copy constructed, we need to call destructors
- // or if !alloc we did nothing to the old 'd'.
- freeData(d);
+ // we're detached and we can just move data around
+ if (i == size()) {
+ d->copyAppend(n, t);
} else {
- Data::deallocate(d);
+ T copy(t);
+ d->insert(d.begin() + i, n, copy);
}
}
- d = x;
-
- Q_ASSERT(d->data());
- Q_ASSERT(uint(d->size) <= d->alloc);
-#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- Q_ASSERT(d != Data::unsharableEmpty());
-#endif
- Q_ASSERT(d != Data::sharedNull());
- Q_ASSERT(d->alloc >= uint(aalloc));
-}
-
-#if defined(Q_CC_MSVC)
-QT_WARNING_POP
-#endif
-
-template<typename T>
-Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
-{
- if (uint(i) >= uint(d->size)) {
- return T();
- }
- return d->begin()[i];
-}
-template<typename T>
-Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
-{
- return uint(i) >= uint(d->size) ? defaultValue : d->begin()[i];
-}
-
-template <typename T>
-void QVector<T>::append(const T &t)
-{
- const bool isTooSmall = uint(d->size + 1) > d->alloc;
- if (!isDetached() || isTooSmall) {
- T copy(t);
- QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
- realloc(isTooSmall ? d->size + 1 : d->alloc, opt);
-
- if (QTypeInfo<T>::isComplex)
- new (d->end()) T(std::move(copy));
- else
- *d->end() = std::move(copy);
-
- } else {
- if (QTypeInfo<T>::isComplex)
- new (d->end()) T(t);
- else
- *d->end() = t;
- }
- ++d->size;
+ return d.begin() + i;
}
template <typename T>
-void QVector<T>::append(T &&t)
+typename QVector<T>::iterator
+QVector<T>::insert(int i, rvalue_ref t)
{
- const bool isTooSmall = uint(d->size + 1) > d->alloc;
- if (!isDetached() || isTooSmall) {
- QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
- realloc(isTooSmall ? d->size + 1 : d->alloc, opt);
- }
-
- new (d->end()) T(std::move(t));
+ Q_ASSERT_X(size_t(i) <= size_t(d->size), "QVector<T>::insert", "index out of range");
- ++d->size;
-}
-
-template <typename T>
-void QVector<T>::removeLast()
-{
- Q_ASSERT(!isEmpty());
- Q_ASSERT(d->alloc);
-
- if (d->ref.isShared())
- detach();
- --d->size;
- if (QTypeInfo<T>::isComplex)
- (d->data() + d->size)->~T();
-}
-
-template <typename T>
-typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
-{
- Q_ASSERT_X(isValidIterator(before), "QVector::insert", "The specified iterator argument 'before' is invalid");
-
- const auto offset = std::distance(d->begin(), before);
- if (n != 0) {
- const T copy(t);
- if (!isDetached() || d->size + n > int(d->alloc))
- realloc(d->size + n, QArrayData::Grow);
- if (!QTypeInfoQuery<T>::isRelocatable) {
- T *b = d->end();
- T *i = d->end() + n;
- while (i != b)
- new (--i) T;
- i = d->end();
- T *j = i + n;
- b = d->begin() + offset;
- while (i != b)
- *--j = *--i;
- i = b+n;
- while (i != b)
- *--i = copy;
- } else {
- T *b = d->begin() + offset;
- T *i = b + n;
- memmove(static_cast<void *>(i), static_cast<const void *>(b), (d->size - offset) * sizeof(T));
- while (i != b)
- new (--i) T(copy);
- }
- d->size += n;
- }
- return d->begin() + offset;
-}
+ const size_t newSize = size() + 1;
+ if (d->needsDetach() || newSize > d->allocatedCapacity()) {
+ typename Data::ArrayOptions flags = d->detachFlags() | Data::GrowsForward;
+ if (size_t(i) <= newSize / 4)
+ flags |= Data::GrowsBackwards;
-template <typename T>
-typename QVector<T>::iterator QVector<T>::insert(iterator before, T &&t)
-{
- Q_ASSERT_X(isValidIterator(before), "QVector::insert", "The specified iterator argument 'before' is invalid");
-
- const auto offset = std::distance(d->begin(), before);
- if (!isDetached() || d->size + 1 > int(d->alloc))
- realloc(d->size + 1, QArrayData::Grow);
- if (!QTypeInfoQuery<T>::isRelocatable) {
- T *i = d->end();
- T *j = i + 1;
- T *b = d->begin() + offset;
- // 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));
- }
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize), flags));
+ const_iterator where = constBegin() + i;
+ detached->copyAppend(constBegin(), where);
+ detached->moveAppend(std::addressof(t), std::addressof(t) + 1);
+ detached->copyAppend(where, constEnd());
+ d.swap(detached);
} else {
- T *b = d->begin() + offset;
- memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (d->size - offset) * sizeof(T));
- new (b) T(std::move(t));
+ d->insert(d.begin() + i, std::move(t));
}
- d->size += 1;
- return d->begin() + offset;
+ return d.begin() + i;
}
template <typename T>
typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
{
- Q_ASSERT_X(isValidIterator(abegin), "QVector::erase", "The specified iterator argument 'abegin' is invalid");
- Q_ASSERT_X(isValidIterator(aend), "QVector::erase", "The specified iterator argument 'aend' is invalid");
-
- const auto itemsToErase = aend - abegin;
-
- if (!itemsToErase)
- return abegin;
-
- Q_ASSERT(abegin >= d->begin());
- Q_ASSERT(aend <= d->end());
- Q_ASSERT(abegin <= aend);
-
- const auto itemsUntouched = abegin - d->begin();
-
- // FIXME we could do a proper realloc, which copy constructs only needed data.
- // FIXME we are about to delete data - maybe it is good time to shrink?
- // FIXME the shrink is also an issue in removeLast, that is just a copy + reduce of this.
- if (d->alloc) {
- detach();
- abegin = d->begin() + itemsUntouched;
- aend = abegin + itemsToErase;
- if (!QTypeInfoQuery<T>::isRelocatable) {
- iterator moveBegin = abegin + itemsToErase;
- iterator moveEnd = d->end();
- while (moveBegin != moveEnd) {
- if (QTypeInfo<T>::isComplex)
- static_cast<T *>(abegin)->~T();
- new (abegin++) T(*moveBegin++);
- }
- if (abegin < d->end()) {
- // destroy rest of instances
- destruct(abegin, d->end());
- }
- } else {
- destruct(abegin, aend);
- // QTBUG-53605: static_cast<void *> masks clang errors of the form
- // error: destination for this 'memmove' call is a pointer to class containing a dynamic class
- // FIXME maybe use std::is_polymorphic (as soon as allowed) to avoid the memmove
- memmove(static_cast<void *>(abegin), static_cast<void *>(aend),
- (d->size - itemsToErase - itemsUntouched) * sizeof(T));
- }
- d->size -= int(itemsToErase);
- }
- return d->begin() + itemsUntouched;
-}
+ Q_ASSERT_X(isValidIterator(const_iterator(abegin)), "QVector::erase", "The specified iterator argument 'abegin' is invalid");
+ Q_ASSERT_X(isValidIterator(const_iterator(aend)), "QVector::erase", "The specified iterator argument 'aend' is invalid");
+ Q_ASSERT(aend >= abegin);
-template <typename T>
-bool QVector<T>::operator==(const QVector<T> &v) const
-{
- if (d == v.d)
- return true;
- if (d->size != v.d->size)
- return false;
- const T *vb = v.d->begin();
- const T *b = d->begin();
- const T *e = d->end();
- return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(vb, v.d->size));
-}
+ // d.begin() so we don't detach just yet
+ int i = std::distance(d.begin(), abegin);
+ int n = std::distance(abegin, aend);
+ remove(i, n);
-template <typename T>
-QVector<T> &QVector<T>::fill(const T &from, int asize)
-{
- const T copy(from);
- resize(asize < 0 ? d->size : asize);
- if (d->size) {
- T *i = d->end();
- T *b = d->begin();
- while (i != b)
- *--i = copy;
- }
- return *this;
+ return d.begin() + i;
}
template <typename T>
-QVector<T> &QVector<T>::operator+=(const QVector &l)
+inline QVector<T> &QVector<T>::fill(parameter_type t, int newSize)
{
- if (d->size == 0) {
- *this = l;
+ if (newSize == -1)
+ newSize = size();
+ if (d->needsDetach() || newSize > capacity()) {
+ // must allocate memory
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize),
+ d->detachFlags()));
+ detached->copyAppend(newSize, t);
+ d.swap(detached);
} else {
- uint newSize = d->size + l.d->size;
- const bool isTooSmall = newSize > d->alloc;
- if (!isDetached() || isTooSmall) {
- QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
- realloc(isTooSmall ? newSize : d->alloc, opt);
- }
-
- if (d->alloc) {
- T *w = d->begin() + newSize;
- T *i = l.d->end();
- T *b = l.d->begin();
- while (i != b) {
- if (QTypeInfo<T>::isComplex)
- new (--w) T(*--i);
- else
- *--w = *--i;
- }
- d->size = newSize;
- }
+ // we're detached
+ const T copy(t);
+ d->assign(d.begin(), d.begin() + qMin(size(), newSize), t);
+ if (newSize > size())
+ d->copyAppend(newSize - size(), copy);
}
return *this;
}
-template <typename T>
-int QVector<T>::indexOf(const T &t, int from) const
+namespace QtPrivate {
+template <typename T, typename U>
+int indexOf(const QVector<T> &vector, const U &u, int from)
{
if (from < 0)
- from = qMax(from + d->size, 0);
- if (from < d->size) {
- T* n = d->begin() + from - 1;
- T* e = d->end();
+ from = qMax(from + vector.size(), 0);
+ if (from < vector.size()) {
+ auto n = vector.begin() + from - 1;
+ auto e = vector.end();
while (++n != e)
- if (*n == t)
- return n - d->begin();
+ if (*n == u)
+ return n - vector.begin();
}
return -1;
}
-template <typename T>
-int QVector<T>::lastIndexOf(const T &t, int from) const
+template <typename T, typename U>
+int lastIndexOf(const QVector<T> &vector, const U &u, int from)
{
if (from < 0)
- from += d->size;
- else if (from >= d->size)
- from = d->size-1;
+ from += vector.d->size;
+ else if (from >= vector.size())
+ from = vector.size() - 1;
if (from >= 0) {
- T* b = d->begin();
- T* n = d->begin() + from + 1;
+ auto b = vector.begin();
+ auto n = vector.begin() + from + 1;
while (n != b) {
- if (*--n == t)
+ if (*--n == u)
return n - b;
}
}
return -1;
}
+}
template <typename T>
-bool QVector<T>::contains(const T &t) const
+int QVector<T>::indexOf(const T &t, int from) const noexcept
{
- const T *b = d->begin();
- const T *e = d->end();
- return std::find(b, e, t) != e;
+ return QtPrivate::indexOf<T, T>(*this, t, from);
}
template <typename T>
-int QVector<T>::count(const T &t) const
+int QVector<T>::lastIndexOf(const T &t, int from) const noexcept
{
- const T *b = d->begin();
- const T *e = d->end();
- return int(std::count(b, e, t));
+ return QtPrivate::lastIndexOf(*this, t, from);
}
template <typename T>
-Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int len) const
+inline QVector<T> QVector<T>::mid(int pos, int len) const
{
using namespace QtPrivate;
- switch (QContainerImplHelper::mid(d->size, &pos, &len)) {
+ switch (QContainerImplHelper::mid(d.size, &pos, &len)) {
case QContainerImplHelper::Null:
case QContainerImplHelper::Empty:
- return QVector<T>();
+ return QVector();
case QContainerImplHelper::Full:
return *this;
case QContainerImplHelper::Subset:
break;
}
- QVector<T> midResult;
- midResult.realloc(len);
- T *srcFrom = d->begin() + pos;
- T *srcTo = d->begin() + pos + len;
- midResult.copyConstruct(srcFrom, srcTo, midResult.data());
- midResult.d->size = len;
- return midResult;
+ // Allocate memory
+ DataPointer copied(Data::allocate(len));
+ copied->copyAppend(constBegin() + pos, constBegin() + pos + len);
+ return copied;
}
Q_DECLARE_SEQUENTIAL_ITERATOR(Vector)
@@ -1153,4 +795,7 @@ QVector<QStringRef> QStringRef::split(QChar sep, Qt::SplitBehavior behavior, Qt:
QT_END_NAMESPACE
+#include <QtCore/qbytearraylist.h>
+#include <QtCore/qstringlist.h>
+
#endif // QVECTOR_H
diff --git a/src/corelib/tools/qvector_msvc.cpp b/src/corelib/tools/qvector_msvc.cpp
index cee343e72b..7e87467d42 100644
--- a/src/corelib/tools/qvector_msvc.cpp
+++ b/src/corelib/tools/qvector_msvc.cpp
@@ -47,12 +47,5 @@
# error "This file must be compiled with no precompiled headers"
#endif
-// invert the setting of QT_STRICT_ITERATORS, whichever it was
-#ifdef QT_STRICT_ITERATORS
-# undef QT_STRICT_ITERATORS
-#else
-# define QT_STRICT_ITERATORS
-#endif
-
// the Q_TEMPLATE_EXTERN at the bottom of qvector.h will do the trick
#include <QtCore/qvector.h>
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index e078ab4409..ff300bcf7b 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -13,6 +13,7 @@ HEADERS += \
tools/qcontainertools_impl.h \
tools/qcryptographichash.h \
tools/qduplicatetracker_p.h \
+ tools/qflatmap_p.h \
tools/qfreelist_p.h \
tools/qhash.h \
tools/qhashfunctions.h \
@@ -48,7 +49,6 @@ HEADERS += \
tools/qvector.h \
tools/qversionnumber.h
-
SOURCES += \
tools/qarraydata.cpp \
tools/qbitarray.cpp \